/* ReachedGoal id removed checks against waypoints and is now checking surfaces */ qboolean ReachedGoal( gentity_t *goal ) { if ( NPCInfo->aiFlags & NPCAI_TOUCHED_GOAL ) { NPCInfo->aiFlags &= ~NPCAI_TOUCHED_GOAL; return qtrue; } return STEER::Reached(NPC, goal, NPCInfo->goalRadius, !!FlyingCreature(NPC)); }
qboolean NPC_ClearPathToGoal( vec3_t dir, gentity_t *goal ) { trace_t trace; float radius, dist, tFrac; //FIXME: What does do about area portals? THIS IS BROKEN //if ( gi.inPVS( NPC->r.currentOrigin, goal->r.currentOrigin ) == qfalse ) // return qfalse; //Look ahead and see if we're clear to move to our goal position if ( NAV_CheckAhead( NPC, goal->r.currentOrigin, &trace, ( NPC->clipmask & ~CONTENTS_BODY )|CONTENTS_BOTCLIP ) ) { //VectorSubtract( goal->r.currentOrigin, NPC->r.currentOrigin, dir ); return qtrue; } if (!FlyingCreature(NPC)) { //See if we're too far above if ( fabs( NPC->r.currentOrigin[2] - goal->r.currentOrigin[2] ) > 48 ) return qfalse; } //This is a work around radius = ( NPC->r.maxs[0] > NPC->r.maxs[1] ) ? NPC->r.maxs[0] : NPC->r.maxs[1]; dist = Distance( NPC->r.currentOrigin, goal->r.currentOrigin ); tFrac = 1.0f - ( radius / dist ); if ( trace.fraction >= tFrac ) return qtrue; //See if we're looking for a navgoal if ( goal->flags & FL_NAVGOAL ) { //Okay, didn't get all the way there, let's see if we got close enough: if ( NAV_HitNavGoal( trace.endpos, NPC->r.mins, NPC->r.maxs, goal->r.currentOrigin, NPCInfo->goalRadius, FlyingCreature( NPC ) ) ) { //VectorSubtract(goal->r.currentOrigin, NPC->r.currentOrigin, dir); return qtrue; } } return qfalse; }
static void Sniper_CheckMoveState( void ) { //See if we're a scout if ( !(NPCInfo->scriptFlags & SCF_CHASE_ENEMIES) )//NPCInfo->behaviorState == BS_STAND_AND_SHOOT ) { if ( NPCInfo->goalEntity == NPC->enemy ) { AImove = qfalse; return; } } //See if we're running away else if ( NPCInfo->squadState == SQUAD_RETREAT ) { if ( TIMER_Done( NPC, "flee" ) ) { NPCInfo->squadState = SQUAD_IDLE; } else { faceEnemy = qfalse; } } else if ( NPCInfo->squadState == SQUAD_IDLE ) { if ( !NPCInfo->goalEntity ) { AImove = qfalse; return; } } //See if we're moving towards a goal, not the enemy if ( ( NPCInfo->goalEntity != NPC->enemy ) && ( NPCInfo->goalEntity != NULL ) ) { //Did we make it? if ( NAV_HitNavGoal( NPC->currentOrigin, NPC->mins, NPC->maxs, NPCInfo->goalEntity->currentOrigin, 16, FlyingCreature( NPC ) ) || ( NPCInfo->squadState == SQUAD_SCOUT && enemyLOS && enemyDist <= 10000 ) ) { int newSquadState = SQUAD_STAND_AND_SHOOT; //we got where we wanted to go, set timers based on why we were running switch ( NPCInfo->squadState ) { case SQUAD_RETREAT://was running away TIMER_Set( NPC, "duck", (NPC->max_health - NPC->health) * 100 ); TIMER_Set( NPC, "hideTime", Q_irand( 3000, 7000 ) ); newSquadState = SQUAD_COVER; break; case SQUAD_TRANSITION://was heading for a combat point TIMER_Set( NPC, "hideTime", Q_irand( 2000, 4000 ) ); break; case SQUAD_SCOUT://was running after player break; default: break; } NPC_ReachedGoal(); //don't attack right away TIMER_Set( NPC, "attackDelay", Q_irand( (6-NPCInfo->stats.aim)*50, (6-NPCInfo->stats.aim)*100 ) ); //FIXME: Slant for difficulty levels, too? //don't do something else just yet TIMER_Set( NPC, "roamTime", Q_irand( 1000, 4000 ) ); //stop fleeing if ( NPCInfo->squadState == SQUAD_RETREAT ) { TIMER_Set( NPC, "flee", -level.time ); NPCInfo->squadState = SQUAD_IDLE; } return; } //keep going, hold of roamTimer until we get there TIMER_Set( NPC, "roamTime", Q_irand( 4000, 8000 ) ); } }
//qboolean NAV_HitNavGoal( vec3_t point, vec3_t mins, vec3_t maxs, gentity_t *goal, qboolean flying ); qboolean ReachedGoal( gentity_t *goal ) { //FIXME: For script waypoints, need a special check /* int goalWpNum; vec3_t vec; //vec3_t angles; float delta; if ( goal->flags & FL_NAVGOAL ) {//waypoint_navgoal return NAV_HitNavGoal( NPC->currentOrigin, NPC->mins, NPC->maxs, goal, FlyingCreature( NPC ) ); } if ( goal == NPCInfo->tempGoal && !(goal->flags & FL_NAVGOAL)) {//MUST touch waypoints, even if moving to it //This is odd, it just checks to see if they are on the same //surface and the tempGoal in in the FOV - does NOT check distance! // are we on same surface? //FIXME: NPC->waypoint reset every frame, need to find it first //Should we do that here? (Still will do it only once per frame) if ( NPC->waypoint >= 0 && NPC->waypoint < num_waypoints ) { goalWpNum = NAV_FindWaypointAt ( goal->currentOrigin ); if ( NPC->waypoint != goalWpNum ) { return qfalse; } } VectorSubtract ( NPCInfo->tempGoal->currentOrigin, NPC->currentOrigin, vec); //Who cares if it's in our FOV?! /* // is it in our FOV vectoangles ( vec, angles ); delta = AngleDelta ( NPC->client->ps.viewangles[YAW], angles[YAW] ); if ( fabs ( delta ) > NPCInfo->stats.hfov ) { return qfalse; } */ /* //If in the same waypoint as tempGoal, we're there, right? if ( goal->waypoint >= 0 && goal->waypoint < num_waypoints ) { if ( NPC->waypoint == goal->waypoint ) { return qtrue; } } */ /* if ( VectorLengthSquared( vec ) < (64*64) ) {//Close enough return qtrue; } return qfalse; } */ if ( NPCInfo->aiFlags & NPCAI_TOUCHED_GOAL ) { NPCInfo->aiFlags &= ~NPCAI_TOUCHED_GOAL; return qtrue; } /* if ( goal->s.eFlags & EF_NODRAW ) { goalWpNum = NAV_FindWaypointAt( goal->currentOrigin ); if ( NPC->waypoint == goalWpNum ) { return qtrue; } return qfalse; } if(goal->client && goal->health <= 0) {//trying to get to dead guy goalWpNum = NAV_FindWaypointAt( goal->currentOrigin ); if ( NPC->waypoint == goalWpNum ) { VectorSubtract(NPC->currentOrigin, goal->currentOrigin, vec); vec[2] = 0; delta = VectorLengthSquared(vec); if(delta <= 800) {//with 20-30 of other guy's origin return qtrue; } } } */ return NAV_HitNavGoal( NPC->r.currentOrigin, NPC->r.mins, NPC->r.maxs, goal->r.currentOrigin, NPCInfo->goalRadius, FlyingCreature( NPC ) ); }
static void Grenadier_CheckMoveState( void ) { //See if we're a scout if ( !(NPCInfo->scriptFlags & SCF_CHASE_ENEMIES) )//behaviorState == BS_STAND_AND_SHOOT ) { if ( NPCInfo->goalEntity == NPC->enemy ) { doMove = qfalse; return; } } //See if we're running away else if ( NPCInfo->squadState == SQUAD_RETREAT ) { if ( TIMER_Done( NPC, "flee" ) ) { NPCInfo->squadState = SQUAD_IDLE; } else { faceEnemy = qfalse; } } /* else if ( NPCInfo->squadState == SQUAD_IDLE ) { if ( !NPCInfo->goalEntity ) { doMove = qfalse; return; } //Should keep moving toward player when we're out of range... right? } */ //See if we're moving towards a goal, not the enemy if ( ( NPCInfo->goalEntity != NPC->enemy ) && ( NPCInfo->goalEntity != NULL ) ) { //Did we make it? if ( STEER::Reached(NPC, NPCInfo->goalEntity, 16, !!FlyingCreature(NPC)) || ( NPCInfo->squadState == SQUAD_SCOUT && enemyLOS && enemyDist <= 10000 ) ) { //int newSquadState = SQUAD_STAND_AND_SHOOT; //we got where we wanted to go, set timers based on why we were running switch ( NPCInfo->squadState ) { case SQUAD_RETREAT://was running away TIMER_Set( NPC, "duck", (NPC->max_health - NPC->health) * 100 ); TIMER_Set( NPC, "hideTime", Q_irand( 3000, 7000 ) ); //newSquadState = SQUAD_COVER; break; case SQUAD_TRANSITION://was heading for a combat point TIMER_Set( NPC, "hideTime", Q_irand( 2000, 4000 ) ); break; case SQUAD_SCOUT://was running after player break; default: break; } NPC_ReachedGoal(); //don't attack right away TIMER_Set( NPC, "attackDelay", Q_irand( 250, 500 ) ); //FIXME: Slant for difficulty levels //don't do something else just yet TIMER_Set( NPC, "roamTime", Q_irand( 1000, 4000 ) ); //stop fleeing if ( NPCInfo->squadState == SQUAD_RETREAT ) { TIMER_Set( NPC, "flee", -level.time ); NPCInfo->squadState = SQUAD_IDLE; } return; } //keep going, hold of roamTimer until we get there TIMER_Set( NPC, "roamTime", Q_irand( 4000, 8000 ) ); } if ( !NPCInfo->goalEntity ) { if ( NPCInfo->scriptFlags & SCF_CHASE_ENEMIES ) { NPCInfo->goalEntity = NPC->enemy; NPCInfo->goalRadius = (NPC->maxs[0]*1.5f); } } }