#include "System/GameDataFunction.h" #include #include "Library/Area/AreaObj.h" #include "Library/Area/AreaObjUtil.h" #include "Library/Base/Macros.h" #include "Library/Layout/LayoutActor.h" #include "Library/LiveActor/ActorPoseUtil.h" #include "Library/Math/MathUtil.h" #include "Library/Message/MessageHolder.h" #include "Library/Placement/PlacementFunction.h" #include "Library/Placement/PlacementId.h" #include "Library/Placement/PlacementInfo.h" #include "Library/Resource/ResourceFunction.h" #include "Library/Scene/Scene.h" #include "Library/Scene/SceneObjHolder.h" #include "Library/Scene/SceneObjUtil.h" #include "Library/Yaml/ByamlUtil.h" #include "Camera/ScenarioStartCamera.h" #include "Item/Shine.h" #include "Item/ShineInfo.h" #include "Layout/ShopLayoutInfo.h" #include "MapObj/RiseMapPartsHolder.h" #include "Npc/WorldTravelingNpc.h" #include "Player/PlayerFunction.h" #include "Scene/QuestInfo.h" #include "Scene/QuestInfoHolder.h" #include "Scene/TemporaryScenarioCameraHolder.h" #include "Sequence/ChangeStageInfo.h" #include "System/GameDataUtil.h" #include "System/GameProgressData.h" #include "System/MapDataHolder.h" #include "System/MoonRockData.h" #include "System/PlayerHitPointData.h" #include "System/WorldList.h" #include "Util/ClothUtil.h" #include "Util/ScenePrepoFunction.h" #include "Util/SpecialBuildUtil.h" #include "Util/StageLayoutFunction.h" namespace GameDataFunction { GameDataHolder* getGameDataHolder(const al::IUseSceneObjHolder* scene_obj_holder) { return al::getSceneObj(scene_obj_holder); } GameDataHolder* getGameDataHolder(const al::SceneObjHolder* scene_obj_holder) { return scene_obj_holder->getObj(); } GameDataHolder* getGameDataHolder(al::GameDataHolderBase* game_data_holder) { return static_cast(game_data_holder); } GameDataFile* getGameDataFile(GameDataHolderWriter writer) { return writer->getGameDataFile(); } void setPlayingFileId(GameDataHolderWriter writer, s32 file_id) { writer->setPlayingFileId(file_id); } void initializeData(GameDataHolderWriter writer, s32 file_id) { writer->initializeDataId(file_id); } bool isPlayDemoOpening(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isPlayDemoOpening(); } bool isGameClear(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isGameClear(); } void setRequireSave(GameDataHolderWriter writer) { writer->setRequireSave(); } void setRequireSaveFrame(GameDataHolderWriter writer) { writer->setRequireSaveFrame(); } s64 getPlayTimeTotal(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPlayTimeTotal(); } s64 getPlayTimeAcrossFile(GameDataHolderAccessor accessor) { return accessor->getPlayTimeAcrossFile(); } s64 getSaveDataIdForPrepo(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getSaveDataIdForPrepo(); } void startDemoStage(GameDataHolderWriter writer, const char* stage_name) { writer->getGameDataFile()->startDemoStage(stage_name); } bool tryChangeNextStage(GameDataHolderWriter writer, const ChangeStageInfo* info) { if (info->isEmpty()) return false; writer->changeNextStage(info); return true; } bool tryChangeNextStageWithStartRaceFlag(GameDataHolderWriter writer, const ChangeStageInfo* info) { if (info->isEmpty()) return false; writer->changeNextStage(info, GameDataFile::RaceType_Flag); return true; } bool tryChangeNextStageWithStartRaceYukimaru(GameDataHolderWriter writer, const ChangeStageInfo* info) { if (info->isEmpty()) return false; writer->changeNextStage(info, GameDataFile::RaceType_Yukimaru); return true; } bool tryChangeNextStageWithDemoWorldWarp(GameDataHolderWriter writer, const char* stage_name) { writer->changeNextStageWithDemoWorldWarp(stage_name); return true; } bool tryChangeNextStageWithWorldWarpHole(GameDataHolderWriter writer, const char* stage_name) { return writer->tryChangeNextStageWithWorldWarpHole(stage_name); } void changeNextStageWithStartTimeBalloon(GameDataHolderWriter writer, s32 scenario_no) { ChangeStageInfo info{writer, "TimeBalloonStart", getCurrentStageName(writer), false, scenario_no, ChangeStageInfo::RESET_MINI_GAME1}; writer->changeNextStage(&info); } const char* getCurrentStageName(GameDataHolderAccessor accessor) { return accessor->getCurrentStageName(); } void changeNextStageWithEndTimeBalloon(GameDataHolderWriter writer) { ChangeStageInfo info{writer, "TimeBalloonStart", getCurrentStageName(writer)}; writer->changeNextStage(&info); } void changeNextStageWithCloset(GameDataHolderWriter writer) { ChangeStageInfo info{writer, "ClosetStart", getCurrentStageName(writer)}; writer->changeNextStage(&info); } void findAreaAndChangeNextStage(GameDataHolderWriter writer, const al::LiveActor* actor, const sead::Vector3f* pos_override) { if (writer->getGameDataFile()->get_a2c() && writer->getGameDataFile()->getChangeStageInfo()->getSubScenarioType() != ChangeStageInfo::DEFAULT_SUB_SCENARIO) return; sead::Vector3f pos = al::getTrans(actor); if (pos_override) pos.set(*pos_override); al::AreaObj* area = al::tryFindAreaObj(actor, "ChangeStageArea", pos); ChangeStageInfo info{writer, *area->getPlacementInfo()}; tryChangeNextStage(writer, &info); } void returnPrevStage(GameDataHolderWriter writer) { writer->returnPrevStage(); } bool isTimeBalloonSequence(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getChangeStageInfo()->getSubScenarioType() == ChangeStageInfo::RESET_MINI_GAME1; } const char* getNextStageName(GameDataHolderAccessor accessor) { return accessor->getNextStageName(); } const char* getCurrentStageName(GameDataHolderAccessor accessor, s32 file_id) { return accessor->getCurrentStageName(file_id); } static bool isSeaOfTreeStage(const char* stage_name) { return al::isEqualString(stage_name, "ForestWorldWoodsStage") || al::isEqualString(stage_name, "ForestWorldWoodsCostumeStage") || al::isEqualString(stage_name, "ForestWorldWoodsTreasureStage"); } bool isSeaOfTreeStage(GameDataHolderAccessor accessor) { return isSeaOfTreeStage(getCurrentStageName(accessor)); } const char* getNextStageName(GameDataHolderAccessor accessor, s32 file_id) { return accessor->getNextStageName(file_id); } s32 calcNextScenarioNo(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->calcNextScenarioNo(); } void restartStage(GameDataHolderWriter writer) { writer->getGameDataFile()->restartStage(); } void missAndRestartStage(GameDataHolderWriter writer) { writer->validateCheckpointWarp(); writer->enableExplainAmiibo(); writer->getGameDataFile()->missAndRestartStage(); } bool isMissEndPrevStageForInit(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isMissEndPrevStage(); } bool isMissEndPrevStageForSceneDead(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isMissEndPrevStage(); } void reenterStage(GameDataHolderWriter writer) { writer->setStageEnding(); } s32 getNextWorldId(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getNextWorldId(); } s32 getPrevWorldId(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPrevWorldId(); } s32 getWorldNumForNewReleaseShop(GameDataHolderAccessor accessor) { const GameProgressData* game_progress_data = accessor->getGameDataFile()->getGameProgressData(); s32 unlock_world_num = game_progress_data->getUnlockWorldNum(); s32 count = 0; for (s32 i = 0; i < unlock_world_num; i++) { s32 world_id = game_progress_data->getWorldIdForWorldWarpHole(i); if (!isAlreadyGoWorld(accessor, world_id)) continue; const char* world_name = getWorldDevelopName(accessor, world_id); const sead::PtrArray>& list = accessor->getWorldsForNewReleaseShop(); for (s32 j = 0; j < list.size(); j++) { if (al::isEqualString(world_name, list[j]->cstr())) { count++; break; } } } return count; } // TODO: check what's happening here static s32 blackBox(s32 value) { __asm__("" : "+r"(value)); return value; } template static s32 search(s32 count, F fn) { for (s32 i = 0; i < count; i++) { s32 status = fn(i); if ((blackBox(status | 4) & 7) != 4) return status; } return 2; } s32 getWorldIdForNewReleaseShop(GameDataHolderAccessor accessor, s32 index) { const GameProgressData* game_progress_data = accessor->getGameDataFile()->getGameProgressData(); s32 result; s32 status = search(game_progress_data->getUnlockWorldNum(), [&](s32 i) { s32 world_id = game_progress_data->getWorldIdForWorldWarpHole(i); if (!isAlreadyGoWorld(accessor, world_id)) return 4; const char* world_name = getWorldDevelopName(accessor, world_id); const sead::PtrArray>& list = accessor->getWorldsForNewReleaseShop(); for (s32 j = 0; j < list.size(); j++) { if (al::isEqualString(world_name, list[j]->cstr())) { if (index == 0) { result = world_id; return 1; } else { index--; return 0; } } } return 0; }); return status == 2 ? 0 : result; } bool isForwardWorldWarpDemo(GameDataHolderAccessor accessor) { s32 prev_world_id = getPrevWorldId(accessor); s32 next_world_id = getNextWorldId(accessor); s32 world_num = getWorldNum(accessor); s32 next_world_id_for_demo = -1; s32 prev_world_id_for_demo = -1; for (s32 i = 0; i < world_num; i++) { s32 world_id = accessor->getGameDataFile()->getGameProgressData()->getWorldIdForWorldMap(i); if (world_id == prev_world_id) prev_world_id_for_demo = i; if (world_id == next_world_id) next_world_id_for_demo = i; } if (prev_world_id_for_demo == -1) prev_world_id_for_demo = prev_world_id; if (next_world_id_for_demo == -1) next_world_id_for_demo = next_world_id; return prev_world_id_for_demo <= next_world_id_for_demo; } s32 getWorldNum(GameDataHolderAccessor accessor) { return accessor->getWorldList()->getWorldNum(); } bool isFirstTimeNextWorld(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isFirstTimeNextWorld(); } bool checkIsNewWorldInAlreadyGoWorld(GameDataHolderAccessor accessor) { s32 world_id = getCurrentWorldIdNoDevelop(accessor); if (!isAlreadyGoWorld(accessor, world_id)) return false; const GameProgressData* game_progress_data = accessor->getGameDataFile()->getGameProgressData(); bool is_after_current_world = false; for (s32 i = 0; i < game_progress_data->getUnlockWorldNum(); i++) { if (!is_after_current_world) { if (game_progress_data->getWorldIdForWorldWarpHole(i) == world_id) is_after_current_world = true; continue; } if (accessor->getGameDataFile()->isAlreadyGoWorld( game_progress_data->getWorldIdForWorldWarpHole(i))) return false; } return is_after_current_world; } static s32 getScenarioNoImpl(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getScenarioNo(); } s32 getScenarioNo(const al::LiveActor* actor) { return getScenarioNoImpl(actor); } s32 getScenarioNo(const al::LayoutActor* layout) { return getScenarioNoImpl(layout); } s32 getScenarioNoPlacement(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getScenarioNoPlacement(); } bool isEqualScenario(const RiseMapPartsHolder* actor, s32 scenario_no) { return getScenarioNo(actor) == scenario_no; } s32 getMainQuestMin(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; return accessor->getWorldList()->getMainQuestMin(getCurrentWorldId(actor), getScenarioNoImpl(actor)); } s32 getCurrentWorldId(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCurrentWorldId(); } s32 getCurrentWorldIdNoDevelop(GameDataHolderAccessor accessor) { return sead::Mathi::clampMin(getCurrentWorldId(accessor), 0); } void clearStartId(GameDataHolderWriter writer) { writer->getGameDataFile()->clearStartId(); } void setCheckpointId(GameDataHolderWriter writer, const al::PlacementId* placement_id) { writer->setCheckpointId(placement_id); } void setRestartPointId(GameDataHolderWriter writer, const al::PlacementId* placement_id) { writer->getGameDataFile()->setRestartPointId(placement_id); } const char* tryGetRestartPointIdString(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->tryGetRestartPointIdString(); } const char* tryGetPlayerStartId(GameDataHolderAccessor accessor) { return accessor->getNextPlayerStartId(); } bool isPlayerStartObj(const al::LiveActor* actor, const al::ActorInitInfo& info) { return isPlayerStartObj(actor, *info.placementInfo); } bool isPlayerStartObj(const al::LiveActor* actor, const al::PlacementInfo& placement_info) { const char* str = tryGetPlayerStartId(actor); if (!str) return false; const char* start_id = nullptr; bool has_start_id = al::tryGetStringArg(&start_id, placement_info, "ChangeStageId"); return start_id && has_start_id && al::isEqualString(str, start_id); } bool isPlayerStartObj(const al::LiveActor* actor, const char* start_id) { const char* str = tryGetPlayerStartId(actor); return str && al::isEqualString(str, start_id); } bool isPlayerStartLinkedObj(const al::LiveActor* actor, const al::ActorInitInfo& info, const char* link_name) { s32 link_num = al::calcLinkChildNum(info, link_name); for (s32 i = 0; i < link_num; i++) { al::PlacementInfo placement_info; al::getLinksInfoByIndex(&placement_info, info, link_name, i); if (isPlayerStartObj(actor, placement_info)) return true; } return false; } void setStartShine(const al::LiveActor* actor, const ShineInfo* info) { getGameDataHolder(actor)->getGameDataFile()->setStartShine(info); } s32 getStartShineNextIndex(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getStartShineNextIndex(); } bool isAlreadyShowExplainCheckpointFlag(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isAlreadyShowExplainCheckpointFlag(); } bool isEnableShowExplainCheckpointFlag(GameDataHolderAccessor accessor) { return true; } void showExplainCheckpointFlag(GameDataHolderAccessor accessor) { accessor->getGameDataFile()->showExplainCheckpointFlag(); } void getLifeMaxUpItem(const al::LiveActor* actor) { if (PlayerFunction::isPlayerDeadStatus(actor)) return; GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->getPlayerHitPointData()->getMaxUpItem(); } s32 getPlayerHitPoint(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPlayerHitPointData()->getCurrent(); } s32 getPlayerHitPointMaxCurrent(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPlayerHitPointData()->getMaxCurrent(); } s32 getPlayerHitPointMaxNormal(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPlayerHitPointData()->getMaxWithoutItem(); } bool isPlayerHitPointMax(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPlayerHitPointData()->isMaxCurrent(); } bool isPlayerHitPointMaxWithItem(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPlayerHitPointData()->isMaxWithItem(); } void recoveryPlayer(const al::LiveActor* actor) { if (PlayerFunction::isPlayerDeadStatus(actor)) return; GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->getPlayerHitPointData()->recover(); } void recoveryPlayerForDebug(const al::LiveActor* actor) { if (PlayerFunction::isPlayerDeadStatus(actor)) return; GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->getPlayerHitPointData()->recoverForDebug(); } void recoveryPlayerMax(const al::LiveActor* actor) { if (PlayerFunction::isPlayerDeadStatus(actor)) return; GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->getPlayerHitPointData()->recoverMax(); } void recoveryPlayerForSystem(const GameDataHolder* game_data_holder) { game_data_holder->getGameDataFile()->getPlayerHitPointData()->recover(); } void recoveryPlayerMaxForSystem(const GameDataHolder* game_data_holder) { game_data_holder->getGameDataFile()->getPlayerHitPointData()->recoverMax(); } void initPlayerHitPointForSystem(const GameDataHolder* game_data_holder) { game_data_holder->getGameDataFile()->getPlayerHitPointData()->init(); } void damagePlayer(GameDataHolderWriter writer) { writer->getGameDataFile()->getPlayerHitPointData()->damage(); } void killPlayer(GameDataHolderWriter writer) { writer->getGameDataFile()->getPlayerHitPointData()->kill(); } bool isPlayerLifeZero(GameDataHolderAccessor accessor) { return getPlayerHitPoint(accessor) <= 0; } bool isGotShine(GameDataHolderAccessor accessor, const ShineInfo* info) { return accessor->getGameDataFile()->isGotShine(info); } bool isGotShine(GameDataHolderAccessor accessor, const al::PlacementId* placement_id) { ShineInfo shine_info; shine_info.init(getCurrentStageName(accessor), al::makeStringPlacementId(placement_id).cstr(), nullptr, nullptr, ShineInfo::Type_Shine); return isGotShine(accessor, &shine_info); } bool isGotShine(GameDataHolderAccessor accessor, const char* stage_name, const char* obj_id) { ShineInfo shine_info; shine_info.init(stage_name, obj_id, nullptr, nullptr, ShineInfo::Type_Shine); return isGotShine(accessor, &shine_info); } bool isGotShine(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->isGotShine(index); } bool isGotShine(const Shine* shine) { return shine->isGot(); } void setGotShine(GameDataHolderWriter writer, const ShineInfo* info) { writer->getGameDataFile()->setGotShine(info); } s32 getGotShineNum(GameDataHolderAccessor accessor, s32 file_id) { return file_id == -1 ? accessor->getGameDataFile()->getShineNum() : accessor->getGameDataFile(file_id)->getShineNum(); } const ShineInfo* getLatestGetShineInfo(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getLatestGetShineInfo(); } s32 getCurrentShineNum(GameDataHolderAccessor accessor) { if (isGameClear(accessor)) { s32 world_num = getWorldNum(accessor); s32 count = 0; for (s32 i = 0; i < world_num; i++) count += sead::Mathi::clampMin(accessor->getGameDataFile()->getShineNum(i) - accessor->getGameDataFile()->getPayShineNum(i), 0); return count; } return sead::Mathi::clampMin(accessor->getGameDataFile()->getShineNum() - accessor->getGameDataFile()->getPayShineNum(), 0); } s32 getTotalShineNum(GameDataHolderAccessor accessor, s32 file_id) { return file_id == -1 ? accessor->getGameDataFile()->getTotalShineNum() : accessor->getGameDataFile(file_id)->getTotalShineNum(); } s32 getTotalShopShineNum(GameDataHolderAccessor accessor, s32 file_id) { return file_id == -1 ? accessor->getGameDataFile()->getTotalShopShineNum() : accessor->getGameDataFile(file_id)->getTotalShopShineNum(); } bool tryGetNextMainScenarioLabel(sead::BufferedSafeString* out_label, sead::BufferedSafeString* out_stage_name, const al::IUseSceneObjHolder* scene_obj_holder) { GameDataHolderAccessor accessor{scene_obj_holder}; return accessor->getGameDataFile()->tryGetNextMainScenarioLabel(out_label, out_stage_name); } s32 getMainScenarioNumMax(GameDataHolderAccessor accessor) { return 10; } void setMainScenarioNo(GameDataHolderWriter writer, s32 scenario_no) { writer->getGameDataFile()->setMainScenarioNo(scenario_no); } bool tryGetNextMainScenarioPos(sead::Vector3f* out, GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->tryGetNextMainScenarioPos(out); } bool isPlayScenarioCamera(GameDataHolderAccessor accessor, const QuestInfo* info) { return accessor->getGameDataFile()->isPlayScenarioCamera(info); } bool isPlayAlreadyScenarioStartCamera(GameDataHolderAccessor accessor, s32 quest_no) { return accessor->isPlayAlreadyScenarioStartCamera(quest_no); } bool isEnterStageFirst(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isEnterStageFirst(); } bool isNextMainShine(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->isNextMainShine(index); } bool isMainShine(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->isMainShine(index); } bool isLatestGetMainShine(GameDataHolderAccessor accessor, const ShineInfo* info) { return accessor->getGameDataFile()->isLatestGetMainShine(info); } s32 tryFindLinkedShineIndex(const al::LiveActor* actor, const al::ActorInitInfo& info) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->tryFindLinkedShineIndex(info, actor); } s32 tryFindLinkedShineIndex(const al::LiveActor* actor, const al::ActorInitInfo& info, s32 link_index) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->tryFindLinkedShineIndex(info, link_index, actor); } s32 tryFindLinkedShineIndexByLinkName(const al::LiveActor* actor, const al::ActorInitInfo& info, const char* link_name) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->tryFindLinkedShineIndexByLinkName(actor, info, link_name); } s32 calcLinkedShineNum(const al::LiveActor* actor, const al::ActorInitInfo& info) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->calcLinkedShineNum(info); } s32 tryFindShineIndex(const al::LiveActor* actor, const al::ActorInitInfo& info) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->tryFindShineIndex(info); } s32 tryFindShineIndex(const al::LiveActor* actor, const char* stage_name, const char* obj_id) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->tryFindShineIndex(stage_name, obj_id); } s32 tryFindShineUniqueId(const al::Scene* scene, const ShineInfo* shine_info) { GameDataHolderAccessor accessor{scene}; return accessor->getGameDataFile()->tryFindUniqueId(shine_info); } void disableHintByShineIndex(const al::LiveActor* actor, s32 index) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->disableHintById(index); } void enableHintByShineIndex(const al::LiveActor* actor, s32 index) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->enableHintById(index); } bool calcIsGetMainShineAll(const al::IUseSceneObjHolder* scene_obj_holder) { GameDataHolderAccessor accessor{scene_obj_holder}; return accessor->getGameDataFile()->calcIsGetMainShineAll(scene_obj_holder); } bool calcIsGetShineAllInWorld(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->calcIsGetShineAllInWorld(world_id); } bool calcIsGetShineAllInAllWorld(GameDataHolderAccessor accessor) { for (s32 i = 0; i < getWorldNum(accessor); i++) if (!calcIsGetShineAllInWorld(accessor, i)) return false; return true; } bool tryFindAndInitShineInfoByOptionalId(ShineInfo* info, GameDataHolderAccessor accessor, const char* optional_id) { return accessor->getGameDataFile()->tryFindAndInitShineInfoByOptionalId(info, optional_id); } namespace { class SceneObjAccessor : public al::IUseSceneObjHolder { public: SceneObjAccessor(al::SceneObjHolder* scene_obj_holder) : mSceneObjHolder(scene_obj_holder) {} al::SceneObjHolder* getSceneObjHolder() const override { return mSceneObjHolder; } private: al::SceneObjHolder* mSceneObjHolder; }; } // namespace bool isGotLinkedShineBeforeInitActor(const al::ActorInitInfo& actor_info, const char* link_name) { SceneObjAccessor scene_obj_accessor{actor_info.actorSceneInfo.sceneObjHolder}; GameDataHolderAccessor accessor{&scene_obj_accessor}; return accessor->getGameDataFile()->isGotShine( accessor->getGameDataFile()->tryFindLinkedShineIndexByLinkName(&scene_obj_accessor, actor_info, link_name)); } bool checkIsComplete(const al::IUseSceneObjHolder* scene_obj_holder, s32 file_id) { const GameDataFile* game_data_file = getGameDataHolder(scene_obj_holder)->getGameDataFile(file_id); for (s32 i = 0; i < getWorldNum(scene_obj_holder); i++) if (!game_data_file->calcIsGetShineAllInWorld(i)) return false; al::Resource* resource = al::findOrCreateResource("SystemData/HackObjList", nullptr); al::ByamlIter iter{al::findResourceYaml(resource, "HackObjList", nullptr)}; s32 hack_obj_count = iter.getSize(); for (s32 i = 0; i < hack_obj_count; i++) { al::ByamlIter subiter; iter.tryGetIterByIndex(&subiter, i); if (al::tryGetByamlKeyBoolOrFalse(subiter, "IsDebug")) continue; const char* hack_name = al::getByamlKeyString(subiter, "HackName"); if (!isExistInHackDictionary(scene_obj_holder, hack_name, file_id)) return false; } if (!rs::isCompleteCloth(scene_obj_holder, file_id) || !rs::isCompleteCap(scene_obj_holder, file_id) || !rs::checkCompleteGift(scene_obj_holder, file_id) || !rs::checkCompleteSticker(scene_obj_holder, file_id)) return false; if (getCollectedBgmNum(scene_obj_holder, file_id) != getCollectedBgmMaxNum(scene_obj_holder)) return false; return true; } bool isEnableOpenMoonRock(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->isEnableOpenMoonRock(getCurrentWorldIdNoDevelop(actor)); } void openMoonRock(const al::LiveActor* actor, const al::PlacementId*) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->unlockHintAddByMoonRock(); } bool isOpenMoonRock(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isOpenMoonRock(getCurrentWorldIdNoDevelop(accessor)); } bool isEnableShowDemoOpenMoonRockFirst(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getMoonRockData()->isEnableShowDemoOpenMoonRockFirst(); } bool isEnableShowDemoOpenMoonRockWorld(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getMoonRockData()->isEnableShowDemoOpenMoonRockWorld( getCurrentWorldIdNoDevelop(accessor)); } void showDemoOpenMoonRockFirst(GameDataHolderAccessor accessor) { accessor->getGameDataFile()->getMoonRockData()->showDemoOpenMoonRockFirst(); } void showDemoOpenMoonRockWorld(GameDataHolderAccessor accessor) { accessor->getGameDataFile()->getMoonRockData()->showDemoOpenMoonRockWorld( getCurrentWorldIdNoDevelop(accessor)); } s32 calcMoonRockTalkMessageIndex(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getMoonRockData()->calcMoonRockTalkMessageIndex(); } void addMoonRockTalkMessageIndex(GameDataHolderWriter writer) { writer->getGameDataFile()->getMoonRockData()->addMoonRockTalkMessageIndex( getCurrentWorldId(writer)); } bool isAppearedMoonRockTalkMessage(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getMoonRockData()->isAppearedMoonRockTalkMessage( getCurrentWorldId(accessor)); } void addPayShine(GameDataHolderWriter writer, s32 count) { writer->getGameDataFile()->addPayShine(count); } void addPayShineCurrentAll(GameDataHolderWriter writer) { writer->getGameDataFile()->addPayShineCurrentAll(); } s32 getPayShineNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPayShineNum(); } s32 getPayShineNum(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->getPayShineNum(world_id); } s32 getTotalPayShineNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getTotalPayShineNum(); } s32 getTotalPayShineNumClamp(GameDataHolderAccessor accessor) { return sead::Mathi::clampMax(getTotalPayShineNum(accessor), 999); } bool isPayShineAllInAllWorld(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isPayShineAllInAllWorld(); } void addKey(GameDataHolderWriter writer, s32 count) { writer->getGameDataFile()->addKey(count); } s32 getKeyNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getKeyNum(); } s32 getCurrentKeyNum(GameDataHolderAccessor accessor) { return getKeyNum(accessor) - getOpenDoorLockNum(accessor); } s32 getOpenDoorLockNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getOpenDoorLockNum(); } void openDoorLock(GameDataHolderWriter writer, const al::PlacementId* placement_id) { if (isOpenDoorLock(writer, placement_id)) return; writer->getGameDataFile()->addOpenDoorLockNum(1); writer->getGameDataFile()->setStartedObj(placement_id); } bool isOpenDoorLock(GameDataHolderAccessor accessor, const al::PlacementId* placement_id) { return accessor->getGameDataFile()->isStartedObj(placement_id); } void setObjStarted(GameDataHolder* game_data_holder, const al::PlacementId* placement_id) { game_data_holder->getGameDataFile()->setStartedObj(placement_id); } bool isObjStarted(const GameDataHolder* game_data_holder, const al::PlacementId* placement_id) { return game_data_holder->getGameDataFile()->isStartedObj(placement_id); } bool isObjStarted(GameDataHolderAccessor accessor, const char* stage_name, const char* obj_id) { return accessor->getGameDataFile()->isStartedObj(stage_name, obj_id); } void saveObjS32(GameDataHolderWriter writer, const al::PlacementId* placement_id, s32 value) { writer->getGameDataFile()->setSaveObjS32(placement_id, value); } bool tryFindSaveObjS32Value(s32* out, GameDataHolderAccessor accessor, const al::PlacementId* placement_id) { if (const GameDataFile::SaveObjS32* obj = accessor->getGameDataFile()->tryFindSaveObjS32(placement_id)) { *out = obj->value; return true; } return false; } void onObjNoWriteSaveData(GameDataHolderWriter writer, const al::PlacementId* placement_id) { writer->onObjNoWriteSaveData(placement_id); } void offObjNoWriteSaveData(GameDataHolderWriter writer, const al::PlacementId* placement_id) { writer->offObjNoWriteSaveData(placement_id); } bool isOnObjNoWriteSaveData(GameDataHolderAccessor accessor, const al::PlacementId* placement_id) { return accessor->isOnObjNoWriteSaveData(placement_id); } void onObjNoWriteSaveDataResetMiniGame(GameDataHolderWriter writer, const al::PlacementId* placement_id) { writer->onObjNoWriteSaveDataResetMiniGame(placement_id); } void offObjNoWriteSaveDataResetMiniGame(GameDataHolderWriter writer, const al::PlacementId* placement_id) { writer->offObjNoWriteSaveDataResetMiniGame(placement_id); } bool isOnObjNoWriteSaveDataResetMiniGame(GameDataHolderAccessor accessor, const al::PlacementId* placement_id) { return accessor->isOnObjNoWriteSaveDataResetMiniGame(placement_id); } void onObjNoWriteSaveDataInSameScenario(GameDataHolder* game_data_holder, const al::PlacementId* placement_id) { game_data_holder->onObjNoWriteSaveDataInSameScenario(placement_id); } bool isOnObjNoWriteSaveDataInSameScenario(const GameDataHolder* game_data_holder, const al::PlacementId* placement_id) { return game_data_holder->isOnObjNoWriteSaveDataInSameScenario(placement_id); } void setSessionEventProgress(GameDataHolderWriter writer, const SessionEventProgress& progress) { writer->getGameDataFile()->setSessionEventProgress(progress); } const SessionEventProgress& getSessionEventProgress(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getSessionEventProgress(); } bool isPayCoinToSphinx(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->isPayCoinToSphinx(); } void payCoinToSphinx(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->payCoinToSphinx(); } static GameDataFile::CapStatus getCapStatusForJango(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCapStatusForJango(); } static void setCapStatusForJango(GameDataHolderAccessor accessor, GameDataFile::CapStatus status) { return accessor->getGameDataFile()->setCapStatusForJango(status); } static GameDataFile::CapStatus getCapStatusForJangoSubArea(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCapStatusForJangoSubArea(); } static void setCapStatusForJangoSubArea(GameDataHolderAccessor accessor, GameDataFile::CapStatus status) { return accessor->getGameDataFile()->setCapStatusForJangoSubArea(status); } bool isRemovedCapByJango(const al::LiveActor* actor) { if (!isMainStage(actor)) return getCapStatusForJangoSubArea(actor) == GameDataFile::CapStatus::Removed; return getCapStatusForJango(actor) == GameDataFile::CapStatus::Removed; } bool isGetCapFromJango(const al::LiveActor* actor) { if (!isMainStage(actor)) return getCapStatusForJangoSubArea(actor) == GameDataFile::CapStatus::GotBack; return getCapStatusForJango(actor) == GameDataFile::CapStatus::GotBack; } void removeCapByJango(const al::LiveActor* actor) { if (!isMainStage(actor)) { setCapStatusForJangoSubArea(actor, GameDataFile::CapStatus::Removed); return; } setCapStatusForJango(actor, GameDataFile::CapStatus::Removed); } void getCapFromJango(const al::LiveActor* actor) { if (!isMainStage(actor)) { setCapStatusForJangoSubArea(actor, GameDataFile::CapStatus::GotBack); return; } setCapStatusForJango(actor, GameDataFile::CapStatus::GotBack); } void addJangoCount(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->addJangoCount(); } s32 getJangoCount(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->getJangoCount(); } bool isFirstWorldTravelingStatus(const WorldTravelingNpc* actor) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->isFirstWorldTravelingStatus(); } void saveWorldTravelingStatus(const WorldTravelingNpc* actor, const char* status) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->saveWorldTravelingStatus(status); } const char* getWorldTravelingStatus(const WorldTravelingNpc* actor) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->getWorldTravelingStatus(); } bool isRaceStart(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isRaceStart(); } bool isRaceStartFlag(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceType() == GameDataFile::RaceType_Flag; } bool isRaceStartYukimaru(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceType() == GameDataFile::RaceType_Yukimaru; } bool isRaceStartYukimaruTutorial(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceType() == GameDataFile::RaceType_YukimaruTutorial; } bool isRaceWin(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceResult() == GameDataFile::RaceResult_Win; } bool isRaceWin(GameDataHolderAccessor, s32) { return false; } bool isRaceResultSecond(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceResult() == GameDataFile::RaceResult_Second; } bool isRaceResultThird(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceResult() == GameDataFile::RaceResult_Third; } bool isRaceLose(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceResult() == GameDataFile::RaceResult_Lose; } bool isRaceCancel(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceResult() == GameDataFile::RaceResult_Cancel; } void winRace(GameDataHolderWriter writer) { writer->getGameDataFile()->winRace(); } void endRaceResultSecond(GameDataHolderWriter writer) { writer->getGameDataFile()->setRaceResult(GameDataFile::RaceResult_Second); } void endRaceResultThird(GameDataHolderWriter writer) { writer->getGameDataFile()->setRaceResult(GameDataFile::RaceResult_Third); } void loseRace(GameDataHolderWriter writer) { writer->getGameDataFile()->setRaceResult(GameDataFile::RaceResult_Lose); } static s32 getRaceRivalLevelImpl(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceRivalLevel(); } s32 getRaceRivalLevel(const al::LiveActor* actor) { return getRaceRivalLevelImpl(actor); } s32 getRaceRivalLevel(const al::Scene* scene) { return getRaceRivalLevelImpl(scene); } void setRaceRivalLevel(const al::LiveActor* actor, s32 level) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setRaceRivalLevel(level); } void setLastRaceRanking(GameDataHolderAccessor accessor, s32 ranking) { accessor->getGameDataFile()->setLastRaceRanking(ranking); } s32 getLastRaceRanking(GameDataHolderWriter writer) { return writer->getGameDataFile()->getLastRaceRanking(); } void incrementRaceLoseCount(const al::Scene* scene, s32 level) { GameDataHolderAccessor accessor{scene}; accessor->getGameDataFile()->incrementRaceLoseCount(level); } s32 getRaceLoseCount(const al::LiveActor* actor, s32 level) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->getRaceLoseCount(level); } void addCoinCollect(GameDataHolderWriter writer, const al::PlacementId* placement_id) { writer->getGameDataFile()->addCoinCollect(placement_id); } void useCoinCollect(GameDataHolderWriter writer, s32 count) { writer->getGameDataFile()->useCoinCollect(count); } bool isGotCoinCollect(GameDataHolderAccessor accessor, const al::ActorInitInfo& actor_info) { al::PlacementId placement_id; al::tryGetPlacementId(&placement_id, actor_info); return accessor->getGameDataFile()->isGotCoinCollect(&placement_id); } s32 getCoinCollectNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCoinCollectNum(); } s32 getCoinCollectGotNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCoinCollectGotNum(); } s32 getCoinCollectGotNum(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->getCoinCollectGotNum(world_id); } s32 getCoinCollectNumMax(GameDataHolderAccessor accessor) { return accessor->getCoinCollectNumMax(getCurrentWorldId(accessor)); } s32 getCoinCollectNumMax(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getCoinCollectNumMax(world_id); } bool tryFindExistCoinCollectStagePosExcludeHomeStageInCurrentWorld( sead::Vector3f* out_pos, const char** out_stage_name, GameDataHolderAccessor accessor) { s32 world_id = getCurrentWorldIdNoDevelop(accessor); if (const char* stage_name = accessor->getGameDataFile()->tryFindExistCoinCollectStageName(world_id)) { if (accessor->getWorldList()->tryFindTransOnMainStageByStageName( out_pos, stage_name, getWorldScenarioNo(accessor, world_id))) { *out_stage_name = stage_name; return true; } } return false; } s32 getWorldScenarioNo(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->getScenarioNo(world_id); } void addCoin(GameDataHolderWriter writer, s32 count) { writer->getGameDataFile()->addCoin(count); } void subCoin(GameDataHolderWriter writer, s32 count) { writer->getGameDataFile()->addCoin(-count); } s32 getCoinNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCoinNum(); } s32 getTotalCoinNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getTotalCoinNum(); } bool isAppearCourseName(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isAppearCourseName(); } void setStageHakoniwa(GameDataHolderWriter writer) { writer->getGameDataFile()->setStageHakoniwa(); } bool isEnableCheckpointWarp(GameDataHolderAccessor accessor) { return accessor->isEnableCheckpointWarp(); } void validateCheckpointWarp(GameDataHolderWriter writer) { writer->validateCheckpointWarp(); } void invalidateCheckpointWarp(GameDataHolderWriter writer) { writer->invalidateCheckpointWarp(); } s32 getCheckpointNumMaxInWorld(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCheckpointNumMaxInWorld(); } const sead::Vector3f& getCheckpointTransInWorld(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->getCheckpointTransInWorld( getCheckpointObjIdInWorld(accessor, index)); } const sead::Vector3f& getCheckpointTransInWorld(GameDataHolderAccessor accessor, const char* obj_id) { return accessor->getGameDataFile()->getCheckpointTransInWorld(obj_id); } const char* getCheckpointObjIdInWorld(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->getCheckpointObjIdInWorld(index); } bool isGotCheckpointInWorld(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->isGotCheckpointInWorld(index); } bool isGotCheckpoint(GameDataHolderAccessor accessor, al::PlacementId* placement_id) { return accessor->getGameDataFile()->isGotCheckpoint(placement_id); } s32 calcGotCheckpointNumInWorld(GameDataHolderAccessor accessor) { s32 max = getCheckpointNumMaxInWorld(accessor); s32 count = 0; for (s32 i = 0; i < max; i++) if (isGotCheckpointInWorld(accessor, i)) count++; return count; } void changeNextSceneByGotCheckpoint(GameDataHolderWriter writer, s32 index) { writer->getGameDataFile()->changeNextSceneByGotCheckpoint(index); } void changeNextSceneByHome(GameDataHolderWriter writer) { writer->getGameDataFile()->changeNextSceneByHome(); } bool isWarpCheckpoint(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isWarpCheckpoint(); } const char* getCheckpointWarpObjId(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCheckpointWarpObjId(); } void registerCheckpointTrans(GameDataHolderWriter writer, const al::PlacementId* placement_id, const sead::Vector3f& trans) { writer->getGameDataFile()->registerCheckpointTrans(placement_id, trans); } bool isEnableUnlockHint(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isEnableUnlockHint(); } void unlockHint(GameDataHolderWriter writer) { writer->getGameDataFile()->unlockHint(); } void unlockHintAmiibo(GameDataHolderWriter writer) { writer->getGameDataFile()->unlockHintAmiibo(); } s32 calcHintNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->calcHintNum(); } s32 calcRestHintNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->calcRestHintNum(); } bool checkExistHint(GameDataHolderAccessor accessor) { return calcHintNum(accessor) > 0; } s32 getHintNumMax(GameDataHolderAccessor accessor) { return 70; } const sead::Vector3f& calcHintTrans(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->calcHintTrans(index); } const sead::Vector3f& getLatestHintTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getLatestHint()->trans; } bool checkLatestHintSeaOfTree(GameDataHolderAccessor accessor) { return isSeaOfTreeStage(accessor->getGameDataFile()->getLatestHint()->stageName.cstr()); } s32 calcHintMoonRockNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->calcHintMoonRockNum(); } s32 getHintMoonRockNumMax(GameDataHolderAccessor accessor) { return 25; } const sead::Vector3f& calcHintMoonRockTrans(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->calcHintMoonRockTrans(index); } void initializeHintList(GameDataHolderWriter writer) { writer->getGameDataFile()->initializeHintList(); } const sead::Vector3f& calcHintTransMostEasy(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->calcHintTransMostEasy(); } bool calcHintTransMostNear(sead::Vector3f* out, GameDataHolderAccessor accessor, const sead::Vector3f& pos) { s32 hint_num = calcHintNum(accessor); if (hint_num == 0) return false; f32 min_dist = sead::Mathf::maxNumber(); for (s32 i = 0; i < hint_num; i++) { sead::Vector3f trans = calcHintTrans(accessor, i); f32 dist = (trans - pos).length(); if (dist < min_dist) { out->set(trans); min_dist = dist; } } return true; } bool checkHintSeaOfTree(GameDataHolderAccessor accessor, s32 index) { return isSeaOfTreeStage(accessor->getGameDataFile()->findHint(index).stageName.cstr()); } bool checkHintSeaOfTreeMoonRock(GameDataHolderAccessor accessor, s32 index) { return isSeaOfTreeStage(accessor->getGameDataFile()->findHintMoonRock(index).stageName.cstr()); } s32 findUnlockShineNum(bool* out_is_game_clear, GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->findUnlockShineNumCurrentWorld(out_is_game_clear); } s32 findUnlockShineNumByWorldId(bool* out_is_game_clear, GameDataHolderAccessor accessor, s32 world_id) { return accessor->findUnlockShineNum(out_is_game_clear, world_id); } bool isUnlockedWorld(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->isUnlockedWorld(world_id); } bool isUnlockedNextWorld(GameDataHolderAccessor accessor) { bool is_game_clear = false; s32 unlock_shine_num = findUnlockShineNum(&is_game_clear, accessor); return is_game_clear || getPayShineNum(accessor) >= unlock_shine_num; } bool isUnlockedAllWorld(GameDataHolderAccessor accessor) { return isUnlockedWorld(accessor, getWorldIndexSpecial2()); } bool isUnlockedCurrentWorld(GameDataHolderAccessor accessor) { return isUnlockedWorld(accessor, getCurrentWorldIdNoDevelop(accessor)); } bool isCollectShineForNextWorldAndNotUnlockNextWorld(const al::LiveActor* actor) { return !isUnlockedNextWorld(actor) && rs::checkGetEnoughShineInCurrentWorld(actor); } bool isAlreadyGoWorld(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->isAlreadyGoWorld(world_id); } bool isMainStage(GameDataHolderAccessor accessor) { return al::isEqualString(getMainStageName(accessor, getCurrentWorldId(accessor)), getCurrentStageName(accessor)); } const char* getMainStageName(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getWorldList()->getMainStageName(world_id); } const char* tryGetCurrentMainStageName(GameDataHolderAccessor accessor) { s32 world_id = getCurrentWorldId(accessor); if (world_id >= 1) { const char* stage_name = getMainStageName(accessor, world_id); if (stage_name && !al::isEqualString(stage_name, "")) return stage_name; } return getMainStageName(accessor, 0); } const char16* tryGetWorldName(const al::LayoutActor* layout, s32 world_id) { al::StringTmp<128> label; label.format("WorldName_%s", getWorldDevelopName(layout, world_id)); return al::getSystemMessageString(layout, "StageName", label.cstr()); } const char16* tryGetWorldNameCurrent(const al::LayoutActor* layout) { return tryGetWorldName(layout, getCurrentWorldId(layout)); } const char16* tryGetRegionNameCurrent(const al::LayoutActor* layout) { s32 world_id = getCurrentWorldId(layout); al::StringTmp<128> label; label.format("RegionName_%s", getWorldDevelopName(layout, world_id)); return al::getSystemMessageString(layout, "StageName", label.cstr()); } const char* getWorldDevelopName(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getWorldList()->getWorldDevelopName(sead::Mathi::max(world_id, 0)); } const char* getWorldDevelopNameCurrent(GameDataHolderAccessor accessor) { return accessor->getWorldList()->getWorldDevelopName( accessor->getGameDataFile()->getCurrentWorldIdNoDevelop()); } s32 getWorldScenarioNum(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getWorldList()->getWorldScenarioNum(sead::Mathi::max(world_id, 0)); } const char* findMainStageNameByDevelopName(GameDataHolderAccessor accessor, const char* name) { for (s32 i = 0; i < getWorldNum(accessor); i++) if (al::isEqualString(getWorldDevelopName(accessor, i), name)) return getMainStageName(accessor, i); return nullptr; } s32 findWorldIdByDevelopName(GameDataHolderAccessor accessor, const char* name) { for (s32 i = 0; i < getWorldNum(accessor); i++) if (al::isEqualString(getWorldDevelopName(accessor, i), name)) return i; return 0; } static s32 tryFindWorldIdByMainStageNameImpl(GameDataHolderAccessor accessor, const char* stage_name) { return accessor->getWorldList()->tryFindWorldIndexByMainStageName(stage_name); } s32 tryFindWorldIdByMainStageName(const al::Scene* scene, const char* stage_name) { return tryFindWorldIdByMainStageNameImpl(scene, stage_name); } s32 tryFindWorldIdByMainStageName(const al::IUseSceneObjHolder* scene_obj_holder, const char* stage_name) { return tryFindWorldIdByMainStageNameImpl(scene_obj_holder, stage_name); } bool checkEnableUnlockWorldSpecial1(const al::LiveActor* actor) { if (isUnlockedWorld(actor, getWorldIndexSpecial1()) || isUnlockedWorld(actor, getWorldIndexSpecial2())) return false; bool is_game_clear = false; s32 unlock_shine_num = findUnlockShineNum(&is_game_clear, actor); return is_game_clear && getTotalPayShineNum(actor) >= unlock_shine_num; } bool checkEnableUnlockWorldSpecial2(const al::LiveActor* actor) { if (!isUnlockedWorld(actor, getWorldIndexSpecial1()) || isUnlockedWorld(actor, getWorldIndexSpecial2())) return false; bool is_game_clear = false; s32 unlock_shine_num = findUnlockShineNum(&is_game_clear, actor); return is_game_clear && getTotalPayShineNum(actor) >= unlock_shine_num; } const char16* tryGetWorldNameByFileId(const al::LayoutActor* layout, s32 file_id) { GameDataHolderAccessor accessor{layout}; s32 world_id = accessor->getGameDataFile(file_id)->getCurrentWorldIdForDisp(); return tryGetWorldName(layout, world_id); } bool isNewSaveDataByFileId(const al::LayoutActor* layout, s32 file_id) { GameDataHolderAccessor accessor{layout}; return accessor->getGameDataFile(file_id)->isPlayDemoOpening(); } u64 getLastUpdateFileTime(const al::LayoutActor* layout, s32 file_id) { GameDataHolderAccessor accessor{layout}; return accessor->getGameDataFile(file_id)->getLastUpdateTime(); } static bool isGotShine(const GameDataHolder* game_data_holder, const char* stage_name, const char* obj_id) { ShineInfo shine_info; shine_info.init(stage_name, obj_id, nullptr, nullptr, ShineInfo::Type_Shine); return game_data_holder->getGameDataFile()->isGotShine(&shine_info); } void makeTextureSaveDataFileName(sead::BufferedSafeString* out, const nn::g3d::ResFile* res_file, const GameDataHolder* game_data_holder, s32 file_id) { const GameDataFile* game_data_file = game_data_holder->getGameDataFile(file_id); s32 world_id = sead::Mathi::clampMin(game_data_file->getCurrentWorldIdForDisp(), 0); const char* world_name = game_data_holder->getWorldList()->getWorldDevelopName(world_id); s32 main_scenario_no = game_data_file->getMainScenarioNo(world_id); s32 scenario_no = game_data_file->getScenarioNo(world_id); if (world_id == getWorldIndexPeach()) { if (game_data_file->getTotalPayShineNumForDisp() == 999) { out->format("PeachWorldCapOn"); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; } out->format("PeachWorld"); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; } if (game_data_holder->getWorldList()->isEqualMoonRockScenarioNo(world_id, scenario_no)) { out->format("%sWorldMoonRock", world_name); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; out->format("%sWorldED", world_name); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; out->format("%sWorld", world_name); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; return; } if (game_data_holder->getWorldList()->isEqualAfterEndingScenarioNo(world_id, scenario_no)) { out->format("%sWorldED", world_name); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; out->format("%sWorld", world_name); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; return; } if (world_id == getWorldIndexCity()) { if (scenario_no == 1) { out->format("CityWorld00"); return; } if (scenario_no == 2) { if (main_scenario_no <= 3) { out->format("CityWorld01"); return; } out->format("CityWorld02"); return; } if (isCityWorldCeremonyAll(world_id, scenario_no)) { out->format("CityWorld03"); return; } out->format("CityWorld"); return; } if (world_id == getWorldIndexSea()) { if (scenario_no == 1) { if (main_scenario_no == 0) { s32 count = 0; if (isGotShine(game_data_holder, "SeaWorldHomeStage", "obj382")) count++; if (isGotShine(game_data_holder, "SeaWorldLighthouseZone", "obj16")) count++; if (isGotShine(game_data_holder, "SeaWorldLavaZone", "obj168")) count++; if (isGotShine(game_data_holder, "SeaWorldDamageBallZone", "obj60")) count++; if (count == 0) { out->format("SeaWorld00"); return; } out->format("SeaWorld01"); return; } if (main_scenario_no == 1) { out->format("SeaWorld02"); return; } } out->format("SeaWorld"); return; } if (game_data_file->isPlayDemoOpening()) { out->format("Empty"); return; } if (main_scenario_no >= 0) { out->format("%sWorld%02d", world_name, main_scenario_no); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; } out->format("%sWorld", world_name); if (agl::g3d::ResFile::GetTextureIndex(res_file, out->cstr()) != -1) return; } void unlockWorld(GameDataHolderWriter writer, s32 world_id) { writer->getGameDataFile()->unlockWorld(world_id); } static s32 getUnlockWorldIdForWorldMapImpl(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->getGameProgressData()->getWorldIdForWorldMap(world_id); } s32 getUnlockWorldIdForWorldMap(const al::LayoutActor* layout, s32 world_id) { return getUnlockWorldIdForWorldMapImpl(layout, world_id); } s32 getUnlockWorldIdForWorldMap(const al::LiveActor* actor, s32 world_id) { return getUnlockWorldIdForWorldMapImpl(actor, world_id); } s32 getUnlockWorldIdForWorldMap(const al::Scene* scene, s32 world_id) { return getUnlockWorldIdForWorldMapImpl(scene, world_id); } s32 getUnlockWorldIdForWorldMap(const GameDataHolder* game_data_holder, s32 world_id) { return game_data_holder->getGameDataFile()->getGameProgressData()->getWorldIdForWorldMap( world_id); } static s32 getUnlockWorldNumForWorldMapImpl(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->getUnlockWorldNum(); } s32 getUnlockWorldNumForWorldMap(const al::Scene* scene) { return getUnlockWorldNumForWorldMapImpl(scene); } s32 getUnlockWorldNumForWorldMap(const al::LiveActor* actor) { return getUnlockWorldNumForWorldMapImpl(actor); } s32 getUnlockWorldNumForWorldMap(const al::LayoutActor* layout) { return getUnlockWorldNumForWorldMapImpl(layout); } static s32 calcNextLockedWorldIdForWorldMapImpl(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->getGameProgressData()->calcNextLockedWorldIdForWorldMap( world_id); } s32 calcNextLockedWorldIdForWorldMap(const al::LayoutActor* layout, s32 world_id) { return calcNextLockedWorldIdForWorldMapImpl(layout, world_id); } s32 calcNextLockedWorldIdForWorldMap(const al::Scene* scene, s32 world_id) { return calcNextLockedWorldIdForWorldMapImpl(scene, world_id); } static s32 calcNextLockedWorldNumForWorldMapImpl(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->calcNextLockedWorldNumForWorldMap(); } s32 calcNextLockedWorldNumForWorldMap(const al::Scene* scene) { return calcNextLockedWorldNumForWorldMapImpl(scene); } s32 calcNextLockedWorldNumForWorldMap(const al::LayoutActor* layout) { return calcNextLockedWorldNumForWorldMapImpl(layout); } s32 getWorldIdForShineList(const al::LayoutActor* layout, s32 world_id) { GameDataHolderAccessor accessor{layout}; return accessor->getGameDataFile()->getGameProgressData()->getWorldIdForShineList(world_id); } s32 calcWorldNumForShineList(const al::LayoutActor* layout) { GameDataHolderAccessor accessor{layout}; return accessor->getGameDataFile()->getGameProgressData()->calcWorldNumForShineList(); } s32 getLatestUnlockWorldIdForShineTowerMeter(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->getGameProgressData()->getWorldIdForWorldWarpHole( getUnlockWorldNumForWorldMapImpl(accessor) - 1); } bool isClearSandWorldScenario1(const al::Scene* scene) { GameDataHolderAccessor accessor{scene}; s32 world_id = accessor->getWorldList()->tryFindWorldIndexByDevelopName("Sand"); return getWorldScenarioNo(scene, world_id) > 1; } bool isClearCityWorldScenario1(const al::Scene* scene) { GameDataHolderAccessor accessor{scene}; s32 world_id = accessor->getWorldList()->tryFindWorldIndexByDevelopName("City"); return getWorldScenarioNo(scene, world_id) > 1; } bool isClearSkyWorldScenario1(const al::Scene* scene) { GameDataHolderAccessor accessor{scene}; s32 world_id = accessor->getWorldList()->tryFindWorldIndexByDevelopName("Sky"); return getWorldScenarioNo(scene, world_id) > 1; } bool isCityWorldScenario2(const al::IUseSceneObjHolder* scene_obj_holder) { if (isWorldCity(scene_obj_holder) && rs::getActiveQuestNum(scene_obj_holder) > 0) { s32 quest_no = rs::getActiveQuestNo(scene_obj_holder); if (quest_no >= 2 && quest_no <= 6) return true; } return false; } s32 calcNextWorldId(GameDataHolderAccessor accessor) { return accessor->getWorldList()->tryFindWorldIndexByMainStageName(accessor->getNextStageName()); } bool isPlayDemoWorldWarp(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isPlayDemoWorldWarp(); } bool isPlayDemoWorldWarpHole(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isPlayDemoWorldWarpHole(); } void noPlayDemoWorldWarp(GameDataHolderWriter writer) { writer->getGameDataFile()->noPlayDemoWorldWarp(); } bool isPlayDemoReturnToHome(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isPlayDemoReturnToHome(); } void requestPlayDemoReturnToHome(GameDataHolderWriter writer) { writer->getGameDataFile()->requestPlayDemoReturnToHome(); } bool isPlayDemoAwardSpecial(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isPlayDemoAwardSpecial(); } void requestPlayDemoAwardSpecial(GameDataHolderWriter writer) { writer->getGameDataFile()->requestPlayDemoAwardSpecial(); } bool isPlayDemoLavaErupt(GameDataHolderAccessor accessor) { return accessor->isPlayDemoLavaErupt(); } bool isPlayDemoPlayerDownForBattleKoopaAfter(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isPlayDemoPlayerDownForBattleKoopaAfter(); } void disablePlayDemoPlayerDownForBattleKoopaAfter(GameDataHolderWriter writer) { writer->getGameDataFile()->disablePlayDemoPlayerDownForBattleKoopaAfter(); } void enteredStage(GameDataHolderWriter writer) { writer->getGameDataFile()->enteredStage(); writer->resetTemporaryScenarioCameraHolder(); } const char* getCurrentCostumeTypeName(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCurrentCostumeName(); } const char* getCurrentCapTypeName(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getCurrentCapName(); } void wearCostume(GameDataHolderWriter writer, const char* name) { writer->getGameDataFile()->wearCostume(name); rs::trySavePrepoChangeClothEvent(name, getPlayTimeTotal(writer), getSaveDataIdForPrepo(writer), getPlayTimeAcrossFile(writer)); } void wearCap(GameDataHolderWriter writer, const char* name) { writer->getGameDataFile()->wearCap(name); rs::trySavePrepoChangeCapEvent(name, getPlayTimeTotal(writer), getSaveDataIdForPrepo(writer), getPlayTimeAcrossFile(writer)); } void wearCostumeRandom(al::IUseSceneObjHolder* scene_obj_holder) { const char* current = getCurrentCostumeTypeName(scene_obj_holder); const char* target = "Mario"; s32 total_num = rs::calcHaveClothNum(scene_obj_holder); if (total_num != 1) { s32 seen_num = 1; for (s32 i = 0; i < rs::getClothListSize(scene_obj_holder); i++) { if (!rs::isHaveCloth(scene_obj_holder, i) || al::isEqualString(current, rs::getClothList(scene_obj_holder)[i]->name)) continue; f32 chance = 100.0f / (total_num - seen_num++); if (al::getRandom(0.0f, 100.0f) < chance) { target = rs::getClothList(scene_obj_holder)[i]->name; break; } } } GameDataHolderAccessor accessor{scene_obj_holder}; accessor->getGameDataFile()->wearCostume(target); } void wearCapRandom(al::IUseSceneObjHolder* scene_obj_holder) { const char* current = getCurrentCapTypeName(scene_obj_holder); const char* target = "Mario"; s32 total_num = rs::calcHaveCapNum(scene_obj_holder); if (total_num != 1) { s32 seen_num = 1; for (s32 i = 0; i < rs::getCapListSize(scene_obj_holder); i++) { if (!rs::isHaveCap(scene_obj_holder, i) || al::isEqualString(current, rs::getClothList(scene_obj_holder)[i]->name)) continue; f32 chance = 100.0f / (total_num - seen_num++); if (al::getRandom(0.0f, 100.0f) < chance) { target = rs::getCapList(scene_obj_holder)[i]->name; break; } } } GameDataHolderAccessor accessor{scene_obj_holder}; accessor->getGameDataFile()->wearCap(target); } void tryWearCostumeRandomIfEnable(al::IUseSceneObjHolder* scene_obj_holder) { if (isCostumeRandomMode(scene_obj_holder)) wearCostumeRandom(scene_obj_holder); } void tryWearCapRandomIfEnable(al::IUseSceneObjHolder* scene_obj_holder) { if (isCapRandomMode(scene_obj_holder)) wearCapRandom(scene_obj_holder); } bool isCostumeRandomMode(al::IUseSceneObjHolder* scene_obj_holder) { GameDataHolderAccessor accessor{scene_obj_holder}; return accessor->getGameDataFile()->isCostumeRandom(); } bool isCapRandomMode(al::IUseSceneObjHolder* scene_obj_holder) { GameDataHolderAccessor accessor{scene_obj_holder}; return accessor->getGameDataFile()->isCapRandom(); } void setCostumeRandomMode(al::IUseSceneObjHolder* scene_obj_holder) { GameDataHolderAccessor accessor{scene_obj_holder}; accessor->getGameDataFile()->setCostumeRandom(true); rs::trySavePrepoChangeClothEvent("Random", getPlayTimeTotal(scene_obj_holder), getSaveDataIdForPrepo(scene_obj_holder), getPlayTimeAcrossFile(scene_obj_holder)); } void setCapRandomMode(al::IUseSceneObjHolder* scene_obj_holder) { GameDataHolderAccessor accessor{scene_obj_holder}; accessor->getGameDataFile()->setCapRandom(true); rs::trySavePrepoChangeCapEvent("Random", getPlayTimeTotal(scene_obj_holder), getSaveDataIdForPrepo(scene_obj_holder), getPlayTimeAcrossFile(scene_obj_holder)); } void resetCostumeRandomMode(al::IUseSceneObjHolder* scene_obj_holder) { GameDataHolderAccessor accessor{scene_obj_holder}; accessor->getGameDataFile()->setCostumeRandom(false); } void resetCapRandomMode(al::IUseSceneObjHolder* scene_obj_holder) { GameDataHolderAccessor accessor{scene_obj_holder}; accessor->getGameDataFile()->setCapRandom(false); } const sead::PtrArray& getShopItemInfoList(GameDataHolderAccessor accessor) { return *&accessor->getShopItemInfoList(); } bool isExistHackObjInfo(GameDataHolderAccessor accessor, const char* hack_name) { return getHackObjInfo(accessor, hack_name) != nullptr; } const HackObjInfo* getHackObjInfo(GameDataHolderAccessor accessor, const char* hack_name) { const sead::PtrArray& list = accessor->getHackObjList(); for (s32 i = 0; i < list.size(); i++) if (al::isEqualString(list.unsafeAt(i)->hackName, hack_name)) return list.unsafeAt(i); return nullptr; } void addHackDictionary(GameDataHolderWriter writer, const char* hack_name) { writer->getGameDataFile()->addHackDictionary(hack_name); } bool isExistInHackDictionary(GameDataHolderAccessor accessor, const char* hack_name) { return accessor->getGameDataFile()->isExistInHackDictionary(hack_name); } bool isExistInHackDictionary(GameDataHolderAccessor accessor, const char* hack_name, s32 file_id) { return accessor->getGameDataFile(file_id)->isExistInHackDictionary(hack_name); } bool isShowHackTutorial(GameDataHolderAccessor accessor, const char* hack_name, const char* suffix) { return accessor->isShowHackTutorial(hack_name, suffix); } void setShowHackTutorial(GameDataHolderWriter writer, const char* hack_name, const char* suffix) { writer->setShowHackTutorial(hack_name, suffix); } bool isShowBindTutorial(GameDataHolderAccessor accessor, const BindInfo& bind_info) { return accessor->isShowBindTutorial(bind_info.name); } void setShowBindTutorial(GameDataHolderWriter writer, const BindInfo& bind_info) { writer->setShowBindTutorial(bind_info.name); } bool isGotShine(GameDataHolderAccessor accessor, s32 world_id, s32 index) { return accessor->getGameDataFile()->isGotShine(world_id, index); } bool isOpenShineName(const al::LayoutActor* layout, s32 world_id, s32 index) { GameDataHolderAccessor accessor{layout}; return accessor->getGameDataFile()->isOpenShineName(world_id, index); } bool checkAchievementShine(const al::LayoutActor* layout, s32 world_id, s32 index) { GameDataHolderAccessor accessor{layout}; return accessor->getGameDataFile()->checkAchievementShine(world_id, index); } s32 calcShineNumInOneShine(const al::LayoutActor* layout, s32 world_id, s32 index) { GameDataHolderAccessor accessor{layout}; return sead::Mathi::clampMax( accessor->getGameDataFile()->calcShineNumInOneShine(world_id, index), 99); } ALWAYS_INLINE static const char16* getShineMessage(const al::IUseSceneObjHolder* scene_obj_holder, const al::IUseMessageSystem* message_system, s32 world_id, s32 index) { const GameDataFile::HintInfo* info = getGameDataHolder(scene_obj_holder)->getGameDataFile()->findShine(world_id, index); al::StringTmp<128> label; al::PlacementId placement_id{info->objId.cstr(), nullptr, nullptr}; rs::makeMessageLabel(&label, &placement_id, "ScenarioName"); return al::isExistLabelInStageMessage(message_system, info->stageName.cstr(), label.cstr()) ? al::getStageMessageString(message_system, info->stageName.cstr(), label.cstr()) : u"シャイン名未設定"; } const char16* tryFindShineMessage(const al::LayoutActor* layout, s32 world_id, s32 index) { return getShineMessage(layout, layout, world_id, index); } const char16* tryFindShineMessage(const al::LiveActor* actor, const al::IUseMessageSystem* message_system, s32 world_id, s32 index) { return getShineMessage(actor, message_system, world_id, index); } u64 findShineGetTime(const al::LayoutActor* layout, s32 world_id, s32 index) { return getGameDataHolder(layout)->getGameDataFile()->findShine(world_id, index)->getTime; } bool checkMoonRockShineForShineList(const al::LayoutActor* layout, s32 world_id, s32 index) { return getGameDataHolder(layout)->getGameDataFile()->findShine(world_id, index)->isMoonRock; } bool checkUnlockHintByHintNpcForShineList(const al::LayoutActor* layout, s32 world_id, s32 index) { return getGameDataHolder(layout) ->getGameDataFile() ->findShine(world_id, index) ->isHintStatusUnlockByNpc(); } bool checkUnlockHintByAmiiboForShineList(const al::LayoutActor* layout, s32 world_id, s32 index) { return getGameDataHolder(layout) ->getGameDataFile() ->findShine(world_id, index) ->isHintStatusUnlockByAmiibo(); } bool checkShineSeaOfTreeForShineList(const al::LayoutActor* layout, s32 world_id, s32 index) { return isSeaOfTreeStage( getGameDataHolder(layout)->getGameDataFile()->findShine(world_id, index)->stageName.cstr()); } s32 getWorldTotalShineNum(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->getWorldTotalShineNum(world_id); } s32 getWorldTotalShineNumMax(GameDataHolderAccessor accessor, s32 world_id) { return accessor->getGameDataFile()->getWorldTotalShineNumMax(world_id); } void findShineTrans(sead::Vector3f* out, GameDataHolderAccessor accessor, s32 world_id, s32 index) { out->set(accessor->getGameDataFile()->findShine(world_id, index)->trans); } const sead::Vector3f& getHomeTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getHomeTrans(); } bool isExistHome(GameDataHolderAccessor accessor) { return isGameClear(accessor) || (isActivateHome(accessor) && isUnlockedCurrentWorld(accessor)); } bool isActivateHome(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->isActivateHome(); } s32 getMiniGameNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->calcMiniGameNum(); } s32 getMiniGameNumMax(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getMiniGameNumMax(); } const sead::Vector3f& getMiniGameTrans(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->getMiniGameTrans(index); } const char* getMiniGameName(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->getMiniGameName(index); } const sead::Vector3f& getRaceStartTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceStartTrans(); } const sead::Vector3f& getRaceGoalTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getRaceGoalTrans(); } const sead::Vector3f& getHintNpcTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getHintNpcTrans(); } const sead::Vector3f& getShopNpcTrans(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->getShopNpcTrans(index); } bool isShopSellout(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->isShopSellout(index); } s32 calcShopNum(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->calcShopNum(); } s32 getShopNpcIconNumMax(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getShopNpcIconNumMax(); } bool isExistRaceStartNpc(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isExistRaceStartNpc(); } bool isExistHintNpc(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isExistHintNpc(); } const sead::Matrix34f& getCurrentMapView(GameDataHolderAccessor accessor) { return accessor->getMapDataHolder()->findViewMtx(getCurrentWorldIdNoDevelop(accessor)); } bool isExistJango(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isExistJango(); } const sead::Vector3f& getJangoTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getJangoTrans(); } bool isExistAmiiboNpc(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isExistAmiiboNpc(); } const sead::Vector3f& getAmiiboNpcTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getAmiiboNpcTrans(); } bool isInInvalidOpenMapStage(GameDataHolderAccessor accessor) { return accessor->isInvalidOpenMapStage(getCurrentStageName(accessor), getScenarioNoImpl(accessor)); } const sead::Vector3f& getStageMapPlayerPos(GameDataHolderAccessor accessor) { return accessor->getStageMapPlayerPos(); } bool isExistTimeBalloonNpc(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isExistTimeBalloonNpc(); } const sead::Vector3f& getTimeBalloonNpcTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getTimeBalloonNpcTrans(); } bool isExistPoetter(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isExistPoetter(); } const sead::Vector3f& getPoetterTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getPoetterTrans(); } const sead::Vector3f& getMoonRockTrans(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getMoonRockTrans(); } void setHomeTrans(const al::LiveActor* actor, const sead::Vector3f& trans) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setHomeTrans(trans); } void setRaceStartNpcTrans(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setRaceStartNpcTrans(al::getTrans(actor)); } void setRaceStartTrans(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setRaceStartTrans(al::getTrans(actor)); } void setRaceGoalTrans(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setRaceGoalTrans(al::getTrans(actor)); } void setHintNpcTrans(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setHintNpcTrans(al::getTrans(actor)); } void setJangoTrans(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setJangoTrans(al::getTrans(actor)); } void disableJangoTrans(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->disableJangoTrans(); } void setAmiiboNpcTrans(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setAmiiboNpcTrans(al::getTrans(actor)); } void setShopNpcTrans(const al::LiveActor* actor, const char* name, s32 type) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->setShopNpcTrans(al::getTrans(actor), name, type); } void setShopNpcTrans(GameDataHolderAccessor accessor, const al::PlacementInfo& placement_info) { sead::Vector3f trans = sead::Vector3f::zero; al::getTrans(&trans, placement_info); const char* name = nullptr; if (al::tryGetStringArg(&name, placement_info, "StoreName")) accessor->getGameDataFile()->setShopNpcTrans(trans, name, 0); } void setMiniGameInfo(GameDataHolderAccessor accessor, const al::PlacementInfo& placement_info) { sead::Vector3f trans = sead::Vector3f::zero; al::getTrans(&trans, placement_info); const char* name = nullptr; if (al::tryGetStringArg(&name, placement_info, "MiniGameName")) accessor->getGameDataFile()->setMiniGameInfo(trans, name); } void setTimeBalloonTrans(GameDataHolderAccessor accessor, const sead::Vector3f& trans) { accessor->getGameDataFile()->setTimeBalloonNpcTrans(trans); } void setPoetterTrans(GameDataHolderAccessor accessor, const sead::Vector3f& trans) { accessor->getGameDataFile()->setPoetterTrans(trans); } void setStageMapPlayerPos(GameDataHolderWriter writer, const sead::Vector3f& pos) { writer->setStageMapPlayerPos(pos); } void setMoonRockTrans(GameDataHolderWriter writer, const sead::Vector3f& trans) { writer->getGameDataFile()->setMoonRockTrans(trans); } s32 getHomeLevel(GameDataHolderAccessor accessor) { if (rs::isModeE3Rom() || rs::isModeE3LiveRom()) return 3; return accessor->getGameDataFile()->getGameProgressData()->getHomeLevel(); } void upHomeLevel(GameDataHolderWriter writer) { writer->getGameDataFile()->getGameProgressData()->upHomeLevel(); } void activateHome(GameDataHolderWriter writer) { writer->getGameDataFile()->setActivateHome(); } bool isLaunchHome(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->isLaunchHome(); } void launchHome(GameDataHolderWriter writer) { writer->getGameDataFile()->getGameProgressData()->launchHome(); } bool isCrashHome(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->isCrashHome(); } void crashHome(GameDataHolderWriter writer) { writer->getGameDataFile()->getGameProgressData()->crashHome(); } bool isRepairHome(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->isRepairHome(); } void repairHome(GameDataHolderWriter writer) { writer->getGameDataFile()->getGameProgressData()->repairHome(); } bool isBossAttackedHome(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->isBossAttackedHome(); } void bossAttackHome(GameDataHolderWriter writer) { writer->getGameDataFile()->getGameProgressData()->bossAttackHome(); } bool isRepairHomeByCrashedBoss(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->isRepairHomeByCrashedBoss(); } void repairHomeByCrashedBoss(GameDataHolderWriter writer) { writer->getGameDataFile()->getGameProgressData()->repairHomeByCrashedBoss(); } bool isFindKoopaNext(GameDataHolderAccessor accessor, s32 world_id) { return accessor->isFindKoopaNext(world_id); } bool isBossAttackedHomeNext(GameDataHolderAccessor accessor, s32 world_id) { return accessor->isBossAttackedHomeNext(world_id); } bool isFindKoopa(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->getGameProgressData()->isFindKoopa(); } void findKoopa(GameDataHolderWriter writer) { writer->getGameDataFile()->getGameProgressData()->findKoopa(); } bool isEnableCap(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isEnableCap(); } bool isMeetCap(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isMeetCap(); } void enableCap(GameDataHolderWriter writer) { writer->getGameDataFile()->meetCap(); } void disableCapByPlacement(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->disableCapByPlacement(); } bool isTalkedCapNearHomeInWaterfall(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; return accessor->getGameDataFile()->getGameProgressData()->isTalkedCapNearHomeInWaterfall(); } void talkCapNearHomeInWaterfall(const al::LiveActor* actor) { GameDataHolderAccessor accessor{actor}; accessor->getGameDataFile()->getGameProgressData()->talkCapNearHomeInWaterfall(); } bool isFlagOnTalkMessageInfo(const al::IUseSceneObjHolder* scene_obj_holder, s32 index) { GameDataHolderAccessor accessor{scene_obj_holder}; return accessor->getGameDataFile()->isFlagOnTalkMessageInfo(index); } void onFlagTalkMessageInfo(const al::IUseSceneObjHolder* scene_obj_holder, s32 index) { GameDataHolderAccessor accessor{scene_obj_holder}; accessor->getGameDataFile()->setFlagOnTalkMessageInfo(index); } s32 getWorldIndexHat() { return 0; } s32 getWorldIndexWaterfall() { return 1; } s32 getWorldIndexSand() { return 2; } s32 getWorldIndexForest() { return 3; } s32 getWorldIndexLake() { return 4; } s32 getWorldIndexCloud() { return 5; } s32 getWorldIndexClash() { return 6; } s32 getWorldIndexCity() { return 7; } s32 getWorldIndexSea() { return 8; } s32 getWorldIndexSnow() { return 9; } s32 getWorldIndexLava() { return 10; } s32 getWorldIndexBoss() { return 11; } s32 getWorldIndexSky() { return 12; } s32 getWorldIndexMoon() { return 13; } s32 getWorldIndexPeach() { return 14; } s32 getWorldIndexSpecial1() { return 15; } s32 getWorldIndexSpecial2() { return 16; } bool isWorldCap(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Cap"); } bool isWorldWaterfall(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Waterfall"); } bool isWorldSand(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Sand"); } bool isWorldForest(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Forest"); } bool isWorldLake(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Lake"); } bool isWorldCloud(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Cloud"); } bool isWorldClash(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Clash"); } bool isWorldCity(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "City"); } bool isWorldSnow(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Snow"); } bool isWorldSea(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Sea"); } bool isWorldBoss(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Attack"); } bool isWorldSky(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Sky"); } bool isWorldMoon(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Moon"); } bool isWorldPeach(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Peach"); } bool isWorldSpecial1(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Special1"); } bool isWorldSpecial2(GameDataHolderAccessor accessor) { return al::isEqualString(getWorldDevelopName(accessor, getCurrentWorldId(accessor)), "Special2"); } bool isWorldTypeMoon(GameDataHolderAccessor, s32 world_id) { return world_id == getWorldIndexMoon() || world_id == getWorldIndexSpecial1() || world_id == getWorldIndexSpecial2(); } bool isSnowMainScenario1(const al::IUseSceneObjHolder* scene_obj_holder) { return rs::getActiveQuestNum(scene_obj_holder) > 0 && rs::getActiveQuestList(scene_obj_holder)[0]->getQuestNo() == 0; } bool isSnowMainScenario2(const al::IUseSceneObjHolder* scene_obj_holder) { return rs::getActiveQuestNum(scene_obj_holder) > 0 && rs::getActiveQuestList(scene_obj_holder)[0]->getQuestNo() == 1; } bool isHomeShipStage(const GameDataHolder* game_data_holder) { return al::isEqualString(game_data_holder->getCurrentStageName(), getHomeShipStageName()); } const char* getHomeShipStageName() { return "HomeShipInsideStage"; } bool isCityWorldCeremonyAll(s32 world_id, s32 scenario_no) { if (world_id != getWorldIndexCity()) return false; switch (scenario_no) { case 3: case 7: case 11: return true; default: return false; } } bool isCityWorldCeremonyAgain(s32 world_id, s32 scenario_no) { if (world_id != getWorldIndexCity()) return false; switch (scenario_no) { case 7: case 11: return true; default: return false; } } bool isGoToCeremonyFromInsideHomeShip(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isGoToCeremonyFromInsideHomeShip(); } void registerScenarioStartCameraInfo(const ScenarioStartCamera* actor, s32 id, al::CameraTicket* camera) { getGameDataHolder(actor)->getTemporaryScenarioCameraHolder()->registInfo(id, camera); } bool isEnableExplainAmiibo(GameDataHolderAccessor accessor) { return accessor->isEnableExplainAmiibo(); } void endExplainAmiibo(GameDataHolderWriter writer) { writer->disableExplainAmiibo(); } void startSearchHintByAmiibo(GameDataHolderWriter writer) { writer->startSearchHintByAmiibo(); } void endSearchHintByAmiibo(GameDataHolderWriter writer) { writer->endSearchHintByAmiibo(); } void setKidsModeOn(const al::Scene* scene) { GameDataHolderAccessor accessor{scene}; accessor->getGameDataFile()->setKidsMode(true); } void setKidsModeOff(const al::Scene* scene) { GameDataHolderAccessor accessor{scene}; accessor->getGameDataFile()->setKidsMode(false); } bool isCollectedBgm(GameDataHolderAccessor accessor, const char* name, const char* situation_name) { return accessor->getGameDataFile()->isCollectedBgm(name, situation_name); } const CollectBgm& getCollectBgmByIndex(GameDataHolderAccessor accessor, s32 index) { return accessor->getGameDataFile()->getCollectBgmByIndex(index); } bool trySetCollectedBgm(GameDataHolderWriter writer, const char* name, const char* situation_name) { return writer->getGameDataFile()->trySetCollectedBgm(name, situation_name); } s32 getCollectedBgmNum(GameDataHolderWriter writer) { return writer->getGameDataFile()->getCollectedBgmNum(); } s32 getCollectedBgmNum(GameDataHolderAccessor accessor, s32 file_id) { return accessor->getGameDataFile(file_id)->getCollectedBgmNum(); } s32 getCollectedBgmMaxNum(GameDataHolderWriter writer) { return writer->getGameDataFile()->getCollectedBgmMaxNum(); } void registerShineInfo(GameDataHolderAccessor accessor, const ShineInfo* info, const sead::Vector3f& trans) { accessor->getGameDataFile()->registerShineInfo(info, trans); } void setHintTrans(GameDataHolderAccessor accessor, s32 index, const sead::Vector3f& trans) { if (isMainStage(accessor)) accessor->getGameDataFile()->setHintTrans(index, trans); } void resetHintTrans(GameDataHolderAccessor accessor, s32 index) { accessor->getGameDataFile()->resetHintTrans(index); } bool isKoopaLv3(GameDataHolderAccessor accessor) { return accessor->getGameDataFile()->isKoopaLv3(); } } // namespace GameDataFunction