Created
June 17, 2023 05:52
-
-
Save leoetlino/6e08d1626e5e082a03ce7be9fd91efed to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
bool MapIcon::Tower::isVisited() const { | |
gmd::StructHandle IsVisitLocation; | |
if (!gmd::GameDataMgr::instance()->getStruct(&IsVisitLocation, "IsVisitLocation")) { | |
return false; | |
} | |
bool visited; | |
if (!gmd::GameDataMgr::instance()->getBool(&visited, IsVisitLocation, mLocationNameHash)) { | |
return false; | |
} | |
return visited; | |
} | |
bool MapIcon::Shrine::isVisited() const { | |
gmd::StructHandle IsVisitLocation; | |
if (!gmd::GameDataMgr::instance()->getStruct(&IsVisitLocation, "IsVisitLocation")) { | |
return false; | |
} | |
bool visited; | |
if (!gmd::GameDataMgr::instance()->getBool2(&visited, IsVisitLocation, mLocationNameHash)) { | |
return false; | |
} | |
return visited; | |
} | |
bool MapIcon::LargeDungeon::isVisited() const { | |
gmd::StructHandle IsVisitLocation; | |
if (!gmd::GameDataMgr::instance()->getStruct(&IsVisitLocation, "IsVisitLocation")) { | |
return false; | |
} | |
bool visited; | |
if (!gmd::GameDataMgr::instance()->getBool(&visited, IsVisitLocation, mNameHash)) { | |
return false; | |
} | |
return visited; | |
} | |
bool MapIcon::Cave::isVisited() const { | |
gmd::StructHandle IsVisitLocation; | |
if (!gmd::GameDataMgr::instance()->getStruct(&IsVisitLocation, "IsVisitLocation")) { | |
return false; | |
} | |
bool visited; | |
if (!gmd::GameDataMgr::instance()->getBool2(&visited, IsVisitLocation, mLocationNameHash) || | |
!visited) { | |
return false; | |
} | |
if (mInstanceIdHash != 0) { | |
bool visited_cave = true; | |
gmd::StructHandle IsVisitLocationArea_CaveEntrance; | |
if (gmd::GameDataMgr::instance()->getStruct(&IsVisitLocationArea_CaveEntrance, | |
"IsVisitLocationArea_CaveEntrance")) { | |
gmd::GameDataMgr::instance()->getBool(&visited_cave, IsVisitLocationArea_CaveEntrance, | |
mInstanceIdHash); | |
if (!visited_cave) { | |
return false; | |
} | |
} | |
} | |
return true; | |
} | |
bool MapIcon::Spot::isVisited() const { | |
auto* location_table = RSDB::instance()->Location; | |
if (!location_table) { | |
return false; | |
} | |
const auto& location = location_table->rows[mLocationIdx]; | |
const auto category = location.Category; | |
const auto dependence_location_hash = location.DependenceLocationHash; | |
switch (category) { | |
case LocationCategory::SkyArchipelago: | |
case LocationCategory::SpotBigWater: | |
case LocationCategory::SpotBigArtifact: | |
case LocationCategory::SpotBigMagma: | |
case LocationCategory::SpotBigTimber: | |
case LocationCategory::SpotBigMountain: | |
case LocationCategory::SpotBigOther: | |
case LocationCategory::SpotMiddleWater: | |
case LocationCategory::SpotMiddleArtifact: | |
case LocationCategory::SpotMiddleMagma: | |
case LocationCategory::SpotMiddleTimber: | |
case LocationCategory::SpotMiddleMountain: | |
case LocationCategory::SpotMiddleOther: | |
case LocationCategory::SpotBigWithNameIcon: { | |
gmd::StructHandle handle; | |
if (!gmd::GameDataMgr::instance()->getStruct(&handle, "IsVisitLocation")) { | |
return false; | |
} | |
bool value; | |
if (!gmd::GameDataMgr::instance()->getBool(&value, handle, mLocationNameHash)) { | |
return false; | |
} | |
return value; | |
} | |
case LocationCategory::District: | |
case LocationCategory::SpotSmallWater: | |
case LocationCategory::SpotSmallArtifact: | |
case LocationCategory::SpotSmallMagma: | |
case LocationCategory::SpotSmallTimber: | |
case LocationCategory::SpotSmallMountain: | |
case LocationCategory::SpotSmallOther: { | |
if (dependence_location_hash == 0) { | |
return true; | |
} | |
gmd::StructHandle handle; | |
if (!gmd::GameDataMgr::instance()->getStruct(&handle, "IsOpenCannon")) { | |
return false; | |
} | |
bool value; | |
gmd::GameDataMgr::instance()->getBool2(&value, handle, dependence_location_hash); | |
return value; | |
} | |
default: | |
return false; | |
} | |
} | |
bool MapIcon::SpecialWarpPoint::isVisited() const { | |
if (!unkGmdGetter(0x34326518)) { | |
return false; | |
} | |
bool value = false; | |
switch (mType) { | |
case 0: | |
// WarpPos_StartIsland_WakeupAltar | |
return true; | |
case 1: | |
// WarpPoint_BlueprintShrine | |
gmd::GameDataMgr::instance()->getBool(&value, "OpenWarpPoint_BlueprintShrine"); | |
return value; | |
} | |
return false; | |
} | |
bool MapIcon::Labo::isVisited() const { | |
gmd::StructHandle handle; | |
if (!gmd::GameDataMgr::instance()->getStruct(&handle, "IsVisitLocation")) { | |
return false; | |
} | |
bool value; | |
if (!gmd::GameDataMgr::instance()->getBool2(&value, handle, mLocationNameHash)) { | |
return false; | |
} | |
return value; | |
} | |
bool MapIcon::PlaceOfInterest::isVisited() const { | |
bool value = false; | |
// from the game::location::Location | |
if (mOverrideIconFlagHash != 0) { | |
if (mOverrideIconFlagType == 0) { | |
gmd::GameDataMgr::instance()->getBool(&value, mOverrideIconFlagHash); | |
} else { | |
gmd::GameDataMgr::instance()->getBoolExp(&value, mOverrideIconFlagHash); | |
} | |
} else { | |
gmd::StructHandle handle; | |
if (gmd::GameDataMgr::instance()->getStruct(&handle, "IsVisitLocation")) { | |
gmd::GameDataMgr::instance()->getBool2(&value, handle, mLocationNameHash); | |
} | |
} | |
return value; | |
} | |
bool MapIcon::Shop::isVisited() const { | |
auto* location_table = RSDB::instance()->Location; | |
if (!location_table) { | |
return false; | |
} | |
const auto& location = location_table->rows[mLocationIdx]; | |
const auto dependence_location_hash = location.DependenceLocationHash; | |
const auto override_icon_flag_hash = location.OverrideIconFlagHash; | |
bool value = false; | |
if (override_icon_flag_hash != 0) { | |
if (mIsBoolExpFlag) { | |
gmd::GameDataMgr::instance()->getBoolExp(&value, override_icon_flag_hash); | |
} else { | |
gmd::GameDataMgr::instance()->getBool(&value, override_icon_flag_hash); | |
} | |
} else { | |
gmd::StructHandle handle; | |
if (gmd::GameDataMgr::instance()->getStruct(&handle, "IsVisitLocation")) { | |
gmd::GameDataMgr::instance()->getBool2(&value, handle, dependence_location_hash); | |
} | |
} | |
return value; | |
} | |
bool MapIcon::FairyFountain::isVisited() const { | |
// flag names from: | |
// GameParameter/FairyFountainGlobalSetting/Default.game__ui__FairyFountainGlobalSetting.bgyml | |
// | |
// - Fairy_MapOpen | |
// - Fairy_MapOpen_DressFairy_00 | |
// - Fairy_MapOpen_DressFairy_01 | |
// - Fairy_MapOpen_DressFairy_02 | |
// - HaveTalked.HorseGod001 | |
if (mHaveKnownFlagHash == 0) { | |
return true; | |
} | |
bool value; | |
if (mHaveKnownFlagType == 0) { | |
if (!gmd::GameDataMgr::instance()->getBool(&value, mHaveKnownFlagHash)) { | |
return false; | |
} | |
} else { | |
if (!gmd::GameDataMgr::instance()->getBoolExp(&value, mHaveKnownFlagHash)) { | |
return false; | |
} | |
} | |
return value; | |
} | |
bool MapIcon::ImportantShop::isVisited() const { | |
// EvilStatue "HaveKnownFlag": | |
// - HaveKnownDemonStatue_00 | |
// - HaveKnownDemonStatue_01 | |
// - HaveKnownDemonStatue_02 | |
// - HaveKnownDemonStatue_03 | |
// - HaveKnownDemonStatue_04 | |
// - HaveKnownDemonStatue_05 | |
// otherwise, the flag is the location's OverrideIconFlagHash | |
if (mFlagHash == 0) { | |
return true; | |
} | |
bool value; | |
if (mFlagType == 0) { | |
if (!gmd::GameDataMgr::instance()->getBool(&value, mFlagHash)) { | |
return false; | |
} | |
} else { | |
if (!gmd::GameDataMgr::instance()->getBoolExp(&value, mFlagHash)) { | |
return false; | |
} | |
} | |
return value; | |
} | |
bool MapIcon::ZonauRelief::isVisited() const { | |
auto* location_table = RSDB::instance()->Location; | |
if (!location_table) { | |
return false; | |
} | |
const auto& location = location_table->rows[mLocationIdx]; | |
const auto override_icon_flag_hash = location.OverrideIconFlagHash; | |
if (override_icon_flag_hash == 0) { | |
return true; | |
} | |
bool value; | |
if (mIsBoolExpFlag) { | |
gmd::GameDataMgr::instance()->getBoolExp(&value, override_icon_flag_hash); | |
} else { | |
gmd::GameDataMgr::instance()->getBool(&value, override_icon_flag_hash); | |
} | |
return value; | |
} | |
float MapIcon::calcMapCompletion() const { | |
int count = 0; | |
int total = 0; | |
// Towers | |
// | |
// LocationArea category: Tower | |
total += mTowers.size(); | |
for (const Tower* tower : mTowers) { | |
count += tower->isVisited(); | |
} | |
// Shrines and Lightroots | |
// | |
// LocationArea categories: Shrine, CheckPoint | |
// - must have OverrideIconType = None | |
for (const Shrine& shrine : mShrines) { | |
count += shrine.isVisited(); | |
sead::FixedSafeString<256> name; | |
shrine.getName(&name); // unused debug code? | |
} | |
total += mShrines.size(); | |
// Temples | |
// | |
// LargeDungeonWater/Fire/Wind/Thunder/Soul | |
for (const LargeDungeon* dungeon : mLargeDungeons) { | |
count += dungeon->isVisited(); | |
} | |
total += mLargeDungeons.size(); | |
// Caves | |
// | |
// LocationArea categories: CaveEntranceNormal, CaveEntranceSpecial, CaveEntranceWell | |
// - must have OverrideIconType = None | |
// - each entry can have multiple Trans values; each position generates a marker | |
for (const Cave& cave : mCaves) { | |
count += cave.isVisited(); | |
sead::FixedSafeString<256> name; | |
cave.getName(&name); | |
} | |
total += mCaves.size(); | |
// Spots | |
// | |
// LocationArea categories: | |
// ['District', 'SkyArchipelago', 'SpotBigWater', 'SpotBigArtifact', 'SpotBigMagma', | |
// 'SpotBigTimber', 'SpotBigMountain', 'SpotBigOther', 'SpotMiddleWater', 'SpotMiddleArtifact', | |
// 'SpotMiddleMagma', 'SpotMiddleTimber', 'SpotMiddleMountain', 'SpotMiddleOther', | |
// 'SpotSmallWater', 'SpotSmallArtifact', 'SpotSmallMagma', 'SpotSmallTimber', | |
// 'SpotSmallMountain', 'SpotSmallOther', 'SpotBigWithNameIcon'] | |
// | |
// - must have OverrideIconType = None | |
// - each entry can have multiple Trans values; each position generates a marker | |
// (up to a maximum of 32) | |
for (const Spot& spot : mSpots) { | |
count += spot.isVisited(); | |
sead::FixedSafeString<256> name; | |
spot.getName(&name); | |
} | |
total += mSpots.size(); | |
// Special fast travel locations | |
// | |
// WarpPos_StartIsland_WakeupAltar | |
// WarpPoint_BlueprintShrine | |
for (const SpecialWarpPoint& warp_point : mSpecialWarpPoints) { | |
count += warp_point.isVisited(); | |
} | |
total += mSpecialWarpPoints.size(); | |
// Hateno lab | |
count += mHatenoLabo->isVisited(); | |
total += 1; | |
// Places of interest | |
// | |
// - LocationArea categories: City, Stable | |
// - must have OverrideIconType = None | |
// | |
// - LocationArea (any category) | |
// - must have OverrideIconType = ['Building', 'Castle', 'NewspaperPublisher', | |
// 'PlayerHouse', 'JobField'] | |
for (const PlaceOfInterest* place : mPlacesOfInterest) { | |
count += place->isVisited(); | |
} | |
total += mPlacesOfInterest.size(); | |
// Shops (and places that are not actually shops) | |
// | |
// - LocationArea categories: ['ShopInn', 'ShopGeneral', 'ShopArmor', 'ShopDye', 'ShopJewelry'] | |
// - must have OverrideIconType = None | |
// - each entry can have multiple Trans values; each position generates a marker | |
// | |
// - LocationArea (any category) | |
// - must have OverrideIconType = ['SmallEvilStatue', 'TreasureBoxShop', 'CookingShop', | |
// 'ScrapShop', 'Bar', 'RentalZarashiShop', 'HorseStableBranchOffice', 'FigureGallery', | |
// 'InvestigatingGroupBase', 'Farm', 'School', 'Circuit_Uotori', 'Circuit_Ichikara'] | |
// - each entry can have multiple Trans values; each position generates a marker | |
for (const Shop& shop : mShops) { | |
count += shop.isVisited(); | |
sead::FixedSafeString<256> name; | |
shop.getName(&name); | |
} | |
total += mShops.size(); | |
// Koroks | |
// (self-explanatory so I won't bother decompiling isVisited()) | |
for (const Korok& korok : mKoroks) { | |
count += korok.isVisited(); | |
} | |
total += mKoroks.size(); | |
// Device dispensers | |
for (const RecycleBox& box : mRecycleBoxes) { | |
count += box.isVisited(); | |
} | |
total += mRecycleBoxes.size(); | |
// Dragon tears | |
for (const DragonTear* tear : mDragonTears) { | |
count += tear->isVisited(); | |
} | |
total += mDragonTears.size(); | |
// Fairy fountains | |
// OverrideIconType = ['FairyFountain', 'HorseFairyFountain'] | |
for (const FairyFountain* fountain : mFairyFountains) { | |
count += fountain->isVisited(); | |
// + unused debug crap | |
} | |
total += mFairyFountains.size(); | |
// Important shops | |
// OverrideIconType = ['EvilStatue', 'SmeltShop', 'ForgeShop', 'BatteryExchangeShop'] | |
for (const ImportantShop* shop : mImportantShops) { | |
count += shop->isVisited(); | |
// + unused debug crap | |
} | |
total += mImportantShops.size(); | |
// Ancient stone tablets | |
// OverrideIconType = 'ZonauRelief' | |
for (const ZonauRelief& relief : mZonauReliefs) { | |
count += relief.isVisited(); | |
// + unused debug crap | |
} | |
total += mZonauReliefs.size(); | |
if (total <= 0) | |
return 0.0; | |
else | |
return float(count) / float(total); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment