#include "b_local.h"#include "g_nav.h"#include "../icarus/Q3_Interface.h"#include "../namespace_begin.h"#include "../namespace_end.h"Go to the source code of this file.
Defines | |
| #define | APEX_HEIGHT 200.0f |
| #define | PARA_WIDTH (sqrt(APEX_HEIGHT)+sqrt(APEX_HEIGHT)) |
| #define | JUMP_SPEED 200.0f |
Functions | |
| void | G_Cube (vec3_t mins, vec3_t maxs, vec3_t color, float alpha) |
| void | NPC_CheckGetNewWeapon (void) |
| qboolean | PM_InKnockDown (playerState_t *ps) |
| void | NPC_AimAdjust (int change) |
| qboolean | NPC_SomeoneLookingAtMe (gentity_t *ent) |
| void | NPC_BSAdvanceFight (void) |
| void | Disappear (gentity_t *self) |
| void | MakeOwnerInvis (gentity_t *self) |
| void | BeamOut (gentity_t *self) |
| void | NPC_BSCinematic (void) |
| void | NPC_BSWait (void) |
| void | NPC_BSInvestigate (void) |
| qboolean | NPC_CheckInvestigate (int alertEventNum) |
| void | NPC_BSSleep (void) |
| qboolean | NPC_MoveDirClear (int forwardmove, int rightmove, qboolean reset) |
| void | NPC_BSFollowLeader (void) |
| void | NPC_BSJump (void) |
| void | NPC_BSRemove (void) |
| void | NPC_BSSearch (void) |
| void | NPC_BSSearchStart (int homeWp, bState_t bState) |
| void | NPC_BSNoClip (void) |
| void | NPC_BSWander (void) |
| void | G_AddVoiceEvent (gentity_t *self, int event, int speakDebounceTime) |
| void | WP_DropWeapon (gentity_t *dropper, vec3_t velocity) |
| void | ChangeWeapon (gentity_t *ent, int newWeapon) |
| void | NPC_Surrender (void) |
| qboolean | NPC_CheckSurrender (void) |
| void | NPC_BSFlee (void) |
| void | NPC_StartFlee (gentity_t *enemy, vec3_t dangerPoint, int dangerLevel, int fleeTimeMin, int fleeTimeMax) |
| void | G_StartFlee (gentity_t *self, gentity_t *enemy, vec3_t dangerPoint, int dangerLevel, int fleeTimeMin, int fleeTimeMax) |
| void | NPC_BSEmplaced (void) |
Variables | |
| qboolean | showBBoxes |
| vec3_t | NPCDEBUG_BLUE |
|
|
Definition at line 730 of file NPC_behavior.c. |
|
|
Definition at line 732 of file NPC_behavior.c. |
|
|
Definition at line 731 of file NPC_behavior.c. |
|
|
Definition at line 194 of file NPC_behavior.c. References gentity_s::client, Disappear(), gentity_t, level, gentity_s::nextthink, NULL, gclient_s::playerTeam, gentity_s::s, gclient_s::squadname, TEAM_FREE, entityState_s::teamowner, gentity_s::think, and level_locals_t::time.
00195 {
00196 // gentity_t *tent = G_Spawn();
00197
00198 /*
00199 tent->owner = self;
00200 tent->think = MakeOwnerInvis;
00201 tent->nextthink = level.time + 1800;
00202 //G_AddEvent( ent, EV_PLAYER_TELEPORT, 0 );
00203 tent = G_TempEntity( self->client->pcurrentOrigin, EV_PLAYER_TELEPORT );
00204 */
00205 //fixme: doesn't actually go away!
00206 self->nextthink = level.time + 1500;
00207 self->think = Disappear;
00208 self->client->squadname = NULL;
00209 self->client->playerTeam = self->s.teamowner = TEAM_FREE;
00210 //self->r.svFlags |= SVF_BEAMING; //this appears unused in SP as well
00211 }
|
|
||||||||||||
|
|
|
|
Definition at line 185 of file NPC_behavior.c. References EF_NODRAW, entityState_s::eFlags, gentity_t, gentity_s::nextthink, gentity_s::s, and gentity_s::think. Referenced by BeamOut().
|
|
||||||||||||||||
|
Definition at line 23 of file NPC_sounds.c.
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 16 of file g_nav.c. References vec3_t. Referenced by NAV_StackedCanyon(), NPC_BSJump(), and NPC_ShowDebugInfo().
00017 {
00018
00019 }
|
|
||||||||||||||||||||||||||||
|
Definition at line 1636 of file NPC_behavior.c. References gentity_t, gentity_s::NPC, NPC_StartFlee(), RestoreNPCGlobals(), SaveNPCGlobals(), SetNPCGlobals(), and vec3_t. Referenced by ST_StartFlee().
01637 {
01638 if ( !self->NPC )
01639 {//player
01640 return;
01641 }
01642 SaveNPCGlobals();
01643 SetNPCGlobals( self );
01644
01645 NPC_StartFlee( enemy, dangerPoint, dangerLevel, fleeTimeMin, fleeTimeMax );
01646
01647 RestoreNPCGlobals();
01648 }
|
|
|
|
|
|
Definition at line 3098 of file NPC_combat.c. References gNPCstats_e::aim, gNPC_t::currentAim, g_spskill, vmCvar_t::integer, NPC, NPCInfo, Q_irand(), gNPC_t::stats, TIMER_Done(), TIMER_Exists(), and TIMER_Set(). Referenced by NPC_BSEmplaced(), NPC_BSFollowLeader(), NPC_BSGM_Attack(), NPC_BSGrenadier_Attack(), and NPC_BSST_Attack().
03099 {
03100 if ( !TIMER_Exists( NPC, "aimDebounce" ) )
03101 {
03102 int debounce = 500+(3-g_spskill.integer)*100;
03103 TIMER_Set( NPC, "aimDebounce", Q_irand( debounce,debounce+1000 ) );
03104 //int debounce = 1000+(3-g_spskill.integer)*500;
03105 //TIMER_Set( NPC, "aimDebounce", Q_irand( debounce, debounce+2000 ) );
03106 return;
03107 }
03108 if ( TIMER_Done( NPC, "aimDebounce" ) )
03109 {
03110 int debounce;
03111
03112 NPCInfo->currentAim += change;
03113 if ( NPCInfo->currentAim > NPCInfo->stats.aim )
03114 {//can never be better than max aim
03115 NPCInfo->currentAim = NPCInfo->stats.aim;
03116 }
03117 else if ( NPCInfo->currentAim < -30 )
03118 {//can never be worse than this
03119 NPCInfo->currentAim = -30;
03120 }
03121
03122 //Com_Printf( "%s new aim = %d\n", NPC->NPC_type, NPCInfo->currentAim );
03123
03124 debounce = 500+(3-g_spskill.integer)*100;
03125 TIMER_Set( NPC, "aimDebounce", Q_irand( debounce,debounce+1000 ) );
03126 //int debounce = 1000+(3-g_spskill.integer)*500;
03127 //TIMER_Set( NPC, "aimDebounce", Q_irand( debounce, debounce+2000 ) );
03128 }
03129 }
|
|
|
Definition at line 29 of file NPC_behavior.c. References entityShared_t::absmin, AngleVectors(), CalcEntitySpot(), gNPC_t::captureGoal, CHECK_FOV, gentity_s::client, entityShared_t::currentOrigin, gNPC_t::desiredPitch, trace_t::endpos, gentity_s::enemy, gNPC_t::enemyLastVisibility, gclient_s::enemyTeam, enemyVisibility, trace_t::entityNum, usercmd_s::forwardmove, g_entities, gentity_t, gNPC_t::goalTime, level, MASK_SHOT, entityShared_t::maxs, gentity_s::NPC, NPC, NPC_CheckAttack(), NPC_CheckEnemy(), NPC_CheckVisibility(), NPC_EnemyTooFar(), NPC_SetMoveGoal(), NPC_UpdateShootAngles(), NPCInfo, NULL, entityState_s::number, PITCH, gclient_s::playerTeam, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::r, random, usercmd_s::rightmove, gentity_s::s, gNPC_t::shootAngles, SPOT_HEAD, SPOT_WEAPON, TID_BSTATE, level_locals_t::time, trap_ICARUS_IsInitialized(), trap_ICARUS_TaskIDComplete(), trap_Trace(), ucmd, vec3_t, vectoangles(), VectorCopy, VectorMA, VectorNormalize(), VectorSubtract, playerState_s::viewangles, VIS_FOV, VIS_SHOOT, and WeaponThink(). Referenced by NPC_BehaviorSet_Default().
00030 {//FIXME: IMPLEMENT
00031 //Head to Goal if I can
00032
00033 //Make sure we're still headed where we want to capture
00034 if ( NPCInfo->captureGoal )
00035 {//FIXME: if no captureGoal, what do we do?
00036 //VectorCopy( NPCInfo->captureGoal->r.currentOrigin, NPCInfo->tempGoal->r.currentOrigin );
00037 //NPCInfo->goalEntity = NPCInfo->tempGoal;
00038
00039 NPC_SetMoveGoal( NPC, NPCInfo->captureGoal->r.currentOrigin, 16, qtrue, -1, NULL );
00040
00041 // NAV_ClearLastRoute(NPC);
00042 NPCInfo->goalTime = level.time + 100000;
00043 }
00044
00045 // NPC_BSRun();
00046
00047 NPC_CheckEnemy(qtrue, qfalse, qtrue);
00048
00049 //FIXME: Need melee code
00050 if( NPC->enemy )
00051 {//See if we can shoot him
00052 vec3_t delta, forward;
00053 vec3_t angleToEnemy;
00054 vec3_t hitspot, muzzle, diff, enemy_org, enemy_head;
00055 float distanceToEnemy;
00056 qboolean attack_ok = qfalse;
00057 qboolean dead_on = qfalse;
00058 float attack_scale = 1.0;
00059 float aim_off;
00060 float max_aim_off = 64;
00061
00062 //Yaw to enemy
00063 VectorMA(NPC->enemy->r.absmin, 0.5, NPC->enemy->r.maxs, enemy_org);
00064 CalcEntitySpot( NPC, SPOT_WEAPON, muzzle );
00065
00066 VectorSubtract (enemy_org, muzzle, delta);
00067 vectoangles ( delta, angleToEnemy );
00068 distanceToEnemy = VectorNormalize(delta);
00069
00070 if(!NPC_EnemyTooFar(NPC->enemy, distanceToEnemy*distanceToEnemy, qtrue))
00071 {
00072 attack_ok = qtrue;
00073 }
00074
00075 if(attack_ok)
00076 {
00077 NPC_UpdateShootAngles(angleToEnemy, qfalse, qtrue);
00078
00079 NPCInfo->enemyLastVisibility = enemyVisibility;
00080 enemyVisibility = NPC_CheckVisibility ( NPC->enemy, CHECK_FOV);//CHECK_360|//CHECK_PVS|
00081
00082 if(enemyVisibility == VIS_FOV)
00083 {//He's in our FOV
00084
00085 attack_ok = qtrue;
00086 CalcEntitySpot( NPC->enemy, SPOT_HEAD, enemy_head);
00087
00088 if(attack_ok)
00089 {
00090 trace_t tr;
00091 gentity_t *traceEnt;
00092 //are we gonna hit him if we shoot at his center?
00093 trap_Trace ( &tr, muzzle, NULL, NULL, enemy_org, NPC->s.number, MASK_SHOT );
00094 traceEnt = &g_entities[tr.entityNum];
00095 if( traceEnt != NPC->enemy &&
00096 (!traceEnt || !traceEnt->client || !NPC->client->enemyTeam || NPC->client->enemyTeam != traceEnt->client->playerTeam) )
00097 {//no, so shoot for the head
00098 attack_scale *= 0.75;
00099 trap_Trace ( &tr, muzzle, NULL, NULL, enemy_head, NPC->s.number, MASK_SHOT );
00100 traceEnt = &g_entities[tr.entityNum];
00101 }
00102
00103 VectorCopy( tr.endpos, hitspot );
00104
00105 if( traceEnt == NPC->enemy || (traceEnt->client && NPC->client->enemyTeam && NPC->client->enemyTeam == traceEnt->client->playerTeam) )
00106 {
00107 dead_on = qtrue;
00108 }
00109 else
00110 {
00111 attack_scale *= 0.5;
00112 if(NPC->client->playerTeam)
00113 {
00114 if(traceEnt && traceEnt->client && traceEnt->client->playerTeam)
00115 {
00116 if(NPC->client->playerTeam == traceEnt->client->playerTeam)
00117 {//Don't shoot our own team
00118 attack_ok = qfalse;
00119 }
00120 }
00121 }
00122 }
00123 }
00124
00125 if( attack_ok )
00126 {
00127 //ok, now adjust pitch aim
00128 VectorSubtract (hitspot, muzzle, delta);
00129 vectoangles ( delta, angleToEnemy );
00130 NPC->NPC->desiredPitch = angleToEnemy[PITCH];
00131 NPC_UpdateShootAngles(angleToEnemy, qtrue, qfalse);
00132
00133 if( !dead_on )
00134 {//We're not going to hit him directly, try a suppressing fire
00135 //see if where we're going to shoot is too far from his origin
00136 AngleVectors (NPCInfo->shootAngles, forward, NULL, NULL);
00137 VectorMA ( muzzle, distanceToEnemy, forward, hitspot);
00138 VectorSubtract(hitspot, enemy_org, diff);
00139 aim_off = VectorLength(diff);
00140 if(aim_off > random() * max_aim_off)//FIXME: use aim value to allow poor aim?
00141 {
00142 attack_scale *= 0.75;
00143 //see if where we're going to shoot is too far from his head
00144 VectorSubtract(hitspot, enemy_head, diff);
00145 aim_off = VectorLength(diff);
00146 if(aim_off > random() * max_aim_off)
00147 {
00148 attack_ok = qfalse;
00149 }
00150 }
00151 attack_scale *= (max_aim_off - aim_off + 1)/max_aim_off;
00152 }
00153 }
00154 }
00155 }
00156
00157 if( attack_ok )
00158 {
00159 if( NPC_CheckAttack( attack_scale ))
00160 {//check aggression to decide if we should shoot
00161 enemyVisibility = VIS_SHOOT;
00162 WeaponThink(qtrue);
00163 }
00164 else
00165 attack_ok = qfalse;
00166 }
00167 //Don't do this- only for when stationary and trying to shoot an enemy
00168 // else
00169 // NPC->cantHitEnemyCounter++;
00170 }
00171 else
00172 {//FIXME:
00173 NPC_UpdateShootAngles(NPC->client->ps.viewangles, qtrue, qtrue);
00174 }
00175
00176 if(!ucmd.forwardmove && !ucmd.rightmove)
00177 {//We reached our captureGoal
00178 if(trap_ICARUS_IsInitialized(NPC->s.number))
00179 {
00180 trap_ICARUS_TaskIDComplete( NPC, TID_BSTATE );
00181 }
00182 }
00183 }
|
|
|
Definition at line 213 of file NPC_behavior.c. References CalcEntitySpot(), gNPC_t::desiredPitch, gNPC_t::desiredYaw, gNPC_t::lockedDesiredPitch, gNPC_t::lockedDesiredYaw, NPC, NPC_MoveToGoal(), NPC_UpdateAngles(), NPCInfo, PITCH, qtrue, SCF_FIRE_WEAPON, gNPC_t::scriptFlags, SPOT_HEAD_LEAN, UpdateGoal(), vec3_t, vectoangles(), VectorSubtract, gNPC_t::watchTarget, WeaponThink(), and YAW. Referenced by NPC_BehaviorSet_Default(), and NPC_RunBehavior().
00214 {
00215
00216 if( NPCInfo->scriptFlags & SCF_FIRE_WEAPON )
00217 {
00218 WeaponThink( qtrue );
00219 }
00220
00221 if ( UpdateGoal() )
00222 {//have a goalEntity
00223 //move toward goal, should also face that goal
00224 NPC_MoveToGoal( qtrue );
00225 }
00226
00227 if ( NPCInfo->watchTarget )
00228 {//have an entity which we want to keep facing
00229 //NOTE: this will override any angles set by NPC_MoveToGoal
00230 vec3_t eyes, viewSpot, viewvec, viewangles;
00231
00232 CalcEntitySpot( NPC, SPOT_HEAD_LEAN, eyes );
00233 CalcEntitySpot( NPCInfo->watchTarget, SPOT_HEAD_LEAN, viewSpot );
00234
00235 VectorSubtract( viewSpot, eyes, viewvec );
00236
00237 vectoangles( viewvec, viewangles );
00238
00239 NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw = viewangles[YAW];
00240 NPCInfo->lockedDesiredPitch = NPCInfo->desiredPitch = viewangles[PITCH];
00241 }
00242
00243 NPC_UpdateAngles( qtrue, qtrue );
00244 }
|
|
|
Definition at line 1650 of file NPC_behavior.c. References entityState_s::angles, entityShared_t::currentOrigin, gNPC_t::desiredPitch, gNPC_t::desiredYaw, gentity_s::enemy, gNPC_t::enemyLastSeenLocation, g_entities, gentity_t, level, NPC, NPC_AimAdjust(), NPC_CheckEnemyExt(), NPC_ClearLOS4(), NPC_FaceEnemy(), NPC_ShotEntity(), NPC_UpdateAngles(), NPCInfo, entityState_s::number, gentity_s::painDebounceTime, Q_irand(), qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, SCF_DONT_FIRE, SCF_FIRE_WEAPON, gNPC_t::scriptFlags, gentity_s::takedamage, level_locals_t::time, vec3_t, VectorCopy, entityState_s::weapon, WeaponThink(), and WP_SABER. Referenced by NPC_RunBehavior().
01651 {
01652 qboolean enemyLOS = qfalse;
01653 qboolean enemyCS = qfalse;
01654 qboolean faceEnemy = qfalse;
01655 qboolean shoot = qfalse;
01656 vec3_t impactPos;
01657
01658 //Don't do anything if we're hurt
01659 if ( NPC->painDebounceTime > level.time )
01660 {
01661 NPC_UpdateAngles( qtrue, qtrue );
01662 return;
01663 }
01664
01665 if( NPCInfo->scriptFlags & SCF_FIRE_WEAPON )
01666 {
01667 WeaponThink( qtrue );
01668 }
01669
01670 //If we don't have an enemy, just idle
01671 if ( NPC_CheckEnemyExt(qfalse) == qfalse )
01672 {
01673 if ( !Q_irand( 0, 30 ) )
01674 {
01675 NPCInfo->desiredYaw = NPC->s.angles[1] + Q_irand( -90, 90 );
01676 }
01677 if ( !Q_irand( 0, 30 ) )
01678 {
01679 NPCInfo->desiredPitch = Q_irand( -20, 20 );
01680 }
01681 NPC_UpdateAngles( qtrue, qtrue );
01682 return;
01683 }
01684
01685 if ( NPC_ClearLOS4( NPC->enemy ) )
01686 {
01687 int hit;
01688 gentity_t *hitEnt;
01689
01690 enemyLOS = qtrue;
01691
01692 hit = NPC_ShotEntity( NPC->enemy, impactPos );
01693 hitEnt = &g_entities[hit];
01694
01695 if ( hit == NPC->enemy->s.number || ( hitEnt && hitEnt->takedamage ) )
01696 {//can hit enemy or will hit glass or other minor breakable (or in emplaced gun), so shoot anyway
01697 enemyCS = qtrue;
01698 NPC_AimAdjust( 2 );//adjust aim better longer we have clear shot at enemy
01699 VectorCopy( NPC->enemy->r.currentOrigin, NPCInfo->enemyLastSeenLocation );
01700 }
01701 }
01702 /*
01703 else if ( trap_InPVS( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin ) )
01704 {
01705 NPCInfo->enemyLastSeenTime = level.time;
01706 faceEnemy = qtrue;
01707 NPC_AimAdjust( -1 );//adjust aim worse longer we cannot see enemy
01708 }
01709 */
01710
01711 if ( enemyLOS )
01712 {//FIXME: no need to face enemy if we're moving to some other goal and he's too far away to shoot?
01713 faceEnemy = qtrue;
01714 }
01715 if ( enemyCS )
01716 {
01717 shoot = qtrue;
01718 }
01719
01720 if ( faceEnemy )
01721 {//face the enemy
01722 NPC_FaceEnemy( qtrue );
01723 }
01724 else
01725 {//we want to face in the dir we're running
01726 NPC_UpdateAngles( qtrue, qtrue );
01727 }
01728
01729 if ( NPCInfo->scriptFlags & SCF_DONT_FIRE )
01730 {
01731 shoot = qfalse;
01732 }
01733
01734 if ( NPC->enemy && NPC->enemy->enemy )
01735 {
01736 if ( NPC->enemy->s.weapon == WP_SABER && NPC->enemy->enemy->s.weapon == WP_SABER )
01737 {//don't shoot at an enemy jedi who is fighting another jedi, for fear of injuring one or causing rogue blaster deflections (a la Obi Wan/Vader duel at end of ANH)
01738 shoot = qfalse;
01739 }
01740 }
01741 if ( shoot )
01742 {//try to shoot if it's time
01743 if( !(NPCInfo->scriptFlags & SCF_FIRE_WEAPON) ) // we've already fired, no need to do it again here
01744 {
01745 WeaponThink( qtrue );
01746 }
01747 }
01748 }
|
|
|
Definition at line 1444 of file NPC_behavior.c. References BS_DEFAULT, BS_FLEE, BUTTON_WALKING, usercmd_s::buttons, entityShared_t::currentOrigin, gNPC_t::desiredPitch, gNPC_t::desiredYaw, gNPC_t::distToGoal, DotProduct, flrand(), usercmd_s::forwardmove, gentity_t, gNPC_t::goalEntity, gNPC_t::investigateGoal, gNPC_t::lastGoalEntity, gentity_s::lastWaypoint, NAV_GetNearestNode(), NPC, NPC_CheckGetNewWeapon(), NPC_CheckSurrender(), NPC_MoveToGoal(), NPC_SetMoveGoal(), NPC_Surrender(), NPC_UpdateAngles(), NPCInfo, NULL, qboolean, qfalse, qtrue, gentity_s::r, gentity_s::s, SQUAD_IDLE, gNPC_t::squadState, gNPC_t::tempBehavior, gNPC_t::tempGoal, TIMER_Done(), trap_Nav_GetNodeEdge(), trap_Nav_GetNodeNumEdges(), trap_Nav_GetNodePosition(), ucmd, vec3_t, VectorNormalize(), VectorSubtract, vectoyaw(), gentity_s::waypoint, WAYPOINT_NONE, entityState_s::weapon, and WP_NONE. Referenced by NPC_BehaviorSet_Charmed(), NPC_BehaviorSet_Default(), and NPC_RunBehavior().
01445 {//FIXME: keep checking for danger
01446 gentity_t *goal;
01447
01448 if ( TIMER_Done( NPC, "flee" ) && NPCInfo->tempBehavior == BS_FLEE )
01449 {
01450 NPCInfo->tempBehavior = BS_DEFAULT;
01451 NPCInfo->squadState = SQUAD_IDLE;
01452 //FIXME: should we set some timer to make him stay in this spot for a bit,
01453 //so he doesn't just suddenly turn around and come back at the enemy?
01454 //OR, just stop running toward goal for last second or so of flee?
01455 }
01456 if ( NPC_CheckSurrender() )
01457 {
01458 return;
01459 }
01460 goal = NPCInfo->goalEntity;
01461 if ( !goal )
01462 {
01463 goal = NPCInfo->lastGoalEntity;
01464 if ( !goal )
01465 {//???!!!
01466 goal = NPCInfo->tempGoal;
01467 }
01468 }
01469
01470 if ( goal )
01471 {
01472 qboolean moved;
01473 qboolean reverseCourse = qtrue;
01474
01475 //FIXME: if no weapon, find one and run to pick it up?
01476
01477 //Let's try to find a waypoint that gets me away from this thing
01478 if ( NPC->waypoint == WAYPOINT_NONE )
01479 {
01480 NPC->waypoint = NAV_GetNearestNode( NPC, NPC->lastWaypoint );
01481 }
01482 if ( NPC->waypoint != WAYPOINT_NONE )
01483 {
01484 int numEdges = trap_Nav_GetNodeNumEdges( NPC->waypoint );
01485
01486 if ( numEdges != WAYPOINT_NONE )
01487 {
01488 vec3_t dangerDir;
01489 int nextWp;
01490 int branchNum;
01491
01492 VectorSubtract( NPCInfo->investigateGoal, NPC->r.currentOrigin, dangerDir );
01493 VectorNormalize( dangerDir );
01494
01495 for ( branchNum = 0; branchNum < numEdges; branchNum++ )
01496 {
01497 vec3_t branchPos, runDir;
01498
01499 nextWp = trap_Nav_GetNodeEdge( NPC->waypoint, branchNum );
01500 trap_Nav_GetNodePosition( nextWp, branchPos );
01501
01502 VectorSubtract( branchPos, NPC->r.currentOrigin, runDir );
01503 VectorNormalize( runDir );
01504 if ( DotProduct( runDir, dangerDir ) > flrand( 0, 0.5 ) )
01505 {//don't run toward danger
01506 continue;
01507 }
01508 //FIXME: don't want to ping-pong back and forth
01509 NPC_SetMoveGoal( NPC, branchPos, 0, qtrue, -1, NULL );
01510 reverseCourse = qfalse;
01511 break;
01512 }
01513 }
01514 }
01515
01516 moved = NPC_MoveToGoal( qfalse );//qtrue? (do try to move straight to (away from) goal)
01517
01518 if ( NPC->s.weapon == WP_NONE && (moved == qfalse || reverseCourse) )
01519 {//No weapon and no escape route... Just cower? Need anim.
01520 NPC_Surrender();
01521 NPC_UpdateAngles( qtrue, qtrue );
01522 return;
01523 }
01524 //If our move failed, then just run straight away from our goal
01525 //FIXME: We really shouldn't do this.
01526 if ( moved == qfalse )
01527 {
01528 vec3_t dir;
01529 float dist;
01530 if ( reverseCourse )
01531 {
01532 VectorSubtract( NPC->r.currentOrigin, goal->r.currentOrigin, dir );
01533 }
01534 else
01535 {
01536 VectorSubtract( goal->r.currentOrigin, NPC->r.currentOrigin, dir );
01537 }
01538 NPCInfo->distToGoal = dist = VectorNormalize( dir );
01539 NPCInfo->desiredYaw = vectoyaw( dir );
01540 NPCInfo->desiredPitch = 0;
01541 ucmd.forwardmove = 127;
01542 }
01543 else if ( reverseCourse )
01544 {
01545 //ucmd.forwardmove *= -1;
01546 //ucmd.rightmove *= -1;
01547 //VectorScale( NPC->client->ps.moveDir, -1, NPC->client->ps.moveDir );
01548 NPCInfo->desiredYaw *= -1;
01549 }
01550 //FIXME: can stop after a safe distance?
01551 //ucmd.upmove = 0;
01552 ucmd.buttons &= ~BUTTON_WALKING;
01553 //FIXME: what do we do once we've gotten to our goal?
01554 }
01555 NPC_UpdateAngles( qtrue, qtrue );
01556
01557 NPC_CheckGetNewWeapon();
01558 }
|
|
|
Definition at line 524 of file NPC_behavior.c. References AEL_MINOR, AEL_SUSPICIOUS, level_locals_t::alertEvents, gentity_s::alliedTeam, BOTH_ATTACK1, BOTH_ATTACK2, BOTH_ATTACK3, BOTH_MELEE1, BOTH_MELEE2, BS_DEFAULT, BS_FOLLOW_LEADER, BS_HUNT_AND_KILL, BS_STAND_GUARD, BUTTON_WALKING, usercmd_s::buttons, CalcEntitySpot(), CHECK_360, CHECK_FOV, CHECK_PVS, CHECK_SHOOT, gentity_s::client, gNPC_t::confusionTime, entityShared_t::currentOrigin, gNPC_t::desiredPitch, gNPC_t::desiredYaw, gentity_s::enemy, gNPC_t::enemyCheckDebounceTime, gNPC_t::enemyLastSeenTime, gclient_s::enemyTeam, enemyVisibility, FL_NOTARGET, gentity_s::flags, gNPC_t::followDist, usercmd_s::forwardmove, G_ClearEnemy(), G_SetEnemy(), gNPC_t::goalEntity, gentity_s::health, gNPCstats_e::hfov, alertEvent_s::ID, gNPC_t::lastAlertID, gclient_s::leader, playerState_s::legsAnim, alertEvent_s::level, level, playerState_s::moveDir, gentity_s::NPC, NPC, NPC_AimAdjust(), NPC_AimWiggle(), NPC_BSStandGuard(), NPC_CheckAlertEvents(), NPC_CheckEnemy(), NPC_CheckVisibility(), NPC_GetHFOVPercentage(), NPC_MoveDirClear(), NPC_SlideMoveToGoal(), NPC_UpdateAngles(), NPC_UpdateFiringAngles(), NPCInfo, alertEvent_s::owner, PITCH, gclient_s::playerTeam, gclient_s::ps, Q_irand(), qfalse, qtrue, gentity_s::r, usercmd_s::rightmove, SCF_IGNORE_ALERTS, SCF_LOOK_FOR_ENEMIES, gNPC_t::scriptFlags, SPOT_HEAD, SPOT_WEAPON, gNPC_t::stats, gNPC_t::tempBehavior, level_locals_t::time, TIMER_Set(), ucmd, vec3_origin, vec3_t, vectoangles(), VectorNormalize(), VectorScale, VectorSubtract, gNPCstats_e::vfov, playerState_s::viewangles, VIS_PVS, VIS_SHOOT, visibility_t, playerState_s::weapon, WeaponThink(), WP_SABER, and YAW. Referenced by NPC_BehaviorSet_Charmed(), NPC_BehaviorSet_Default(), NPC_BSDefault(), and NPC_BSJedi_FollowLeader().
00525 {
00526 vec3_t vec;
00527 float leaderDist;
00528 visibility_t leaderVis;
00529 int curAnim;
00530
00531 if ( !NPC->client->leader )
00532 {//ok, stand guard until we find an enemy
00533 if( NPCInfo->tempBehavior == BS_HUNT_AND_KILL )
00534 {
00535 NPCInfo->tempBehavior = BS_DEFAULT;
00536 }
00537 else
00538 {
00539 NPCInfo->tempBehavior = BS_STAND_GUARD;
00540 NPC_BSStandGuard();
00541 }
00542 return;
00543 }
00544
00545 if ( !NPC->enemy )
00546 {//no enemy, find one
00547 NPC_CheckEnemy( NPCInfo->confusionTime<level.time, qfalse, qtrue );//don't find new enemy if this is tempbehav
00548 if ( NPC->enemy )
00549 {//just found one
00550 NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 3000, 10000 );
00551 }
00552 else
00553 {
00554 if ( !(NPCInfo->scriptFlags&SCF_IGNORE_ALERTS) )
00555 {
00556 int eventID = NPC_CheckAlertEvents( qtrue, qtrue, -1, qfalse, AEL_MINOR );
00557 if ( level.alertEvents[eventID].level >= AEL_SUSPICIOUS && (NPCInfo->scriptFlags&SCF_LOOK_FOR_ENEMIES) )
00558 {
00559 NPCInfo->lastAlertID = level.alertEvents[eventID].ID;
00560 if ( !level.alertEvents[eventID].owner ||
00561 !level.alertEvents[eventID].owner->client ||
00562 level.alertEvents[eventID].owner->health <= 0 ||
00563 level.alertEvents[eventID].owner->client->playerTeam != NPC->client->enemyTeam )
00564 {//not an enemy
00565 }
00566 else
00567 {
00568 //FIXME: what if can't actually see enemy, don't know where he is... should we make them just become very alert and start looking for him? Or just let combat AI handle this... (act as if you lost him)
00569 G_SetEnemy( NPC, level.alertEvents[eventID].owner );
00570 NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 3000, 10000 );
00571 NPCInfo->enemyLastSeenTime = level.time;
00572 TIMER_Set( NPC, "attackDelay", Q_irand( 500, 1000 ) );
00573 }
00574 }
00575
00576 }
00577 }
00578 if ( !NPC->enemy )
00579 {
00580 if ( NPC->client->leader
00581 && NPC->client->leader->enemy
00582 && NPC->client->leader->enemy != NPC
00583 && ( (NPC->client->leader->enemy->client&&NPC->client->leader->enemy->client->playerTeam==NPC->client->enemyTeam)
00584 ||(/*NPC->client->leader->enemy->r.svFlags&SVF_NONNPC_ENEMY*/0&&NPC->client->leader->enemy->alliedTeam==NPC->client->enemyTeam) )
00585 && NPC->client->leader->enemy->health > 0 )
00586 { //rwwFIXMEFIXME: use SVF_NONNPC_ENEMY?
00587 G_SetEnemy( NPC, NPC->client->leader->enemy );
00588 NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 3000, 10000 );
00589 NPCInfo->enemyLastSeenTime = level.time;
00590 }
00591 }
00592 }
00593 else
00594 {
00595 if ( NPC->enemy->health <= 0 || (NPC->enemy->flags&FL_NOTARGET) )
00596 {
00597 G_ClearEnemy( NPC );
00598 if ( NPCInfo->enemyCheckDebounceTime > level.time + 1000 )
00599 {
00600 NPCInfo->enemyCheckDebounceTime = level.time + Q_irand( 1000, 2000 );
00601 }
00602 }
00603 else if ( NPC->client->ps.weapon && NPCInfo->enemyCheckDebounceTime < level.time )
00604 {
00605 NPC_CheckEnemy( (NPCInfo->confusionTime<level.time||NPCInfo->tempBehavior!=BS_FOLLOW_LEADER), qfalse, qtrue );//don't find new enemy if this is tempbehav
00606 }
00607 }
00608
00609 if ( NPC->enemy && NPC->client->ps.weapon )
00610 {//If have an enemy, face him and fire
00611 if ( NPC->client->ps.weapon == WP_SABER )//|| NPCInfo->confusionTime>level.time )
00612 {//lightsaber user or charmed enemy
00613 if ( NPCInfo->tempBehavior != BS_FOLLOW_LEADER )
00614 {//not already in a temp bState
00615 //go after the guy
00616 NPCInfo->tempBehavior = BS_HUNT_AND_KILL;
00617 NPC_UpdateAngles(qtrue, qtrue);
00618 return;
00619 }
00620 }
00621
00622 enemyVisibility = NPC_CheckVisibility ( NPC->enemy, CHECK_FOV|CHECK_SHOOT );//CHECK_360|CHECK_PVS|
00623 if ( enemyVisibility > VIS_PVS )
00624 {//face
00625 vec3_t enemy_org, muzzle, delta, angleToEnemy;
00626 float distanceToEnemy;
00627
00628 CalcEntitySpot( NPC->enemy, SPOT_HEAD, enemy_org );
00629 NPC_AimWiggle( enemy_org );
00630
00631 CalcEntitySpot( NPC, SPOT_WEAPON, muzzle );
00632
00633 VectorSubtract( enemy_org, muzzle, delta);
00634 vectoangles( delta, angleToEnemy );
00635 distanceToEnemy = VectorNormalize( delta );
00636
00637 NPCInfo->desiredYaw = angleToEnemy[YAW];
00638 NPCInfo->desiredPitch = angleToEnemy[PITCH];
00639 NPC_UpdateFiringAngles( qtrue, qtrue );
00640
00641 if ( enemyVisibility >= VIS_SHOOT )
00642 {//shoot
00643 NPC_AimAdjust( 2 );
00644 if ( NPC_GetHFOVPercentage( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, NPC->client->ps.viewangles, NPCInfo->stats.hfov ) > 0.6f
00645 && NPC_GetHFOVPercentage( NPC->enemy->r.currentOrigin, NPC->r.currentOrigin, NPC->client->ps.viewangles, NPCInfo->stats.vfov ) > 0.5f )
00646 {//actually withing our front cone
00647 WeaponThink( qtrue );
00648 }
00649 }
00650 else
00651 {
00652 NPC_AimAdjust( 1 );
00653 }
00654
00655 //NPC_CheckCanAttack(1.0, qfalse);
00656 }
00657 else
00658 {
00659 NPC_AimAdjust( -1 );
00660 }
00661 }
00662 else
00663 {//FIXME: combine with vector calc below
00664 vec3_t head, leaderHead, delta, angleToLeader;
00665
00666 CalcEntitySpot( NPC->client->leader, SPOT_HEAD, leaderHead );
00667 CalcEntitySpot( NPC, SPOT_HEAD, head );
00668 VectorSubtract (leaderHead, head, delta);
00669 vectoangles ( delta, angleToLeader );
00670 VectorNormalize(delta);
00671 NPC->NPC->desiredYaw = angleToLeader[YAW];
00672 NPC->NPC->desiredPitch = angleToLeader[PITCH];
00673
00674 NPC_UpdateAngles(qtrue, qtrue);
00675 }
00676
00677 //leader visible?
00678 leaderVis = NPC_CheckVisibility( NPC->client->leader, CHECK_PVS|CHECK_360|CHECK_SHOOT );// ent->e_UseFunc = useF_NULL;
00679
00680
00681 //Follow leader, stay within visibility and a certain distance, maintain a distance from.
00682 curAnim = NPC->client->ps.legsAnim;
00683 if ( curAnim != BOTH_ATTACK1 && curAnim != BOTH_ATTACK2 && curAnim != BOTH_ATTACK3 && curAnim != BOTH_MELEE1 && curAnim != BOTH_MELEE2 )
00684 {//Don't move toward leader if we're in a full-body attack anim
00685 //FIXME, use IdealDistance to determine if we need to close distance
00686 float followDist = 96.0f;//FIXME: If there are enmies, make this larger?
00687 float backupdist, walkdist, minrundist;
00688 float leaderHDist;
00689
00690 if ( NPCInfo->followDist )
00691 {
00692 followDist = NPCInfo->followDist;
00693 }
00694 backupdist = followDist/2.0f;
00695 walkdist = followDist*0.83;
00696 minrundist = followDist*1.33;
00697
00698 VectorSubtract(NPC->client->leader->r.currentOrigin, NPC->r.currentOrigin, vec);
00699 leaderDist = VectorLength( vec );//FIXME: make this just nav distance?
00700 //never get within their radius horizontally
00701 vec[2] = 0;
00702 leaderHDist = VectorLength( vec );
00703 if( leaderHDist > backupdist && (leaderVis != VIS_SHOOT || leaderDist > walkdist) )
00704 {//We should close in?
00705 NPCInfo->goalEntity = NPC->client->leader;
00706
00707 NPC_SlideMoveToGoal();
00708 if ( leaderVis == VIS_SHOOT && leaderDist < minrundist )
00709 {
00710 ucmd.buttons |= BUTTON_WALKING;
00711 }
00712 }
00713 else if ( leaderDist < backupdist )
00714 {//We should back off?
00715 NPCInfo->goalEntity = NPC->client->leader;
00716 NPC_SlideMoveToGoal();
00717
00718 //reversing direction
00719 ucmd.forwardmove = -ucmd.forwardmove;
00720 ucmd.rightmove = -ucmd.rightmove;
00721 VectorScale( NPC->client->ps.moveDir, -1, NPC->client->ps.moveDir );
00722 }//otherwise, stay where we are
00723 //check for do not enter and stop if there's one there...
00724 if ( ucmd.forwardmove || ucmd.rightmove || VectorCompare( vec3_origin, NPC->client->ps.moveDir ) )
00725 {
00726 NPC_MoveDirClear( ucmd.forwardmove, ucmd.rightmove, qtrue );
00727 }
00728 }
00729 }
|
|
|
Definition at line 252 of file NPC_behavior.c.
00253 {
00254 /*
00255 //FIXME: maybe allow this to be set as a tempBState in a script? Just specify the
00256 //investigateGoal, investigateDebounceTime and investigateCount? (Needs a macro)
00257 vec3_t invDir, invAngles, spot;
00258 gentity_t *saveGoal;
00259 //BS_INVESTIGATE would turn toward goal, maybe take a couple steps towards it,
00260 //look for enemies, then turn away after your investigate counter was down-
00261 //investigate counter goes up every time you set it...
00262
00263 if(level.time > NPCInfo->enemyCheckDebounceTime)
00264 {
00265 NPCInfo->enemyCheckDebounceTime = level.time + (NPCInfo->stats.vigilance * 1000);
00266 NPC_CheckEnemy(qtrue, qfalse);
00267 if(NPC->enemy)
00268 {//FIXME: do anger script
00269 NPCInfo->goalEntity = NPC->enemy;
00270 // NAV_ClearLastRoute(NPC);
00271 NPCInfo->behaviorState = BS_RUN_AND_SHOOT;
00272 NPCInfo->tempBehavior = BS_DEFAULT;
00273 NPC_AngerSound();
00274 return;
00275 }
00276 }
00277
00278 NPC_SetAnim( NPC, SETANIM_TORSO, TORSO_WEAPONREADY3, SETANIM_FLAG_NORMAL );
00279
00280 if(NPCInfo->stats.vigilance <= 1.0 && NPCInfo->eventOwner)
00281 {
00282 VectorCopy(NPCInfo->eventOwner->r.currentOrigin, NPCInfo->investigateGoal);
00283 }
00284
00285 saveGoal = NPCInfo->goalEntity;
00286 if( level.time > NPCInfo->walkDebounceTime )
00287 {
00288 vec3_t vec;
00289
00290 VectorSubtract(NPCInfo->investigateGoal, NPC->r.currentOrigin, vec);
00291 vec[2] = 0;
00292 if(VectorLength(vec) > 64)
00293 {
00294 if(Q_irand(0, 100) < NPCInfo->investigateCount)
00295 {//take a full step
00296 //NPCInfo->walkDebounceTime = level.time + 1400;
00297 //actually finds length of my BOTH_WALK anim
00298 NPCInfo->walkDebounceTime = PM_AnimLength( NPC->client->clientInfo.animFileIndex, BOTH_WALK1 );
00299 }
00300 }
00301 }
00302
00303 if( level.time < NPCInfo->walkDebounceTime )
00304 {//walk toward investigateGoal
00305
00306 /*
00307 NPCInfo->goalEntity = NPCInfo->tempGoal;
00308 // NAV_ClearLastRoute(NPC);
00309 VectorCopy(NPCInfo->investigateGoal, NPCInfo->tempGoal->r.currentOrigin);
00310 */
00311
00312 /* NPC_SetMoveGoal( NPC, NPCInfo->investigateGoal, 16, qtrue );
00313
00314 NPC_MoveToGoal( qtrue );
00315
00316 //FIXME: walk2?
00317 NPC_SetAnim(NPC,SETANIM_LEGS,BOTH_WALK1,SETANIM_FLAG_NORMAL);
00318
00319 ucmd.buttons |= BUTTON_WALKING;
00320 }
00321 else
00322 {
00323
00324 NPC_SetAnim(NPC,SETANIM_LEGS,BOTH_STAND1,SETANIM_FLAG_NORMAL);
00325
00326 if(NPCInfo->hlookCount > 30)
00327 {
00328 if(Q_irand(0, 10) > 7)
00329 {
00330 NPCInfo->hlookCount = 0;
00331 }
00332 }
00333 else if(NPCInfo->hlookCount < -30)
00334 {
00335 if(Q_irand(0, 10) > 7)
00336 {
00337 NPCInfo->hlookCount = 0;
00338 }
00339 }
00340 else if(NPCInfo->hlookCount == 0)
00341 {
00342 NPCInfo->hlookCount = Q_irand(-1, 1);
00343 }
00344 else if(Q_irand(0, 10) > 7)
00345 {
00346 if(NPCInfo->hlookCount > 0)
00347 {
00348 NPCInfo->hlookCount++;
00349 }
00350 else//lookCount < 0
00351 {
00352 NPCInfo->hlookCount--;
00353 }
00354 }
00355
00356 if(NPCInfo->vlookCount >= 15)
00357 {
00358 if(Q_irand(0, 10) > 7)
00359 {
00360 NPCInfo->vlookCount = 0;
00361 }
00362 }
00363 else if(NPCInfo->vlookCount <= -15)
00364 {
00365 if(Q_irand(0, 10) > 7)
00366 {
00367 NPCInfo->vlookCount = 0;
00368 }
00369 }
00370 else if(NPCInfo->vlookCount == 0)
00371 {
00372 NPCInfo->vlookCount = Q_irand(-1, 1);
00373 }
00374 else if(Q_irand(0, 10) > 8)
00375 {
00376 if(NPCInfo->vlookCount > 0)
00377 {
00378 NPCInfo->vlookCount++;
00379 }
00380 else//lookCount < 0
00381 {
00382 NPCInfo->vlookCount--;
00383 }
00384 }
00385
00386 //turn toward investigateGoal
00387 CalcEntitySpot( NPC, SPOT_HEAD, spot );
00388 VectorSubtract(NPCInfo->investigateGoal, spot, invDir);
00389 VectorNormalize(invDir);
00390 vectoangles(invDir, invAngles);
00391 NPCInfo->desiredYaw = AngleNormalize360(invAngles[YAW] + NPCInfo->hlookCount);
00392 NPCInfo->desiredPitch = AngleNormalize360(invAngles[PITCH] + NPCInfo->hlookCount);
00393 }
00394
00395 NPC_UpdateAngles(qtrue, qtrue);
00396
00397 NPCInfo->goalEntity = saveGoal;
00398 // NAV_ClearLastRoute(NPC);
00399
00400 if(level.time > NPCInfo->investigateDebounceTime)
00401 {
00402 NPCInfo->tempBehavior = BS_DEFAULT;
00403 }
00404
00405 NPC_CheckSoundEvents();
00406 */
00407 }
|
|
|
Definition at line 733 of file NPC_behavior.c. References gNPC_t::aiFlags, AngleDelta(), AngleNormalize360(), APEX_HEIGHT, BOTH_CROUCH1, BOTH_INAIR1, BOTH_LAND1, gentity_s::client, entityShared_t::currentOrigin, gNPC_t::desiredPitch, gNPC_t::desiredYaw, ENTITYNUM_NONE, FL_NO_KNOCKBACK, gentity_s::flags, usercmd_s::forwardmove, G_Cube(), gNPC_t::goalEntity, gNPC_t::goalTime, playerState_s::gravity, entityState_s::groundEntityNum, JS_CROUCHING, JS_FACING, JS_JUMPING, JS_LANDING, JS_WAITING, gNPC_t::jumpState, playerState_s::legsTimer, level, gNPC_t::lockedDesiredPitch, gNPC_t::lockedDesiredYaw, entityShared_t::maxs, MIN_ANGLE_ERROR, entityShared_t::mins, NPC, NPC_ClearGoal(), NPC_SetAnim(), NPC_UpdateAngles(), NPCAI_MOVING, NPCDEBUG_BLUE, NPCInfo, PITCH, gentity_s::pos1, gclient_s::ps, qtrue, gentity_s::r, gentity_s::s, SETANIM_BOTH, SETANIM_FLAG_HOLD, SETANIM_FLAG_OVERRIDE, SETANIM_LEGS, showBBoxes, sqrt(), TID_MOVE_NAV, level_locals_t::time, trap_ICARUS_TaskIDComplete(), ucmd, vec3_t, vectoangles(), VectorAdd, VectorClear, VectorCopy, VectorMA, VectorNormalize(), VectorScale, VectorSubtract, playerState_s::velocity, playerState_s::viewangles, and YAW. Referenced by NPC_BehaviorSet_Default().
00734 {
00735 vec3_t dir, angles, p1, p2, apex;
00736 float time, height, forward, z, xy, dist, yawError, apexHeight;
00737
00738 if( !NPCInfo->goalEntity )
00739 {//Should have task completed the navgoal
00740 return;
00741 }
00742
00743 if ( NPCInfo->jumpState != JS_JUMPING && NPCInfo->jumpState != JS_LANDING )
00744 {
00745 //Face navgoal
00746 VectorSubtract(NPCInfo->goalEntity->r.currentOrigin, NPC->r.currentOrigin, dir);
00747 vectoangles(dir, angles);
00748 NPCInfo->desiredPitch = NPCInfo->lockedDesiredPitch = AngleNormalize360(angles[PITCH]);
00749 NPCInfo->desiredYaw = NPCInfo->lockedDesiredYaw = AngleNormalize360(angles[YAW]);
00750 }
00751
00752 NPC_UpdateAngles ( qtrue, qtrue );
00753 yawError = AngleDelta ( NPC->client->ps.viewangles[YAW], NPCInfo->desiredYaw );
00754 //We don't really care about pitch here
00755
00756 switch ( NPCInfo->jumpState )
00757 {
00758 case JS_FACING:
00759 if ( yawError < MIN_ANGLE_ERROR )
00760 {//Facing it, Start crouching
00761 NPC_SetAnim(NPC, SETANIM_LEGS, BOTH_CROUCH1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD);
00762 NPCInfo->jumpState = JS_CROUCHING;
00763 }
00764 break;
00765 case JS_CROUCHING:
00766 if ( NPC->client->ps.legsTimer > 0 )
00767 {//Still playing crouching anim
00768 return;
00769 }
00770
00771 //Create a parabola
00772
00773 if ( NPC->r.currentOrigin[2] > NPCInfo->goalEntity->r.currentOrigin[2] )
00774 {
00775 VectorCopy( NPC->r.currentOrigin, p1 );
00776 VectorCopy( NPCInfo->goalEntity->r.currentOrigin, p2 );
00777 }
00778 else if ( NPC->r.currentOrigin[2] < NPCInfo->goalEntity->r.currentOrigin[2] )
00779 {
00780 VectorCopy( NPCInfo->goalEntity->r.currentOrigin, p1 );
00781 VectorCopy( NPC->r.currentOrigin, p2 );
00782 }
00783 else
00784 {
00785 VectorCopy( NPC->r.currentOrigin, p1 );
00786 VectorCopy( NPCInfo->goalEntity->r.currentOrigin, p2 );
00787 }
00788
00789 //z = xy*xy
00790 VectorSubtract( p2, p1, dir );
00791 dir[2] = 0;
00792
00793 //Get xy and z diffs
00794 xy = VectorNormalize( dir );
00795 z = p1[2] - p2[2];
00796
00797 apexHeight = APEX_HEIGHT/2;
00798 /*
00799 //Determine most desirable apex height
00800 apexHeight = (APEX_HEIGHT * PARA_WIDTH/xy) + (APEX_HEIGHT * z/128);
00801 if ( apexHeight < APEX_HEIGHT * 0.5 )
00802 {
00803 apexHeight = APEX_HEIGHT*0.5;
00804 }
00805 else if ( apexHeight > APEX_HEIGHT * 2 )
00806 {
00807 apexHeight = APEX_HEIGHT*2;
00808 }
00809 */
00810
00811 //FIXME: length of xy will change curve of parabola, need to account for this
00812 //somewhere... PARA_WIDTH
00813
00814 z = (sqrt(apexHeight + z) - sqrt(apexHeight));
00815
00816 assert(z >= 0);
00817
00818 // Com_Printf("apex is %4.2f percent from p1: ", (xy-z)*0.5/xy*100.0f);
00819
00820 xy -= z;
00821 xy *= 0.5;
00822
00823 assert(xy > 0);
00824
00825 VectorMA( p1, xy, dir, apex );
00826 apex[2] += apexHeight;
00827
00828 VectorCopy(apex, NPC->pos1);
00829
00830 //Now we have the apex, aim for it
00831 height = apex[2] - NPC->r.currentOrigin[2];
00832 time = sqrt( height / ( .5 * NPC->client->ps.gravity ) );
00833 if ( !time )
00834 {
00835 // Com_Printf("ERROR no time in jump\n");
00836 return;
00837 }
00838
00839 // set s.origin2 to the push velocity
00840 VectorSubtract ( apex, NPC->r.currentOrigin, NPC->client->ps.velocity );
00841 NPC->client->ps.velocity[2] = 0;
00842 dist = VectorNormalize( NPC->client->ps.velocity );
00843
00844 forward = dist / time;
00845 VectorScale( NPC->client->ps.velocity, forward, NPC->client->ps.velocity );
00846
00847 NPC->client->ps.velocity[2] = time * NPC->client->ps.gravity;
00848
00849 // Com_Printf( "%s jumping %s, gravity at %4.0f percent\n", NPC->targetname, vtos(NPC->client->ps.velocity), NPC->client->ps.gravity/8.0f );
00850
00851 NPC->flags |= FL_NO_KNOCKBACK;
00852 NPCInfo->jumpState = JS_JUMPING;
00853 //FIXME: jumpsound?
00854 break;
00855 case JS_JUMPING:
00856
00857 if ( showBBoxes )
00858 {
00859 VectorAdd(NPC->r.mins, NPC->pos1, p1);
00860 VectorAdd(NPC->r.maxs, NPC->pos1, p2);
00861 G_Cube( p1, p2, NPCDEBUG_BLUE, 0.5 );
00862 }
00863
00864 if ( NPC->s.groundEntityNum != ENTITYNUM_NONE)
00865 {//Landed, start landing anim
00866 //FIXME: if the
00867 VectorClear(NPC->client->ps.velocity);
00868 NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_LAND1, SETANIM_FLAG_OVERRIDE|SETANIM_FLAG_HOLD);
00869 NPCInfo->jumpState = JS_LANDING;
00870 //FIXME: landsound?
00871 }
00872 else if ( NPC->client->ps.legsTimer > 0 )
00873 {//Still playing jumping anim
00874 //FIXME: apply jump velocity here, a couple frames after start, not right away
00875 return;
00876 }
00877 else
00878 {//still in air, but done with jump anim, play inair anim
00879 NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_INAIR1, SETANIM_FLAG_OVERRIDE);
00880 }
00881 break;
00882 case JS_LANDING:
00883 if ( NPC->client->ps.legsTimer > 0 )
00884 {//Still playing landing anim
00885 return;
00886 }
00887 else
00888 {
00889 NPCInfo->jumpState = JS_WAITING;
00890
00891
00892 //task complete no matter what...
00893 NPC_ClearGoal();
00894 NPCInfo->goalTime = level.time;
00895 NPCInfo->aiFlags &= ~NPCAI_MOVING;
00896 ucmd.forwardmove = 0;
00897 NPC->flags &= ~FL_NO_KNOCKBACK;
00898 //Return that the goal was reached
00899 trap_ICARUS_TaskIDComplete( NPC, TID_MOVE_NAV );
00900
00901 //Or should we keep jumping until reached goal?
00902
00903 /*
00904 NPCInfo->goalEntity = UpdateGoal();
00905 if ( !NPCInfo->goalEntity )
00906 {
00907 NPC->flags &= ~FL_NO_KNOCKBACK;
00908 Q3_TaskIDComplete( NPC, TID_MOVE_NAV );
00909 }
00910 */
00911
00912 }
00913 break;
00914 case JS_WAITING:
00915 default:
00916 NPCInfo->jumpState = JS_FACING;
00917 break;
00918 }
00919 }
|
|
|
|
|
Definition at line 939 of file NPC_behavior.c. References gNPC_t::aiFlags, AngleNormalize360(), gNPC_t::behaviorState, BOTH_GUARD_IDLE1, BOTH_GUARD_LOOKAROUND1, BS_DEFAULT, BS_HUNT_AND_KILL, BS_SEARCH, BS_STAND_GUARD, BSET_LOSTENEMY, entityShared_t::currentOrigin, gNPC_t::desiredYaw, gentity_s::enemy, flrand(), G_ActivateBehavior(), gNPC_t::goalEntity, gNPC_t::homeWp, gNPC_t::investigateDebounceTime, level, NAV_FindClosestWaypointForEnt(), NPC, NPC_BSRunAndShoot(), NPC_CheckEnemy(), NPC_MoveToGoal(), NPC_SetAnim(), NPC_UpdateAngles(), NPCAI_ENROUTE_TO_HOMEWP, NPCInfo, Q_irand(), qfalse, qtrue, gentity_s::r, SETANIM_BOTH, SETANIM_FLAG_NORMAL, gNPC_t::tempBehavior, gNPC_t::tempGoal, level_locals_t::time, trap_Nav_GetNodeEdge(), trap_Nav_GetNodeNumEdges(), trap_Nav_GetNodePosition(), vec3_t, VectorSubtract, vectoyaw(), gentity_s::waypoint, and WAYPOINT_NONE. Referenced by NPC_BehaviorSet_Charmed(), NPC_BehaviorSet_Default(), and NPC_BSWampa_Default().
00940 {
00941 NPC_CheckEnemy(qtrue, qfalse, qtrue);
00942 //Look for enemies, if find one:
00943 if ( NPC->enemy )
00944 {
00945 if( NPCInfo->tempBehavior == BS_SEARCH )
00946 {//if tempbehavior, set tempbehavior to default
00947 NPCInfo->tempBehavior = BS_DEFAULT;
00948 }
00949 else
00950 {//if bState, change to run and shoot
00951 NPCInfo->behaviorState = BS_HUNT_AND_KILL;
00952 NPC_BSRunAndShoot();
00953 }
00954 return;
00955 }
00956
00957 //FIXME: what if our goalEntity is not NULL and NOT our tempGoal - they must
00958 //want us to do something else? If tempBehavior, just default, else set
00959 //to run and shoot...?
00960
00961 //FIXME: Reimplement
00962
00963 if ( !NPCInfo->investigateDebounceTime )
00964 {//On our way to a tempGoal
00965 float minGoalReachedDistSquared = 32*32;
00966 vec3_t vec;
00967
00968 //Keep moving toward our tempGoal
00969 NPCInfo->goalEntity = NPCInfo->tempGoal;
00970
00971 VectorSubtract ( NPCInfo->tempGoal->r.currentOrigin, NPC->r.currentOrigin, vec);
00972 if ( vec[2] < 24 )
00973 {
00974 vec[2] = 0;
00975 }
00976
00977 if ( NPCInfo->tempGoal->waypoint != WAYPOINT_NONE )
00978 {
00979 /*
00980 //FIXME: can't get the radius...
00981 float wpRadSq = waypoints[NPCInfo->tempGoal->waypoint].radius * waypoints[NPCInfo->tempGoal->waypoint].radius;
00982 if ( minGoalReachedDistSquared > wpRadSq )
00983 {
00984 minGoalReachedDistSquared = wpRadSq;
00985 }
00986 */
00987
00988 minGoalReachedDistSquared = 32*32;//12*12;
00989 }
00990
00991 if ( VectorLengthSquared( vec ) < minGoalReachedDistSquared )
00992 {
00993 //Close enough, just got there
00994 NPC->waypoint = NAV_FindClosestWaypointForEnt( NPC, WAYPOINT_NONE );
00995
00996 if ( ( NPCInfo->homeWp == WAYPOINT_NONE ) || ( NPC->waypoint == WAYPOINT_NONE ) )
00997 {
00998 //Heading for or at an invalid waypoint, get out of this bState
00999 if( NPCInfo->tempBehavior == BS_SEARCH )
01000 {//if tempbehavior, set tempbehavior to default
01001 NPCInfo->tempBehavior = BS_DEFAULT;
01002 }
01003 else
01004 {//if bState, change to stand guard
01005 NPCInfo->behaviorState = BS_STAND_GUARD;
01006 NPC_BSRunAndShoot();
01007 }
01008 return;
01009 }
01010
01011 if ( NPC->waypoint == NPCInfo->homeWp )
01012 {
01013 //Just Reached our homeWp, if this is the first time, run your lostenemyscript
01014 if ( NPCInfo->aiFlags & NPCAI_ENROUTE_TO_HOMEWP )
01015 {
01016 NPCInfo->aiFlags &= ~NPCAI_ENROUTE_TO_HOMEWP;
01017 G_ActivateBehavior( NPC, BSET_LOSTENEMY );
01018 }
01019
01020 }
01021
01022 //Com_Printf("Got there.\n");
01023 //Com_Printf("Looking...");
01024 if( !Q_irand(0, 1) )
01025 {
01026 NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_GUARD_LOOKAROUND1, SETANIM_FLAG_NORMAL);
01027 }
01028 else
01029 {
01030 NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_GUARD_IDLE1, SETANIM_FLAG_NORMAL);
01031 }
01032 NPCInfo->investigateDebounceTime = level.time + Q_irand(3000, 10000);
01033 }
01034 else
01035 {
01036 NPC_MoveToGoal( qtrue );
01037 }
01038 }
01039 else
01040 {
01041 //We're there
01042 if ( NPCInfo->investigateDebounceTime > level.time )
01043 {
01044 //Still waiting around for a bit
01045 //Turn angles every now and then to look around
01046 if ( NPCInfo->tempGoal->waypoint != WAYPOINT_NONE )
01047 {
01048 if ( !Q_irand( 0, 30 ) )
01049 {
01050 int numEdges = trap_Nav_GetNodeNumEdges( NPCInfo->tempGoal->waypoint );
01051
01052 if ( numEdges != WAYPOINT_NONE )
01053 {
01054 int branchNum = Q_irand( 0, numEdges - 1 );
01055
01056 vec3_t branchPos, lookDir;
01057
01058 int nextWp = trap_Nav_GetNodeEdge( NPCInfo->tempGoal->waypoint, branchNum );
01059 trap_Nav_GetNodePosition( nextWp, branchPos );
01060
01061 VectorSubtract( branchPos, NPCInfo->tempGoal->r.currentOrigin, lookDir );
01062 NPCInfo->desiredYaw = AngleNormalize360( vectoyaw( lookDir ) + flrand( -45, 45 ) );
01063 }
01064
01065 //pick an angle +-45 degrees off of the dir of a random branch
01066 //from NPCInfo->tempGoal->waypoint
01067 //int branch = Q_irand( 0, (waypoints[NPCInfo->tempGoal->waypoint].numNeighbors - 1) );
01068 //int nextWp = waypoints[NPCInfo->tempGoal->waypoint].nextWaypoint[branch][NPC->client->moveType];
01069 //vec3_t lookDir;
01070
01071 //VectorSubtract( waypoints[nextWp].origin, NPCInfo->tempGoal->r.currentOrigin, lookDir );
01072 //Look in that direction +- 45 degrees
01073 //NPCInfo->desiredYaw = AngleNormalize360( vectoyaw( lookDir ) + Q_flrand( -45, 45 ) );
01074 }
01075 }
01076 //Com_Printf(".");
01077 }
01078 else
01079 {//Just finished waiting
01080 NPC->waypoint = NAV_FindClosestWaypointForEnt( NPC, WAYPOINT_NONE );
01081
01082 if ( NPC->waypoint == NPCInfo->homeWp )
01083 {
01084 int numEdges = trap_Nav_GetNodeNumEdges( NPCInfo->tempGoal->waypoint );
01085
01086 if ( numEdges != WAYPOINT_NONE )
01087 {
01088 int branchNum = Q_irand( 0, numEdges - 1 );
01089
01090 int nextWp = trap_Nav_GetNodeEdge( NPCInfo->homeWp, branchNum );
01091 trap_Nav_GetNodePosition( nextWp, NPCInfo->tempGoal->r.currentOrigin );
01092 NPCInfo->tempGoal->waypoint = nextWp;
01093 }
01094
01095 /*
01096 //Pick a random branch
01097 int branch = Q_irand( 0, (waypoints[NPCInfo->homeWp].numNeighbors - 1) );
01098 int nextWp = waypoints[NPCInfo->homeWp].nextWaypoint[branch][NPC->client->moveType];
01099
01100 VectorCopy( waypoints[nextWp].origin, NPCInfo->tempGoal->r.currentOrigin );
01101 NPCInfo->tempGoal->waypoint = nextWp;
01102 //Com_Printf("\nHeading for wp %d...\n", waypoints[NPCInfo->homeWp].nextWaypoint[branch][NPC->client->moveType]);
01103 */
01104 }
01105 else
01106 {//At a branch, so return home
01107 trap_Nav_GetNodePosition( NPCInfo->homeWp, NPCInfo->tempGoal->r.currentOrigin );
01108 NPCInfo->tempGoal->waypoint = NPCInfo->homeWp;
01109 /*
01110 VectorCopy( waypoints[NPCInfo->homeWp].origin, NPCInfo->tempGoal->r.currentOrigin );
01111 NPCInfo->tempGoal->waypoint = NPCInfo->homeWp;
01112 //Com_Printf("\nHeading for wp %d...\n", NPCInfo->homeWp);
01113 */
01114 }
01115
01116 NPCInfo->investigateDebounceTime = 0;
01117 //Start moving toward our tempGoal
01118 NPCInfo->goalEntity = NPCInfo->tempGoal;
01119 NPC_MoveToGoal( qtrue );
01120 }
01121 }
01122
01123 NPC_UpdateAngles( qtrue, qtrue );
01124 }
|
|
||||||||||||
|
|
Definition at line 500 of file NPC_behavior.c. References AEL_MINOR, BSET_AWAKE, G_ActivateBehavior(), NPC, NPC_CheckAlertEvents(), qfalse, and qtrue. Referenced by NPC_BehaviorSet_Default().
00501 {
00502 int alertEvent = NPC_CheckAlertEvents( qtrue, qfalse, -1, qfalse, AEL_MINOR );
00503
00504 //There is an event to look at
00505 if ( alertEvent >= 0 )
00506 {
00507 G_ActivateBehavior(NPC, BSET_AWAKE);
00508 return;
00509 }
00510
00511 /*
00512 if ( level.time > NPCInfo->enemyCheckDebounceTime )
00513 {
00514 if ( NPC_CheckSoundEvents() != -1 )
00515 {//only 1 alert per second per 0.1 of vigilance
00516 NPCInfo->enemyCheckDebounceTime = level.time + (NPCInfo->stats.vigilance * 10000);
00517 G_ActivateBehavior(NPC, BSET_AWAKE);
00518 }
00519 }
00520 */
00521 }
|
|
|
Definition at line 246 of file NPC_behavior.c. References NPC_UpdateAngles(), and qtrue. Referenced by NPC_BehaviorSet_Default().
00247 {
00248 NPC_UpdateAngles( qtrue, qtrue );
00249 }
|
|
|
Definition at line 1193 of file NPC_behavior.c. References AngleNormalize360(), BOTH_GUARD_IDLE1, BOTH_GUARD_LOOKAROUND1, entityShared_t::currentOrigin, gNPC_t::desiredYaw, flrand(), gNPC_t::goalEntity, gNPC_t::investigateDebounceTime, level, NAV_FindClosestWaypointForEnt(), NPC, NPC_MoveToGoal(), NPC_SetAnim(), NPC_UpdateAngles(), NPCInfo, Q_irand(), qtrue, gentity_s::r, SETANIM_BOTH, SETANIM_FLAG_NORMAL, gNPC_t::tempGoal, level_locals_t::time, trap_Nav_GetNodeEdge(), trap_Nav_GetNodeNumEdges(), trap_Nav_GetNodePosition(), vec3_t, VectorSubtract, vectoyaw(), gentity_s::waypoint, and WAYPOINT_NONE. Referenced by NPC_BehaviorSet_Charmed(), NPC_BehaviorSet_Default(), and NPC_BSWampa_Default().
01194 {//FIXME: don't actually go all the way to the next waypoint, just move in fits and jerks...?
01195 if ( !NPCInfo->investigateDebounceTime )
01196 {//Starting out
01197 float minGoalReachedDistSquared = 64;//32*32;
01198 vec3_t vec;
01199
01200 //Keep moving toward our tempGoal
01201 NPCInfo->goalEntity = NPCInfo->tempGoal;
01202
01203 VectorSubtract ( NPCInfo->tempGoal->r.currentOrigin, NPC->r.currentOrigin, vec);
01204
01205 if ( NPCInfo->tempGoal->waypoint != WAYPOINT_NONE )
01206 {
01207 minGoalReachedDistSquared = 64;
01208 }
01209
01210 if ( VectorLengthSquared( vec ) < minGoalReachedDistSquared )
01211 {
01212 //Close enough, just got there
01213 NPC->waypoint = NAV_FindClosestWaypointForEnt( NPC, WAYPOINT_NONE );
01214
01215 if( !Q_irand(0, 1) )
01216 {
01217 NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_GUARD_LOOKAROUND1, SETANIM_FLAG_NORMAL);
01218 }
01219 else
01220 {
01221 NPC_SetAnim(NPC, SETANIM_BOTH, BOTH_GUARD_IDLE1, SETANIM_FLAG_NORMAL);
01222 }
01223 //Just got here, so Look around for a while
01224 NPCInfo->investigateDebounceTime = level.time + Q_irand(3000, 10000);
01225 }
01226 else
01227 {
01228 //Keep moving toward goal
01229 NPC_MoveToGoal( qtrue );
01230 }
01231 }
01232 else
01233 {
01234 //We're there
01235 if ( NPCInfo->investigateDebounceTime > level.time )
01236 {
01237 //Still waiting around for a bit
01238 //Turn angles every now and then to look around
01239 if ( NPCInfo->tempGoal->waypoint != WAYPOINT_NONE )
01240 {
01241 if ( !Q_irand( 0, 30 ) )
01242 {
01243 int numEdges = trap_Nav_GetNodeNumEdges( NPCInfo->tempGoal->waypoint );
01244
01245 if ( numEdges != WAYPOINT_NONE )
01246 {
01247 int branchNum = Q_irand( 0, numEdges - 1 );
01248
01249 vec3_t branchPos, lookDir;
01250
01251 int nextWp = trap_Nav_GetNodeEdge( NPCInfo->tempGoal->waypoint, branchNum );
01252 trap_Nav_GetNodePosition( nextWp, branchPos );
01253
01254 VectorSubtract( branchPos, NPCInfo->tempGoal->r.currentOrigin, lookDir );
01255 NPCInfo->desiredYaw = AngleNormalize360( vectoyaw( lookDir ) + flrand( -45, 45 ) );
01256 }
01257 }
01258 }
01259 }
01260 else
01261 {//Just finished waiting
01262 NPC->waypoint = NAV_FindClosestWaypointForEnt( NPC, WAYPOINT_NONE );
01263
01264 if ( NPC->waypoint != WAYPOINT_NONE )
01265 {
01266 int numEdges = trap_Nav_GetNodeNumEdges( NPC->waypoint );
01267
01268 if ( numEdges != WAYPOINT_NONE )
01269 {
01270 int branchNum = Q_irand( 0, numEdges - 1 );
01271
01272 int nextWp = trap_Nav_GetNodeEdge( NPC->waypoint, branchNum );
01273 trap_Nav_GetNodePosition( nextWp, NPCInfo->tempGoal->r.currentOrigin );
01274 NPCInfo->tempGoal->waypoint = nextWp;
01275 }
01276
01277 NPCInfo->investigateDebounceTime = 0;
01278 //Start moving toward our tempGoal
01279 NPCInfo->goalEntity = NPCInfo->tempGoal;
01280 NPC_MoveToGoal( qtrue );
01281 }
01282 }
01283 }
01284
01285 NPC_UpdateAngles( qtrue, qtrue );
01286 }
|
|
|
Definition at line 3060 of file NPC_combat.c. References gentity_s::enemy, gentity_t, gNPC_t::goalEntity, gentity_s::inuse, NPC, NPC_SearchForWeapons(), NPC_SetPickUpGoal(), NPCInfo, NULL, gentity_s::s, gNPC_t::tempGoal, TIMER_Done(), entityState_s::weapon, and WP_NONE.
03061 {
03062 if ( NPC->s.weapon == WP_NONE && NPC->enemy )
03063 {//if running away because dropped weapon...
03064 if ( NPCInfo->goalEntity
03065 && NPCInfo->goalEntity == NPCInfo->tempGoal
03066 && NPCInfo->goalEntity->enemy
03067 && !NPCInfo->goalEntity->enemy->inuse )
03068 {//maybe was running at a weapon that was picked up
03069 NPCInfo->goalEntity = NULL;
03070 }
03071 if ( TIMER_Done( NPC, "panic" ) && NPCInfo->goalEntity == NULL )
03072 {//need a weapon, any lying around?
03073 gentity_t *foundWeap = NPC_SearchForWeapons();
03074 if ( foundWeap )
03075 {//try to nav to it
03076 /*
03077 if ( !trap_Nav_GetBestPathBetweenEnts( NPC, foundWeap, NF_CLEAR_PATH )
03078 || trap_Nav_GetBestNodeAltRoute( NPC->waypoint, foundWeap->waypoint ) == WAYPOINT_NONE )
03079 {//can't possibly have a route to any OR can't possibly have a route to this one OR don't have a route to this one
03080 if ( !NAV_ClearPathToPoint( NPC, NPC->r.mins, NPC->r.maxs, foundWeap->r.currentOrigin, NPC->clipmask, ENTITYNUM_NONE ) )
03081 {//don't even have a clear straight path to this one
03082 }
03083 else
03084 {
03085 NPC_SetPickUpGoal( foundWeap );
03086 }
03087 }
03088 else
03089 */
03090 {
03091 NPC_SetPickUpGoal( foundWeap );
03092 }
03093 }
03094 }
03095 }
03096 }
|
|
|
Definition at line 409 of file NPC_behavior.c. References level_locals_t::alertEvents, gNPC_t::behaviorState, BS_HUNT_AND_KILL, BS_INVESTIGATE, BSET_AWAKE, gentity_s::client, entityShared_t::currentOrigin, gNPCstats_e::earshot, EF_NODRAW, gentity_s::enemy, ET_NPC, ET_PLAYER, entityState_s::eType, gNPC_t::eventOwner, FL_NOTARGET, G_ActivateBehavior(), G_SetEnemy(), gentity_t, gNPC_t::goalEntity, gNPC_t::goalRadius, gNPC_t::investigateCount, gNPC_t::investigateDebounceTime, gNPC_t::investigateGoal, alertEvent_s::level, level, NPC, NPCInfo, alertEvent_s::owner, gclient_s::playerTeam, alertEvent_s::position, qboolean, qfalse, qtrue, gentity_s::r, alertEvent_s::radius, gentity_s::s, gNPC_t::stats, gNPC_t::tempBehavior, level_locals_t::time, trap_InPVS(), ValidEnemy(), vec3_t, VectorCopy, and gNPCstats_e::vigilance.
00410 {
00411 gentity_t *owner = level.alertEvents[alertEventNum].owner;
00412 int invAdd = level.alertEvents[alertEventNum].level;
00413 vec3_t soundPos;
00414 float soundRad = level.alertEvents[alertEventNum].radius;
00415 float earshot = NPCInfo->stats.earshot;
00416
00417 VectorCopy( level.alertEvents[alertEventNum].position, soundPos );
00418
00419 //NOTE: Trying to preserve previous investigation behavior
00420 if ( !owner )
00421 {
00422 return qfalse;
00423 }
00424
00425 if ( owner->s.eType != ET_PLAYER && owner->s.eType != ET_NPC && owner == NPCInfo->goalEntity )
00426 {
00427 return qfalse;
00428 }
00429
00430 if ( owner->s.eFlags & EF_NODRAW )
00431 {
00432 return qfalse;
00433 }
00434
00435 if ( owner->flags & FL_NOTARGET )
00436 {
00437 return qfalse;
00438 }
00439
00440 if ( soundRad < earshot )
00441 {
00442 return qfalse;
00443 }
00444
00445 //if(!trap_InPVSIgnorePortals(ent->r.currentOrigin, NPC->r.currentOrigin))//should we be able to hear through areaportals?
00446 if ( !trap_InPVS( soundPos, NPC->r.currentOrigin ) )
00447 {//can hear through doors?
00448 return qfalse;
00449 }
00450
00451 if ( owner->client && owner->client->playerTeam && NPC->client->playerTeam && owner->client->playerTeam != NPC->client->playerTeam )
00452 {
00453 if( (float)NPCInfo->investigateCount >= (NPCInfo->stats.vigilance*200) && owner )
00454 {//If investigateCount == 10, just take it as enemy and go
00455 if ( ValidEnemy( owner ) )
00456 {//FIXME: run angerscript
00457 G_SetEnemy( NPC, owner );
00458 NPCInfo->goalEntity = NPC->enemy;
00459 NPCInfo->goalRadius = 12;
00460 NPCInfo->behaviorState = BS_HUNT_AND_KILL;
00461 return qtrue;
00462 }
00463 }
00464 else
00465 {
00466 NPCInfo->investigateCount += invAdd;
00467 }
00468 //run awakescript
00469 G_ActivateBehavior(NPC, BSET_AWAKE);
00470
00471 /*
00472 if ( Q_irand(0, 10) > 7 )
00473 {
00474 NPC_AngerSound();
00475 }
00476 */
00477
00478 //NPCInfo->hlookCount = NPCInfo->vlookCount = 0;
00479 NPCInfo->eventOwner = owner;
00480 VectorCopy( soundPos, NPCInfo->investigateGoal );
00481 if ( NPCInfo->investigateCount > 20 )
00482 {
00483 NPCInfo->investigateDebounceTime = level.time + 10000;
00484 }
00485 else
00486 {
00487 NPCInfo->investigateDebounceTime = level.time + (NPCInfo->investigateCount*500);
00488 }
00489 NPCInfo->tempBehavior = BS_INVESTIGATE;
00490 return qtrue;
00491 }
00492
00493 return qfalse;
00494 }
|
|
|
Definition at line 1341 of file NPC_behavior.c. References gentity_s::client, entityShared_t::currentOrigin, gentity_s::enemy, ENTITYNUM_NONE, playerState_s::fd, forcedata_s::forcePowerDebounce, FP_SABER_DEFENSE, playerState_s::groundEntityNum, gentity_s::health, InFOV(), level, NPC, NPC_SomeoneLookingAtMe(), gentity_s::painDebounceTime, PM_InKnockDown(), gclient_s::ps, qboolean, qfalse, gentity_s::r, gentity_s::s, TID_MOVE_NAV, level_locals_t::time, trap_ICARUS_TaskIDPending(), trap_InPVS(), entityState_s::weapon, playerState_s::weaponTime, WP_FLECHETTE, WP_NONE, WP_REPEATER, WP_ROCKET_LAUNCHER, WP_SABER, and WP_STUN_BATON. Referenced by NPC_BSFlee(), and NPC_RunBehavior().
01342 {
01343 if ( !trap_ICARUS_TaskIDPending( NPC, TID_MOVE_NAV )
01344 && NPC->client->ps.groundEntityNum != ENTITYNUM_NONE
01345 && !NPC->client->ps.weaponTime && !PM_InKnockDown( &NPC->client->ps )
01346 && NPC->enemy && NPC->enemy->client && NPC->enemy->enemy == NPC && NPC->enemy->s.weapon != WP_NONE && NPC->enemy->s.weapon != WP_STUN_BATON
01347 && NPC->enemy->health > 20 && NPC->enemy->painDebounceTime < level.time - 3000 && NPC->enemy->client->ps.fd.forcePowerDebounce[FP_SABER_DEFENSE] < level.time - 1000 )
01348 {//don't surrender if scripted to run somewhere or if we're in the air or if we're busy or if we don't have an enemy or if the enemy is not mad at me or is hurt or not a threat or busy being attacked
01349 //FIXME: even if not in a group, don't surrender if there are other enemies in the PVS and within a certain range?
01350 if ( NPC->s.weapon != WP_ROCKET_LAUNCHER
01351 && NPC->s.weapon != WP_REPEATER
01352 && NPC->s.weapon != WP_FLECHETTE
01353 && NPC->s.weapon != WP_SABER )
01354 {//jedi and heavy weapons guys never surrender
01355 //FIXME: rework all this logic into some orderly fashion!!!
01356 if ( NPC->s.weapon != WP_NONE )
01357 {//they have a weapon so they'd have to drop it to surrender
01358 //don't give up unless low on health
01359 if ( NPC->health > 25 /*|| NPC->health >= NPC->max_health*/ )
01360 { //rwwFIXMEFIXME: Keep max health not a ps state?
01361 return qfalse;
01362 }
01363 //if ( g_crosshairEntNum == NPC->s.number && NPC->painDebounceTime > level.time )
01364 if (NPC_SomeoneLookingAtMe(NPC) && NPC->painDebounceTime > level.time)
01365 {//if he just shot me, always give up
01366 //fall through
01367 }
01368 else
01369 {//don't give up unless facing enemy and he's very close
01370 if ( !InFOV( NPC->enemy, NPC, 60, 30 ) )
01371 {//I'm not looking at them
01372 return qfalse;
01373 }
01374 else if ( DistanceSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ) < 65536/*256*256*/ )
01375 {//they're not close
01376 return qfalse;
01377 }
01378 else if ( !trap_InPVS( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ) )
01379 {//they're not in the same room
01380 return qfalse;
01381 }
01382 }
01383 }
01384 //fixme: this logic keeps making npc's randomly surrender
01385 /*
01386 if ( NPCInfo->group && NPCInfo->group->numGroup <= 1 )
01387 {//I'm alone but I was in a group//FIXME: surrender anyway if just melee or no weap?
01388 if ( NPC->s.weapon == WP_NONE
01389 //NPC has a weapon
01390 || (NPC->enemy && NPC->enemy->s.number < MAX_CLIENTS)
01391 || (NPC->enemy->s.weapon == WP_SABER&&NPC->enemy->client&&!NPC->enemy->client->ps.saberHolstered)
01392 || (NPC->enemy->NPC && NPC->enemy->NPC->group && NPC->enemy->NPC->group->numGroup > 2) )
01393 {//surrender only if have no weapon or fighting a player or jedi or if we are outnumbered at least 3 to 1
01394 if ( (NPC->enemy && NPC->enemy->s.number < MAX_CLIENTS) )
01395 {//player is the guy I'm running from
01396 //if ( g_crosshairEntNum == NPC->s.number )
01397 if (NPC_SomeoneLookingAtMe(NPC))
01398 {//give up if player is aiming at me
01399 NPC_Surrender();
01400 NPC_UpdateAngles( qtrue, qtrue );
01401 return qtrue;
01402 }
01403 else if ( NPC->enemy->s.weapon == WP_SABER )
01404 {//player is using saber
01405 if ( InFOV( NPC, NPC->enemy, 60, 30 ) )
01406 {//they're looking at me
01407 if ( DistanceSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ) < 16384 )
01408 {//they're close
01409 if ( trap_InPVS( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ) )
01410 {//they're in the same room
01411 NPC_Surrender();
01412 NPC_UpdateAngles( qtrue, qtrue );
01413 return qtrue;
01414 }
01415 }
01416 }
01417 }
01418 }
01419 else if ( NPC->enemy )
01420 {//???
01421 //should NPC's surrender to others?
01422 if ( InFOV( NPC, NPC->enemy, 30, 30 ) )
01423 {//they're looking at me
01424 if ( DistanceSquared( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ) < 4096 )
01425 {//they're close
01426 if ( trap_InPVS( NPC->r.currentOrigin, NPC->enemy->r.currentOrigin ) )
01427 {//they're in the same room
01428 //FIXME: should player-team NPCs not fire on surrendered NPCs?
01429 NPC_Surrender();
01430 NPC_UpdateAngles( qtrue, qtrue );
01431 return qtrue;
01432 }
01433 }
01434 }
01435 }
01436 }
01437 }
01438 */
01439 }
01440 }
01441 return qfalse;
01442 }
|
|
||||||||||||||||
|
Definition at line 1079 of file NPC_AI_Jedi.c. References trace_t::allsolid, AngleVectors(), gentity_s::client, gentity_s::clipmask, CONTENTS_BOTCLIP, entityShared_t::currentOrigin, trace_t::endpos, gentity_s::enemy, trace_t::entityNum, ENTITYNUM_NONE, playerState_s::fd, forcedata_s::forceJumpCharge, usercmd_s::forwardmove, trace_t::fraction, gNPC_t::goalEntity, playerState_s::groundEntityNum, entityShared_t::maxs, entityShared_t::mins, playerState_s::moveDir, NPC, NPCInfo, NULL, entityState_s::number, PITCH, gclient_s::ps, qboolean, qfalse, qtrue, gentity_s::r, usercmd_s::rightmove, ROLL, gentity_s::s, trace_t::startsolid, STEPSIZE, trap_Trace(), ucmd, usercmd_s::upmove, vec3_t, VectorClear, VectorCopy, VectorMA, VectorScale, playerState_s::viewangles, and YAW. Referenced by NPC_BSFollowLeader().
01080 {
01081 vec3_t forward, right, testPos, angles, mins;
01082 trace_t trace;
01083 float fwdDist, rtDist;
01084 float bottom_max = -STEPSIZE*4 - 1;
01085
01086 if ( !forwardmove && !rightmove )
01087 {//not even moving
01088 //Com_Printf( "%d skipping walk-cliff check (not moving)\n", level.time );
01089 return qtrue;
01090 }
01091
01092 if ( ucmd.upmove > 0 || NPC->client->ps.fd.forceJumpCharge )
01093 {//Going to jump
01094 //Com_Printf( "%d skipping walk-cliff check (going to jump)\n", level.time );
01095 return qtrue;
01096 }
01097
01098 if ( NPC->client->ps.groundEntityNum == ENTITYNUM_NONE )
01099 {//in the air
01100 //Com_Printf( "%d skipping walk-cliff check (in air)\n", level.time );
01101 return qtrue;
01102 }
01103 /*
01104 if ( fabs( AngleDelta( NPC->r.currentAngles[YAW], NPCInfo->desiredYaw ) ) < 5.0 )//!ucmd.angles[YAW] )
01105 {//Not turning much, don't do this
01106 //NOTE: Should this not happen only if you're not turning AT ALL?
01107 // You could be turning slowly but moving fast, so that would
01108 // still let you walk right off a cliff...
01109 //NOTE: Or maybe it is a good idea to ALWAYS do this, regardless
01110 // of whether ot not we're turning? But why would we be walking
01111 // straight into a wall or off a cliff unless we really wanted to?
01112 return;
01113 }
01114 */
01115
01116 //FIXME: to really do this right, we'd have to actually do a pmove to predict where we're
01117 //going to be... maybe this should be a flag and pmove handles it and sets a flag so AI knows
01118 //NEXT frame? Or just incorporate current velocity, runspeed and possibly friction?
01119 VectorCopy( NPC->r.mins, mins );
01120 mins[2] += STEPSIZE;
01121 angles[PITCH] = angles[ROLL] = 0;
01122 angles[YAW] = NPC->client->ps.viewangles[YAW];//Add ucmd.angles[YAW]?
01123 AngleVectors( angles, forward, right, NULL );
01124 fwdDist = ((float)forwardmove)/2.0f;
01125 rtDist = ((float)rightmove)/2.0f;
01126 VectorMA( NPC->r.currentOrigin, fwdDist, forward, testPos );
01127 VectorMA( testPos, rtDist, right, testPos );
01128 trap_Trace( &trace, NPC->r.currentOrigin, mins, NPC->r.maxs, testPos, NPC->s.number, NPC->clipmask|CONTENTS_BOTCLIP );
01129 if ( trace.allsolid || trace.startsolid )
01130 {//hmm, trace started inside this brush... how do we decide if we should continue?
01131 //FIXME: what do we do if we start INSIDE a CONTENTS_BOTCLIP? Try the trace again without that in the clipmask?
01132 if ( reset )
01133 {
01134 trace.fraction = 1.0f;
01135 }
01136 VectorCopy( testPos, trace.endpos );
01137 //return qtrue;
01138 }
01139 if ( trace.fraction < 0.6 )
01140 {//Going to bump into something very close, don't move, just turn
01141 if ( (NPC->enemy && trace.entityNum == NPC->enemy->s.number) || (NPCInfo->goalEntity && trace.entityNum == NPCInfo->goalEntity->s.number) )
01142 {//okay to bump into enemy or goal
01143 //Com_Printf( "%d bump into enemy/goal okay\n", level.time );
01144 return qtrue;
01145 }
01146 else if ( reset )
01147 {//actually want to screw with the ucmd
01148 //Com_Printf( "%d avoiding walk into wall (entnum %d)\n", level.time, trace.entityNum );
01149 ucmd.forwardmove = 0;
01150 ucmd.rightmove = 0;
01151 VectorClear( NPC->client->ps.moveDir );
01152 }
01153 return qfalse;
01154 }
01155
01156 if ( NPCInfo->goalEntity )
01157 {
01158 if ( NPCInfo->goalEntity->r.currentOrigin[2] < NPC->r.currentOrigin[2] )
01159 {//goal is below me, okay to step off at least that far plus stepheight
01160 bottom_max += NPCInfo->goalEntity->r.currentOrigin[2] - NPC->r.currentOrigin[2];
01161 }
01162 }
01163 VectorCopy( trace.endpos, testPos );
01164 testPos[2] += bottom_max;
01165
01166 trap_Trace( &trace, trace.endpos, mins, NPC->r.maxs, testPos, NPC->s.number, NPC->clipmask );
01167
01168 //FIXME:Should we try to see if we can still get to our goal using the waypoint network from this trace.endpos?
01169 //OR: just put NPC clip brushes on these edges (still fall through when die)
01170
01171 if ( trace.allsolid || trace.startsolid )
01172 {//Not going off a cliff
01173 //Com_Printf( "%d walk off cliff okay (droptrace in solid)\n", level.time );
01174 return qtrue;
01175 }
01176
01177 if ( trace.fraction < 1.0 )
01178 {//Not going off a cliff
01179 //FIXME: what if plane.normal is sloped? We'll slide off, not land... plus this doesn't account for slide-movement...
01180 //Com_Printf( "%d walk off cliff okay will hit entnum %d at dropdist of %4.2f\n", level.time, trace.entityNum, (trace.fraction*bottom_max) );
01181 return qtrue;
01182 }
01183
01184 //going to fall at least bottom_max, don't move, just turn... is this bad, though? What if we want them to drop off?
01185 if ( reset )
01186 {//actually want to screw with the ucmd
01187 //Com_Printf( "%d avoiding walk off cliff\n", level.time );
01188 ucmd.forwardmove *= -1.0;//= 0;
01189 ucmd.rightmove *= -1.0;//= 0;
01190 VectorScale( NPC->client->ps.moveDir, -1, NPC->client->ps.moveDir );
01191 }
01192 return qfalse;
01193 }
|
|
|
Definition at line 1042 of file NPC_utils.c.
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 1560 of file NPC_behavior.c. References AEL_DANGER, gNPC_t::behaviorState, BS_DEFAULT, BS_FLEE, BS_HUNT_AND_KILL, BSET_FLEE, CLASS_PROTOCOL, gentity_s::client, level_locals_t::combatPoints, CP_AVOID, CP_COVER, CP_HAS_ROUTE, CP_NO_PVS, entityShared_t::currentOrigin, G_ActivateBehavior(), G_SetEnemy(), gentity_t, gNPC_t::group, gentity_s::health, gNPC_t::investigateGoal, level, NPC, gclient_s::NPC_class, NPC_FindCombatPoint(), NPC_SetCombatPoint(), NPC_SetMoveGoal(), NPCInfo, NULL, AIGroupInfo_s::numGroup, combatPoint_t::origin, Q_irand(), qtrue, gentity_s::r, gentity_s::s, SQUAD_RETREAT, gNPC_t::squadState, gNPC_t::tempBehavior, TID_MOVE_NAV, TIMER_Set(), trap_ICARUS_TaskIDPending(), vec3_t, VectorCopy, entityState_s::weapon, and WP_NONE. Referenced by G_CheckForDanger(), G_StartFlee(), NPC_RunBehavior(), and ST_Commander().
01561 {
01562 int cp = -1;
01563
01564 if ( trap_ICARUS_TaskIDPending( NPC, TID_MOVE_NAV ) )
01565 {//running somewhere that a script requires us to go, don't interrupt that!
01566 return;
01567 }
01568
01569 //if have a fleescript, run that instead
01570 if ( G_ActivateBehavior( NPC, BSET_FLEE ) )
01571 {
01572 return;
01573 }
01574 //FIXME: play a flee sound? Appropriate to situation?
01575 if ( enemy )
01576 {
01577 G_SetEnemy( NPC, enemy );
01578 }
01579
01580 //FIXME: if don't have a weapon, find nearest one we have a route to and run for it?
01581 if ( dangerLevel > AEL_DANGER || NPC->s.weapon == WP_NONE || ((!NPCInfo->group || NPCInfo->group->numGroup <= 1) && NPC->health <= 10 ) )
01582 {//IF either great danger OR I have no weapon OR I'm alone and low on health, THEN try to find a combat point out of PVS
01583 cp = NPC_FindCombatPoint( NPC->r.currentOrigin, NPC->r.currentOrigin, dangerPoint, CP_COVER|CP_AVOID|CP_HAS_ROUTE|CP_NO_PVS, 128, -1 );
01584 }
01585 //FIXME: still happens too often...
01586 if ( cp == -1 )
01587 {//okay give up on the no PVS thing
01588 cp = NPC_FindCombatPoint( NPC->r.currentOrigin, NPC->r.currentOrigin, dangerPoint, CP_COVER|CP_AVOID|CP_HAS_ROUTE, 128, -1 );
01589 if ( cp == -1 )
01590 {//okay give up on the avoid
01591 cp = NPC_FindCombatPoint( NPC->r.currentOrigin, NPC->r.currentOrigin, dangerPoint, CP_COVER|CP_HAS_ROUTE, 128, -1 );
01592 if ( cp == -1 )
01593 {//okay give up on the cover
01594 cp = NPC_FindCombatPoint( NPC->r.currentOrigin, NPC->r.currentOrigin, dangerPoint, CP_HAS_ROUTE, 128, -1 );
01595 }
01596 }
01597 }
01598
01599 //see if we got a valid one
01600 if ( cp != -1 )
01601 {//found a combat point
01602 NPC_SetCombatPoint( cp );
01603 NPC_SetMoveGoal( NPC, level.combatPoints[cp].origin, 8, qtrue, cp, NULL );
01604 NPCInfo->behaviorState = BS_HUNT_AND_KILL;
01605 NPCInfo->tempBehavior = BS_DEFAULT;
01606 }
01607 else
01608 {//need to just run like hell!
01609 if ( NPC->s.weapon != WP_NONE )
01610 {
01611 return;//let's just not flee?
01612 }
01613 else
01614 {
01615 //FIXME: other evasion AI? Duck? Strafe? Dodge?
01616 NPCInfo->tempBehavior = BS_FLEE;
01617 //Run straight away from here... FIXME: really want to find farthest waypoint/navgoal from this pos... maybe based on alert event radius?
01618 NPC_SetMoveGoal( NPC, dangerPoint, 0, qtrue, -1, NULL );
01619 //store the danger point
01620 VectorCopy( dangerPoint, NPCInfo->investigateGoal );//FIXME: make a new field for this?
01621 }
01622 }
01623 //FIXME: localize this Timer?
01624 TIMER_Set( NPC, "attackDelay", Q_irand( 500, 2500 ) );
01625 //FIXME: is this always applicable?
01626 NPCInfo->squadState = SQUAD_RETREAT;
01627 TIMER_Set( NPC, "flee", Q_irand( fleeTimeMin, fleeTimeMax ) );
01628 TIMER_Set( NPC, "panic", Q_irand( 1000, 4000 ) );//how long to wait before trying to nav to a dropped weapon
01629
01630 if (NPC->client->NPC_class != CLASS_PROTOCOL)
01631 {
01632 TIMER_Set( NPC, "duck", 0 );
01633 }
01634 }
|
|
|
Definition at line 1317 of file NPC_behavior.c. References gNPC_t::blockedSpeechDebounceTime, gentity_s::client, EV_PUSHED1, EV_PUSHED3, G_AddVoiceEvent(), level, NPC, NPCInfo, PM_InKnockDown(), gclient_s::ps, Q_irand(), gentity_s::s, gNPC_t::surrenderTime, level_locals_t::time, entityState_s::weapon, playerState_s::weaponTime, WP_NONE, WP_SABER, and WP_STUN_BATON. Referenced by NPC_BSFlee().
01318 {//FIXME: say "don't shoot!" if we weren't already surrendering
01319 if ( NPC->client->ps.weaponTime || PM_InKnockDown( &NPC->client->ps ) )
01320 {
01321 return;
01322 }
01323 if ( NPC->s.weapon != WP_NONE &&
01324 NPC->s.weapon != WP_STUN_BATON &&
01325 NPC->s.weapon != WP_SABER )
01326 {
01327 //WP_DropWeapon( NPC, NULL ); //rwwFIXMEFIXME: Do this (gonna need a system for notifying client of removal)
01328 }
01329 if ( NPCInfo->surrenderTime < level.time - 5000 )
01330 {//haven't surrendered for at least 6 seconds, tell them what you're doing
01331 //FIXME: need real dialogue EV_SURRENDER
01332 NPCInfo->blockedSpeechDebounceTime = 0;//make sure we say this
01333 G_AddVoiceEvent( NPC, Q_irand( EV_PUSHED1, EV_PUSHED3 ), 3000 );
01334 }
01335 // NPC_SetAnim( NPC, SETANIM_TORSO, TORSO_SURRENDER_START, SETANIM_FLAG_HOLD|SETANIM_FLAG_OVERRIDE );
01336 // NPC->client->ps.torsoTimer = 1000;
01337 NPCInfo->surrenderTime = level.time + 1000;//stay surrendered for at least 1 second
01338 //FIXME: while surrendering, make a big sight/sound alert? Or G_AlertTeam?
01339 }
|
|
|
Definition at line 1216 of file bg_panimate.c.
01217 {
01218 switch ( (ps->legsAnim) )
01219 {
01220 case BOTH_KNOCKDOWN1:
01221 case BOTH_KNOCKDOWN2:
01222 case BOTH_KNOCKDOWN3:
01223 case BOTH_KNOCKDOWN4:
01224 case BOTH_KNOCKDOWN5:
01225 return qtrue;
01226 break;
01227 case BOTH_GETUP1:
01228 case BOTH_GETUP2:
01229 case BOTH_GETUP3:
01230 case BOTH_GETUP4:
01231 case BOTH_GETUP5:
01232 case BOTH_FORCE_GETUP_F1:
01233 case BOTH_FORCE_GETUP_F2:
01234 case BOTH_FORCE_GETUP_B1:
01235 case BOTH_FORCE_GETUP_B2:
01236 case BOTH_FORCE_GETUP_B3:
01237 case BOTH_FORCE_GETUP_B4:
01238 case BOTH_FORCE_GETUP_B5:
01239 case BOTH_GETUP_BROLL_B:
01240 case BOTH_GETUP_BROLL_F:
01241 case BOTH_GETUP_BROLL_L:
01242 case BOTH_GETUP_BROLL_R:
01243 case BOTH_GETUP_FROLL_B:
01244 case BOTH_GETUP_FROLL_F:
01245 case BOTH_GETUP_FROLL_L:
01246 case BOTH_GETUP_FROLL_R:
01247 if ( ps->legsTimer )
01248 {
01249 return qtrue;
01250 }
01251 break;
01252 }
01253 return qfalse;
01254 }
|
|
||||||||||||
|
|
|
|
Definition at line 14 of file NPC_behavior.c. Referenced by NPC_BSJump(). |
|
|
Definition at line 13 of file NPC_behavior.c. |