00001
00002 #include "revolt.h"
00003 #include "editai.h"
00004 #include "model.h"
00005 #include "main.h"
00006 #include "camera.h"
00007 #include "input.h"
00008 #include "level.h"
00009 #include "draw.h"
00010 #include "text.h"
00011 #include "grid.h"
00012 #include "aizone.h"
00013 #include "timing.h"
00014
00015
00016
00017 static long CurrentEditAiNodeBro;
00018 static long EditAiStartNode;
00019 static REAL EditAiNodeTotalDist;
00020
00021 AINODE *CurrentEditAiNode = NULL;
00022 AINODE *LastEditAiNode = NULL;
00023 long EditAiNodeNum;
00024 AINODE *EditAiNode;
00025 MODEL EditAiNodeModel[2];
00026
00028
00030
00031 void InitEditAiNodes(void)
00032 {
00033 EditAiNode = (AINODE*)malloc(sizeof(AINODE) * MAX_AINODES);
00034 if (!EditAiNode)
00035 {
00036 Box(NULL, "Can't alloc memory for edit AI nodes!", MB_OK);
00037 QuitGame = TRUE;
00038 }
00039 }
00040
00042
00044
00045 void KillEditAiNodes(void)
00046 {
00047 free(EditAiNode);
00048 }
00049
00051
00053
00054 void LoadEditAiNodes(char *file)
00055 {
00056 long i, j;
00057 FILE *fp;
00058 FILE_AINODE fan;
00059
00060
00061
00062 fp = fopen(file, "rb");
00063
00064
00065
00066 if (!fp)
00067 {
00068 fp = fopen(file, "wb");
00069 if (!fp) return;
00070 i = 0;
00071 fwrite(&i, sizeof(i), 1, fp);
00072 fclose(fp);
00073 fp = fopen(file, "rb");
00074 if (!fp) return;
00075 }
00076
00077
00078
00079 fread(&EditAiNodeNum, sizeof(EditAiNodeNum), 1, fp);
00080
00081 for (i = 0 ; i < EditAiNodeNum ; i++)
00082 {
00083
00084
00085
00086 fread(&fan, sizeof(fan), 1, fp);
00087
00088 VecMulScalar(&fan.Node[0].Pos, EditScale);
00089 VecMulScalar(&fan.Node[1].Pos, EditScale);
00090
00091
00092
00093 EditAiNode[i].Node[0] = fan.Node[0];
00094 EditAiNode[i].Node[1] = fan.Node[1];
00095
00096 EditAiNode[i].Priority = fan.Priority;
00097 EditAiNode[i].StartNode = fan.StartNode;
00098 EditAiNode[i].RacingLine = fan.RacingLine;
00099 EditAiNode[i].RacingLineSpeed = fan.RacingLineSpeed;
00100 EditAiNode[i].CentreSpeed = fan.CentreSpeed;
00101 EditAiNode[i].FinishDist = fan.FinishDist;
00102
00103 for (j = 0 ; j < MAX_AINODE_LINKS ; j++)
00104 {
00105 if (fan.Prev[j] != -1)
00106 EditAiNode[i].Prev[j] = EditAiNode + fan.Prev[j];
00107 else
00108 EditAiNode[i].Prev[j] = NULL;
00109
00110 if (fan.Next[j] != -1)
00111 EditAiNode[i].Next[j] = EditAiNode + fan.Next[j];
00112 else
00113 EditAiNode[i].Next[j] = NULL;
00114 }
00115 }
00116
00117
00118
00119 fread(&EditAiStartNode, sizeof(EditAiStartNode), 1, fp);
00120
00121
00122
00123 fread(&EditAiNodeTotalDist, sizeof(EditAiNodeTotalDist), 1, fp);
00124
00125
00126
00127 fclose(fp);
00128 }
00129
00131
00133
00134 void CalcEditAiNodeDistances(void)
00135 {
00136 long i, j, k, flag;
00137 VEC centre, vec;
00138 AIZONE *zone;
00139 REAL dist, ndist;
00140
00141
00142
00143 if (!AiZones)
00144 {
00145 EditAiStartNode = 0;
00146 }
00147 else
00148 {
00149 ndist = 1000000.0f;
00150 for (i = 0 ; i < EditAiNodeNum ; i++)
00151 {
00152
00153
00154
00155 AddVector(&EditAiNode[i].Node[0].Pos, &EditAiNode[i].Node[1].Pos, ¢re);
00156 VecMulScalar(¢re, 0.5f);
00157
00158
00159
00160 zone = AiZoneHeaders[0].Zones;
00161 for (j = 0 ; j < AiZoneHeaders[0].Count ; j++, zone++)
00162 {
00163 flag = FALSE;
00164 for (k = 0 ; k < 3 ; k++)
00165 {
00166 dist = PlaneDist(&zone->Plane[k], ¢re);
00167 if (dist < -zone->Size[k] || dist > zone->Size[k])
00168 {
00169 flag = TRUE;
00170 break;
00171 }
00172 }
00173 }
00174
00175
00176
00177 if (!flag)
00178 {
00179 SubVector(&LEV_StartPos, ¢re, &vec);
00180 dist = Length(&vec);
00181 if (dist < ndist)
00182 {
00183
00184
00185
00186 ndist = dist;
00187 EditAiStartNode = i;
00188 }
00189 }
00190 }
00191 }
00192
00193
00194
00195
00196 EditAiNodeTotalDist = 0.0f;
00197
00198 for (i = 0 ; i < EditAiNodeNum ; i++)
00199 {
00200 EditAiNode[i].FinishDist = 0.0f;
00201 }
00202
00203 EditAiNode[EditAiStartNode].FinishDist = 0.0f;
00204 CalcOneNodeDistance(&EditAiNode[EditAiStartNode], FALSE);
00205 }
00206
00208
00210
00211 void CalcOneNodeDistance(AINODE *node, long flag)
00212 {
00213 long i;
00214 VEC centre, vec;
00215 REAL dist;
00216
00217
00218
00219
00220
00221
00222
00223
00224 AddVector(&node->Node[0].Pos, &node->Node[1].Pos, ¢re)
00225 VecMulScalar(¢re, 0.5f);
00226
00227
00228
00229 for (i = 0 ; i < MAX_AINODE_LINKS ; i++) if (node->Prev[i])
00230 {
00231
00232
00233
00234 AddVector(&node->Prev[i]->Node[0].Pos, &node->Prev[i]->Node[1].Pos, &vec)
00235 VecMulScalar(&vec, 0.5f);
00236
00237 SubVector(&vec, ¢re, &vec);
00238 dist = Length(&vec) + node->FinishDist;
00239
00240
00241
00242 if (node->Prev[i] == &EditAiNode[EditAiStartNode])
00243 {
00244 EditAiNodeTotalDist = dist;
00245 continue;
00246 }
00247
00248
00249
00250 if (dist > node->Prev[i]->FinishDist && node->Prev[i]->FinishDist)
00251 {
00252 continue;
00253 }
00254
00255
00256
00257 node->Prev[i]->FinishDist = dist;
00258 CalcOneNodeDistance(node->Prev[i], TRUE);
00259 }
00260 }
00261
00263
00265
00266 void SaveEditAiNodes(char *file)
00267 {
00268 long i, j;
00269 FILE *fp;
00270 FILE_AINODE fan;
00271 char bak[256];
00272
00273
00274
00275 memcpy(bak, file, strlen(file) - 3);
00276 wsprintf(bak + strlen(file) - 3, "fa-");
00277 remove(bak);
00278 rename(file, bak);
00279
00280
00281
00282 fp = fopen(file, "wb");
00283 if (!fp) return;
00284
00285
00286
00287 fwrite(&EditAiNodeNum, sizeof(EditAiNodeNum), 1, fp);
00288
00289
00290
00291 for (i = 0 ; i < EditAiNodeNum ; i++)
00292 {
00293
00294
00295
00296 fan.Node[0] = EditAiNode[i].Node[0];
00297 fan.Node[1] = EditAiNode[i].Node[1];
00298
00299 fan.Priority = EditAiNode[i].Priority;
00300 fan.StartNode = EditAiNode[i].StartNode;
00301 fan.RacingLine = EditAiNode[i].RacingLine;
00302 fan.RacingLineSpeed = EditAiNode[i].RacingLineSpeed;
00303 fan.CentreSpeed = EditAiNode[i].CentreSpeed;
00304 fan.FinishDist = EditAiNode[i].FinishDist;
00305
00306 for (j = 0 ; j < MAX_AINODE_LINKS ; j++)
00307 {
00308 if (EditAiNode[i].Prev[j])
00309 fan.Prev[j] = (long)(EditAiNode[i].Prev[j] - EditAiNode);
00310 else
00311 fan.Prev[j] = -1;
00312
00313 if (EditAiNode[i].Next[j])
00314 fan.Next[j] = (long)(EditAiNode[i].Next[j] - EditAiNode);
00315 else
00316 fan.Next[j] = -1;
00317 }
00318
00319
00320
00321 fwrite(&fan, sizeof(fan), 1, fp);
00322 }
00323
00324
00325
00326 fwrite(&EditAiStartNode, sizeof(EditAiStartNode), 1, fp);
00327
00328
00329
00330 fwrite(&EditAiNodeTotalDist, sizeof(EditAiNodeTotalDist), 1, fp);
00331
00332
00333
00334 fclose(fp);
00335 Box("Saved AI node File:", file, MB_OK);
00336 }
00337
00339
00341
00342 void LoadEditAiNodeModels(void)
00343 {
00344 LoadModel("edit\\ainode2.m", &EditAiNodeModel[0], -1, 1, LOADMODEL_FORCE_TPAGE, 100);
00345 LoadModel("edit\\ainode1.m", &EditAiNodeModel[1], -1, 1, LOADMODEL_FORCE_TPAGE, 100);
00346 }
00347
00349
00351
00352 void FreeEditAiNodeModels(void)
00353 {
00354 FreeModel(&EditAiNodeModel[0], 1);
00355 FreeModel(&EditAiNodeModel[1], 1);
00356 }
00357
00359
00361
00362 AINODE *AllocEditAiNode(void)
00363 {
00364
00365
00366
00367 if (EditAiNodeNum >= MAX_AINODES)
00368 return NULL;
00369
00370
00371
00372 return &EditAiNode[EditAiNodeNum++];
00373 }
00374
00376
00378
00379 void FreeEditAiNode(AINODE *node)
00380 {
00381 long idx, i, j;
00382
00383
00384
00385 for (i = 0 ; i < EditAiNodeNum ; i++)
00386 {
00387 for (j = 0 ; j < MAX_AINODE_LINKS ; j++)
00388 {
00389 if (EditAiNode[i].Prev[j] == node) EditAiNode[i].Prev[j] = NULL;
00390 if (EditAiNode[i].Next[j] == node) EditAiNode[i].Next[j] = NULL;
00391 }
00392 }
00393
00394
00395
00396 idx = (long)(node - EditAiNode);
00397
00398
00399
00400 for (i = idx ; i < EditAiNodeNum - 1; i++)
00401 {
00402 EditAiNode[i] = EditAiNode[i + 1];
00403 }
00404
00405
00406
00407 EditAiNodeNum--;
00408
00409
00410
00411 for (i = 0 ; i < EditAiNodeNum ; i++)
00412 {
00413 for (j = 0 ; j < MAX_AINODE_LINKS ; j++)
00414 {
00415 if (EditAiNode[i].Prev[j] > node) EditAiNode[i].Prev[j]--;
00416 if (EditAiNode[i].Next[j] > node) EditAiNode[i].Next[j]--;
00417 }
00418 }
00419 }
00420
00422
00424
00425 void EditAiNodes(void)
00426 {
00427 long i, j, nbro;
00428 AINODE *node, *nnode;
00429 VEC vec;
00430 MAT mat, mat2;
00431 ONE_AINODE tempnode;
00432 float rad, z, sx, sy;
00433
00434
00435
00436 if (CAM_MainCamera->Type != CAM_EDIT)
00437 {
00438 CurrentEditAiNode = NULL;
00439 return;
00440 }
00441
00442
00443
00444 if (MouseRight)
00445 {
00446 RotMatrixZYX(&mat, (float)-Mouse.lY / 3072, -(float)Mouse.lX / 3072, 0);
00447 MulMatrix(&CAM_MainCamera->WMatrix, &mat, &mat2);
00448 CopyMatrix(&mat2, &CAM_MainCamera->WMatrix);
00449
00450 CAM_MainCamera->WMatrix.m[RY] = 0;
00451 NormalizeVector(&CAM_MainCamera->WMatrix.mv[X]);
00452 CrossProduct(&CAM_MainCamera->WMatrix.mv[Z], &CAM_MainCamera->WMatrix.mv[X], &CAM_MainCamera->WMatrix.mv[Y]);
00453 NormalizeVector(&CAM_MainCamera->WMatrix.mv[Y]);
00454 CrossProduct(&CAM_MainCamera->WMatrix.mv[X], &CAM_MainCamera->WMatrix.mv[Y], &CAM_MainCamera->WMatrix.mv[Z]);
00455 }
00456
00457
00458
00459 if (Keys[DIK_T] && !LastKeys[DIK_T])
00460 {
00461 if (Keys[DIK_LSHIFT])
00462 {
00463 for (i = 0 ; i < EditAiNodeNum ; i++)
00464 {
00465 tempnode = EditAiNode[i].Node[0];
00466 EditAiNode[i].Node[0] = EditAiNode[i].Node[1];
00467 EditAiNode[i].Node[1] = tempnode;
00468
00469 EditAiNode[i].RacingLine = 1 - EditAiNode[i].RacingLine;
00470 }
00471 }
00472 else if (CurrentEditAiNode)
00473 {
00474 tempnode = CurrentEditAiNode->Node[0];
00475 CurrentEditAiNode->Node[0] = CurrentEditAiNode->Node[1];
00476 CurrentEditAiNode->Node[1] = tempnode;
00477
00478 CurrentEditAiNode->RacingLine = 1 - CurrentEditAiNode->RacingLine;
00479 }
00480 }
00481
00482
00483
00484 if (Keys[DIK_R] && !LastKeys[DIK_R] && Keys[DIK_LSHIFT])
00485 {
00486 for (i = 0 ; i < EditAiNodeNum ; i++)
00487 {
00488 for (j = 0 ; j < MAX_AINODE_LINKS ; j++)
00489 {
00490 node = EditAiNode[i].Prev[j];
00491 EditAiNode[i].Prev[j] = EditAiNode[i].Next[j];
00492 EditAiNode[i].Next[j] = node;
00493 }
00494 }
00495 }
00496
00497
00498
00499 if (Keys[DIK_LCONTROL] && Keys[DIK_F4] && !LastKeys[DIK_F4])
00500 {
00501 CalcEditAiNodeDistances();
00502 SaveEditAiNodes(GetLevelFilename("fan", FILENAME_MAKE_BODY | FILENAME_GAME_SETTINGS));
00503 }
00504
00505
00506
00507 if ((Keys[DIK_RETURN] && !LastKeys[DIK_RETURN]) || (Keys[DIK_BACKSPACE] && !LastKeys[DIK_BACKSPACE]) || (Keys[DIK_SPACE] && !LastKeys[DIK_SPACE]))
00508 {
00509 nnode = NULL;
00510 z = RenderSettings.FarClip;
00511
00512 node = EditAiNode;
00513 for (i = 0 ; i < EditAiNodeNum ; i++, node++)
00514 {
00515 for (j = 0 ; j < 2 ; j++)
00516 {
00517 RotTransVector(&ViewMatrix, &ViewTrans, &node->Node[j].Pos, &vec);
00518
00519 if (vec.v[Z] < RenderSettings.NearClip || vec.v[Z] >= RenderSettings.FarClip) continue;
00520
00521 sx = vec.v[X] * RenderSettings.GeomPers / vec.v[Z] + REAL_SCREEN_XHALF;
00522 sy = vec.v[Y] * RenderSettings.GeomPers / vec.v[Z] + REAL_SCREEN_YHALF;
00523
00524 rad = 24 * RenderSettings.GeomPers / vec.v[Z];
00525
00526 if (MouseXpos > sx - rad && MouseXpos < sx + rad && MouseYpos > sy - rad && MouseYpos < sy + rad)
00527 {
00528 if (vec.v[Z] < z)
00529 {
00530 nnode = node;
00531 z = vec.v[Z];
00532 nbro = j;
00533 }
00534 }
00535 }
00536 }
00537 if (nnode)
00538 {
00539 if (Keys[DIK_SPACE])
00540 {
00541 LastEditAiNode = CurrentEditAiNode;
00542 CurrentEditAiNode = nnode;
00543 CurrentEditAiNodeBro = nbro;
00544
00545 Keys[DIK_NUMPADPLUS] = TRUE;
00546 LastKeys[DIK_NUMPADPLUS] = FALSE;
00547 }
00548 else if (Keys[DIK_BACKSPACE])
00549 {
00550 LastEditAiNode = nnode;
00551 return;
00552 }
00553 else
00554 {
00555 CurrentEditAiNode = nnode;
00556 CurrentEditAiNodeBro = nbro;
00557 return;
00558 }
00559 }
00560 }
00561
00562
00563
00564 if (Keys[DIK_INSERT] && !LastKeys[DIK_INSERT])
00565 {
00566 if ((node = AllocEditAiNode()))
00567 {
00568 GetEditNodePos(&CAM_MainCamera->WPos, MouseXpos, MouseYpos, &node->Node[1].Pos);
00569
00570 node->Node[0].Pos.v[X] = node->Node[1].Pos.v[X];
00571 node->Node[0].Pos.v[Y] = node->Node[1].Pos.v[Y] - 64;
00572 node->Node[0].Pos.v[Z] = node->Node[1].Pos.v[Z];
00573
00574 node->Node[0].Speed = 30;
00575 node->Node[1].Speed = 30;
00576
00577 node->Priority = 0;
00578 node->RacingLine = 0.5f;
00579 node->RacingLineSpeed = 30;
00580 node->CentreSpeed = 30;
00581
00582 CurrentEditAiNode = node;
00583 CurrentEditAiNodeBro = 1;
00584 }
00585 }
00586
00587
00588
00589 if (!CurrentEditAiNode) return;
00590
00591
00592
00593 if (Keys[DIK_RETURN] && !LastKeys[DIK_RETURN])
00594 {
00595 CurrentEditAiNode = NULL;
00596 return;
00597 }
00598
00599
00600
00601 if (Keys[DIK_DELETE] && !LastKeys[DIK_DELETE])
00602 {
00603 FreeEditAiNode(CurrentEditAiNode);
00604 CurrentEditAiNode = NULL;
00605 return;
00606 }
00607
00608
00609
00610 if (Keys[DIK_LSHIFT])
00611 LastKeys[DIK_1] = LastKeys[DIK_2] = LastKeys[DIK_3] = LastKeys[DIK_4] = LastKeys[DIK_5] = LastKeys[DIK_6] = LastKeys[DIK_7] = LastKeys[DIK_8] = 0;
00612
00613 if (Keys[DIK_1] && !LastKeys[DIK_1] && CurrentEditAiNode->Node[0].Speed) CurrentEditAiNode->Node[0].Speed--;
00614 if (Keys[DIK_2] && !LastKeys[DIK_2] && CurrentEditAiNode->Node[0].Speed < 100) CurrentEditAiNode->Node[0].Speed++;
00615
00616 if (Keys[DIK_3] && !LastKeys[DIK_3] && CurrentEditAiNode->Node[1].Speed) CurrentEditAiNode->Node[1].Speed--;
00617 if (Keys[DIK_4] && !LastKeys[DIK_4] && CurrentEditAiNode->Node[1].Speed < 100) CurrentEditAiNode->Node[1].Speed++;
00618
00619 if (Keys[DIK_5] && !LastKeys[DIK_5] && CurrentEditAiNode->RacingLineSpeed) CurrentEditAiNode->RacingLineSpeed--;
00620 if (Keys[DIK_6] && !LastKeys[DIK_6] && CurrentEditAiNode->RacingLineSpeed < 100) CurrentEditAiNode->RacingLineSpeed++;
00621
00622 if (Keys[DIK_7] && !LastKeys[DIK_7] && CurrentEditAiNode->CentreSpeed) CurrentEditAiNode->CentreSpeed--;
00623 if (Keys[DIK_8] && !LastKeys[DIK_8] && CurrentEditAiNode->CentreSpeed < 100) CurrentEditAiNode->CentreSpeed++;
00624
00625
00626
00627 if (Keys[DIK_NUMPADENTER] && !LastKeys[DIK_NUMPADENTER]) CurrentEditAiNode->Priority ^= TRUE;
00628
00629
00630
00631 if (Keys[DIK_NUMPAD0] && !LastKeys[DIK_NUMPAD0])
00632 {
00633 for (i = 0 ; i < EditAiNodeNum ; i++)
00634 EditAiNode[i].StartNode = FALSE;
00635
00636 CurrentEditAiNode->StartNode = TRUE;
00637 }
00638
00639
00640
00641 if (Keys[DIK_NUMPADSLASH] && CurrentEditAiNode->RacingLine > 0.0f) CurrentEditAiNode->RacingLine -= 0.002f;
00642 if (Keys[DIK_NUMPADSTAR] && CurrentEditAiNode->RacingLine < 1.0f) CurrentEditAiNode->RacingLine += 0.002f;
00643
00644
00645
00646 if (Keys[DIK_NUMPADPLUS] && !LastKeys[DIK_NUMPADPLUS] && LastEditAiNode && CurrentEditAiNode != LastEditAiNode)
00647 {
00648 for (i = j = 0 ; i < MAX_AINODE_LINKS ; i++) if (CurrentEditAiNode->Prev[i] == LastEditAiNode || CurrentEditAiNode->Next[i] == LastEditAiNode) j++;
00649
00650 if (!j) for (i = 0 ; i < MAX_AINODE_LINKS ; i++) if (!CurrentEditAiNode->Prev[i])
00651 {
00652 for (j = 0 ; j < MAX_AINODE_LINKS ; j++) if (!LastEditAiNode->Next[j])
00653 {
00654 CurrentEditAiNode->Prev[i] = LastEditAiNode;
00655 LastEditAiNode->Next[j] = CurrentEditAiNode;
00656 break;
00657 }
00658 break;
00659 }
00660 }
00661
00662
00663
00664 if (Keys[DIK_NUMPADMINUS] && !LastKeys[DIK_NUMPADMINUS] && LastEditAiNode && CurrentEditAiNode != LastEditAiNode)
00665 {
00666 for (i = 0 ; i < MAX_AINODE_LINKS ; i++) if (CurrentEditAiNode->Prev[i] == LastEditAiNode)
00667 {
00668 for (j = 0 ; j < MAX_AINODE_LINKS ; j++) if (LastEditAiNode->Next[j] == CurrentEditAiNode)
00669 {
00670 CurrentEditAiNode->Prev[i] = NULL;
00671 LastEditAiNode->Next[j] = NULL;
00672 break;
00673 }
00674 break;
00675 }
00676 }
00677
00678
00679
00680 if (MouseLeft)
00681 {
00682 GetEditNodePos(&CAM_MainCamera->WPos, MouseXpos, MouseYpos, &CurrentEditAiNode->Node[CurrentEditAiNodeBro].Pos);
00683 }
00684 }
00685
00687
00689
00690 void DrawAiNodes(void)
00691 {
00692 long i, j, k;
00693 ONE_AINODE *node;
00694 VEC v1, v2;
00695 char buf[128];
00696 short flag;
00697
00698
00699
00700 for (i = 0 ; i < EditAiNodeNum ; i++)
00701 {
00702 for (j = 0 ; j < 2 ; j++)
00703 {
00704 node = &EditAiNode[i].Node[j];
00705
00706
00707
00708 flag = MODEL_PLAIN;
00709 if (i == EditAiStartNode)
00710 {
00711 flag |= MODEL_SCALE;
00712 ModelScale = (float)sin((float)TIME2MS(CurrentTimer()) / 300.0f) * 0.5f + 1.0f;
00713 }
00714
00715 if (LastEditAiNode != &EditAiNode[i] || (FrameCount & 4))
00716 {
00717 DrawModel(&EditAiNodeModel[j], &IdentityMatrix, &node->Pos, flag);
00718 }
00719
00720
00721
00722 for (k = 0 ; k < MAX_AINODE_LINKS ; k++) if (EditAiNode[i].Next[k])
00723 {
00724 v1.v[X] = EditAiNode[i].Node[j].Pos.v[X];
00725 v1.v[Y] = EditAiNode[i].Node[j].Pos.v[Y];
00726 v1.v[Z] = EditAiNode[i].Node[j].Pos.v[Z];
00727
00728 v2.v[X] = EditAiNode[i].Next[k]->Node[j].Pos.v[X];
00729 v2.v[Y] = EditAiNode[i].Next[k]->Node[j].Pos.v[Y];
00730 v2.v[Z] = EditAiNode[i].Next[k]->Node[j].Pos.v[Z];
00731
00732 if (!j)
00733 {
00734 DrawLine(&v1, &v2, 0x000000, 0xff0000);
00735 }
00736 else
00737 {
00738 DrawLine(&v1, &v2, 0x000000, 0x00ff00);
00739 }
00740 }
00741
00742
00743
00744 if (CurrentEditAiNode == &EditAiNode[i] && CurrentEditAiNodeBro == j)
00745 {
00746 DrawAxis(&IdentityMatrix, &node->Pos);
00747 }
00748 }
00749
00750
00751
00752 for (j = 0 ; j < MAX_AINODE_LINKS ; j++) if (EditAiNode[i].Next[j])
00753 {
00754 v1.v[X] = (EditAiNode[i].Node[0].Pos.v[X] * EditAiNode[i].RacingLine) + (EditAiNode[i].Node[1].Pos.v[X] * (1 - EditAiNode[i].RacingLine));
00755 v1.v[Y] = (EditAiNode[i].Node[0].Pos.v[Y] * EditAiNode[i].RacingLine) + (EditAiNode[i].Node[1].Pos.v[Y] * (1 - EditAiNode[i].RacingLine));
00756 v1.v[Z] = (EditAiNode[i].Node[0].Pos.v[Z] * EditAiNode[i].RacingLine) + (EditAiNode[i].Node[1].Pos.v[Z] * (1 - EditAiNode[i].RacingLine));
00757
00758 v2.v[X] = (EditAiNode[i].Next[j]->Node[0].Pos.v[X] * EditAiNode[i].Next[j]->RacingLine) + (EditAiNode[i].Next[j]->Node[1].Pos.v[X] * (1 - EditAiNode[i].Next[j]->RacingLine));
00759 v2.v[Y] = (EditAiNode[i].Next[j]->Node[0].Pos.v[Y] * EditAiNode[i].Next[j]->RacingLine) + (EditAiNode[i].Next[j]->Node[1].Pos.v[Y] * (1 - EditAiNode[i].Next[j]->RacingLine));
00760 v2.v[Z] = (EditAiNode[i].Next[j]->Node[0].Pos.v[Z] * EditAiNode[i].Next[j]->RacingLine) + (EditAiNode[i].Next[j]->Node[1].Pos.v[Z] * (1 - EditAiNode[i].Next[j]->RacingLine));
00761
00762 DrawLine(&v1, &v2, 0xffffff, 0xffffff);
00763 }
00764
00765
00766
00767 SET_TPAGE(TPAGE_FONT);
00768 wsprintf(buf, "%ld", (long)EditAiNode[i].FinishDist);
00769 RotTransVector(&ViewMatrix, &ViewTrans, &v1, &v2);
00770 v2.v[X] -= 48.0f;
00771 v2.v[Y] -= 32.0f;
00772 DumpText3D(&v2, 16, 32, 0xffffffff, buf);
00773
00774
00775
00776 DrawLine(&EditAiNode[i].Node[0].Pos, &EditAiNode[i].Node[1].Pos, 0xffff00, 0xffff00);
00777 }
00778 }
00779
00781
00783
00784 void DisplayAiNodeInfo(AINODE *node)
00785 {
00786 char buf[128];
00787
00788
00789
00790 wsprintf(buf, "Priority: %s", node->Priority ? "Yes" : "No");
00791 DumpText(450, 0, 8, 16, 0xffffff, buf);
00792
00793
00794
00795 wsprintf(buf, "Start Node: %s", node->StartNode ? "Yes" : "No");
00796 DumpText(450, 24, 8, 16, 0x00ffff, buf);
00797
00798
00799
00800 wsprintf(buf, "Green Speed: %d", node->Node[0].Speed);
00801 DumpText(450, 48, 8, 16, 0x00ff00, buf);
00802
00803 wsprintf(buf, "Red Speed: %d", node->Node[1].Speed);
00804 DumpText(450, 72, 8, 16, 0xff0000, buf);
00805
00806 wsprintf(buf, "Racing Speed: %d", node->RacingLineSpeed);
00807 DumpText(450, 96, 8, 16, 0x0000ff, buf);
00808
00809 wsprintf(buf, "Centre Speed: %d", node->CentreSpeed);
00810 DumpText(450, 120, 8, 16, 0xffff00, buf);
00811
00812
00813
00814 wsprintf(buf, "Track dist: %d", (long)EditAiNodeTotalDist);
00815 DumpText(450, 152, 8, 16, 0xff00ff, buf);
00816 }
00817
00819
00821
00822 void GetEditNodePos(VEC *campos, float xpos, float ypos, VEC *nodepos)
00823 {
00824 long i;
00825 NEWCOLLPOLY *poly;
00826 VEC vec, offset, dest;
00827 float time, depth, ntime;
00828
00829
00830
00831 vec.v[X] = xpos - REAL_SCREEN_XHALF;
00832 vec.v[Y] = ypos - REAL_SCREEN_YHALF;
00833 vec.v[Z] = RenderSettings.GeomPers;
00834
00835 RotVector(&CAM_MainCamera->WMatrix, &vec, &offset);
00836 NormalizeVector(&offset);
00837 offset.v[X] *= RenderSettings.FarClip;
00838 offset.v[Y] *= RenderSettings.FarClip;
00839 offset.v[Z] *= RenderSettings.FarClip;
00840
00841 AddVector(&offset, &CAM_MainCamera->WPos, &dest);
00842 DrawLine(campos, &dest, 0xffff00, 0xffff00);
00843
00844
00845
00846 ntime = 1.0f;
00847
00848 poly = COL_WorldCollPoly;
00849 for (i = 0 ; i < COL_NWorldCollPolys ; i++, poly++)
00850 {
00851 if (LinePlaneIntersect(campos, &dest, &poly->Plane, &time, &depth))
00852 {
00853 if (PlaneDist(&poly->Plane, &CAM_MainCamera->WPos) > 0)
00854 {
00855 if (time > 0 && time < ntime)
00856 {
00857 vec.v[X] = campos->v[X] + offset.v[X] * time;
00858 vec.v[Y] = campos->v[Y] + offset.v[Y] * time;
00859 vec.v[Z] = campos->v[Z] + offset.v[Z] * time;
00860
00861 if (PointInCollPolyBounds(&vec, poly))
00862 {
00863 CopyVec(&vec, nodepos);
00864 ntime = time;
00865 }
00866 }
00867 }
00868 }
00869 }
00870
00871 poly = COL_InstanceCollPoly;
00872 for (i = 0 ; i < COL_NInstanceCollPolys ; i++, poly++)
00873 {
00874 if (LinePlaneIntersect(campos, &dest, &poly->Plane, &time, &depth))
00875 {
00876 if (PlaneDist(&poly->Plane, &CAM_MainCamera->WPos) > 0)
00877 {
00878 if (time > 0 && time < ntime)
00879 {
00880 vec.v[X] = campos->v[X] + offset.v[X] * time;
00881 vec.v[Y] = campos->v[Y] + offset.v[Y] * time;
00882 vec.v[Z] = campos->v[Z] + offset.v[Z] * time;
00883
00884 if (PointInCollPolyBounds(&vec, poly))
00885 {
00886 CopyVec(&vec, nodepos);
00887 ntime = time;
00888 }
00889 }
00890 }
00891 }
00892 }
00893
00894
00895
00896 if (ntime == 1.0f)
00897 {
00898 SetVector(&vec, 0, 0, RenderSettings.GeomPers);
00899 RotTransVector(&CAM_MainCamera->WMatrix, &CAM_MainCamera->WPos, &vec, nodepos);
00900 }
00901 }