Mario Kart 64
Loading...
Searching...
No Matches
path_utils.inc.c
Go to the documentation of this file.
1#include <ultra64.h>
2#include <macros.h>
3#include <defines.h>
4#include <path.h>
5#include <course.h>
6#include "main.h"
8
9bool are_in_curve(UNUSED s32 arg0, u16 pathPointIndex) {
10 s16 thing = gCurrentTrackConsecutiveCurveCountsPath[pathPointIndex];
11 if (thing > 0) {
12 return true;
13 }
14 return false;
15}
16
17bool is_far_from_path(s32 playerIndex) {
18 f32 value = gTrackPositionFactor[playerIndex];
19 if ((1.1f <= value) || (value <= -1.1f)) {
20 return true;
21 }
22 return false;
23}
24
38f32 calculate_track_position_factor(f32 posX, f32 posZ, u16 pathPointIndex, s32 pathIndex) {
39 f32 leftX;
40 f32 leftZ;
41 f32 rightX;
42 f32 rightZ;
43 f32 boundarySquaredDistance;
44 f32 positionFactor;
45 TrackPathPoint* leftPathPoint;
46 TrackPathPoint* rightPathPoint;
47
48 leftPathPoint = &gTrackLeftPaths[pathIndex][pathPointIndex];
49 rightPathPoint = &gTrackRightPaths[pathIndex][pathPointIndex];
50
51 leftX = leftPathPoint->posX;
52 leftZ = leftPathPoint->posZ;
53 rightX = rightPathPoint->posX;
54 rightZ = rightPathPoint->posZ;
55
56 boundarySquaredDistance = ((rightX - leftX) * (rightX - leftX)) + ((rightZ - leftZ) * (rightZ - leftZ));
57
58 // Avoid division by zero for very close or identical boundary points
59 if (boundarySquaredDistance < 0.01f) {
60 return 0.0f;
61 }
62 // Calculate normalized position factor using vector projection
63 // Formula: 2 * (dot product of vectors) / (squared magnitude) - 1
64 // This maps the position to a -1 to 1 range
65 positionFactor =
66 ((2.0f * ((rightX - leftX) * (posX - leftX) + (rightZ - leftZ) * (posZ - leftZ))) / boundarySquaredDistance) -
67 1.0f;
68 return positionFactor;
69}
70
71void update_player_position_factor(s32 playerId, u16 pathPointIndex, s32 pathIndex) {
72 UNUSED Vec3f pad;
73 gTrackPositionFactor[playerId] = 0.0f;
75 if ((gPlayers[playerId].type & PLAYER_EXISTS) != 0) {
77 gPlayers[playerId].pos[0], gPlayers[playerId].pos[2], pathPointIndex, pathIndex);
78 }
79 }
80}
81
82void calculate_track_offset_position(u16 pathPointIndex, f32 lerpFactor, f32 offsetDistance, s16 pathIndex) {
83 UNUSED s32 pad[4];
84 f32 pathPointOneX;
85 f32 pathPointOneZ;
86 f32 pathPointTwoX;
87 f32 pathPointTwoZ;
88 UNUSED s32 pad2;
89 f32 xdiff;
90 f32 zdiff;
91 f32 segmentLength;
92 UNUSED f32 temp_f12;
93 UNUSED f32 temp_f2_2;
95 TrackPathPoint* pathPointTwo;
96 TrackPathPoint* pathPointOne;
97
98 pathPointOne = &gTrackPaths[pathIndex][pathPointIndex];
99 pathPointOneX = pathPointOne->posX;
100 pathPointOneZ = pathPointOne->posZ;
101 pathPointTwo = &gTrackPaths[pathIndex][(pathPointIndex + 1) % gSelectedPathCount];
102 pathPointTwoX = pathPointTwo->posX;
103 pathPointTwoZ = pathPointTwo->posZ;
104
105 // Calculate vector between path
106 zdiff = pathPointTwoZ - pathPointOneZ;
107 xdiff = pathPointTwoX - pathPointOneX;
108 if (xdiff && xdiff) {}
109
110 segmentLength = sqrtf((xdiff * xdiff) + (zdiff * zdiff));
111 if (segmentLength < 0.01f) {
112 gOffsetPosition[0] = pathPointTwoX;
113 gOffsetPosition[2] = pathPointTwoZ;
114 } else {
115 gOffsetPosition[0] =
116 ((0.5f - (lerpFactor * 0.5f)) * (((offsetDistance * zdiff) / segmentLength) + pathPointOneX)) +
117 ((1.0f - (0.5f - (lerpFactor * 0.5f))) * (((offsetDistance * -zdiff) / segmentLength) + pathPointOneX));
118 gOffsetPosition[2] =
119 ((0.5f - (lerpFactor * 0.5f)) * (((offsetDistance * -xdiff) / segmentLength) + pathPointOneZ)) +
120 ((1.0f - (0.5f - (lerpFactor * 0.5f))) * (((offsetDistance * xdiff) / segmentLength) + pathPointOneZ));
121 }
122}
123
131void set_track_offset_position(u16 pathPointIndex, f32 trackOffset, s16 pathIndex) {
132 TrackPathPoint* path1;
133 TrackPathPoint* path2;
134 f32 x1;
135 f32 z1;
136 f32 x3;
137 f32 z3;
138 f32 x2;
139 f32 z2;
140 f32 x4;
141 f32 z4;
142 f32 temp_f0;
143 f32 temp_f12;
144
145 path1 = &gTrackLeftPaths[pathIndex][pathPointIndex];
146 path2 = &gTrackRightPaths[pathIndex][pathPointIndex];
147
148 x1 = (f32) path1->posX;
149 z1 = (f32) path1->posZ;
150
151 x2 = (f32) path2->posX;
152 z2 = (f32) path2->posZ;
153
154 pathPointIndex += 1;
155 pathPointIndex = pathPointIndex % gPathCountByPathIndex[pathIndex];
156
157 path1 = &gTrackLeftPaths[pathIndex][pathPointIndex];
158 path2 = &gTrackRightPaths[pathIndex][pathPointIndex];
159
160 x3 = (f32) path1->posX;
161 z3 = (f32) path1->posZ;
162
163 x4 = (f32) path2->posX;
164 z4 = (f32) path2->posZ;
165
166 temp_f0 = 0.5f - (trackOffset / 2.0f);
167 temp_f12 = 1.0f - temp_f0;
168 gOffsetPosition[0] = ((temp_f0 * (x1 + x3)) / 2.0f) + ((temp_f12 * (x2 + x4)) / 2.0f);
169 gOffsetPosition[2] = ((temp_f0 * (z1 + z3)) / 2.0f) + ((temp_f12 * (z2 + z4)) / 2.0f);
170}
171
172s16 func_8000BD94(f32 posX, f32 posY, f32 posZ, s32 pathIndex) {
173 f32 x_dist;
174 f32 y_dist;
175 f32 z_dist;
176 f32 considerSquaredDistance;
177 f32 minimumSquaredDistance;
178 s32 considerPathPointIndex;
179 s32 pathPathPointCount;
180 s16 nearestPathPointIndex;
181 TrackPathPoint* pathPathPoints;
182 TrackPathPoint* considerPathPoint;
183
184 pathPathPoints = gTrackPaths[pathIndex];
185 pathPathPointCount = gPathCountByPathIndex[pathIndex];
186 considerPathPoint = &pathPathPoints[0];
187 x_dist = (f32) considerPathPoint->posX - posX;
188 y_dist = (f32) considerPathPoint->posY - posY;
189 z_dist = (f32) considerPathPoint->posZ - posZ;
190 minimumSquaredDistance = (x_dist * x_dist) + (y_dist * y_dist) + (z_dist * z_dist);
191 nearestPathPointIndex = 0;
192 for (considerPathPointIndex = 1; considerPathPointIndex < pathPathPointCount;
193 considerPathPoint++, considerPathPointIndex++) {
194 x_dist = (f32) considerPathPoint->posX - posX;
195 y_dist = (f32) considerPathPoint->posY - posY;
196 z_dist = (f32) considerPathPoint->posZ - posZ;
197 considerSquaredDistance = (x_dist * x_dist) + (y_dist * y_dist) + (z_dist * z_dist);
198 if (considerSquaredDistance < minimumSquaredDistance) {
199 nearestPathPointIndex = considerPathPointIndex;
200 minimumSquaredDistance = considerSquaredDistance;
201 }
202 }
203 return nearestPathPointIndex;
204}
205
206s16 find_closest_pathPoint_track_section(f32 posX, f32 posY, f32 posZ, u16 trackSectionId, s32* pathIndex) {
207 TrackPathPoint* pathPathPoints;
208 TrackPathPoint* considerPathPoint;
209 f32 x_dist;
210 f32 y_dist;
211 f32 z_dist;
212 f32 considerSquaredDistance;
213 f32 minimumSquaredDistance;
214 s32 considerPathPointIndex;
215 s32 pathPathPointCount;
216 s32 temp_t0;
217 s32 var_a1;
218 s32 var_t1;
219 s32 considerPathIndex;
220 s32 var_t4;
221 s16 nearestPathPointIndex;
222
223 minimumSquaredDistance = 1000000.0f;
224 temp_t0 = *pathIndex;
225 nearestPathPointIndex = 0;
226 var_t1 = 0;
227 var_a1 = 0;
228 pathPathPoints = gTrackPaths[temp_t0];
229 pathPathPointCount = gPathCountByPathIndex[temp_t0];
230 considerPathPoint = &pathPathPoints[0];
231 for (considerPathPointIndex = 0; considerPathPointIndex < pathPathPointCount;
232 considerPathPointIndex++, considerPathPoint++) {
233 if ((considerPathPoint->trackSectionId == trackSectionId) || (gCurrentCourseId == COURSE_AWARD_CEREMONY)) {
234 var_t1 = 1;
235 x_dist = (f32) considerPathPoint->posX - posX;
236 y_dist = (f32) considerPathPoint->posY - posY;
237 z_dist = (f32) considerPathPoint->posZ - posZ;
238 considerSquaredDistance = (x_dist * x_dist) + (y_dist * y_dist) + (z_dist * z_dist);
239 if (considerSquaredDistance < minimumSquaredDistance) {
240 nearestPathPointIndex = considerPathPointIndex;
241 var_a1 = 1;
242 minimumSquaredDistance = considerSquaredDistance;
243 }
244 }
245 }
246 if (var_t1 == 0) {
247 for (considerPathIndex = 0; considerPathIndex < 4; considerPathIndex++) {
248 if ((considerPathIndex != temp_t0) && (gSizePath[considerPathIndex] >= 2)) {
249 pathPathPoints = gTrackPaths[considerPathIndex];
250 considerPathPoint = &pathPathPoints[0];
251 pathPathPointCount = gPathCountByPathIndex[considerPathIndex];
252 for (considerPathPointIndex = 0; considerPathPointIndex < pathPathPointCount;
253 considerPathPointIndex++, considerPathPoint++) {
254 if (considerPathPoint->trackSectionId == trackSectionId) {
255 x_dist = (f32) considerPathPoint->posX - posX;
256 y_dist = (f32) considerPathPoint->posY - posY;
257 z_dist = (f32) considerPathPoint->posZ - posZ;
258 considerSquaredDistance = (x_dist * x_dist) + (y_dist * y_dist) + (z_dist * z_dist);
259 if (considerSquaredDistance < minimumSquaredDistance) {
260 nearestPathPointIndex = considerPathPointIndex;
261 var_t4 = considerPathIndex;
262 var_a1 = 2;
263 minimumSquaredDistance = considerSquaredDistance;
264 }
265 }
266 }
267 }
268 }
269 }
270 if (var_a1 == 0) {
271 pathPathPoints = gTrackPaths[0];
272 pathPathPointCount = gPathCountByPathIndex[0];
273 considerPathPoint = &pathPathPoints[0];
274 x_dist = (f32) considerPathPoint->posX - posX;
275 y_dist = (f32) considerPathPoint->posY - posY;
276 z_dist = (f32) considerPathPoint->posZ - posZ;
277 minimumSquaredDistance = (x_dist * x_dist) + (y_dist * y_dist) + (z_dist * z_dist);
278 nearestPathPointIndex = 0;
279 for (considerPathPointIndex = 1; considerPathPointIndex < pathPathPointCount;
280 considerPathPoint++, considerPathPointIndex++) {
281 x_dist = (f32) considerPathPoint->posX - posX;
282 y_dist = (f32) considerPathPoint->posY - posY;
283 z_dist = (f32) considerPathPoint->posZ - posZ;
284 considerSquaredDistance = (x_dist * x_dist) + (y_dist * y_dist) + (z_dist * z_dist);
285 if (considerSquaredDistance < minimumSquaredDistance) {
286 nearestPathPointIndex = considerPathPointIndex;
287 var_t4 = 0;
288 var_a1 = 2;
289 minimumSquaredDistance = considerSquaredDistance;
290 }
291 }
292 }
293 if (var_a1 == 2) {
294 *pathIndex = var_t4;
295 }
296 return nearestPathPointIndex;
297}
298
305s16 update_path_index_with_track(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, s32 pathIndex, u16 trackSectionId) {
306 s16 nearestPathPointIndex;
307 s16 searchIndex;
308 s16 considerIndex;
309 s32 pathPathPointCount;
310 f32 x_dist;
311 f32 y_dist;
312 f32 z_dist;
313 f32 minimumDistance;
314 f32 squaredDistance;
315 TrackPathPoint* pathPathPoints;
316 TrackPathPoint* considerPathPoint;
317
318 nearestPathPointIndex = -1;
319 minimumDistance = 500.0f * 500.0f;
320 pathPathPointCount = gPathCountByPathIndex[pathIndex];
321 pathPathPoints = gTrackPaths[pathIndex];
322 for (searchIndex = pathPointIndex - 3; searchIndex < pathPointIndex + 7; searchIndex++) {
323 // Its possible for searchIndex to be less than 0 or greater than the number of path in a given path
324 // This is done to ensure we access gTrackPaths at a valid index
325 considerIndex = (searchIndex + pathPathPointCount) % pathPathPointCount;
326 considerPathPoint = &pathPathPoints[considerIndex];
327 if (considerPathPoint->trackSectionId == trackSectionId) {
328 x_dist = considerPathPoint->posX - posX;
329 y_dist = considerPathPoint->posY - posY;
330 z_dist = considerPathPoint->posZ - posZ;
331 squaredDistance = (x_dist * x_dist) + (y_dist * y_dist) + (z_dist * z_dist);
332 if (squaredDistance < minimumDistance) {
333 minimumDistance = squaredDistance;
334 nearestPathPointIndex = considerIndex;
335 }
336 }
337 }
338 return nearestPathPointIndex;
339}
340
346s16 update_path_index(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, s32 pathIndex) {
347 s16 nearestPathPointIndex;
348 s16 searchIndex;
349 s16 considerIndex;
350 bool pathPointFound;
351 s32 pathPathPointCount;
352 f32 x_dist;
353 f32 y_dist;
354 f32 z_dist;
355 f32 minimumDistance;
356 f32 squaredDistance;
357 TrackPathPoint* pathPathPoints;
358 TrackPathPoint* considerPathPoint;
359
360 pathPointFound = false;
361 nearestPathPointIndex = -1;
362 minimumDistance = 400.0f * 400.0f;
363 pathPathPointCount = gPathCountByPathIndex[pathIndex];
364 pathPathPoints = gTrackPaths[pathIndex];
365 for (searchIndex = pathPointIndex - 3; searchIndex < pathPointIndex + 7; searchIndex++) {
366 // Its possible for searchIndex to be less than 0 or greater than the number of path in a given path
367 // This is done to ensure we access gTrackPaths at a valid index
368 considerIndex = (searchIndex + pathPathPointCount) % pathPathPointCount;
369 considerPathPoint = &pathPathPoints[considerIndex];
370 x_dist = considerPathPoint->posX - posX;
371 y_dist = considerPathPoint->posY - posY;
372 z_dist = considerPathPoint->posZ - posZ;
373 squaredDistance = (x_dist * x_dist) + (y_dist * y_dist) + (z_dist * z_dist);
374 if (squaredDistance < minimumDistance) {
375 minimumDistance = squaredDistance;
376 nearestPathPointIndex = considerIndex;
377 pathPointFound = true;
378 }
379 }
380 if (pathPointFound == false) {
381 for (searchIndex = pathPointIndex - 3; searchIndex < pathPointIndex + 7; searchIndex++) {
382 considerIndex = ((searchIndex + pathPathPointCount) % pathPathPointCount);
383 considerPathPoint = &pathPathPoints[considerIndex];
389 if (considerPathPoint && considerPathPoint) {};
390 }
391 }
392 return nearestPathPointIndex;
393}
394
395void tweak_path_index_wario_stadium(UNUSED f32 posX, f32 posY, UNUSED f32 posZ, s16* pathPointIndex, UNUSED s32 arg4) {
396 s16 var_v0;
397
398 var_v0 = *pathPointIndex;
399 if ((gCurrentCourseId == COURSE_WARIO_STADIUM) && (var_v0 >= 0x475) && (var_v0 < 0x480) && (posY < 0.0f)) {
400 var_v0 = 0x0398;
401 }
402 *pathPointIndex = var_v0;
403}
404
405void adjust_path_at_start_line(UNUSED f32 posX, UNUSED f32 posY, f32 posZ, s16* pathPointIndex, s32 pathIndex) {
406 s16 pathPoint;
407 pathPoint = *pathPointIndex;
408 if (pathPoint == 0) {
409 if (gPathStartZ < posZ) {
410 pathPoint = gPathCountByPathIndex[pathIndex] - 1;
411 }
412 } else if (((pathPoint + 1) == gPathCountByPathIndex[pathIndex]) && (posZ <= gPathStartZ)) {
413 pathPoint = 0;
414 }
415 *pathPointIndex = pathPoint;
416}
417
418s16 update_path_index_track_section(f32 posX, f32 posY, f32 posZ, Player* player, s32 playerId, s32* pathIndex) {
419 u16 trackSectionId;
420 s16 ret;
421
422 trackSectionId = get_track_section_id(player->collision.meshIndexZX);
423 if ((trackSectionId <= 0) || (trackSectionId >= 0x33)) {
424 trackSectionId = gPlayersTrackSectionId[playerId];
425 }
426 gPlayersTrackSectionId[playerId] = trackSectionId;
427 ret = find_closest_pathPoint_track_section(posX, posY, posZ, trackSectionId, pathIndex);
428 gPathIndexByPlayerId[playerId] = *pathIndex;
429 return ret;
430}
431
445s16 update_player_path(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, Player* player, s32 playerId, s32 pathIndex) {
446 s16 newPathPoint;
447 UNUSED s16 stackPadding0;
448 UNUSED s32 stackPadding1;
449 UNUSED s32 stackPadding2;
450 TrackPathPoint* temp_v1;
451
452 // Human player handling (non-AI controlled)
453 if ((player->type & PLAYER_HUMAN) && !(player->type & PLAYER_CPU)) {
454 newPathPoint = update_path_index_with_track(posX, posY, posZ, pathPointIndex, pathIndex,
456 if (newPathPoint == -1) {
457 newPathPoint = update_path_index_track_section(posX, posY, posZ, player, playerId, &pathIndex);
458 }
459 } else { // AI or special case player handling
460 if (D_801631E0[playerId] == true) {
461 if (player->unk_0CA & 1) {
462 temp_v1 = &gTrackPaths[pathIndex][pathPointIndex];
463 player->pos[0] = (f32) temp_v1->posX;
464 player->pos[1] = (f32) temp_v1->posY;
465 player->pos[2] = (f32) temp_v1->posZ;
466 player->unk_0CA &= ~0x0001;
467 return pathPointIndex;
468 }
469 if (playerId == ((s32) D_80163488 % 8)) {
470 check_bounding_collision(&player->collision, 10.0f, posX, posY, posZ);
472 newPathPoint = update_path_index_with_track(posX, posY, posZ, pathPointIndex, pathIndex,
473 gPlayersTrackSectionId[playerId]);
474 if (newPathPoint == -1) {
475 newPathPoint = update_path_index(posX, posY, posZ, pathPointIndex, pathIndex);
476 }
477 if (newPathPoint == -1) {
478 newPathPoint = find_closest_pathPoint_track_section(posX, posY, posZ,
479 gPlayersTrackSectionId[playerId], &pathIndex);
480 temp_v1 = &gTrackPaths[pathIndex][newPathPoint];
481 player->pos[0] = (f32) temp_v1->posX;
482 player->pos[1] = (f32) temp_v1->posY;
483 player->pos[2] = (f32) temp_v1->posZ;
484 }
485 } else {
486 newPathPoint = update_path_index(posX, posY, posZ, pathPointIndex, pathIndex);
487 if (newPathPoint == -1) {
488 newPathPoint = func_8000BD94(posX, posY, posZ, pathIndex);
489 temp_v1 = &gTrackPaths[pathIndex][newPathPoint];
490 posX = (f32) temp_v1->posX;
491 posY = (f32) temp_v1->posY;
492 posZ = (f32) temp_v1->posZ;
493 player->pos[0] = posX;
494 player->pos[1] = posY;
495 player->pos[2] = posZ;
496 check_bounding_collision(&player->collision, 10.0f, posX, posY, posZ);
498 }
499 }
500 } else {
501 newPathPoint = update_path_index(posX, posY, posZ, pathPointIndex, pathIndex);
502 if (newPathPoint == -1) {
503 newPathPoint = update_path_index_track_section(posX, posY, posZ, player, playerId, &pathIndex);
504 }
505 }
506 tweak_path_index_wario_stadium(posX, posY, posZ, &newPathPoint, pathIndex);
507 }
508 adjust_path_at_start_line(posX, posY, posZ, &newPathPoint, pathIndex);
509 return newPathPoint;
510}
511
512s16 find_closest_vehicles_pathPoint(f32 xPos, UNUSED f32 yPos, f32 zPos, s16 pathPointIndex) {
513 f32 xdiff;
514 f32 zdiff;
515 f32 minimumDistance;
516 f32 considerSquaredDistance;
517 s16 realIndex;
518 s16 minimumIndex;
519 s16 considerIndex;
520 Path2D* considerPathPoint;
521
522 minimumDistance = 250000.0f;
523 minimumIndex = -1;
524 for (realIndex = pathPointIndex - 2; realIndex < pathPointIndex + 7; realIndex++) {
525 considerIndex = realIndex;
526 if (realIndex < 0) {
527 considerIndex = realIndex + gVehicle2DPathLength;
528 }
529 considerIndex %= gVehicle2DPathLength;
530 considerPathPoint = &gVehicle2DPathPoint[considerIndex];
531 xdiff = considerPathPoint->x - xPos;
532 zdiff = considerPathPoint->z - zPos;
533 considerSquaredDistance = (xdiff * xdiff) + (zdiff * zdiff);
534 if (considerSquaredDistance < minimumDistance) {
535 minimumDistance = considerSquaredDistance;
536 minimumIndex = considerIndex;
537 }
538 }
539 if (minimumIndex == -1) {
540 minimumIndex = pathPointIndex;
541 }
542 return minimumIndex;
543}
544
545s16 func_8000D24C(f32 posX, f32 posY, f32 posZ, s32* pathIndex) {
546 UNUSED s32 pad;
547 Collision sp24;
548
549 check_bounding_collision(&sp24, 10.0f, posX, posY, posZ);
550 return find_closest_pathPoint_track_section(posX, posY, posZ, get_track_section_id(sp24.meshIndexZX), pathIndex);
551}
552
553s16 func_8000D2B4(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, s32 pathIndex) {
554 s16 pathPoint;
555
556 pathPoint = update_path_index(posX, posY, posZ, pathPointIndex, pathIndex);
557 if (pathPoint == -1) {
558 pathPoint = func_8000D24C(posX, posY, posZ, &pathIndex);
559 }
560 adjust_path_at_start_line(posX, posY, posZ, &pathPoint, pathIndex);
561 return pathPoint;
562}
563
564s16 func_8000D33C(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, s32 pathIndex) {
565 s16 pathPoint;
566
567 pathPoint = update_path_index(posX, posY, posZ, pathPointIndex, pathIndex);
568 if (pathPoint == -1) {
569 pathPoint = func_8000D24C(posX, posY, posZ, &pathIndex);
570 }
571 return pathPoint;
572}
573
576 f32 target;
577 f32 current;
578
579 temp_v0 = &gPlayerTrackPositionFactorInstruction[playerId];
580 current = temp_v0->current;
581 target = temp_v0->target;
582 if (current < target) {
583 current += temp_v0->step;
584 if (target < current) {
585 current = target;
586 }
587 } else if (target < current) {
588 current -= temp_v0->step;
589 if (current < target) {
590 current = target;
591 }
592 }
593 temp_v0->current = current;
594 return current;
595}
596
597void determine_ideal_cpu_position_offset(s32 playerId, u16 pathPoint) {
598 UNUSED s32 stackPadding0;
599 f32 sp48;
600 f32 sp44;
601 UNUSED s32 stackPadding1;
602 UNUSED s32 stackPadding2;
603 UNUSED s32 stackPadding3;
604 f32 stackPadding4;
605 f32 stackPadding5;
606 f32 sp2C;
607 s32 lookAheadDistance;
608 s16 curveCount;
609 u16 thing;
610
611 curveCount = gCurrentTrackConsecutiveCurveCountsPath[pathPoint];
612 lookAheadDistance = 6;
613 sp2C = cpu_track_position_factor(playerId);
614 thing = pathPoint;
615
616 switch (gCurrentCourseId) {
618 lookAheadDistance = 1;
619 break;
621 lookAheadDistance = 7;
622 break;
624 break;
625 default:
626 if (curveCount < 6) {
627 lookAheadDistance = 8;
628 } else if (curveCount >= 0x15) {
629 lookAheadDistance = 20;
630 }
631 break;
632 }
633
634 if (lookAheadDistance >= 8) {
635 if ((gTrackPositionFactor[playerId] > 0.75f) && (gCurrentTrackSectionTypesPath[thing] == RIGHT_LEANING_CURVE)) {
636 lookAheadDistance = 7;
637 }
638 if ((gTrackPositionFactor[playerId] < -0.75f) && (gCurrentTrackSectionTypesPath[thing] == LEFT_LEANING_CURVE)) {
639 lookAheadDistance = 7;
640 }
641 }
642 if (is_far_from_path(playerId) == true) {
643 lookAheadDistance = 5;
644 }
645 if (gCurrentPlayerLookAhead[playerId] < lookAheadDistance) {
646 gCurrentPlayerLookAhead[playerId]++;
647 }
648 if (lookAheadDistance < gCurrentPlayerLookAhead[playerId]) {
649 gCurrentPlayerLookAhead[playerId]--;
650 }
651 pathPoint = (gCurrentPlayerLookAhead[playerId] + pathPoint) % gSelectedPathCount;
653 sp48 = gOffsetPosition[0];
654 sp44 = gOffsetPosition[2];
655 set_track_offset_position(((pathPoint + 1) % gSelectedPathCount) & 0xFFFF, sp2C, gPlayerPathIndex);
656 stackPadding5 = gOffsetPosition[0];
657 gOffsetPosition[0] = (sp48 + stackPadding5) * 0.5f;
658 stackPadding4 = gOffsetPosition[2];
659 gOffsetPosition[2] = (sp44 + stackPadding4) * 0.5f;
660}
661
662s16 func_8000D6D0(Vec3f position, s16* pathPointIndex, f32 speed, f32 arg3, s16 pathIndex, s16 arg5) {
663 f32 temp1;
664 f32 temp2;
665 f32 midX;
666 UNUSED s16 stackPadding1;
667 s16 pathPoint1;
668 s16 pathPoint2;
669 f32 pad3;
670 f32 midY;
671 f32 pad4;
672 f32 midZ;
673 f32 distance;
674 f32 oldPosX;
675 f32 oldPosY;
676 f32 oldPosZ;
677 f32 var_f2;
678 f32 var_f12;
679 f32 var_f14;
680 s16 temp_v0;
681 s32 temp_v1;
682 f32 xdiff;
683 f32 ydiff;
684 f32 zdiff;
685 Vec3f oldPos;
686 TrackPathPoint* path;
687
688 path = gTrackPaths[pathIndex];
689 oldPos[0] = position[0];
690 oldPos[1] = position[1];
691 oldPos[2] = position[2];
692 oldPosX = position[0];
693 oldPosY = position[1];
694 oldPosZ = position[2];
695 temp_v0 = func_8000D2B4(oldPosX, oldPosY, oldPosZ, *pathPointIndex, (s32) pathIndex);
696 *pathPointIndex = temp_v0;
697 temp_v1 = temp_v0 + arg5;
698 pathPoint1 = temp_v1 % gPathCountByPathIndex[pathIndex];
699 pathPoint2 = (temp_v1 + 1) % gPathCountByPathIndex[pathIndex];
700 set_track_offset_position(pathPoint1, arg3, pathIndex);
701 pad3 = gOffsetPosition[0];
702 pad4 = gOffsetPosition[2];
703 set_track_offset_position(pathPoint2, arg3, pathIndex);
704 temp1 = gOffsetPosition[0];
705 temp2 = gOffsetPosition[2];
706 midY = (path[pathPoint1].posY + path[pathPoint2].posY) * 0.5f;
707 midX = (pad3 + temp1) * 0.5f;
708 midZ = (pad4 + temp2) * 0.5f;
709 xdiff = midX - oldPosX;
710 ydiff = midY - oldPosY;
711 zdiff = midZ - oldPosZ;
712 distance = sqrtf((xdiff * xdiff) + (ydiff * ydiff) + (zdiff * zdiff));
713 if (distance > 0.01f) {
714 var_f2 = ((xdiff * speed) / distance) + oldPosX;
715 var_f12 = ((ydiff * speed) / distance) + oldPosY;
716 var_f14 = ((zdiff * speed) / distance) + oldPosZ;
717 } else {
718 var_f2 = oldPosX;
719 var_f12 = oldPosY;
720 var_f14 = oldPosZ;
721 }
722 position[0] = var_f2;
723 position[1] = var_f12;
724 position[2] = var_f14;
725 return get_angle_between_path(oldPos, position);
726}
727
728s16 func_8000D940(Vec3f pos, s16* pathPointIndex, f32 speed, f32 arg3, s16 pathIndex) {
729 UNUSED f32 pad;
730 f32 thing1;
731 f32 thing2;
732 UNUSED s16 stackPadding1;
733 s16 pathPoint1;
734 s16 pathPoint2;
735 UNUSED s16 stackPadding2;
736 f32 pad2;
737 f32 midX;
738 f32 pad3;
739 f32 midY;
740 f32 midZ;
741 f32 distance;
742 f32 temp_f20;
743 f32 temp_f22;
744 f32 temp_f24;
745 f32 var_f2;
746 f32 var_f12;
747 f32 var_f14;
748 s16 temp_v0;
749 f32 xdiff;
750 f32 ydiff;
751 f32 zdiff;
752 s32 pathPointCount;
753 Vec3f sp54;
754
755 sp54[0] = pos[0];
756 sp54[1] = pos[1];
757 sp54[2] = pos[2];
758 pathPointCount = gPathCountByPathIndex[pathIndex];
759 temp_f20 = pos[0];
760 temp_f22 = pos[1];
761 temp_f24 = pos[2];
762 temp_v0 = func_8000D2B4(temp_f20, temp_f22, temp_f24, *pathPointIndex, (s32) pathIndex);
763 *pathPointIndex = temp_v0;
764 pathPoint1 = ((temp_v0 + pathPointCount) - 3) % pathPointCount;
765 pathPoint2 = ((temp_v0 + pathPointCount) - 4) % pathPointCount;
766 set_track_offset_position(pathPoint1, arg3, pathIndex);
767 pad2 = gOffsetPosition[0];
768 pad3 = gOffsetPosition[2];
769 set_track_offset_position(pathPoint2, arg3, pathIndex);
770 thing1 = gOffsetPosition[0];
771 thing2 = gOffsetPosition[2];
772 midY = (gTrackPaths[pathIndex][pathPoint1].posY + gTrackPaths[pathIndex][pathPoint2].posY) * 0.5f;
773 midX = (pad2 + thing1) * 0.5f;
774 midZ = (pad3 + thing2) * 0.5f;
775 xdiff = midX - temp_f20;
776 ydiff = midY - temp_f22;
777 zdiff = midZ - temp_f24;
778 distance = sqrtf((xdiff * xdiff) + (ydiff * ydiff) + (zdiff * zdiff));
779 if (distance > 0.01f) {
780 var_f2 = ((xdiff * speed) / distance) + temp_f20;
781 var_f12 = ((ydiff * speed) / distance) + temp_f22;
782 var_f14 = ((zdiff * speed) / distance) + temp_f24;
783 } else {
784 var_f2 = temp_f20;
785 var_f12 = temp_f22;
786 var_f14 = temp_f24;
787 }
788 pos[0] = var_f2;
789 pos[1] = var_f12;
790 pos[2] = var_f14;
791 return get_angle_between_path(sp54, pos);
792}
793
794s16 update_vehicle_following_path(Vec3f pos, s16* pathPointIndex, f32 speed) {
795 f32 origXPos;
796 f32 origYPos;
797 f32 origZPos;
798 UNUSED s32 stackPadding0;
799 UNUSED s32 stackPadding1;
800 UNUSED s32 stackPadding2;
801 UNUSED s32 stackPadding3;
802 UNUSED s32 stackPadding4;
803 UNUSED s32 stackPadding5;
804 UNUSED s32 stackPadding6;
805 UNUSED s32 stackPadding7;
806 UNUSED s32 stackPadding8;
807 f32 farPathPointAverageX;
808 f32 farPathPointAverageZ;
809 f32 x_dist;
810 f32 y_dist;
811 f32 distance;
812 f32 newX;
813 f32 newZ;
814 s16 newPathPointIndex;
815 s16 farPathPoint1;
816 s16 farPathPoint2;
817 Path2D* temp_a0;
818 Path2D* temp_a2;
819 Vec3f sp38;
820
821 origXPos = pos[0];
822 origYPos = pos[1];
823 origZPos = pos[2];
824 sp38[0] = pos[0];
825 sp38[1] = pos[1];
826 sp38[2] = pos[2];
827 newPathPointIndex = find_closest_vehicles_pathPoint(origXPos, origYPos, origZPos, *pathPointIndex);
828 *pathPointIndex = newPathPointIndex;
829 farPathPoint1 = (newPathPointIndex + 3) % gVehicle2DPathLength;
830 farPathPoint2 = (newPathPointIndex + 4) % gVehicle2DPathLength;
831 temp_a0 = &gVehicle2DPathPoint[farPathPoint1];
832 temp_a2 = &gVehicle2DPathPoint[farPathPoint2];
833 farPathPointAverageX = (temp_a0->x + temp_a2->x) * 0.5f;
834 farPathPointAverageZ = (temp_a0->z + temp_a2->z) * 0.5f;
835 x_dist = farPathPointAverageX - origXPos;
836 y_dist = farPathPointAverageZ - origZPos;
837 distance = sqrtf((x_dist * x_dist) + (y_dist * y_dist));
838 if (distance > 0.01f) {
839 newX = ((x_dist * speed) / distance) + origXPos;
840 newZ = ((y_dist * speed) / distance) + origZPos;
841 } else {
842 newX = origXPos;
843 newZ = origZPos;
844 }
845 pos[0] = newX;
846 pos[1] = origYPos;
847 pos[2] = newZ;
848 return get_angle_between_path(sp38, pos);
849}
s16 gCurrentCourseId
Definition code_800029B0.c:30
s16 get_track_section_id(u16 index)
Definition collision.c:509
u16 check_bounding_collision(Collision *collision, f32 boundingBoxSize, f32 posX, f32 posY, f32 posZ)
Definition collision.c:1358
f32 Vec3f[3]
Definition common_structs.h:6
@ COURSE_WARIO_STADIUM
Definition course.h:45
@ COURSE_YOSHI_VALLEY
Definition course.h:35
@ COURSE_TOADS_TURNPIKE
Definition course.h:41
@ COURSE_AWARD_CEREMONY
Definition course.h:51
#define GET_COURSE_AIMaximumSeparation
Definition course.h:87
u16 gPathIndexByPlayerId[12]
Definition cpu_vehicles_camera_path.c:180
u16 gPathCountByPathIndex[4]
Definition cpu_vehicles_camera_path.c:181
s16 * gCurrentTrackSectionTypesPath
Definition cpu_vehicles_camera_path.c:84
u16 D_801631E0[12]
Definition cpu_vehicles_camera_path.c:86
s32 gVehicle2DPathLength
Definition cpu_vehicles_camera_path.c:139
s32 gPlayerPathIndex
Definition cpu_vehicles_camera_path.c:119
s16 gCurrentPlayerLookAhead[12]
Definition cpu_vehicles_camera_path.c:109
s16 get_angle_between_path(Vec3f arg0, Vec3f arg1)
Definition cpu_vehicles_camera_path.c:555
TrackPathPoint * gTrackPaths[4]
Definition cpu_vehicles_camera_path.c:174
s16 * gCurrentTrackConsecutiveCurveCountsPath
Definition cpu_vehicles_camera_path.c:183
TrackPathPoint * gTrackRightPaths[4]
Definition cpu_vehicles_camera_path.c:176
u16 gSelectedPathCount
Definition cpu_vehicles_camera_path.c:162
f32 gTrackPositionFactor[10]
Definition cpu_vehicles_camera_path.c:68
s32 gSizePath[4]
Definition cpu_vehicles_camera_path.c:106
Path2D * gVehicle2DPathPoint
Definition cpu_vehicles_camera_path.c:138
TrackPositionFactorInstruction gPlayerTrackPositionFactorInstruction[10]
Definition cpu_vehicles_camera_path.c:137
f32 gPathStartZ
Definition cpu_vehicles_camera_path.c:120
Vec3f gOffsetPosition
Definition cpu_vehicles_camera_path.c:51
u16 gPlayersTrackSectionId[12]
Definition cpu_vehicles_camera_path.c:100
TrackPathPoint * gTrackLeftPaths[4]
Definition cpu_vehicles_camera_path.c:175
s32 D_80163488
Definition cpu_vehicles_camera_path.c:128
#define PLAYER_EXISTS
Definition defines.h:80
#define PLAYER_HUMAN
Definition defines.h:79
#define PLAYER_CPU
Definition defines.h:77
#define UNUSED
Definition macros.h:23
Player gPlayers[NUM_PLAYERS]
Definition main.c:68
float sqrtf(float)
@ RIGHT_LEANING_CURVE
Definition path.h:14
@ LEFT_LEANING_CURVE
Definition path.h:15
s16 update_player_path(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, Player *player, s32 playerId, s32 pathIndex)
Definition path_utils.inc.c:445
s16 find_closest_vehicles_pathPoint(f32 xPos, UNUSED f32 yPos, f32 zPos, s16 pathPointIndex)
Definition path_utils.inc.c:512
s16 update_path_index_with_track(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, s32 pathIndex, u16 trackSectionId)
Definition path_utils.inc.c:305
f32 calculate_track_position_factor(f32 posX, f32 posZ, u16 pathPointIndex, s32 pathIndex)
Definition path_utils.inc.c:38
void tweak_path_index_wario_stadium(UNUSED f32 posX, f32 posY, UNUSED f32 posZ, s16 *pathPointIndex, UNUSED s32 arg4)
Definition path_utils.inc.c:395
s16 func_8000D6D0(Vec3f position, s16 *pathPointIndex, f32 speed, f32 arg3, s16 pathIndex, s16 arg5)
Definition path_utils.inc.c:662
s16 func_8000D33C(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, s32 pathIndex)
Definition path_utils.inc.c:564
f32 cpu_track_position_factor(s32 playerId)
Definition path_utils.inc.c:574
s16 update_vehicle_following_path(Vec3f pos, s16 *pathPointIndex, f32 speed)
Definition path_utils.inc.c:794
void update_player_position_factor(s32 playerId, u16 pathPointIndex, s32 pathIndex)
Definition path_utils.inc.c:71
s16 func_8000D940(Vec3f pos, s16 *pathPointIndex, f32 speed, f32 arg3, s16 pathIndex)
Definition path_utils.inc.c:728
s16 update_path_index(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, s32 pathIndex)
Definition path_utils.inc.c:346
bool are_in_curve(UNUSED s32 arg0, u16 pathPointIndex)
Definition path_utils.inc.c:9
void set_track_offset_position(u16 pathPointIndex, f32 trackOffset, s16 pathIndex)
Definition path_utils.inc.c:131
s16 func_8000D2B4(f32 posX, f32 posY, f32 posZ, s16 pathPointIndex, s32 pathIndex)
Definition path_utils.inc.c:553
s16 update_path_index_track_section(f32 posX, f32 posY, f32 posZ, Player *player, s32 playerId, s32 *pathIndex)
Definition path_utils.inc.c:418
s16 func_8000D24C(f32 posX, f32 posY, f32 posZ, s32 *pathIndex)
Definition path_utils.inc.c:545
bool is_far_from_path(s32 playerIndex)
Definition path_utils.inc.c:17
s16 find_closest_pathPoint_track_section(f32 posX, f32 posY, f32 posZ, u16 trackSectionId, s32 *pathIndex)
Definition path_utils.inc.c:206
void determine_ideal_cpu_position_offset(s32 playerId, u16 pathPoint)
Definition path_utils.inc.c:597
void calculate_track_offset_position(u16 pathPointIndex, f32 lerpFactor, f32 offsetDistance, s16 pathIndex)
Definition path_utils.inc.c:82
s16 func_8000BD94(f32 posX, f32 posY, f32 posZ, s32 pathIndex)
Definition path_utils.inc.c:172
void adjust_path_at_start_line(UNUSED f32 posX, UNUSED f32 posY, f32 posZ, s16 *pathPointIndex, s32 pathIndex)
Definition path_utils.inc.c:405
Definition common_structs.h:132
u16 meshIndexZX
Definition common_structs.h:139
Definition cpu_vehicles_camera_path.h:47
s16 z
Definition cpu_vehicles_camera_path.h:49
s16 x
Definition cpu_vehicles_camera_path.h:48
Definition common_structs.h:249
s16 unk_0CA
Definition common_structs.h:304
Collision collision
Definition common_structs.h:324
u16 type
Definition common_structs.h:250
Vec3f pos
Definition common_structs.h:259
Definition path.h:6
s16 posX
Definition path.h:7
u16 trackSectionId
Definition path.h:10
s16 posZ
Definition path.h:9
s16 posY
Definition path.h:8
Definition cpu_vehicles_camera_path.h:21
f32 target
Definition cpu_vehicles_camera_path.h:23
f32 step
Definition cpu_vehicles_camera_path.h:24
f32 current
Definition cpu_vehicles_camera_path.h:22
signed int s32
Definition ultratypes.h:15
signed short int s16
Definition ultratypes.h:13
float f32
Definition ultratypes.h:34
unsigned short int u16
Definition ultratypes.h:14