00001
00002 #include "revolt.h"
00003 #include "editai.h"
00004 #include "car.h"
00005 #include "aizone.h"
00006 #include "ctrlread.h"
00007 #include "object.h"
00008 #include "Control.h"
00009 #include "player.h"
00010 #ifdef _N64
00011 #include "ffs_code.h"
00012 #include "ffs_list.h"
00013 #include "utils.h"
00014 #endif
00015
00016
00017
00018
00019
00020 long AiNodeNum;
00021 AINODE *AiNode;
00022 AINODE_ZONE *AiNodeZone;
00023
00024
00025
00026
00027
00028 #ifdef _PC
00029 void LoadAiNodes(char *file);
00030 #endif
00031 #ifdef _N64
00032 void LoadAiNodes(void);
00033 #endif
00034 void FreeAiNodes(void);
00035 AINODE *AIN_NearestNode(PLAYER *Player, REAL *Dist);
00036 AINODE *AIN_GetForwardNode(PLAYER *Player, REAL MinDist, REAL *Dist);
00037 long AiStartNode;
00038 REAL AiNodeTotalDist;
00039
00041
00043 #ifdef _PC
00044 void LoadAiNodes(char *file)
00045 {
00046 long i, j;
00047 FILE *fp;
00048 FILE_AINODE fan;
00049
00050
00051
00052 AiNode = NULL;
00053 AiNodeNum = 0;
00054
00055 fp = fopen(file, "rb");
00056 if (!fp) return;
00057
00058
00059
00060 fread(&AiNodeNum, sizeof(AiNodeNum), 1, fp);
00061 if (!AiNodeNum) return;
00062
00063 AiNode = (AINODE*)malloc(sizeof(AINODE) * AiNodeNum);
00064 if (!AiNode)
00065 {
00066 AiNodeNum = 0;
00067 return;
00068 }
00069
00070
00071
00072 for (i = 0 ; i < AiNodeNum ; i++)
00073 {
00074
00075
00076
00077 fread(&fan, sizeof(fan), 1, fp);
00078
00079
00080
00081 AiNode[i].Node[0] = fan.Node[0];
00082 AiNode[i].Node[1] = fan.Node[1];
00083
00084 AiNode[i].Centre.v[X] = (fan.Node[0].Pos.v[X] + fan.Node[1].Pos.v[X]) / 2;
00085 AiNode[i].Centre.v[Y] = (fan.Node[0].Pos.v[Y] + fan.Node[1].Pos.v[Y]) / 2;
00086 AiNode[i].Centre.v[Z] = (fan.Node[0].Pos.v[Z] + fan.Node[1].Pos.v[Z]) / 2;
00087 AiNode[i].RVec.v[X] = fan.Node[1].Pos.v[X] - AiNode[i].Centre.v[X];
00088 AiNode[i].RVec.v[Y] = fan.Node[1].Pos.v[Y] - AiNode[i].Centre.v[Y];
00089 AiNode[i].RVec.v[Z] = fan.Node[1].Pos.v[Z] - AiNode[i].Centre.v[Z];
00090 NormalizeVector(&AiNode[i].RVec);
00091
00092 AiNode[i].Priority = fan.Priority;
00093 AiNode[i].StartNode = fan.StartNode;
00094 AiNode[i].RacingLine = fan.RacingLine;
00095 AiNode[i].RacingLineSpeed = fan.RacingLineSpeed;
00096 AiNode[i].CentreSpeed = fan.CentreSpeed;
00097 AiNode[i].FinishDist = fan.FinishDist;
00098
00099 for (j = 0 ; j < MAX_AINODE_LINKS ; j++)
00100 {
00101 if (fan.Prev[j] != -1)
00102 AiNode[i].Prev[j] = AiNode + fan.Prev[j];
00103 else
00104 AiNode[i].Prev[j] = NULL;
00105
00106 if (fan.Next[j] != -1)
00107 AiNode[i].Next[j] = AiNode + fan.Next[j];
00108 else
00109 AiNode[i].Next[j] = NULL;
00110 }
00111 }
00112
00113
00114
00115 fread(&AiStartNode, sizeof(AiStartNode), 1, fp);
00116
00117
00118
00119 fread(&AiNodeTotalDist, sizeof(AiNodeTotalDist), 1, fp);
00120
00121
00122
00123 fclose(fp);
00124 }
00125
00126 #endif
00127
00128 #ifdef _N64
00129 void LoadAiNodes(void)
00130 {
00131 long ii, jj, kk, numread;
00132 FIL *fp;
00133 FILE_AINODE fan;
00134 long Prev, Next;
00135
00136
00137
00138 AiNode = NULL;
00139 AiNodeNum = 0;
00140
00141 printf("Loading AI nodes...\n");
00142 fp = FFS_Open(FFS_TYPE_TRACK | TRK_AINODES);
00143 if (!fp)
00144 {
00145 printf("...AI node file not found!\n");
00146 return;
00147 }
00148
00149
00150
00151 FFS_Read(&AiNodeNum, sizeof(AiNodeNum), fp);
00152 AiNodeNum = EndConvLong(AiNodeNum);
00153 if (!AiNodeNum) return;
00154
00155 AiNode = (AINODE*)malloc(sizeof(AINODE) * AiNodeNum);
00156 if (!AiNode)
00157 {
00158 AiNodeNum = 0;
00159 return;
00160 }
00161
00162
00163
00164 for (ii = 0; ii < AiNodeNum ; ii++)
00165 {
00166
00167
00168 FFS_Read(&fan, sizeof(fan), fp);
00169 fan.RacingLine = EndConvReal(fan.RacingLine);
00170 fan.RacingLineSpeed = EndConvLong(fan.RacingLineSpeed);
00171 fan.CentreSpeed = EndConvLong(fan.CentreSpeed);
00172 fan.FinishDist = EndConvReal(fan.FinishDist);
00173
00174 for (jj = 0; jj < MAX_AINODE_LINKS; jj++)
00175 {
00176 fan.Prev[jj] = EndConvLong(fan.Prev[jj]);
00177 fan.Next[jj] = EndConvLong(fan.Next[jj]);
00178 }
00179 fan.Node[0].Speed = EndConvLong(fan.Node[0].Speed);
00180 fan.Node[0].Pos.v[0] = EndConvReal(fan.Node[0].Pos.v[0]);
00181 fan.Node[0].Pos.v[1] = EndConvReal(fan.Node[0].Pos.v[1]);
00182 fan.Node[0].Pos.v[2] = EndConvReal(fan.Node[0].Pos.v[2]);
00183 fan.Node[1].Speed = EndConvLong(fan.Node[1].Speed);
00184 fan.Node[1].Pos.v[0] = EndConvReal(fan.Node[1].Pos.v[0]);
00185 fan.Node[1].Pos.v[1] = EndConvReal(fan.Node[1].Pos.v[1]);
00186 fan.Node[1].Pos.v[2] = EndConvReal(fan.Node[1].Pos.v[2]);
00187
00188
00189 AiNode[ii].Node[0] = fan.Node[0];
00190 AiNode[ii].Node[1] = fan.Node[1];
00191
00192 AiNode[ii].Centre.v[X] = (fan.Node[0].Pos.v[X] + fan.Node[1].Pos.v[X]) / 2;
00193 AiNode[ii].Centre.v[Y] = (fan.Node[0].Pos.v[Y] + fan.Node[1].Pos.v[Y]) / 2;
00194 AiNode[ii].Centre.v[Z] = (fan.Node[0].Pos.v[Z] + fan.Node[1].Pos.v[Z]) / 2;
00195 AiNode[ii].RVec.v[X] = fan.Node[1].Pos.v[X] - AiNode[ii].Centre.v[X];
00196 AiNode[ii].RVec.v[Y] = fan.Node[1].Pos.v[Y] - AiNode[ii].Centre.v[Y];
00197 AiNode[ii].RVec.v[Z] = fan.Node[1].Pos.v[Z] - AiNode[ii].Centre.v[Z];
00198 NormalizeVector(&AiNode[ii].RVec);
00199
00200 AiNode[ii].Priority = fan.Priority;
00201 AiNode[ii].StartNode = fan.StartNode;
00202 AiNode[ii].RacingLine = fan.RacingLine;
00203 AiNode[ii].RacingLineSpeed = fan.RacingLineSpeed;
00204 AiNode[ii].CentreSpeed = fan.CentreSpeed;
00205 AiNode[ii].FinishDist = fan.FinishDist;
00206
00207 for (jj = 0; jj < MAX_AINODE_LINKS; jj++)
00208 {
00209 if (fan.Prev[jj] != -1)
00210 AiNode[ii].Prev[jj] = AiNode + fan.Prev[jj];
00211 else
00212 AiNode[ii].Prev[jj] = NULL;
00213
00214 if (fan.Next[jj] != -1)
00215 AiNode[ii].Next[jj] = AiNode + fan.Next[jj];
00216 else
00217 AiNode[ii].Next[jj] = NULL;
00218 }
00219 }
00220
00221 printf("...read %d AI nodes.\n", AiNodeNum);
00222
00223
00224 FFS_Read(&AiStartNode, sizeof(AiStartNode), fp);
00225 AiStartNode = EndConvLong(AiStartNode);
00226
00227
00228 FFS_Read(&AiNodeTotalDist, sizeof(AiNodeTotalDist), fp);
00229 AiNodeTotalDist = EndConvReal(AiNodeTotalDist);
00230
00231
00232 FFS_Close(fp);
00233 }
00234 #endif
00235
00237
00239
00240 void FreeAiNodes(void)
00241 {
00242 free(AiNode);
00243 free(AiNodeZone);
00244 }
00245
00247
00249
00250 void ZoneAiNodes(void)
00251 {
00252 long i, j, k;
00253 REAL dist;
00254 char buf[128];
00255 AINODE *lastnode;
00256
00257
00258
00259 if (!AiZoneNum)
00260 {
00261 AiNodeZone = NULL;
00262 return;
00263 }
00264
00265
00266
00267 AiNodeZone = (AINODE_ZONE*)malloc(sizeof(AINODE_ZONE) * AiZoneNum);
00268 if (!AiNodeZone)
00269 {
00270 #ifdef _PC
00271 Box("Warning!", "Couldn't alloc memory for AI node zoning!", MB_OK);
00272 #endif
00273 #ifdef _N64
00274 printf("<!> WARN: Couldn't alloc memory for AI node zoning.\n");
00275 #endif
00276 return;
00277 }
00278
00279
00280
00281 for (i = 0 ; i < AiNodeNum ; i++)
00282 {
00283 AiNode[i].ZoneID = LONG_MAX;
00284
00285 for (j = 0 ; j < AiZoneNum ; j++)
00286 {
00287 for (k = 0 ; k < 3 ; k++)
00288 {
00289 dist = PlaneDist(&AiZones[j].Plane[k], &AiNode[i].Centre);
00290 if (dist < -AiZones[j].Size[k] || dist > AiZones[j].Size[k]) break;
00291 }
00292
00293 if (k == 3 && j < AiNode[i].ZoneID)
00294 {
00295 AiNode[i].ZoneID = j;
00296 }
00297 }
00298
00299 if (AiNode[i].ZoneID == LONG_MAX)
00300 {
00301 #ifdef _PC
00302 wsprintf(buf, "AI node %ld is outside all AI zones!", i);
00303 Box(NULL, buf, MB_OK);
00304 #endif
00305 #ifdef _N64
00306 printf("<!> WARN: AI node %ld is outside all AI zones.\n", i);
00307 #endif
00308 }
00309 }
00310
00311
00312
00313 for (i = 0 ; i < AiZoneNum ; i++)
00314 {
00315 AiNodeZone[i].Count = 0;
00316 AiNodeZone[i].FirstNode = NULL;
00317
00318 for (j = 0 ; j < AiNodeNum ; j++)
00319 {
00320 if (AiNode[j].ZoneID == i)
00321 {
00322 if (!AiNodeZone[i].Count)
00323 {
00324 AiNodeZone[i].FirstNode = &AiNode[j];
00325 AiNode[j].ZonePrev = NULL;
00326 }
00327 else
00328 {
00329 lastnode->ZoneNext = &AiNode[j];
00330 AiNode[j].ZonePrev = lastnode;
00331 }
00332
00333 AiNode[j].ZoneNext = NULL;
00334 AiNodeZone[i].Count++;
00335 lastnode = &AiNode[j];
00336 }
00337 }
00338 }
00339 }
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350 AINODE *AIN_NearestNode(PLAYER *Player, REAL *Dist)
00351 {
00352 AINODE *NearNode = NULL;
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366
00367
00368
00369
00370
00371
00372
00373
00374
00375
00376
00377
00378
00379
00380
00381
00382
00383
00384
00385
00386
00387
00388
00389
00390
00391
00392
00393
00394 return(NearNode);
00395 }
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405 AINODE *AIN_GetForwardNode(PLAYER *Player, REAL MinDist, REAL *Dist)
00406 {
00407 AINODE *NearNode;
00408
00409 REAL Nearest, NearestFwd;
00410 REAL dp;
00411 long RChoice;
00412 VEC Vec1, Vec2;
00413 VEC CarPos;
00414
00415 NearNode = AIN_NearestNode(Player, &Nearest);
00416 if (!NearNode) return (NULL);
00417 CarPos = Player->car.Body->Centre.Pos;
00418 RChoice = Player->CarAI.RouteChoice;
00419
00420 NearestFwd = -1;
00421
00422 while(NearestFwd < MinDist)
00423 {
00424 if (!NearNode->Next[RChoice])
00425 {
00426 *Dist = Nearest;
00427 return(NearNode);
00428 }
00429 Vec1.v[X] = NearNode->Centre.v[X] - CarPos.v[X];
00430 Vec1.v[Y] = NearNode->Centre.v[Y] - CarPos.v[Y];
00431 Vec1.v[Z] = NearNode->Centre.v[Z] - CarPos.v[Z];
00432 Vec2.v[X] = NearNode->Next[RChoice]->Centre.v[X] - NearNode->Centre.v[X];
00433 Vec2.v[Y] = NearNode->Next[RChoice]->Centre.v[Y] - NearNode->Centre.v[Y];
00434 Vec2.v[Z] = NearNode->Next[RChoice]->Centre.v[Z] - NearNode->Centre.v[Z];
00435
00436 dp = DotProduct(&Vec1, &Vec2);
00437 if (dp > 0.5)
00438 {
00439 Vec2.v[X] = NearNode->Next[RChoice]->Centre.v[X] - CarPos.v[X];
00440 Vec2.v[Y] = NearNode->Next[RChoice]->Centre.v[Y] - CarPos.v[Y];
00441 Vec2.v[Z] = NearNode->Next[RChoice]->Centre.v[Z] - CarPos.v[Z];
00442 NearestFwd = abs(VecLen(&Vec2));
00443 }
00444 NearNode = NearNode->Next[RChoice];
00445 }
00446 *Dist = NearestFwd;
00447 return(NearNode->Next[RChoice]);
00448 }
00449
00450
00451
00452
00453 long AIN_PriChoice(PLAYER *Player)
00454 {
00455
00456
00457 return(1);
00458 }
00459
00460