8void CourseMap::init() {
9 void *buffer = LoadFile(
"course.kmp");
13 constexpr u32 AREA_SIGNATURE = 0x41524541;
14 constexpr u32 CANNON_POINT_SIGNATURE = 0x434e5054;
15 constexpr u32 CHECK_PATH_SIGNATURE = 0x434b5048;
16 constexpr u32 CHECK_POINT_SIGNATURE = 0x434b5054;
17 constexpr u32 GEO_OBJ_SIGNATURE = 0x474f424a;
18 constexpr u32 JUGEM_POINT_SIGNATURE = 0x4a475054;
19 constexpr u32 START_POINT_SIGNATURE = 0x4b545054;
20 constexpr u32 POINT_INFO_SIGNATURE = 0x504f5449;
21 constexpr u32 STAGE_INFO_SIGNATURE = 0x53544749;
23 m_startPoint = parseMapdata<MapdataStartPointAccessor>(START_POINT_SIGNATURE);
24 m_checkPath = parseMapdata<MapdataCheckPathAccessor>(CHECK_PATH_SIGNATURE);
25 m_checkPoint = parseMapdata<MapdataCheckPointAccessor>(CHECK_POINT_SIGNATURE);
26 m_geoObj = parseMapdata<MapdataGeoObjAccessor>(GEO_OBJ_SIGNATURE);
27 m_pointInfo = parseMapdata<MapdataPointInfoAccessor>(POINT_INFO_SIGNATURE);
28 m_area = parseMapdata<MapdataAreaAccessor>(AREA_SIGNATURE);
29 m_jugemPoint = parseMapdata<MapdataJugemPointAccessor>(JUGEM_POINT_SIGNATURE);
30 m_cannonPoint = parseMapdata<MapdataCannonPointAccessor>(CANNON_POINT_SIGNATURE);
31 m_stageInfo = parseMapdata<MapdataStageInfoAccessor>(STAGE_INFO_SIGNATURE);
37 constexpr u8 TRANSLATION_MODE_NARROW = 1;
38 if (stageInfo && stageInfo->translationMode() == TRANSLATION_MODE_NARROW) {
39 m_startTmpAngle = 25.0f;
43 m_startTmpAngle = 30.0f;
49 m_startTmp1 = 1200.0f;
53s16 CourseMap::findSector(
const EGG::Vector3f &pos, u16 checkpointIdx, f32 &distanceRatio) {
60 checkpoint->checkSectorAndDistanceRatio(pos, distanceRatio);
61 checkpoint->setSearched();
66 id = checkpoint->id();
72 id = findSectorBetweenSides(pos, checkpoint, distanceRatio);
78 id = findSectorOutsideSector(pos, checkpoint, distanceRatio);
85 return id > -1 ? id : findSectorRegional(pos, checkpoint, distanceRatio);
89s16 CourseMap::findRecursiveSector(
const EGG::Vector3f &pos, s16 depth,
bool searchBackwardsFirst,
91 constexpr s16 MAX_DEPTH = 6;
93 if (depth >= 0 && depth > MAX_DEPTH) {
100 if (!checkpoint->searched()) {
101 completion = checkpoint->checkSectorAndDistanceRatio(pos, distanceRatio);
102 checkpoint->setSearched();
107 return checkpoint->id();
111 if (!searchBackwardsFirst) {
115 distanceRatio < 0.0f) {
116 distanceRatio = 0.0f;
117 return checkpoint->id();
121 if (checkpoint->checkArea() >= 0) {
128 distanceRatio > 0.0f;
131 s16
id = searchNextCheckpoint(pos, depth, checkpoint, distanceRatio, forward,
false);
135 searchPrevCheckpoint(pos, depth, checkpoint, distanceRatio, forward,
true) :
144 distanceRatio > 1.0f) {
145 distanceRatio = 1.0f;
146 return checkpoint->id();
150 if (checkpoint->checkArea() >= 0) {
160 s16
id = searchPrevCheckpoint(pos, depth, checkpoint, distanceRatio, forward,
false);
163 return id == -1 ? searchNextCheckpoint(pos, depth, checkpoint, distanceRatio, forward,
true) :
168u16 CourseMap::getCheckPointEntryOffsetMs(u16 i,
const EGG::Vector3f &pos,
178f32 CourseMap::getCheckPointEntryOffsetExact(u16 i,
const EGG::Vector3f &pos,
189s16 CourseMap::getCurrentAreaID(s16 i,
const EGG::Vector3f &pos, MapdataAreaBase::Type type)
const {
193 if (area->type() == type && area->test(pos)) {
199 for (i = 0; i < getAreaCount(); ++i) {
201 if (area->type() == type && area->test(pos)) {
202 return area->index();
217void CourseMap::DestroyInstance() {
219 auto *instance = s_instance;
220 s_instance =
nullptr;
225CourseMap::CourseMap()
226 : m_course(
nullptr), m_startPoint(
nullptr), m_stageInfo(
nullptr), m_startTmpAngle(0.0f),
227 m_startTmp0(0.0f), m_startTmp1(0.0f), m_startTmp2(0.0f), m_startTmp3(0.0f) {}
230CourseMap::~CourseMap() {
232 s_instance =
nullptr;
233 WARN(
"CourseMap instance not explicitly handled!");
244 delete m_cannonPoint;
249 f32 &distanceRatio) {
253 if (distanceRatio > 0.5f) {
255 id = searchNextCheckpoint(pos, 0, checkpoint, distanceRatio,
false,
false);
262 for (
size_t i = 0; i < checkpoint->nextCount(); ++i) {
265 for (
size_t j = 0; j < next->prevCount(); ++j) {
268 if (prev == checkpoint) {
272 id = findRecursiveSector(pos, 1,
true, prev, distanceRatio,
false);
280 for (
size_t i = 0; i < checkpoint->prevCount(); ++i) {
283 for (
size_t j = 0; j < prev->nextCount(); ++j) {
286 if (next == checkpoint) {
290 id = findRecursiveSector(pos, 1,
false, next, distanceRatio,
false);
298 return searchPrevCheckpoint(pos, 0, checkpoint, distanceRatio,
false,
false);
301 id = searchPrevCheckpoint(pos, 0, checkpoint, distanceRatio,
false,
false);
308 for (
size_t i = 0; i < checkpoint->prevCount(); ++i) {
311 for (
size_t j = 0; j < prev->nextCount(); ++j) {
314 if (next == checkpoint) {
318 id = findRecursiveSector(pos, 1,
false, next, distanceRatio,
false);
327 for (
size_t i = 0; i < checkpoint->nextCount(); ++i) {
330 for (
size_t j = 0; j < next->prevCount(); ++j) {
333 if (prev == checkpoint) {
337 id = findRecursiveSector(pos, 1,
true, prev, distanceRatio,
false);
346 return searchNextCheckpoint(pos, 0, checkpoint, distanceRatio,
false,
false);
353 f32 &distanceRatio) {
357 for (
size_t i = 0; i < checkpoint->nextCount(); ++i) {
360 for (
size_t j = 0; j < next->prevCount(); ++j) {
363 if (prev == checkpoint) {
367 id = findRecursiveSector(pos, 1,
true, prev, distanceRatio,
false);
376 for (
size_t i = 0; i < checkpoint->prevCount(); ++i) {
379 for (
size_t j = 0; j < prev->nextCount(); ++j) {
382 if (next == checkpoint) {
386 id = findRecursiveSector(pos, 1,
false, next, distanceRatio,
false);
395 for (
size_t i = 0; i < checkpoint->nextCount(); ++i) {
396 id = findRecursiveSector(pos, 1,
false, checkpoint->nextPoint(i), distanceRatio,
false);
404 for (
size_t i = 0; i < checkpoint->prevCount(); ++i) {
405 id = findRecursiveSector(pos, 1,
true, checkpoint->prevPoint(i), distanceRatio,
false);
417 f32 &distanceRatio) {
421 for (
size_t i = 0; i < checkpoint->nextCount(); ++i) {
422 id = findRecursiveSector(pos, -1,
false, checkpoint->nextPoint(i), distanceRatio,
false);
430 for (
size_t i = 0; i < checkpoint->prevCount(); ++i) {
431 id = findRecursiveSector(pos, -1,
true, checkpoint->prevPoint(i), distanceRatio,
false);
442s16 CourseMap::searchNextCheckpoint(
const EGG::Vector3f &pos, s16 depth,
444 bool useCache)
const {
446 depth = depth >= 0 ? depth + 1 : -1;
448 for (
size_t i = 0; i < checkpoint->nextCount(); ++i) {
451 if (!useCache || !next->searched()) {
452 id = findRecursiveSector(pos, depth,
false, next, completion, playerIsForwards);
464s16 CourseMap::searchPrevCheckpoint(
const EGG::Vector3f &pos, s16 depth,
466 bool useCache)
const {
468 depth = depth >= 0 ? depth + 1 : -1;
470 for (
size_t i = 0; i < checkpoint->prevCount(); ++i) {
473 if (!useCache || !prev->searched()) {
474 id = findRecursiveSector(pos, depth,
true, prev, completion, playerIsForwards);
486void CourseMap::clearSectorChecked() {
487 for (
size_t i = 0; i < m_checkPoint->size(); ++i) {
488 getCheckPoint(i)->clearSearched();
493void *CourseMap::LoadFile(
const char *filename) {
494 return ResourceManager::Instance()->getFile(filename,
nullptr, ArchiveId::Course);
497CourseMap *CourseMap::s_instance =
nullptr;