mirror of
https://github.com/zeldaret/ss
synced 2026-06-06 11:37:34 -04:00
325 lines
9.3 KiB
C++
325 lines
9.3 KiB
C++
#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 <cstring>
|
|
|
|
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<dScGame_c>::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;
|
|
}
|