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 }