qboolean NPC_TryJump3(const vec3_t pos, float max_xy_dist, float max_z_diff) { if (NPC_CanTryJump()) { NPCInfo->jumpNextCheckTime = level.time + Q_irand(1000, 2000); VectorCopy(pos, NPCInfo->jumpDest); // Can't Try To Jump At A Point In The Air //----------------------------------------- { vec3_t groundTest; VectorCopy(pos, groundTest); groundTest[2] += (NPC->r.mins[2]*3); trap_Trace(&mJumpTrace, NPCInfo->jumpDest, vec3_origin, vec3_origin, groundTest, NPC->s.number, NPC->clipmask ); if (mJumpTrace.fraction >= 1.0f) { return qfalse; //no ground = no jump } } NPCInfo->jumpTarget = 0; NPCInfo->jumpMaxXYDist = (max_xy_dist)?(max_xy_dist):((NPC->client->NPC_class==CLASS_ROCKETTROOPER)?1200:750); NPCInfo->jumpMazZDist = (max_z_diff)?(max_z_diff):((NPC->client->NPC_class==CLASS_ROCKETTROOPER)?-1000:-450); NPCInfo->jumpTime = 0; NPCInfo->jumpBackupTime = 0; return NPC_TryJump(); } return qfalse; }
void Boba_DoSniper( gentity_t *self) { if (TIMER_Done(NPC, "PickNewSniperPoint")) { TIMER_Set(NPC, "PickNewSniperPoint", Q_irand(15000, 25000)); int SniperPoint = NPC_FindCombatPoint(NPC->currentOrigin, 0, NPC->currentOrigin, CP_SNIPE|CP_CLEAR|CP_HAS_ROUTE|CP_TRYFAR|CP_HORZ_DIST_COLL, 0, -1); if (SniperPoint!=-1) { NPC_SetCombatPoint(SniperPoint); NPC_SetMoveGoal( NPC, level.combatPoints[SniperPoint].origin, 20, qtrue, SniperPoint ); } } if (Distance(NPC->currentOrigin, level.combatPoints[NPCInfo->combatPoint].origin)<50.0f) { Boba_FireDecide(); } bool IsOnAPath = !!NPC_MoveToGoal(qtrue); // Resolve Blocked Problems //-------------------------- if (NPCInfo->aiFlags&NPCAI_BLOCKED && NPC->client->moveType!=MT_FLYSWIM && ((level.time - NPCInfo->blockedDebounceTime)>3000) ) { Boba_Printf("BLOCKED: Attempting Jump"); if (IsOnAPath) { if (!NPC_TryJump(NPCInfo->blockedTargetPosition)) { Boba_Printf(" Failed"); } } } NPC_FaceEnemy(qtrue); NPC_UpdateAngles( qtrue, qtrue ); }
//[SPPortComplete] qboolean NPC_JumpBackingUp() {//check for and back up before a large jump if we're supposed to. if (NPCInfo->jumpBackupTime) { if (level.time<NPCInfo->jumpBackupTime) { /* RAFIXME - impliment nav code. STEER::Activate(NPC); STEER::Flee(NPC, NPCInfo->jumpDest); STEER::DeActivate(NPC, &ucmd); */ NPC_FacePosition(NPCInfo->jumpDest, qtrue); NPC_UpdateAngles( qfalse, qtrue ); return qtrue; } NPCInfo->jumpBackupTime = 0; return NPC_TryJump(); } return qfalse; }
qboolean NPC_TryJump2(gentity_t *goal, float max_xy_dist, float max_z_diff) { if (NPC_CanTryJump()) { NPCInfo->jumpNextCheckTime = level.time + Q_irand(1000, 3000); // Can't Jump At Targets In The Air //--------------------------------- if (goal->client && goal->client->ps.groundEntityNum==ENTITYNUM_NONE) { return qfalse; } VectorCopy(goal->r.currentOrigin, NPCInfo->jumpDest); NPCInfo->jumpTarget = goal; NPCInfo->jumpMaxXYDist = (max_xy_dist)?(max_xy_dist):((NPC->client->NPC_class==CLASS_ROCKETTROOPER)?1200:750); NPCInfo->jumpMazZDist = (max_z_diff)?(max_z_diff):((NPC->client->NPC_class==CLASS_ROCKETTROOPER)?-1000:-400); NPCInfo->jumpTime = 0; NPCInfo->jumpBackupTime = 0; return NPC_TryJump(); } return qfalse; }
bool Boba_Flee() { bool EnemyRecentlySeen = ((level.time - NPCInfo->enemyLastSeenTime)<10000); bool ReachedEscapePoint = (Distance(level.combatPoints[NPCInfo->combatPoint].origin, NPC->currentOrigin)<50.0f); bool HasBeenGoneEnough = (level.time>NPCInfo->surrenderTime || (level.time - NPCInfo->enemyLastSeenTime)>400000); // Is It Time To Come Back For Some More? //---------------------------------------- if (!EnemyRecentlySeen || ReachedEscapePoint) { NPC->svFlags |= SVF_NOCLIENT; if (HasBeenGoneEnough) { if ((level.time - NPCInfo->enemyLastSeenTime)>400000) { Boba_Printf(" Gone Too Long, Attempting Respawn"); } if (Boba_Respawn()) { return true; } } else if (ReachedEscapePoint && (NPCInfo->surrenderTime - level.time)>3000) { if (TIMER_Done(NPC, "SpookPlayerTimer")) { vec3_t testDirection; TIMER_Set(NPC, "SpookPlayerTimer", Q_irand(2000, 10000)); switch(Q_irand(0, 1)) { case 0: Boba_Printf("SPOOK: Dust"); Boba_DustFallNear(NPC->enemy->currentOrigin, Q_irand(1,2)); break; case 1: Boba_Printf("SPOOK: Footsteps"); testDirection[0] = (random() * 0.5f) - 1.0f; testDirection[0] += (testDirection[0]>0.0f)?(0.5f):(-0.5f); testDirection[1] = (random() * 0.5f) - 1.0f; testDirection[1] += (testDirection[1]>0.0f)?(0.5f):(-0.5f); testDirection[2] = 1.0f; VectorMA(NPC->enemy->currentOrigin, 400.0f, testDirection, BobaFootStepLoc); BobaFootStepCount = Q_irand(3,8); break; } } if (BobaFootStepCount && TIMER_Done(NPC, "BobaFootStepFakeTimer")) { TIMER_Set(NPC, "BobaFootStepFakeTimer", Q_irand(300, 800)); BobaFootStepCount --; G_SoundAtSpot(BobaFootStepLoc, G_SoundIndex(va("sound/player/footsteps/boot%d", Q_irand(1,4))), qtrue); } if (TIMER_Done(NPC, "ResampleEnemyDirection") && NPC->enemy->resultspeed>10.0f) { TIMER_Set(NPC, "ResampleEnemyDirection", Q_irand(500, 1000)); AverageEnemyDirectionSamples ++; vec3_t moveDir; VectorCopy(NPC->enemy->client->ps.velocity, moveDir); VectorNormalize(moveDir); VectorAdd(AverageEnemyDirection, moveDir, AverageEnemyDirection); } if (g_bobaDebug->integer && AverageEnemyDirectionSamples) { vec3_t endPos; VectorMA(NPC->enemy->currentOrigin, 500.0f / (float)AverageEnemyDirectionSamples, AverageEnemyDirection, endPos); CG_DrawEdge(NPC->enemy->currentOrigin, endPos, EDGE_IMPACT_POSSIBLE); } } } else { NPCInfo->surrenderTime += 100; } // Finish The Flame Thrower First... //----------------------------------- if (NPCInfo->aiFlags&NPCAI_FLAMETHROW) { Boba_DoFlameThrower( NPC ); NPC_FacePosition( NPC->enemy->currentOrigin, qtrue); NPC_UpdateAngles(qtrue, qtrue); return true; } bool IsOnAPath = !!NPC_MoveToGoal(qtrue); if (!ReachedEscapePoint && NPCInfo->aiFlags&NPCAI_BLOCKED && NPC->client->moveType!=MT_FLYSWIM && ((level.time - NPCInfo->blockedDebounceTime)>1000) ) { if (!Boba_CanSeeEnemy(NPC) && Distance(NPC->currentOrigin, level.combatPoints[NPCInfo->combatPoint].origin)<200) { Boba_Printf("BLOCKED: Just Teleporting There"); G_SetOrigin(NPC, level.combatPoints[NPCInfo->combatPoint].origin); } else { Boba_Printf("BLOCKED: Attempting Jump"); if (IsOnAPath) { if (NPC_TryJump(NPCInfo->blockedTargetPosition)) { } else { Boba_Printf(" Failed"); } } else if (EnemyRecentlySeen) { if (NPC_TryJump(NPCInfo->enemyLastSeenLocation)) { } else { Boba_Printf(" Failed"); } } } } NPC_UpdateAngles( qtrue, qtrue ); return true; }
static qboolean NPC_Howler_Move( int randomJumpChance = 0 ) { if ( !TIMER_Done( NPC, "standing" ) ) {//standing around return qfalse; } if ( NPC->client->ps.groundEntityNum == ENTITYNUM_NONE ) {//in air, don't do anything return qfalse; } if ( (!NPC->enemy&&TIMER_Done( NPC, "running" )) || !TIMER_Done( NPC, "walking" ) ) { ucmd.buttons |= BUTTON_WALKING; } if ( (!randomJumpChance||Q_irand( 0, randomJumpChance )) && NPC_MoveToGoal( qtrue ) ) { if ( VectorCompare( NPC->client->ps.moveDir, vec3_origin ) || !NPC->client->ps.speed ) {//uh.... wtf? Got there? if ( NPCInfo->goalEntity ) { NPC_FaceEntity( NPCInfo->goalEntity, qfalse ); } else { NPC_UpdateAngles( qfalse, qtrue ); } return qtrue; } //TEMP: don't want to strafe VectorClear( NPC->client->ps.moveDir ); ucmd.rightmove = 0.0f; // Com_Printf( "Howler moving %d\n",ucmd.forwardmove ); //if backing up, go slow... if ( ucmd.forwardmove < 0.0f ) { ucmd.buttons |= BUTTON_WALKING; //if ( NPC->client->ps.speed > NPCInfo->stats.walkSpeed ) {//don't walk faster than I'm allowed to NPC->client->ps.speed = NPCInfo->stats.walkSpeed; } } else { if ( (ucmd.buttons&BUTTON_WALKING) ) { NPC->client->ps.speed = NPCInfo->stats.walkSpeed; } else { NPC->client->ps.speed = NPCInfo->stats.runSpeed; } } NPCInfo->lockedDesiredYaw = NPCInfo->desiredYaw = NPCInfo->lastPathAngles[YAW]; NPC_UpdateAngles( qfalse, qtrue ); } else if ( NPCInfo->goalEntity ) {//couldn't get where we wanted to go, try to jump there NPC_FaceEntity( NPCInfo->goalEntity, qfalse ); NPC_TryJump( NPCInfo->goalEntity, 400.0f, -256.0f ); } return qtrue; }