00001
00002
00003
00004 #define WIN32_LEAN_AND_MEAN
00005 #include <windows.h>
00006
00007 #include <math.h>
00008 #include <stdlib.h>
00009 #include <assert.h>
00010
00011 #include "GMain.h"
00012
00013 #include "_bot.h"
00014 #include "track.h"
00015 #include "bit.h"
00016
00017 static geBoolean Track_LinkTest(geWorld *World, TrackPt *tp, TrackPt *tp2);
00018 static geBoolean Track_LinkTrack(geWorld *World, Track* t, Track *t2);
00019 static geBoolean Track_FakeTrack(geWorld *World, geVec3d *Pos);
00020 static Track* Track_FindCloseTrack(GenVSI *VSI, geVec3d *StartPos, float ydiff);
00021
00022 geBoolean Bot_CanSeePointToPoint(const geWorld* World, const geVec3d *Pos1, const geVec3d *Pos2);
00023 float DistWeightedY(const geVec3d *Pos1, const geVec3d *Pos2, const float Scale);
00024
00025 #define TRACK_SEARCH_Y_RANGE 40.0f
00026 #define TOWARD_GOAL 1
00027 #define AWAY_FROM_GOAL -1
00028
00029 int32 TrackCount=0;
00030 Track TrackList[MAX_TRACKS+2];
00031
00032 #define MAX_NODES MAX_TRACKS+2
00033
00034 static int32 searchnode[MAX_NODES], searchparent[MAX_NODES];
00035 static uint8 bitarr[(MAX_NODES+7)>>3];
00036
00037
00038
00039
00040 geBoolean Track_OnTrack(TrackData *td)
00041 {
00042 return (td->TrackNdx >= 0);
00043 }
00044
00045
00046
00047
00048 Track* Track_GetNextTrack(Track *t)
00049 {
00050 int32 ndx;
00051
00052 if (!t)
00053 return(&TrackList[0]);
00054
00055 ndx = t - &TrackList[0];
00056 assert(ndx >= 0 && ndx < TrackCount);
00057 ndx++;
00058
00059 if (ndx >= TrackCount)
00060 return NULL;
00061
00062 return (&TrackList[ndx]);
00063 }
00064
00065
00066
00067
00068 void Track_ClearTrack(TrackData *td)
00069 {
00070 td->TrackNdx = -1;
00071 td->PointNdx = -1;
00072 }
00073
00074
00075
00076
00077 Track *Track_GetTrack(TrackData *td)
00078 {
00079 return &TrackList[td->TrackNdx];
00080 }
00081
00082
00083
00084
00085 int32 Track_GetDir(TrackData *td)
00086 {
00087 return td->TrackDir;
00088 }
00089
00090
00091
00092
00093 geBoolean Track_PastStartPoint(TrackData *td)
00094 {
00095 assert(td->TrackNdx > -1);
00096
00097 if (td->TrackDir == 1)
00098 {
00099 return (td->PointNdx > 0);
00100 }
00101 else
00102 if (td->TrackDir == -1)
00103 {
00104 return (td->PointNdx < TrackList[td->PointNdx].PointCount);
00105 }
00106
00107 assert(1==0);
00108 return GE_FALSE;
00109 }
00110
00111
00112
00113
00114 TrackPt *Track_NextPoint(TrackData *td)
00115 {
00116 assert(td->TrackNdx > -1);
00117
00118 td->PointNdx += td->TrackDir;
00119
00120 if (td->PointNdx >= TrackList[td->TrackNdx].PointCount)
00121 {
00122 if (TEST(TrackList[td->TrackNdx].Flags, TRACK_FLAG_LOOP))
00123 {
00124 td->PointNdx = 0;
00125 return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00126 }
00127
00128
00129 return(NULL);
00130 }
00131
00132 if (td->PointNdx < 0)
00133 {
00134 if (TEST(TrackList[td->TrackNdx].Flags, TRACK_FLAG_LOOP))
00135 {
00136 td->PointNdx = TrackList[td->TrackNdx].PointCount - 1;
00137 return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00138 }
00139
00140 td->PointNdx = 0;
00141 return(NULL);
00142 }
00143
00144 assert(td->PointNdx < TrackList[td->TrackNdx].PointCount);
00145
00146 return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00147 }
00148
00149
00150
00151
00152
00153 TrackPt *Track_PrevPoint(TrackData *td)
00154 {
00155 assert(td->TrackNdx > -1);
00156
00157 td->PointNdx -= td->TrackDir;
00158
00159 if (td->PointNdx >= TrackList[td->TrackNdx].PointCount)
00160 {
00161 if (TEST(TrackList[td->TrackNdx].Flags, TRACK_FLAG_LOOP))
00162 {
00163 td->PointNdx = 0;
00164 return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00165 }
00166
00167 return(NULL);
00168 }
00169
00170 if (td->PointNdx < 0)
00171 {
00172 if (TEST(TrackList[td->TrackNdx].Flags, TRACK_FLAG_LOOP))
00173 {
00174 td->PointNdx = TrackList[td->TrackNdx].PointCount - 1;
00175 return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00176 }
00177
00178 return(NULL);
00179 }
00180
00181 assert(td->PointNdx < TrackList[td->TrackNdx].PointCount);
00182
00183 return(&TrackList[td->TrackNdx].PointList[td->PointNdx]);
00184 }
00185
00186
00187
00188
00189
00190 TrackPt *Track_GetPoint(TrackData *td)
00191 {
00192 assert(td);
00193
00194 assert(Track_OnTrack(td));
00195
00196 if (td->PointNdx >= TrackList[td->TrackNdx].PointCount)
00197 td = td;
00198
00199 assert(td->PointNdx < TrackList[td->TrackNdx].PointCount);
00200
00201 return &TrackList[td->TrackNdx].PointList[td->PointNdx];
00202 }
00203
00204
00205
00206
00207 float Track_Length(Track* t)
00208 {
00209 TrackPt *tp;
00210 float dist=0.0f;
00211
00212 for (tp = t->PointList; tp < &t->PointList[t->PointCount-1]; tp++)
00213 {
00214 dist += geVec3d_DistanceBetween(tp->Pos, (tp+1)->Pos);
00215 }
00216
00217 return dist;
00218 }
00219
00220
00221
00222
00223 TrackPt* Track_GetEndPoint(TrackData *td)
00224 {
00225 Track *t = &TrackList[td->TrackNdx];
00226
00227 assert(td);
00228 assert(Track_OnTrack(td));
00229
00230 if (td->TrackDir == 1)
00231 return(&t->PointList[t->PointCount-1]);
00232 else
00233 return(&t->PointList[0]);
00234 }
00235
00236
00237
00238
00239 TrackPt* Track_GetFirstPoint(TrackData *td)
00240 {
00241 Track *t = &TrackList[td->TrackNdx];
00242
00243 assert(td);
00244 assert(Track_OnTrack(td));
00245
00246 if (td->TrackDir == -1)
00247 return(&t->PointList[t->PointCount-1]);
00248 else
00249 return(&t->PointList[0]);
00250 }
00251
00252
00253
00254
00255 static geBoolean Track_LinkTest(geWorld *World, TrackPt *tp, TrackPt *tp2)
00256 {
00257
00258 if (geVec3d_DistanceBetween(tp->Pos, tp2->Pos) > 1100)
00259 return GE_FALSE;
00260
00261 if (fabs(tp->Pos->Y - tp2->Pos->Y) > TRACK_SEARCH_Y_RANGE * 2)
00262 return GE_FALSE;
00263
00264 if (Bot_CanSeePointToPoint(World, tp->Pos, tp2->Pos))
00265 return GE_TRUE;
00266
00267 return GE_FALSE;
00268 }
00269
00270
00271
00272
00273 int32 Track_LinkSet(Track *t, Track *t2)
00274 {
00275 int32 i=0;
00276
00277 for (i = 0; i < MAX_TRACK_VIS; i++)
00278 {
00279 if (t->Vis[i] == t2)
00280 break;
00281
00282
00283 if (!t->Vis[i])
00284 {
00285 t->Vis[i] = t2;
00286 return i;
00287 }
00288 }
00289
00290 assert (i < MAX_TRACK_VIS);
00291
00292 return -1;
00293 }
00294
00295
00296
00297
00298 geBoolean Track_LinkExists(Track *t, Track *t2)
00299 {
00300 int32 i;
00301
00302 for (i = 0; i < MAX_TRACK_VIS; i++)
00303 {
00304 if (t->Vis[i] == t2)
00305 return GE_TRUE;
00306 }
00307
00308 return(GE_FALSE);
00309 }
00310
00311
00312
00313
00314
00315 geBoolean Track_IsOneWay(Track *t)
00316 {
00317 switch (t->Type)
00318 {
00319
00320 case TRACK_TYPE_ELEVATOR_UP:
00321 case TRACK_TYPE_ELEVATOR_DOWN:
00322 case TRACK_TYPE_UP:
00323 case TRACK_TYPE_DOWN:
00324 case TRACK_TYPE_SCAN:
00325 case TRACK_TYPE_TRAVERSE_ONEWAY:
00326 {
00327 return GE_TRUE;
00328 }
00329 }
00330
00331 return GE_FALSE;
00332 }
00333
00334
00335
00336
00337
00338
00339
00340
00341
00342
00343
00344
00345
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360
00361
00362
00363
00364
00365
00366 static geBoolean Track_LinkTrack(geWorld *World, Track* t, Track *t2)
00367 {
00368 TrackPt *tp, *tp2;
00369 geBoolean OneWay, OneWay2;
00370 geBoolean a=GE_FALSE,b=GE_FALSE,c=GE_FALSE,d=GE_FALSE;
00371 int32 *VisFlag, *VisFlag2, i;
00372
00373 int32 ep, ep2;
00374 geBoolean OnePoint = GE_FALSE, OnePoint2 = GE_FALSE;
00375 float e2e, s2s, e2s, s2e;
00376
00377 if (t == t2)
00378 return GE_FALSE;
00379
00380 OneWay = Track_IsOneWay(t);
00381 OneWay2 = Track_IsOneWay(t2);
00382
00383 tp = t->PointList;
00384 ep = t->PointCount - 1;
00385 tp2 = t2->PointList;
00386 ep2 = t2->PointCount - 1;
00387
00388 VisFlag = &t->VisFlag[0];
00389 VisFlag2 = &t2->VisFlag[0];
00390
00391 if (ep == 0) OnePoint = GE_TRUE;
00392 if (ep2 == 0) OnePoint2 = GE_TRUE;
00393
00394 if (OnePoint && OnePoint2)
00395 {
00396
00397 if (!Track_LinkExists(t, t2) &&
00398 Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00399 {
00400 if ((i = Track_LinkSet(t, t2)) > -1)
00401 VisFlag[i] |= 1;
00402 return GE_TRUE;
00403 }
00404 }
00405 else
00406 if (OnePoint)
00407 {
00408 if (OneWay2)
00409 {
00410
00411 s2s = DistWeightedY(t->PointList[0].Pos, t2->PointList[0].Pos, 2.0f);
00412 s2e = DistWeightedY(t->PointList[0].Pos, t2->PointList[ep2].Pos, 2.0f);
00413
00414 if (s2s < s2e)
00415 {
00416 if (!Track_LinkExists(t, t2) &&
00417 Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00418 {
00419 if ((i = Track_LinkSet(t, t2)) > -1)
00420 VisFlag[i] |= 1;
00421 return GE_TRUE;
00422 }
00423 }
00424 else
00425 if (!Track_LinkExists(t2, t) &&
00426 Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2]))
00427 {
00428 if ((i = Track_LinkSet(t2, t)) > -1)
00429 VisFlag2[i] |= 2;
00430 return GE_TRUE;
00431 }
00432 }
00433 else
00434 {
00435
00436 if (!Track_LinkExists(t, t2) &&
00437 (a = Track_LinkTest(World, &t->PointList[0], &t2->PointList[0])) ||
00438 (b = Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2])))
00439 {
00440 if ((i = Track_LinkSet(t, t2)) > -1)
00441 VisFlag[i] |= 1;
00442 if ((i = Track_LinkSet(t2, t)) > -1)
00443 VisFlag2[i] |= 2;
00444 return GE_TRUE;
00445 }
00446 }
00447 }
00448 else
00449 if (OnePoint2)
00450 {
00451 if (OneWay)
00452 {
00453
00454 s2s = DistWeightedY(t->PointList[0].Pos, t2->PointList[0].Pos, 2.0f);
00455 e2s = DistWeightedY(t->PointList[ep].Pos, t2->PointList[0].Pos, 2.0f);
00456
00457 if (e2s < s2s)
00458 {
00459 if (!Track_LinkExists(t, t2) &&
00460 Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0]))
00461 {
00462 if ((i = Track_LinkSet(t, t2)) > -1)
00463 VisFlag[i] |= 4;
00464 return GE_TRUE;
00465 }
00466 }
00467 else
00468 if (!Track_LinkExists(t2, t) &&
00469 Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00470 {
00471 if ((i = Track_LinkSet(t2, t)) > -1)
00472 VisFlag2[i] |= 1;
00473 return GE_TRUE;
00474 }
00475 }
00476 else
00477 {
00478
00479 if (!Track_LinkExists(t, t2) &&
00480 (a = Track_LinkTest(World, &t->PointList[0], &t2->PointList[0])) ||
00481 (b = Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0])))
00482 {
00483 if ((i = Track_LinkSet(t, t2)) > -1)
00484 VisFlag[i] |= 1;
00485 if ((i = Track_LinkSet(t2, t)) > -1)
00486 VisFlag2[i] |= 4;
00487 return GE_TRUE;
00488 }
00489 }
00490 }
00491 else
00492 if (OneWay || OneWay2)
00493 {
00494 e2e = DistWeightedY(t->PointList[ep].Pos, t2->PointList[ep2].Pos, 2.0f);
00495 s2s = DistWeightedY(t->PointList[0].Pos, t2->PointList[0].Pos, 2.0f);
00496 s2e = DistWeightedY(t->PointList[0].Pos, t2->PointList[ep2].Pos, 2.0f);
00497 e2s = DistWeightedY(t->PointList[ep].Pos, t2->PointList[0].Pos, 2.0f);
00498
00499 if (e2e < s2s && e2e < s2e && e2e < e2s)
00500 {
00501
00502 if (OneWay && OneWay2)
00503 return GE_TRUE;
00504
00505 if (OneWay)
00506 {
00507 if (!Track_LinkExists(t, t2) &&
00508 Track_LinkTest(World, &t->PointList[ep], &t2->PointList[ep2]))
00509 {
00510 if ((i = Track_LinkSet(t, t2)) > -1)
00511 VisFlag[i] |= 3;
00512 return GE_TRUE;
00513 }
00514 }
00515
00516 if (OneWay2)
00517 {
00518 if (!Track_LinkExists(t2, t) &&
00519 Track_LinkTest(World, &t->PointList[ep], &t2->PointList[ep2]))
00520 {
00521 if ((i = Track_LinkSet(t2, t)) > -1)
00522 VisFlag2[i] |= 3;
00523 return GE_TRUE;
00524 }
00525 }
00526 }
00527
00528
00529 if (s2s < e2e && s2s < s2e && s2s < e2s)
00530 {
00531
00532 if (OneWay && OneWay2)
00533 return GE_TRUE;
00534
00535 if (OneWay2)
00536 {
00537 if (!Track_LinkExists(t, t2) &&
00538 Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00539 {
00540 if ((i = Track_LinkSet(t, t2)) > -1)
00541 VisFlag[i] |= 1;
00542 return GE_TRUE;
00543 }
00544 }
00545
00546 if (OneWay)
00547 {
00548 if (!Track_LinkExists(t2, t) &&
00549 Track_LinkTest(World, &t->PointList[0], &t2->PointList[0]))
00550 {
00551 if ((i = Track_LinkSet(t2, t)) > -1)
00552 VisFlag2[i] |= 1;
00553 return GE_TRUE;
00554 }
00555 }
00556 }
00557
00558 if (s2e < e2e && s2e < s2s && s2e < e2s)
00559 {
00560
00561 if (OneWay && OneWay2)
00562 {
00563 if (!Track_LinkExists(t2, t) &&
00564 Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2]))
00565 {
00566 if ((i = Track_LinkSet(t2, t)) > -1)
00567 VisFlag2[i] |= 2;
00568 return GE_TRUE;
00569 }
00570 }
00571
00572 if (OneWay2)
00573 {
00574 if (!Track_LinkExists(t2, t) &&
00575 Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2]))
00576 {
00577 if ((i = Track_LinkSet(t2, t)) > -1)
00578 VisFlag2[i] |= 2;
00579 return GE_TRUE;
00580 }
00581 }
00582
00583 if (OneWay)
00584 {
00585 if (!Track_LinkExists(t2, t) &&
00586 Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2]))
00587 {
00588 if ((i = Track_LinkSet(t2, t)) > -1)
00589 VisFlag[i] |= 2;
00590 return GE_TRUE;
00591 }
00592 }
00593 }
00594
00595 if (e2s < e2e && e2s < s2s && e2s < s2e)
00596 {
00597
00598 if (OneWay && OneWay2)
00599 {
00600 if (!Track_LinkExists(t, t2) &&
00601 Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0]))
00602 {
00603 if ((i = Track_LinkSet(t, t2)) > -1)
00604 VisFlag[i] |= 4;
00605 return GE_TRUE;
00606 }
00607 }
00608
00609 if (OneWay || OneWay2)
00610 {
00611 if (!Track_LinkExists(t, t2) &&
00612 Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0]))
00613 {
00614 if ((i = Track_LinkSet(t, t2)) > -1)
00615 VisFlag[i] |= 4;
00616 return GE_TRUE;
00617 }
00618 }
00619 }
00620 }
00621 else
00622 if (!Track_LinkExists(t, t2) &&
00623 ((a = Track_LinkTest(World, &t->PointList[0], &t2->PointList[0])) ||
00624 (b = Track_LinkTest(World, &t->PointList[0], &t2->PointList[ep2])) ||
00625 (c = Track_LinkTest(World, &t->PointList[ep], &t2->PointList[0])) ||
00626 (d = Track_LinkTest(World, &t->PointList[ep], &t2->PointList[ep2]))))
00627 {
00628 if ((i = Track_LinkSet(t, t2)) > -1)
00629 {
00630 if (a) VisFlag[i] |= 1;
00631 if (b) VisFlag[i] |= 2;
00632 if (c) VisFlag[i] |= 4;
00633 if (d) VisFlag[i] |= 3;
00634 }
00635 if ((i = Track_LinkSet(t2, t)) > -1)
00636 {
00637 if (a) VisFlag2[i] |= 1;
00638 if (b) VisFlag2[i] |= 2;
00639 if (c) VisFlag2[i] |= 4;
00640 if (d) VisFlag2[i] |= 3;
00641 }
00642
00643 return GE_TRUE;
00644 }
00645
00646 return GE_FALSE;
00647 }
00648
00649
00650
00651
00652
00653 void Track_LinkTracks(geWorld *World)
00654 {
00655 Track *t, *t2;
00656 assert(World);
00657
00658
00659 for (t = &TrackList[0]; t < &TrackList[TrackCount]; t++)
00660 {
00661 for (t2 = &TrackList[0]; t2 < &TrackList[TrackCount]; t2++)
00662 {
00663 Track_LinkTrack(World, t, t2);
00664 }
00665 }
00666 }
00667
00668
00669
00670
00671
00672 static geBoolean Track_FakeTrack(geWorld *World, geVec3d *Pos)
00673 {
00674 Track *t, *t2;
00675 TrackPt *tp;
00676 geBoolean found = GE_FALSE;
00677
00678
00679
00680 assert(World);
00681
00682 t = &TrackList[MAX_TRACKS];
00683 tp = t->PointList;
00684
00685
00686 t->PointCount = 1;
00687 tp->Pos = Pos;
00688 memset(t->Vis, 0, sizeof(t->Vis));
00689
00690
00691
00692
00693 for (t2 = &TrackList[0]; t2 < &TrackList[TrackCount]; t2++)
00694 {
00695 if (Track_LinkTrack(World, t, t2))
00696 found = TRUE;
00697 }
00698
00699 return (found);
00700 }
00701
00702
00703
00704
00705
00706 Track* Track_FindTrack(GenVSI *VSI, geVec3d *StartPos, geVec3d *TgtPos, int32 player_dir, int32 *track_type, TrackData *td)
00707 {
00708 float near_dist = 999999.0f, ydiff;
00709
00710 int32 end_point[2] = {0,0};
00711 int32 near_dir;
00712
00713 Track *t, *near_track;
00714 TrackPt *tp, *near_tp;
00715
00716 TrackPt *stp,*etp;
00717 float start2tgt_dist, dist0, dist1, bot2start_dist, bot2end_dist, end2tgt_dist, bot2tgt_dist, total_dist2end;
00718 int32 dir = 1;
00719 int32 *type;
00720
00721 geBoolean OneWay = GE_FALSE;
00722 geBoolean found = GE_FALSE;
00723 static StartTrack = 0;
00724
00725 geWorld *World;
00726
00727 World = GenVSI_GetWorld(VSI);
00728 assert(World);
00729
00730 if (td->TrackNdx <= -1)
00731 {
00732 StartTrack = 0;
00733 }
00734 else
00735 {
00736 StartTrack = td->TrackNdx+1;
00737 }
00738
00739 Track_ClearTrack(td);
00740
00741
00742 for (t = &TrackList[StartTrack]; t < &TrackList[TrackCount]; t++)
00743 {
00744 tp = t->PointList;
00745
00746
00747 if (track_type)
00748 {
00749 type = track_type;
00750
00751 while (*type != -1)
00752 {
00753 if (t->Type == *type)
00754 break;
00755 type++;
00756 }
00757
00758 if (*type <= -1)
00759 continue;
00760 }
00761
00762 end_point[1] = t->PointCount - 1;
00763
00764 #if 0
00765
00766 if (TEST(t->flags, TF_TRACK_OCCUPIED))
00767 continue;
00768 #endif
00769
00770 OneWay = Track_IsOneWay(t);
00771
00772 ydiff = TRACK_SEARCH_Y_RANGE;
00773
00774 dist0 = geVec3d_DistanceBetween(StartPos, t->PointList[end_point[0]].Pos);
00775 dist1 = geVec3d_DistanceBetween(StartPos, t->PointList[end_point[1]].Pos);
00776
00777 if (t->Type == TRACK_TYPE_TRAVERSE)
00778 {
00779
00780 TrackPt *tp;
00781 float save_start_dist = 999999.0f,
00782 save_end_dist = 999999.0f, dist;
00783
00784
00785
00786
00787
00788
00789 for (tp = t->PointList; tp < &t->PointList[t->PointCount]; tp++)
00790 {
00791 dist = geVec3d_DistanceBetween(tp->Pos, StartPos);
00792
00793 if (dist < save_start_dist)
00794 {
00795 stp = tp;
00796 save_start_dist = dist;
00797 }
00798
00799 dist = geVec3d_DistanceBetween(tp->Pos, TgtPos);
00800
00801 if (dist < save_end_dist)
00802 {
00803 etp = tp;
00804 save_end_dist = dist;
00805 }
00806 }
00807
00808 if (stp == etp)
00809 continue;
00810
00811
00812 if (etp > stp)
00813 dir = 1;
00814 else
00815 dir = -1;
00816 }
00817 else
00818 if (dist0 <= dist1)
00819 {
00820 stp = &t->PointList[end_point[0]];
00821 etp = &t->PointList[end_point[1]];
00822 dir = 1;
00823
00824 }
00825 else
00826 {
00827 if (OneWay)
00828 continue;
00829
00830 stp = &t->PointList[end_point[1]];
00831 etp = &t->PointList[end_point[0]];
00832 dir = -1;
00833 }
00834
00835 if (player_dir == TOWARD_GOAL)
00836 {
00837
00838 if (memcmp(TgtPos, etp->Pos, sizeof(*TgtPos)) == 0)
00839 {
00840 near_track = t;
00841 near_tp = stp;
00842 near_dir = dir;
00843 found = GE_TRUE;
00844 break;
00845 }
00846 }
00847
00848 bot2start_dist = geVec3d_DistanceBetween(StartPos, stp->Pos);
00849 bot2end_dist = geVec3d_DistanceBetween(StartPos, etp->Pos);
00850
00851 if (bot2start_dist > 1500.0f)
00852 continue;
00853
00854 if (bot2start_dist > near_dist)
00855 continue;
00856
00857 if (fabs(StartPos->Y - stp->Pos->Y) > ydiff)
00858 continue;
00859
00860
00861 total_dist2end = bot2start_dist + Track_Length(t);
00862
00863 start2tgt_dist = geVec3d_DistanceBetween(stp->Pos, TgtPos);
00864 end2tgt_dist = geVec3d_DistanceBetween(etp->Pos, TgtPos);
00865
00866 if (player_dir == TOWARD_GOAL)
00867 {
00868
00869 if (end2tgt_dist > start2tgt_dist)
00870 continue;
00871
00872 end2tgt_dist = DistWeightedY(etp->Pos, TgtPos, 2.0f);
00873 bot2tgt_dist = DistWeightedY(StartPos, TgtPos, 2.0f);
00874
00875
00876 if (end2tgt_dist > bot2tgt_dist)
00877 continue;
00878 }
00879 else
00880 if (player_dir == AWAY_FROM_GOAL)
00881 {
00882
00883 if (end2tgt_dist < start2tgt_dist)
00884 continue;
00885
00886 end2tgt_dist = DistWeightedY(etp->Pos, TgtPos, 2.0f);
00887 bot2tgt_dist = DistWeightedY(StartPos, TgtPos, 2.0f);
00888
00889
00890 if (end2tgt_dist < bot2tgt_dist)
00891 continue;
00892 }
00893
00894 if (!Bot_CanSeePointToPoint(World, StartPos, stp->Pos))
00895 continue;
00896
00897
00898
00899
00900
00901
00902 found = GE_TRUE;
00903 near_dist = bot2start_dist;
00904 near_track = t;
00905 near_tp = stp;
00906 near_dir = dir;
00907 }
00908
00909 if (found)
00910 {
00911
00912 td->TrackNdx = near_track - &TrackList[0];
00913 td->PointNdx = near_tp - &TrackList[td->TrackNdx].PointList[0];
00914 td->TrackDir = near_dir;
00915 return (near_track);
00916 }
00917 else
00918 {
00919 Track_ClearTrack(td);
00920 return (NULL);
00921 }
00922 }
00923
00924
00925
00926
00927 Track* Track_FindFarTrack(GenVSI *VSI, geVec3d *StartPos)
00928 {
00929 float far_dist = 0.0f;
00930
00931 int32 end_point[2] = {0,0};
00932
00933 Track *t, *far_track;
00934
00935
00936 TrackPt *stp;
00937 float bot2start_dist;
00938 int32 dir = 1;
00939
00940 geBoolean OneWay = GE_FALSE;
00941 geBoolean found = GE_FALSE;
00942
00943 int32 StartTrack = 0;
00944
00945 geWorld *World;
00946
00947 World = GenVSI_GetWorld(VSI);
00948 assert(World);
00949
00950
00951 for (t = &TrackList[StartTrack]; t < &TrackList[TrackCount]; t++)
00952 {
00953 stp = t->PointList;
00954
00955
00956 OneWay = Track_IsOneWay(t);
00957
00958 bot2start_dist = geVec3d_DistanceBetween(StartPos, stp->Pos);
00959
00960 if (bot2start_dist < far_dist)
00961 continue;
00962
00963 if (Bot_CanSeePointToPoint(World, StartPos, stp->Pos))
00964 continue;
00965
00966 found = GE_TRUE;
00967 far_dist = bot2start_dist;
00968 far_track = t;
00969 }
00970
00971 if (found)
00972 {
00973 return (far_track);
00974 }
00975
00976 return (NULL);
00977 }
00978
00979
00980 #if 0
00981
00982
00983
00984 static Track* Track_FindCloseTrack(GenVSI *VSI, geVec3d *StartPos, float ydiff)
00985 {
00986 float near_dist = 999999.0f;
00987
00988 Track *t, *near_track;
00989 TrackPt *tp;
00990
00991 TrackPt *stp;
00992 float tgt2start_dist;
00993 int32 dir = 1;
00994
00995 geBoolean OneWay = GE_FALSE;
00996 geBoolean found = GE_FALSE;
00997
00998 int32 StartTrack = 0;
00999
01000 geWorld *World;
01001
01002 float save_start_dist = 999999.0f,
01003 dist;
01004
01005 World = GenVSI_GetWorld(VSI);
01006 assert(World);
01007
01008
01009 for (t = &TrackList[StartTrack]; t < &TrackList[TrackCount]; t++)
01010 {
01011 OneWay = Track_IsOneWay(t);
01012
01013
01014
01015 for (tp = t->PointList; tp < &t->PointList[t->PointCount]; tp++)
01016 {
01017 dist = geVec3d_DistanceBetween(tp->Pos, StartPos);
01018
01019 if (dist < save_start_dist)
01020 {
01021 stp = tp;
01022 save_start_dist = dist;
01023 }
01024 }
01025
01026 tgt2start_dist = geVec3d_DistanceBetween(StartPos, stp->Pos);
01027
01028 if (tgt2start_dist > 1500.0f)
01029 continue;
01030
01031 if (tgt2start_dist > near_dist)
01032 continue;
01033
01034 if (fabs(StartPos->Y - stp->Pos->Y) > ydiff)
01035 continue;
01036
01037 found = GE_TRUE;
01038 near_dist = tgt2start_dist;
01039 near_track = t;
01040 }
01041
01042 if (found)
01043 {
01044 return (near_track);
01045 }
01046
01047 return (NULL);
01048 }
01049 #else
01050
01051
01052
01053 static Track* Track_FindCloseTrack(GenVSI *VSI, geVec3d *StartPos, float ydiff)
01054 {
01055 float near_dist = 999999.0f;
01056
01057 int32 end_point[2] = {0,0};
01058
01059 Track *t, *near_track;
01060 TrackPt *tp;
01061
01062 TrackPt *stp;
01063 float bot2start_dist;
01064 int32 dir = 1;
01065
01066 geBoolean OneWay = GE_FALSE;
01067 geBoolean found = GE_FALSE;
01068
01069 int32 StartTrack = 0;
01070
01071 geWorld *World;
01072
01073 World = GenVSI_GetWorld(VSI);
01074 assert(World);
01075
01076
01077 for (t = &TrackList[StartTrack]; t < &TrackList[TrackCount]; t++)
01078 {
01079 tp = t->PointList;
01080 end_point[1] = t->PointCount - 1;
01081
01082 OneWay = Track_IsOneWay(t);
01083
01084 ydiff = TRACK_SEARCH_Y_RANGE;
01085
01086 {
01087
01088 TrackPt *tp;
01089 float save_start_dist = 999999.0f,
01090 save_end_dist = 999999.0f, dist;
01091
01092
01093 for (tp = t->PointList; tp < &t->PointList[t->PointCount]; tp++)
01094 {
01095 dist = geVec3d_DistanceBetween(tp->Pos, StartPos);
01096
01097 if (dist < save_start_dist)
01098 {
01099 stp = tp;
01100 save_start_dist = dist;
01101 }
01102 }
01103 }
01104
01105 bot2start_dist = geVec3d_DistanceBetween(StartPos, stp->Pos);
01106
01107 if (bot2start_dist > 1500.0f)
01108 continue;
01109
01110 if (bot2start_dist > near_dist)
01111 continue;
01112
01113 if (fabs(StartPos->Y - stp->Pos->Y) > ydiff)
01114 continue;
01115
01116 if (!Bot_CanSeePointToPoint(World, StartPos, stp->Pos))
01117 {
01118 TrackPt *tp;
01119
01120 for (tp = t->PointList; tp < &t->PointList[t->PointCount]; tp++)
01121 {
01122 if (stp == tp)
01123 continue;
01124
01125 if (Bot_CanSeePointToPoint(World, StartPos, tp->Pos))
01126 goto found;
01127 }
01128
01129 continue;
01130 }
01131
01132 found:
01133
01134 found = GE_TRUE;
01135 near_dist = bot2start_dist;
01136 near_track = t;
01137
01138
01139 }
01140
01141 if (found)
01142 {
01143 return (near_track);
01144 }
01145
01146 return (NULL);
01147 }
01148 #endif
01149
01150
01151
01152
01153
01154 geBoolean Track_FindMultiTrack(GenVSI *VSI, geVec3d *StartPos, geVec3d *EndPos, int32 dir, TrackCB *cb, Stack *nodestack)
01155 {
01156 int32 endnode, startnode;
01157 int32 s_plc, s_end, i, j, k, nodenum;
01158 Track *t, *n;
01159 geWorld *World;
01160 geBoolean found = GE_FALSE;
01161
01162 if (!TrackCount)
01163 return GE_FALSE;
01164
01165 World = GenVSI_GetWorld(VSI);
01166 assert(World);
01167
01168
01169 if (!Track_FakeTrack(World, StartPos))
01170 return GE_FALSE;
01171
01172 t = &TrackList[MAX_TRACKS];
01173 assert(t);
01174 startnode = t - TrackList;
01175
01176
01177 if (!t->Vis[0])
01178 return GE_FALSE;
01179
01180 if (dir == -1)
01181 t = Track_FindFarTrack(VSI, EndPos);
01182 else
01183 if (dir == 1)
01184 t = Track_FindCloseTrack(VSI, EndPos, TRACK_SEARCH_Y_RANGE*1.5f);
01185
01186 if (!t)
01187 return GE_FALSE;
01188
01189 endnode = t - TrackList;
01190
01191
01192 memset(bitarr, 0, sizeof(bitarr));
01193
01194
01195 searchnode[0] = startnode;
01196 searchparent[0] = -1;
01197
01198
01199 SET_BITARR(bitarr,startnode);
01200
01201
01202 for(s_plc = 0, s_end = 1; s_plc < s_end; s_plc++)
01203 {
01204
01205 n = &TrackList[searchnode[s_plc]];
01206
01207 for (i = 0; n->Vis[i]; i++)
01208 {
01209 nodenum = n->Vis[i] - &TrackList[0];
01210
01211
01212 if (nodenum < 0)
01213 continue;
01214
01215
01216 if (!TEST_BITARR(bitarr,nodenum))
01217 {
01218
01219 SET_BITARR(bitarr,nodenum);
01220
01221 if (!cb->CB(VSI, cb->Data, &TrackList[nodenum]))
01222 continue;
01223
01224
01225 searchnode[s_end] = nodenum;
01226
01227 searchparent[s_end] = s_plc;
01228
01229 s_end++;
01230
01231 if (nodenum == endnode)
01232 {
01233
01234 found = GE_TRUE;
01235
01236
01237 StackReset(nodestack);
01238
01239 for(k = s_end-1, j=0; k >= 0; k = searchparent[k])
01240 {
01241 if (searchnode[k] >= MAX_TRACKS)
01242 continue;
01243
01244 StackPush(nodestack, searchnode[k]);
01245 }
01246
01247 goto finish;
01248 }
01249 }
01250 }
01251 }
01252
01253 finish:
01254
01255
01256 for (t = &TrackList[0]; t < &TrackList[TrackCount]; t++)
01257 {
01258 for (i = 0; t->Vis[i]; i++)
01259 {
01260 if (t->Vis[i] >= &TrackList[MAX_TRACKS])
01261 t->Vis[i] = 0;
01262 }
01263 }
01264
01265 return (found);
01266
01267 }
01268
01269
01270
01271
01272
01273 geBoolean Track_NextMultiTrack(GenVSI *VSI, geVec3d *StartPos, int32 TrackNdx, TrackData *td)
01274 {
01275 Track *t;
01276 TrackPt *tp, *ep;
01277 geWorld *World;
01278
01279 geBoolean OneWay;
01280
01281 int32 tpoint,dir;
01282 float dist2end,dist2start;
01283
01284 assert(TrackNdx > -1);
01285
01286
01287 t = &TrackList[TrackNdx];
01288 tp = t->PointList;
01289 ep = &t->PointList[t->PointCount - 1];
01290
01291 OneWay = Track_IsOneWay(t);
01292
01293 if (OneWay)
01294 {
01295 td->TrackNdx = t - &TrackList[0];
01296 td->PointNdx = 0;
01297 td->TrackDir = 1;
01298 return GE_TRUE;
01299 }
01300
01301 dist2start = geVec3d_DistanceBetween(StartPos, tp->Pos);
01302 dist2end = geVec3d_DistanceBetween(StartPos, ep->Pos);
01303
01304 World = GenVSI_GetWorld(VSI);
01305
01306 if (dist2start < dist2end)
01307 {
01308
01309 if (Bot_CanSeePointToPoint(World, StartPos, tp->Pos))
01310 {
01311 dir = 1;
01312 tpoint = 0;
01313 }
01314 else
01315 {
01316 dir = -1;
01317 tpoint = t->PointCount - 1;
01318 }
01319 }
01320 else
01321 {
01322
01323 if (Bot_CanSeePointToPoint(World, StartPos, ep->Pos))
01324 {
01325 dir = -1;
01326 tpoint = t->PointCount - 1;
01327 }
01328 else
01329 {
01330 dir = 1;
01331 tpoint = 0;
01332 }
01333 }
01334
01335 td->TrackNdx = t - &TrackList[0];
01336 td->PointNdx = tpoint;
01337 td->TrackDir = dir;
01338
01339 return GE_TRUE;
01340 }
01341
01342
01343
01344