diff --git a/include/Game/SingleGameSection.h b/include/Game/SingleGameSection.h index 7fea2e2e0..95219c896 100644 --- a/include/Game/SingleGameSection.h +++ b/include/Game/SingleGameSection.h @@ -6,6 +6,7 @@ #include "Game/gamePlayData.h" #include "Game/gameStages.h" #include "efx/TChasePos.h" +#include "Radar.h" #include "id32.h" namespace og { @@ -80,7 +81,7 @@ struct SingleGameSection : public BaseGameSection { void drawCaveScreen(); void drawMainMapScreen(); void setDispMemberNavi(og::Screen::DataNavi& data, int naviID); - int calcOtakaraLevel(f32&); + Radar::Mgr::RadarSearchResult calcOtakaraLevel(f32&); inline void setCurrState(StateType* state) { mCurrentState = state; } inline StateType* getCurrState() { return mCurrentState; } diff --git a/include/Radar.h b/include/Radar.h index a508d496c..480dcf4df 100644 --- a/include/Radar.h +++ b/include/Radar.h @@ -70,6 +70,18 @@ struct Radar { }; struct Mgr { + enum RadarSearchResult { + NO_TREASURE_FOUND = 0, // No treasure found + TREASURE_FOUND = 1, // At least one treasure found but not the closest + CLOSEST_TREASURE_FOUND = 2, // Found a closest treasure + + // For antenna beetles + WHISTLE_ACTIVE_TIMER_EXPIRED = 3, // Whistle is active, timer expired + WHISTLE_ACTIVE = 4, // Whistle is active, but timer not expired + + NOT_PROCESSED = 5, // Not yet processed, AKA invalid or default + }; + Mgr(); static void entry(Game::TPositionObject*, Radar::cRadarType, u32); @@ -77,7 +89,7 @@ struct Radar { void attach(Game::TPositionObject*, Radar::cRadarType, u32); void bornFuefuki(); - int calcNearestTreasure(Vector3f& naviPos, f32 searchDist, Vector3f& treasurePos, f32& nearestDistanceSquared); + RadarSearchResult calcNearestTreasure(Vector3f& naviPos, f32 searchDist, Vector3f& treasurePos, f32& nearestDistanceSquared); void clear(); bool detach(Game::TPositionObject*); void dieFuefuki(); @@ -86,13 +98,13 @@ struct Radar { static int getNumOtakaraItems(); void ogDummpyInit(); - Point mPointNode1; // _00 - Point mPointNode2; // _24 - Point* mPointList; // _48 - int mNumObjects; // _4C - int mOtakaraNum; // _50 - int mFuefukiCount; // _54 - int mFuefukiTimer; // _58 + Point mActiveRadarNodes; // _00 + Point mInactiveRadarNodes; // _24 + Point* mPointList; // _48 + int mNumObjects; // _4C + int mTreasureCount; // _50 + int mFuefukiCount; // _54 + int mFuefukiWhistleTimer; // _58 }; static Mgr* mgr; diff --git a/src/plugProjectKandoU/navi_demoCheck.cpp b/src/plugProjectKandoU/navi_demoCheck.cpp index 91aec2787..e3d56ee9e 100644 --- a/src/plugProjectKandoU/navi_demoCheck.cpp +++ b/src/plugProjectKandoU/navi_demoCheck.cpp @@ -380,7 +380,7 @@ bool Navi::demoCheck() // Mark the cave as visited in the pause map screen if (Radar::mgr) { - FOREACH_NODE(Radar::Point, Radar::mgr->mPointNode1.mChild, cPoint) + FOREACH_NODE(Radar::Point, Radar::mgr->mActiveRadarNodes.mChild, cPoint) { if (cPoint->mObjType == Radar::MAP_UNENTERED_CAVE && targetCave->mCaveID.getID() == cPoint->getCaveID()) { cPoint->mObjType = Radar::MAP_INCOMPLETE_CAVE; diff --git a/src/plugProjectKandoU/radarInfo.cpp b/src/plugProjectKandoU/radarInfo.cpp index cc39eeb4e..f78b12c63 100644 --- a/src/plugProjectKandoU/radarInfo.cpp +++ b/src/plugProjectKandoU/radarInfo.cpp @@ -30,8 +30,8 @@ Vector2f Radar::Point::getPosition() */ Radar::Mgr::Mgr() { - mPointNode1.clear(); - mPointNode2.clear(); + mActiveRadarNodes.clear(); + mInactiveRadarNodes.clear(); mNumObjects = RADAR_MAX_OBJECTS; mPointList = new Point[mNumObjects]; @@ -44,8 +44,8 @@ Radar::Mgr::Mgr() */ void Radar::Mgr::clear() { - mPointNode1.clear(); - mPointNode2.clear(); + mActiveRadarNodes.clear(); + mInactiveRadarNodes.clear(); for (int i = 0; i < mNumObjects; i++) { Point* pointList = &mPointList[i]; @@ -54,12 +54,12 @@ void Radar::Mgr::clear() pointList->mObjType = MAP_NULL_ICON; pointList->mCaveID = nullptr; - mPointNode2.add(&mPointList[i]); + mInactiveRadarNodes.add(&mPointList[i]); } - mOtakaraNum = 0; - mFuefukiCount = 0; - mFuefukiTimer = 0; + mTreasureCount = 0; + mFuefukiCount = 0; + mFuefukiWhistleTimer = 0; } /** @@ -83,7 +83,7 @@ void Radar::Mgr::dieFuefuki() * @note Address: 0x8021E574 * @note Size: 0x10 */ -void Radar::Mgr::fuefuki() { mFuefukiTimer++; } +void Radar::Mgr::fuefuki() { mFuefukiWhistleTimer++; } /** * @note Address: 0x8021E584 @@ -94,7 +94,7 @@ void Radar::Mgr::entry(Game::TPositionObject* obj, Radar::cRadarType type, u32 f if (mgr) { mgr->attach(obj, type, flag); if (type == MAP_TREASURE || type == MAP_SWALLOWED_TREASURE || type == MAP_UPGRADE) { - mgr->mOtakaraNum++; + mgr->mTreasureCount++; } } } @@ -118,7 +118,7 @@ bool Radar::Mgr::exit(Game::TPositionObject* obj) int Radar::Mgr::getNumOtakaraItems() { if (mgr) { - return mgr->mOtakaraNum; + return mgr->mTreasureCount; } return 0; } @@ -132,12 +132,12 @@ void Radar::Mgr::attach(Game::TPositionObject* obj, Radar::cRadarType type, u32 detach(obj); // DUMB. this is needed to match as an inline in ogDummpyInit. // (just cast to the damn Point and use it smFh.) - CNode* cPoint = mPointNode2.mChild; - Point* point = static_cast(mPointNode2.mChild); + CNode* cPoint = mInactiveRadarNodes.mChild; + Point* point = static_cast(mInactiveRadarNodes.mChild); if (cPoint) { cPoint->del(); point->setData(obj, type, flag); - mPointNode1.add(cPoint); + mActiveRadarNodes.add(cPoint); } } @@ -147,7 +147,7 @@ void Radar::Mgr::attach(Game::TPositionObject* obj, Radar::cRadarType type, u32 */ bool Radar::Mgr::detach(Game::TPositionObject* obj) { - FOREACH_NODE(Point, mPointNode1.mChild, point) + FOREACH_NODE(Point, mActiveRadarNodes.mChild, point) { if (point->mObject != obj) { continue; @@ -159,10 +159,10 @@ bool Radar::Mgr::detach(Game::TPositionObject* obj) point->setData(nullptr, MAP_NULL_ICON, 0); if (type == MAP_TREASURE || type == MAP_SWALLOWED_TREASURE || type == MAP_UPGRADE) { - mgr->mOtakaraNum--; + mgr->mTreasureCount--; } - mPointNode2.add(point); + mInactiveRadarNodes.add(point); return true; } return false; @@ -172,52 +172,58 @@ bool Radar::Mgr::detach(Game::TPositionObject* obj) * @note Address: 0x8021E774 * @note Size: 0x1E0 */ -int Radar::Mgr::calcNearestTreasure(Vector3f& naviPos, f32 searchDist, Vector3f& treasurePos, f32& dist2) +Radar::Mgr::RadarSearchResult Radar::Mgr::calcNearestTreasure(Vector3f& naviPos, f32 searchDist, Vector3f& treasurePos, + f32& treasureDistance) { + // If any antennae beetles are alive if (mFuefukiCount > 0) { - if (mFuefukiTimer > 0) { - mFuefukiTimer--; - return 4; // Fuefuki active, but timer not expired + if (mFuefukiWhistleTimer > 0) { + mFuefukiWhistleTimer--; + return Radar::Mgr::WHISTLE_ACTIVE; // Whistle is active, but timer not expired } - return 3; // Fuefuki active, timer expired + return Radar::Mgr::WHISTLE_ACTIVE_TIMER_EXPIRED; // Whistle is active, timer expired } - Point* retPoint = nullptr; - int ret = 0; - f32 dist = searchDist; - FOREACH_NODE(Point, mPointNode1.mChild, cPoint) + Point* closestPoint = nullptr; + int treasureCount = 0; + f32 closestDistance = searchDist; + FOREACH_NODE(Point, mActiveRadarNodes.mChild, cPoint) { + // Skip if not a treasure if (cPoint->mObjType != MAP_TREASURE && cPoint->mObjType != MAP_SWALLOWED_TREASURE && cPoint->mObjType != MAP_UPGRADE) { - continue; // Skip if not a treasure + continue; } - ret++; - Game::Creature* cObj = static_cast(cPoint->mObject); - if (!cObj->isTeki()) { - cObj->isPellet(); + treasureCount++; + Game::Creature* creature = static_cast(cPoint->mObject); + if (!creature->isTeki()) { + creature->isPellet(); } - Vector3f objPos = cObj->getPosition(); - Sys::Sphere test; - Vector2f diff = Vector2f(objPos.x, objPos.z); - diff.x -= naviPos.x; - diff.y -= naviPos.z; - cObj->getBoundingSphere(test); - f32 cDist = _lenVec2D(diff) - test.mRadius; - if (cDist <= dist) { - dist = cDist; - retPoint = cPoint; - treasurePos = cObj->getPosition(); - dist2 = cDist; + Vector3f objPos = creature->getPosition(); + + Sys::Sphere boundingSphere; + Vector2f positionOffset = Vector2f(objPos.x, objPos.z); + positionOffset.x -= naviPos.x; + positionOffset.y -= naviPos.z; + creature->getBoundingSphere(boundingSphere); + + // Calculate the distance between the creature and the treasure + f32 cDist = _lenVec2D(positionOffset) - boundingSphere.mRadius; + if (cDist <= closestDistance) { + closestDistance = cDist; + closestPoint = cPoint; + treasurePos = creature->getPosition(); + treasureDistance = cDist; } } - if (retPoint != nullptr) { - return 2; // Found treasure + if (closestPoint != nullptr) { + return Radar::Mgr::CLOSEST_TREASURE_FOUND; // Found treasure } - return ret > 0; // No treasure found + return treasureCount > 0 ? Radar::Mgr::TREASURE_FOUND : Radar::Mgr::NO_TREASURE_FOUND; } /** diff --git a/src/plugProjectKandoU/singleGameSection.cpp b/src/plugProjectKandoU/singleGameSection.cpp index 01cce7090..28b3b061f 100644 --- a/src/plugProjectKandoU/singleGameSection.cpp +++ b/src/plugProjectKandoU/singleGameSection.cpp @@ -1057,27 +1057,31 @@ void SingleGameSection::setDispMemberNavi(og::Screen::DataNavi& data, int naviID * @note Address: N/A * @note Size: 0x148 */ -int SingleGameSection::calcOtakaraLevel(f32& dist) +Radar::Mgr::RadarSearchResult SingleGameSection::calcOtakaraLevel(f32& treasureDistance) { Navi* navi = naviMgr->getActiveNavi(); - int otastate = 5; - dist = 900.0f; + Radar::Mgr::RadarSearchResult treasureSearchResult = Radar::Mgr::NOT_PROCESSED; + treasureDistance = 900.0f; + if (navi) { - Vector3f pos = navi->getPosition(); - Vector3f out; - otastate = Radar::mgr->calcNearestTreasure(pos, 900.0f, out, dist); - if (otastate == 2) { - if (!(1.0f - (dist / 900.0f) < 0.0f)) { - return otastate; + Vector3f playerPosition = navi->getPosition(); + Vector3f treasurePosition; + treasureSearchResult = Radar::mgr->calcNearestTreasure(playerPosition, 900.0f, treasurePosition, treasureDistance); + + if (treasureSearchResult == Radar::Mgr::CLOSEST_TREASURE_FOUND) { + // If the distance is within the range (0 - 900.0f) + if (!(1.0f - (treasureDistance / 900.0f) < 0.0f)) { + return treasureSearchResult; // Return 2 } else { P2DEBUG("stuff"); } - } else if (otastate == 1) { + } else if (treasureSearchResult == Radar::Mgr::TREASURE_FOUND) { rand(); } } - return otastate; + + return treasureSearchResult; } /** @@ -1088,21 +1092,22 @@ void SingleGameSection::updateMainMapScreen() { og::Screen::DispMemberGround disp; - f32 dist; - int otastate = calcOtakaraLevel(dist); + f32 treasureDistance; + Radar::Mgr::RadarSearchResult treasureSearchResult = calcOtakaraLevel(treasureDistance); bool flag = false; - disp.mTreasureDist = dist; - disp.mRadarState = otastate; - if (!mNeedTreasureCalc && otastate == 0 && Screen::gGame2DMgr->is_GameGround()) { + disp.mTreasureDist = treasureDistance; + disp.mRadarState = treasureSearchResult; + if (!mNeedTreasureCalc && treasureSearchResult == Radar::Mgr::NO_TREASURE_FOUND && Screen::gGame2DMgr->is_GameGround()) { flag = true; mNeedTreasureCalc = true; } - if (!mTreasureRadarActive && otastate == 0) { + if (!mTreasureRadarActive && treasureSearchResult == Radar::Mgr::NO_TREASURE_FOUND) { mTreasureRadarActive = true; } - if (mTreasureRadarActive && otastate != 0 && otastate != 5) { + if (mTreasureRadarActive && treasureSearchResult != Radar::Mgr::NO_TREASURE_FOUND + && treasureSearchResult != Radar::Mgr::NOT_PROCESSED) { mTreasureRadarActive = false; mNeedTreasureCalc = false; } diff --git a/src/plugProjectOgawaU/ogObjSMenuMap.cpp b/src/plugProjectOgawaU/ogObjSMenuMap.cpp index f5104ae29..dfdd6ec43 100644 --- a/src/plugProjectOgawaU/ogObjSMenuMap.cpp +++ b/src/plugProjectOgawaU/ogObjSMenuMap.cpp @@ -312,7 +312,7 @@ void ObjSMenuMap::initMapIcon(JKRArchive* arc) Radar::mgr->ogDummpyInit(); } - FOREACH_NODE(Radar::Point, Radar::mgr->mPointNode1.mChild, cPoint) + FOREACH_NODE(Radar::Point, Radar::mgr->mActiveRadarNodes.mChild, cPoint) { int objType = cPoint->mObjType; JUT_ASSERTLINE(569, objType >= 0 && objType < 22, "Radar type ERR!! (%d)\n", objType);