#include "d/d_sc_game.h" #include "common.h" #include "d/d_base.h" #include "d/d_fader.h" #include "d/d_gfx.h" #include "d/d_stage_mgr.h" #include "d/flag/storyflag_manager.h" #include "d/snd/d_snd_state_mgr.h" #include "f/f_base.h" #include "f/f_profile_name.h" #include "m/m_fader_base.h" #include "m/m_vec.h" #include "s/s_FPhase.h" #include "s/s_State.hpp" #include "toBeSorted/arc_managers/layout_arc_manager.h" #include "toBeSorted/arc_managers/oarc_manager.h" #include "toBeSorted/file_manager.h" #include "toBeSorted/minigame_mgr.h" #include "toBeSorted/unk_save_time.h" #include SPECIAL_BASE_PROFILE(GAME, dScGame_c, fProfile::GAME, 0x4, 0x6F9); STATE_VIRTUAL_DEFINE(dScGame_c, Stanby); STATE_VIRTUAL_DEFINE(dScGame_c, Action); SpawnInfo dScGame_c::currentSpawnInfo; SpawnInfo dScGame_c::nextSpawnInfo(dScGame_c::currentSpawnInfo); dScGame_c *dScGame_c::sInstance; u32 dScGame_c::sUpdateFrameCount; u8 dScGame_c::sCurrentLayer; u8 dScGame_c::sReloaderType; bool dScGame_c::sCopyFileBToCurrentAfterRespawn; bool dScGame_c::sDoSomethingWithFileAOnTransition; bool dScGame_c::sPreventClearingSomeFlag; sFPhase::phaseCallback dScGame_c::sCallbacks[] = { &dScGame_c::cb1, &dScGame_c::cb2, &dScGame_c::cb3, nullptr }; void dScGame_c::someGfxThingCallback() { dScGame_c *scGame = dScGame_c::GetInstance(); scGame->somethingWithScreen(); scGame->mFader.draw(); } dScGame_c::dScGame_c() : mPhases(this, sCallbacks), mStateMgr(*this), mStageMgrRef(nullptr), mScreen1(0x85), mScreen2(0x89), field_0x228(0), mReloadTrigger(fProfile::PROFILE_MAX) { resetLinkState(); mBeedleShopState = 0; mLastAreaType = 6; mType0PosFlag = 0; mSavePromptFlag = false; mPreventSaveRespawnInfo = true; sInstance = this; currentSpawnInfo.reset(); } int dScGame_c::create() { sFPhaseBase::sFPhaseState phaseResult = mPhases.step(); if (phaseResult != sFPhaseBase::PHASE_ALL_DONE) { return NOT_READY; } dGfx_c::GetInstance()->setDrawCallback(someGfxThingCallback); return SUCCEEDED; } int dScGame_c::doDelete() { MinigameManager::destroy(); mRelCtrl.do_unlink(); mLayoutCtrl.release(); return SUCCEEDED; } int dScGame_c::execute() { mFader.calc(); mStateMgr.executeState(); MinigameManager::execute(); return SUCCEEDED; } int dScGame_c::draw() { mScreen1.addToDrawList(); mScreen2.addToDrawList(); return SUCCEEDED; } void dScGame_c::deleteReady() { dGfx_c::GetInstance()->setDrawCallback(nullptr); } sFPhaseBase::sFPhaseState dScGame_c::cb1() { mFader.create(); mFader.setFrames(15, 15); mFader.setTypes(dFader_c::FADER_GREY, dFader_c::FADER_GREY); mFader.initForLyt(); mRelCtrl.do_link(); mLayoutCtrl.load(nullptr); return sFPhaseBase::PHASE_NEXT; } sFPhaseBase::sFPhaseState dScGame_c::cb2() { if (!mRelCtrl.do_link()) { return sFPhaseBase::PHASE_RETRY; } if (OarcManager::GetInstance()->ensureAllEntriesLoaded() != D_ARC_RESULT_OK) { return sFPhaseBase::PHASE_RETRY; } if (LayoutArcManager::GetInstance()->ensureAllEntriesLoaded() != D_ARC_RESULT_OK) { return sFPhaseBase::PHASE_RETRY; } MinigameManager::create(); setReloadTrigger(fProfile::STAGE_MANAGER); mStateMgr.changeState(StateID_Stanby); return sFPhaseBase::PHASE_NEXT; } sFPhaseBase::sFPhaseState dScGame_c::cb3() { if (checkChildProcessCreateState()) { return sFPhaseBase::PHASE_RETRY; } return sFPhaseBase::PHASE_NEXT; } void dScGame_c::initializeState_Stanby() { setProcControl(ROOT_DISABLE_EXECUTE | ROOT_DISABLE_DRAW); if (mReloadTrigger == fProfile::STAGE_MANAGER) { copySpawnNextToCurrent(); } dBase_c *base = dBase_c::createBase(mReloadTrigger, this, 0, OTHER); mStageMgrRef.link(base); mReloadTrigger = fProfile::PROFILE_MAX; } void dScGame_c::executeState_Stanby() { mStateMgr.changeState(StateID_Action); } void dScGame_c::finalizeState_Stanby() {} void dScGame_c::initializeState_Action() { mFader.fadeIn(); } void dScGame_c::executeState_Action() { if (mFader.isStatus(mFaderBase_c::FADED_OUT)) { if (attemptDelete()) { mStateMgr.changeState(StateID_Stanby); } } else if (mReloadTrigger != fProfile::PROFILE_MAX) { mFader.fadeOut(); dSndStateMgr_c::GetInstance()->onGotoStage(mFader.getFadeOutFrame()); } } void dScGame_c::finalizeState_Action() {} void dScGame_c::somethingWithScreen() {} void dScGame_c::setRespawnInfo(const mVec3_c &linkPos, const mAng3_c &linkRot, bool unk) { bool isInThunderDragonTrial = MinigameManager::isInMinigameState(MinigameManager::TRIAL_TIME_ATTACK) || MinigameManager::isInMinigameState(MinigameManager::BOSS_RUSH) ? true : false; bool isInHordeFight = isCurrentStage("F403") && !StoryflagManager::sInstance->getFlag(STORYFLAG_HORDE_DEFEATED); s32 areaType = dStageMgr_c::GetInstance()->getAreaType(); if (mPreventSaveRespawnInfo != true && !isInThunderDragonTrial && !isInHordeFight && (areaType != 2 && !isCurrentStage("B100_1") && !sPreventClearingSomeFlag && (areaType != 1 || (mLastAreaType != 1 && mLastAreaType != 2)))) { FileManager::GetInstance()->setT3Info(linkPos, linkRot); if (mLastAreaType != 5 && unk) { StoryflagManager::sInstance->unsetFlag(STORYFLAG_752); } } if (!isInThunderDragonTrial && isCurrentStage("B400") && mLastAreaType != 2) { FileManager::GetInstance()->copyCurrentToFileB(); } sPreventClearingSomeFlag = 0; mPreventSaveRespawnInfo = false; mLastAreaType = areaType; } const LinkReloadInfo &dScGame_c::getLinkReloadInfo() const { return mReloadInfo; } bool dScGame_c::attemptDelete() { if (mStageMgrRef.p_owner == nullptr) { return true; } else { if (!mStageMgrRef.p_owner->mDeleteRequest) { mStageMgrRef.p_owner->deleteRequest(); } return false; } } bool dScGame_c::setReloadTrigger(fProfile::PROFILE_NAME_e trigger) { if (mReloadTrigger != fProfile::PROFILE_MAX) { return false; } mReloadTrigger = trigger; return true; } void dScGame_c::setSpawnInfo(u8 roomid, const mVec3_c &pos, mAng rot) { mSpawnInfo.setSpawnData(currentSpawnInfo.stageName, roomid, sCurrentLayer, 0, pos, rot); } const SpawnInfoExt &dScGame_c::getSpawnInfo() const { return mSpawnInfo; } void dScGame_c::clearSpawnInfo() { mSpawnInfo.setSpawnData("", 0, 0, 0, mVec3_c::Zero, 0); } extern "C" void processEventFlags(); void dScGame_c::triggerExit(s32 room, u16 exitIndex, s32 forcedNight, s32 forcedTrial) { processEventFlags(); // TODO } void SpawnInfoExt::setSpawnData( const char *i_stageName, u8 i_roomid, u8 i_layer, u8 i_entrance, const mVec3_c &pos, mAng rot ) { setData( i_stageName, i_roomid, i_layer, i_entrance, dScGame_c::currentSpawnInfo.night, dScGame_c::currentSpawnInfo.trial, 0, 15, -1 ); mType0Pos = pos; mType0RotY = rot; } void LinkReloadInfo::set(u8 roomid, const mVec3_c &pos, mAng rot, u32 linkParams) { mRoomId = roomid; mPosition = pos; mRotY = rot; mLinkParams = linkParams; mType0CsFlag = 1; } bool dScGame_c::isCurrentStage(const char *stage) { return dScGame_c::currentSpawnInfo.stageName == stage; } extern "C" void fn_801BB9C0(); extern "C" void maybeResetSkykeepPuzzle(bool); void dScGame_c::copySpawnNextToCurrent() { if (sDoSomethingWithFileAOnTransition == true) { fn_801BB9C0(); sDoSomethingWithFileAOnTransition = false; } if (std::strncmp(currentSpawnInfo.stageName, nextSpawnInfo.stageName, 2)) { SaveTimeRelated::GetInstance()->fn_801909A0(); } currentSpawnInfo = nextSpawnInfo; sCurrentLayer = currentSpawnInfo.layer; maybeResetSkykeepPuzzle(false); } void dScGame_c::actuallyTriggerEntrance( const char *stageName, u8 roomid, u8 layer, u8 entrance, int forcedNight, int forcedTrial, u8 transitionType, u16 transitionFadeFrames, s8 field0x28 ) { s32 trial, night; if (forcedTrial == SpawnInfo::RETAIN_TRIAL) { trial = currentSpawnInfo.trial; } else { trial = forcedTrial; } if (forcedNight == SpawnInfo::RETAIN_TOD) { night = currentSpawnInfo.night; } else { night = forcedNight; } nextSpawnInfo.setData( stageName, roomid, layer, entrance, night, trial, transitionType, transitionFadeFrames, field0x28 ); if (dScGame_c::GetInstance() != nullptr) { dScGame_c::GetInstance()->setFadeInType(transitionType); dScGame_c::GetInstance()->setFadeOutType(transitionType); dScGame_c::GetInstance()->setFaderFrames(transitionFadeFrames); dScGame_c::GetInstance()->resetLinkState(); dScGame_c::GetInstance()->setBeedleShopState(0); } } void SpawnInfo::setData( const char *i_stageName, u8 i_roomid, u8 i_layer, u8 i_entrance, s32 i_night, s32 i_trial, u8 i_transitionType, u16 i_fadeFrames, s8 i_field0x28 ) { stageName = i_stageName; room = i_roomid; layer = i_layer; entrance = i_entrance; night = i_night; trial = i_trial; transitionType = i_transitionType; transitionFadeFrames = i_fadeFrames; unk = i_field0x28; }