codemp/game/NPC_goal.c

Go to the documentation of this file.
00001 //b_goal.cpp
00002 #include "b_local.h"
00003 #include "../icarus/Q3_Interface.h"
00004 
00005 extern qboolean FlyingCreature( gentity_t *ent );
00006 /*
00007 SetGoal
00008 */
00009 
00010 void SetGoal( gentity_t *goal, float rating ) 
00011 {
00012         NPCInfo->goalEntity = goal;
00013 //      NPCInfo->goalEntityNeed = rating;
00014         NPCInfo->goalTime = level.time;
00015 //      NAV_ClearLastRoute(NPC);
00016         if ( goal ) 
00017         {
00018 //              Debug_NPCPrintf( NPC, debugNPCAI, DEBUG_LEVEL_INFO, "NPC_SetGoal: %s @ %s (%f)\n", goal->classname, vtos( goal->currentOrigin), rating );
00019         }
00020         else 
00021         {
00022 //              Debug_NPCPrintf( NPC, debugNPCAI, DEBUG_LEVEL_INFO, "NPC_SetGoal: NONE\n" );
00023         }
00024 }
00025 
00026 
00027 /*
00028 NPC_SetGoal
00029 */
00030 
00031 void NPC_SetGoal( gentity_t *goal, float rating ) 
00032 {
00033         if ( goal == NPCInfo->goalEntity ) 
00034         {
00035                 return;
00036         }
00037 
00038         if ( !goal ) 
00039         {
00040 //              Debug_NPCPrintf( NPC, debugNPCAI, DEBUG_LEVEL_ERROR, "NPC_SetGoal: NULL goal\n" );
00041                 return;
00042         }
00043 
00044         if ( goal->client ) 
00045         {
00046 //              Debug_NPCPrintf( NPC, debugNPCAI, DEBUG_LEVEL_ERROR, "NPC_SetGoal: goal is a client\n" );
00047                 return;
00048         }
00049 
00050         if ( NPCInfo->goalEntity ) 
00051         {
00052 //              Debug_NPCPrintf( NPC, debugNPCAI, DEBUG_LEVEL_INFO, "NPC_SetGoal: push %s\n", NPCInfo->goalEntity->classname );
00053                 NPCInfo->lastGoalEntity = NPCInfo->goalEntity;
00054 //              NPCInfo->lastGoalEntityNeed = NPCInfo->goalEntityNeed;
00055         }
00056 
00057         SetGoal( goal, rating );
00058 }
00059 
00060 
00061 /*
00062 NPC_ClearGoal
00063 */
00064 
00065 void NPC_ClearGoal( void ) 
00066 {
00067         gentity_t       *goal;
00068 
00069         if ( !NPCInfo->lastGoalEntity ) 
00070         {
00071                 SetGoal( NULL, 0.0 );
00072                 return;
00073         }
00074 
00075         goal = NPCInfo->lastGoalEntity;
00076         NPCInfo->lastGoalEntity = NULL;
00077 //      NAV_ClearLastRoute(NPC);
00078         if ( goal->inuse && !(goal->s.eFlags & EF_NODRAW) ) 
00079         {
00080 //              Debug_NPCPrintf( NPC, debugNPCAI, DEBUG_LEVEL_INFO, "NPC_ClearGoal: pop %s\n", goal->classname );
00081                 SetGoal( goal, 0 );//, NPCInfo->lastGoalEntityNeed
00082                 return;
00083         }
00084 
00085         SetGoal( NULL, 0.0 );
00086 }
00087 
00088 /*
00089 -------------------------
00090 G_BoundsOverlap
00091 -------------------------
00092 */
00093 
00094 qboolean G_BoundsOverlap(const vec3_t mins1, const vec3_t maxs1, const vec3_t mins2, const vec3_t maxs2)
00095 {//NOTE: flush up against counts as overlapping
00096         if(mins1[0]>maxs2[0])
00097                 return qfalse;
00098 
00099         if(mins1[1]>maxs2[1])
00100                 return qfalse;
00101 
00102         if(mins1[2]>maxs2[2])
00103                 return qfalse;
00104 
00105         if(maxs1[0]<mins2[0])
00106                 return qfalse;
00107 
00108         if(maxs1[1]<mins2[1])
00109                 return qfalse;
00110 
00111         if(maxs1[2]<mins2[2])
00112                 return qfalse;
00113 
00114         return qtrue;
00115 }
00116 
00117 void NPC_ReachedGoal( void )
00118 {
00119 //      Debug_NPCPrintf( NPC, debugNPCAI, DEBUG_LEVEL_INFO, "UpdateGoal: reached goal entity\n" );
00120         NPC_ClearGoal();
00121         NPCInfo->goalTime = level.time;
00122 
00123 //MCG - Begin
00124         NPCInfo->aiFlags &= ~NPCAI_MOVING;
00125         ucmd.forwardmove = 0;
00126         //Return that the goal was reached
00127         trap_ICARUS_TaskIDComplete( NPC, TID_MOVE_NAV );
00128 //MCG - End
00129 }
00130 /*
00131 ReachedGoal
00132 
00133 id removed checks against waypoints and is now checking surfaces
00134 */
00135 //qboolean NAV_HitNavGoal( vec3_t point, vec3_t mins, vec3_t maxs, gentity_t *goal, qboolean flying );
00136 qboolean ReachedGoal( gentity_t *goal ) 
00137 {
00138         //FIXME: For script waypoints, need a special check
00139 /*
00140         int             goalWpNum;
00141         vec3_t  vec;
00142         //vec3_t        angles;
00143         float   delta;
00144 
00145         if ( goal->flags & FL_NAVGOAL )
00146         {//waypoint_navgoal
00147                 return NAV_HitNavGoal( NPC->currentOrigin, NPC->mins, NPC->maxs, goal, FlyingCreature( NPC ) );
00148         }
00149 
00150         if ( goal == NPCInfo->tempGoal && !(goal->flags & FL_NAVGOAL)) 
00151         {//MUST touch waypoints, even if moving to it
00152                 //This is odd, it just checks to see if they are on the same
00153                 //surface and the tempGoal in in the FOV - does NOT check distance!
00154                 // are we on same surface?
00155                 
00156                 //FIXME: NPC->waypoint reset every frame, need to find it first
00157                 //Should we do that here?  (Still will do it only once per frame)
00158                 if ( NPC->waypoint >= 0 && NPC->waypoint < num_waypoints )
00159                 {
00160                         goalWpNum = NAV_FindWaypointAt ( goal->currentOrigin );
00161                         if ( NPC->waypoint != goalWpNum ) 
00162                         {
00163                                 return qfalse;
00164                         }
00165                 }
00166 
00167                 VectorSubtract ( NPCInfo->tempGoal->currentOrigin, NPC->currentOrigin, vec);
00168                 //Who cares if it's in our FOV?!
00169                 /*
00170                 // is it in our FOV
00171                 vectoangles ( vec, angles );
00172                 delta = AngleDelta ( NPC->client->ps.viewangles[YAW], angles[YAW] );
00173                 if ( fabs ( delta ) > NPCInfo->stats.hfov ) 
00174                 {
00175                         return qfalse;
00176                 }
00177                 */
00178 
00179                 /*
00180                 //If in the same waypoint as tempGoal, we're there, right?
00181                 if ( goal->waypoint >= 0 && goal->waypoint < num_waypoints )
00182                 {
00183                         if ( NPC->waypoint == goal->waypoint )
00184                         {
00185                                 return qtrue;
00186                         }
00187                 }
00188                 */
00189 
00190 /*
00191                 if ( VectorLengthSquared( vec ) < (64*64) )
00192                 {//Close enough
00193                         return qtrue;
00194                 }
00195 
00196                 return qfalse;
00197         }
00198 */
00199         if ( NPCInfo->aiFlags & NPCAI_TOUCHED_GOAL ) 
00200         {
00201                 NPCInfo->aiFlags &= ~NPCAI_TOUCHED_GOAL;
00202                 return qtrue;
00203         }
00204 /*
00205         if ( goal->s.eFlags & EF_NODRAW ) 
00206         {
00207                 goalWpNum = NAV_FindWaypointAt( goal->currentOrigin );
00208                 if ( NPC->waypoint == goalWpNum ) 
00209                 {
00210                         return qtrue;
00211                 }
00212                 return qfalse;
00213         }
00214 
00215         if(goal->client && goal->health <= 0)
00216         {//trying to get to dead guy
00217                 goalWpNum = NAV_FindWaypointAt( goal->currentOrigin );
00218                 if ( NPC->waypoint == goalWpNum ) 
00219                 {
00220                         VectorSubtract(NPC->currentOrigin, goal->currentOrigin, vec);
00221                         vec[2] = 0;
00222                         delta = VectorLengthSquared(vec);
00223                         if(delta <= 800)
00224                         {//with 20-30 of other guy's origin
00225                                 return qtrue;
00226                         }
00227                 }
00228         }
00229 */      
00230         return NAV_HitNavGoal( NPC->r.currentOrigin, NPC->r.mins, NPC->r.maxs, goal->r.currentOrigin, NPCInfo->goalRadius, FlyingCreature( NPC ) );
00231 }
00232 
00233 /*
00234 static gentity_t *UpdateGoal( void ) 
00235 
00236 Id removed a lot of shit here... doesn't seem to handle waypoints independantly of goalentity
00237 
00238 In fact, doesn't seem to be any waypoint info on entities at all any more?
00239 
00240 MCG - Since goal is ALWAYS goalEntity, took out a lot of sending goal entity pointers around for no reason
00241 */
00242 
00243 gentity_t *UpdateGoal( void ) 
00244 {
00245         gentity_t       *goal;
00246 
00247         if ( !NPCInfo->goalEntity ) 
00248         {
00249                 return NULL;
00250         }
00251 
00252         if ( !NPCInfo->goalEntity->inuse )
00253         {//Somehow freed it, but didn't clear it
00254                 NPC_ClearGoal();
00255                 return NULL;
00256         }
00257 
00258         goal = NPCInfo->goalEntity;
00259 
00260         if ( ReachedGoal( goal ) ) 
00261         {
00262                 NPC_ReachedGoal();
00263                 goal = NULL;//so they don't keep trying to move to it
00264         }//else if fail, need to tell script so?
00265 
00266         return goal;
00267 }