diff --git a/data/file_list.yml b/data/file_list.yml index 64c53263..f1dd585c 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -61856,107 +61856,107 @@ MapObj/CapMessageDirector.o: - offset: 0x236988 size: 216 label: _ZN18CapMessageDirectorC2Ev - status: NotDecompiled + status: Matching - offset: 0x236a60 size: 204 label: _ZN18CapMessageDirectorC1Ev - status: NotDecompiled + status: Matching - offset: 0x236b2c size: 176 label: _ZN18CapMessageDirector26initAfterPlacementSceneObjERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x236bdc size: 184 label: _ZThn264_N18CapMessageDirector26initAfterPlacementSceneObjERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x236c94 size: 36 label: _ZN18CapMessageDirector7exeWaitEv - status: NotDecompiled + status: Matching - offset: 0x236cb8 size: 240 label: _ZN18CapMessageDirector21tryStartShowPlacementEv - status: NotDecompiled + status: Matching - offset: 0x236da8 size: 300 label: _ZN18CapMessageDirector17exeDelayPlacementEv - status: NotDecompiled + status: Matching - offset: 0x236ed4 size: 156 label: _ZNK18CapMessageDirector13findPlacementEv - status: NotDecompiled + status: Matching - offset: 0x236f70 size: 224 label: _ZN18CapMessageDirector16exeShowPlacementEv - status: NotDecompiled + status: Matching - offset: 0x237050 size: 52 label: _ZN18CapMessageDirector13forceEndInnerEv - status: NotDecompiled + status: Matching - offset: 0x237084 size: 72 label: _ZN18CapMessageDirector16exeShowSystemLowEv - status: NotDecompiled + status: Matching - offset: 0x2370cc size: 28 label: _ZN18CapMessageDirector13exeShowSystemEv - status: NotDecompiled + status: Matching - offset: 0x2370e8 size: 28 label: _ZN18CapMessageDirector21exeShowSystemContinueEv - status: NotDecompiled + status: Matching - offset: 0x237104 size: 28 label: _ZN18CapMessageDirector6exeEndEv - status: NotDecompiled + status: Matching - offset: 0x237120 size: 8 label: _ZNK18CapMessageDirector6isShowEPKc - status: NotDecompiled + status: Matching - offset: 0x237128 size: 116 label: _ZNK18CapMessageDirector7isDelayEPKc - status: NotDecompiled + status: Matching - offset: 0x23719c size: 132 label: _ZNK18CapMessageDirector8isActiveEPKc - status: NotDecompiled + status: Matching - offset: 0x237220 size: 16 label: _ZN18CapMessageDirector27registerCapMessagePlacementEP19CapMessagePlacement - status: NotDecompiled + status: Matching - offset: 0x237230 size: 104 label: _ZN18CapMessageDirector20tryShowMessageSystemEPK18CapMessageShowInfoPK25CapMessageGameDataChecker - status: NotDecompiled + status: Matching - offset: 0x237298 size: 32 label: _ZNK18CapMessageDirector8tryCheckEPK25CapMessageGameDataChecker - status: NotDecompiled + status: Matching - offset: 0x2372b8 size: 132 label: _ZN18CapMessageDirector23tryShowMessageSystemLowEPK18CapMessageShowInfoPK25CapMessageGameDataChecker - status: NotDecompiled + status: Matching - offset: 0x23733c size: 108 label: _ZN18CapMessageDirector28tryShowMessageSystemContinueEPK18CapMessageShowInfoPK25CapMessageGameDataChecker - status: NotDecompiled + status: Matching - offset: 0x2373a8 size: 76 label: _ZN18CapMessageDirector27endCapMessageSystemContinueEv - status: NotDecompiled + status: Matching - offset: 0x2373f4 size: 92 label: _ZN18CapMessageDirector26invalidateAppearCapMessageEv - status: NotDecompiled + status: Matching - offset: 0x237450 size: 12 label: _ZN18CapMessageDirector24validateAppearCapMessageEv - status: NotDecompiled + status: Matching - offset: 0x23745c size: 52 label: _ZN18CapMessageDirector8forceEndEv - status: NotDecompiled + status: Matching MapObj/CapMessageDirectorFunction.o: '.text': - offset: 0x237490 @@ -62044,37 +62044,37 @@ MapObj/CapMessageDirectorFunction.o: - offset: 0x237b3c size: 40 label: _ZNK12_GLOBAL__N_125CapMessageDirectorNrvWait7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x237b64 size: 8 label: _ZNK12_GLOBAL__N_135CapMessageDirectorNrvDelayPlacement7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x237b6c size: 8 label: _ZNK12_GLOBAL__N_134CapMessageDirectorNrvShowPlacement7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x237b74 size: 32 label: _ZNK12_GLOBAL__N_131CapMessageDirectorNrvShowSystem7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x237b94 size: 76 label: _ZNK12_GLOBAL__N_134CapMessageDirectorNrvShowSystemLow7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x237be0 size: 32 label: _ZNK12_GLOBAL__N_139CapMessageDirectorNrvShowSystemContinue7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x237c00 size: 32 label: _ZNK12_GLOBAL__N_124CapMessageDirectorNrvEnd7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x237c20 size: 12 diff --git a/src/Layout/CapMessageLayout.h b/src/Layout/CapMessageLayout.h new file mode 100644 index 00000000..cbb5329d --- /dev/null +++ b/src/Layout/CapMessageLayout.h @@ -0,0 +1,47 @@ +#pragma once + +#include +#include + +#include "Library/Layout/LayoutActor.h" + +namespace al { +class LayoutInitInfo; +} // namespace al + +class CapMessageShowInfo; + +class CapMessageLayout : public al::LayoutActor { +public: + CapMessageLayout(const char* name, const char* layoutName, const al::LayoutInitInfo& initInfo, + const char* archiveName, bool isLocalized); + + void appear() override; + void kill() override; + + void end(); + void start(const CapMessageShowInfo* showInfo); + void startCore(const CapMessageShowInfo* showInfo, bool isContinue); + void startContinue(const CapMessageShowInfo* showInfo); + void setContinueShow(bool isContinueShow); + void tryEnd(); + bool tryEndExistContinueDemo(); + void exeDelay(); + void exeAppear(); + void exeFollowText(); + void exeWait(); + void exeEnd(); + bool isDelay(const char* labelName) const; + bool isShow(const char* labelName) const; + +private: + sead::FixedSafeString<0x100> mMessageName; + sead::FixedSafeString<0x100> mLabelName; + char _360[0x230]; + sead::FixedSafeString<0x40> mReplaceTagName; + s32 mReplaceNumber = 0; + bool mIsContinueShow = false; + u8 _5ed[3] = {}; +}; + +static_assert(sizeof(CapMessageLayout) == 0x5F0, "CapMessageLayout"); diff --git a/src/MapObj/CapMessageDirector.cpp b/src/MapObj/CapMessageDirector.cpp new file mode 100644 index 00000000..c5026eb3 --- /dev/null +++ b/src/MapObj/CapMessageDirector.cpp @@ -0,0 +1,322 @@ +#include "MapObj/CapMessageDirector.h" + +#include "Library/Base/StringUtil.h" +#include "Library/LiveActor/ActorInitFunction.h" +#include "Library/LiveActor/ActorInitUtil.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" + +#include "Layout/CapMessageLayout.h" +#include "MapObj/CapMessageGameDataChecker.h" +#include "MapObj/CapMessageKeeper.h" +#include "MapObj/CapMessagePlacement.h" +#include "MapObj/CapMessageShowInfo.h" + +namespace { +NERVE_IMPL(CapMessageDirector, ShowSystem) +NERVE_IMPL(CapMessageDirector, Wait) +NERVE_IMPL(CapMessageDirector, DelayPlacement) +NERVE_IMPL(CapMessageDirector, ShowPlacement) +NERVE_IMPL(CapMessageDirector, ShowSystemLow) +NERVE_IMPL(CapMessageDirector, ShowSystemContinue) +NERVE_IMPL(CapMessageDirector, End) + +struct CapMessageDirectorNrvGroup { + CapMessageDirectorNrvWait Wait; + CapMessageDirectorNrvDelayPlacement DelayPlacement; + CapMessageDirectorNrvShowPlacement ShowPlacement; + CapMessageDirectorNrvShowSystemLow ShowSystemLow; + CapMessageDirectorNrvShowSystemContinue ShowSystemContinue; + CapMessageDirectorNrvEnd End; +}; + +CapMessageDirectorNrvShowSystem sCapMessageDirectorNrvShowSystem; +CapMessageDirectorNrvGroup sCapMessageDirectorNrvGroup; + +CapMessageGameDataChecker sDefaultCapMessageGameDataChecker; +} // namespace + +CapMessageDirector::CapMessageDirector() + : al::LiveActor("帽子メッセージディレクター(新)"), mLayout(nullptr), mPlacementGroup(nullptr), + mCurrentPlacement(nullptr), mMessageKeeper(nullptr), mIsAppearCapMessageValid(true) { + mPlacementGroup = + new al::DeriveActorGroup("配置帽子メッセージグループ", 32); +} + +void CapMessageDirector::initAfterPlacementSceneObj(const al::ActorInitInfo& info) { + al::initActorSceneInfo(this, info); + al::initExecutorUpdate(this, info, "監視オブジェ"); + al::initNerve(this, &sCapMessageDirectorNrvGroup.Wait, 0); + + mLayout = new CapMessageLayout("帽子メッセージ レイアウト", "TalkMessageInfo", + al::getLayoutInitInfo(info), nullptr, false); + mMessageKeeper = new CapMessageKeeper(); + + makeActorAlive(); +} + +void CapMessageDirector::exeWait() { + al::isFirstStep(this); + tryStartShowPlacement(); +} + +bool CapMessageDirector::tryStartShowPlacement() { + if (!mIsAppearCapMessageValid) + return false; + + if (mPlacementGroup->getActorCount() < 1) { + mCurrentPlacement = nullptr; + return false; + } + + CapMessagePlacement* bestPlacement = nullptr; + s32 bestPriority = -1; + + for (s32 i = 0; i < mPlacementGroup->getActorCount(); i++) { + CapMessagePlacement* placement = mPlacementGroup->getDeriveActor(i); + + if (placement->getAppearPriority() > bestPriority && placement->isActive() && + placement->checkEnbale()) { + bestPriority = placement->getAppearPriority(); + bestPlacement = placement; + } + } + + mCurrentPlacement = bestPlacement; + if (bestPlacement == nullptr) + return false; + + if (bestPlacement->getDelayTime() > 0) + al::setNerve(this, &sCapMessageDirectorNrvGroup.DelayPlacement); + else + al::setNerve(this, &sCapMessageDirectorNrvGroup.ShowPlacement); + + return true; +} + +void CapMessageDirector::exeDelayPlacement() { + al::isFirstStep(this); + + if (!mCurrentPlacement->isActive()) { + mCurrentPlacement = nullptr; + al::setNerve(this, &sCapMessageDirectorNrvGroup.Wait); + return; + } + + CapMessagePlacement* bestPlacement = nullptr; + if (mPlacementGroup->getActorCount() >= 1) { + s32 bestPriority = -1; + + for (s32 i = 0; i < mPlacementGroup->getActorCount(); i++) { + CapMessagePlacement* placement = mPlacementGroup->getDeriveActor(i); + + if (placement->getAppearPriority() > bestPriority && placement->isActive() && + placement->checkEnbale()) { + bestPriority = placement->getAppearPriority(); + bestPlacement = placement; + } + } + } + + if (bestPlacement == nullptr && mCurrentPlacement->isDelayCancel()) { + al::setNerve(this, &sCapMessageDirectorNrvGroup.Wait); + return; + } + + if (bestPlacement != nullptr && mCurrentPlacement != bestPlacement) { + mCurrentPlacement = bestPlacement; + if (bestPlacement->getDelayTime() > 0) + al::setNerve(this, &sCapMessageDirectorNrvGroup.DelayPlacement); + else + al::setNerve(this, &sCapMessageDirectorNrvGroup.ShowPlacement); + return; + } + + if (al::isGreaterEqualStep(this, mCurrentPlacement->getDelayTime())) + al::setNerve(this, &sCapMessageDirectorNrvGroup.ShowPlacement); +} + +CapMessagePlacement* CapMessageDirector::findPlacement() const { + if (mPlacementGroup->getActorCount() < 1) + return nullptr; + + CapMessagePlacement* bestPlacement = nullptr; + s32 bestPriority = -1; + + for (s32 i = 0; i < mPlacementGroup->getActorCount(); i++) { + CapMessagePlacement* placement = mPlacementGroup->getDeriveActor(i); + + if (placement->getAppearPriority() > bestPriority && placement->isActive() && + placement->checkEnbale()) { + bestPriority = placement->getAppearPriority(); + bestPlacement = placement; + } + } + + return bestPlacement; +} + +void CapMessageDirector::exeShowPlacement() { + if (al::isFirstStep(this)) { + mLayout->start(mCurrentPlacement->getShowInfo()); + mCurrentPlacement->showStart(); + } + + if (!mCurrentPlacement->isActive()) { + mCurrentPlacement->showEnd(); + mLayout->tryEnd(); + al::setNerve(this, &sCapMessageDirectorNrvGroup.End); + return; + } + + bool isEnable = mCurrentPlacement->checkEnbale(); + mLayout->setContinueShow(isEnable && mCurrentPlacement->isKeepDisp()); + + if (!mLayout->isAlive()) { + mCurrentPlacement->showEnd(); + if (!isEnable) + al::setNerve(this, &sCapMessageDirectorNrvGroup.Wait); + } +} + +void CapMessageDirector::forceEndInner() { + mLayout->tryEnd(); + al::setNerve(this, &sCapMessageDirectorNrvGroup.End); +} + +void CapMessageDirector::exeShowSystemLow() { + if (!tryStartShowPlacement() && !mLayout->isAlive()) + al::setNerve(this, &sCapMessageDirectorNrvGroup.Wait); +} + +void CapMessageDirector::exeShowSystem() { + if (!mLayout->isAlive()) + al::setNerve(this, &sCapMessageDirectorNrvGroup.Wait); +} + +void CapMessageDirector::exeShowSystemContinue() { + if (!mLayout->isAlive()) + al::setNerve(this, &sCapMessageDirectorNrvGroup.Wait); +} + +void CapMessageDirector::exeEnd() { + if (!mLayout->isAlive()) + al::setNerve(this, &sCapMessageDirectorNrvGroup.Wait); +} + +bool CapMessageDirector::isShow(const char* labelName) const { + return mLayout->isShow(labelName); +} + +bool CapMessageDirector::isDelay(const char* labelName) const { + if (!al::isNerve(this, &sCapMessageDirectorNrvGroup.DelayPlacement)) + return mLayout->isDelay(labelName); + + if (labelName == nullptr) + return true; + + if (mCurrentPlacement != nullptr) + return al::isEqualString(labelName, mCurrentPlacement->getShowInfo()->getLabelName()); + + return mLayout->isDelay(labelName); +} + +bool CapMessageDirector::isActive(const char* labelName) const { + if (mLayout->isShow(labelName)) + return true; + + if (al::isNerve(this, &sCapMessageDirectorNrvGroup.DelayPlacement)) { + if (labelName == nullptr) + return true; + + if (mCurrentPlacement != nullptr) + return al::isEqualString(labelName, mCurrentPlacement->getShowInfo()->getLabelName()); + } + + return mLayout->isDelay(labelName); +} + +s32 CapMessageDirector::registerCapMessagePlacement(CapMessagePlacement* placement) { + return mPlacementGroup->registerActor(placement); +} + +bool CapMessageDirector::tryShowMessageSystem(const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker) { + if (checker != nullptr) { + if (!checker->check(this)) + return false; + } else if (!sDefaultCapMessageGameDataChecker.check(this)) { + return false; + } + + mLayout->start(showInfo); + al::setNerve(this, &sCapMessageDirectorNrvShowSystem); + return true; +} + +bool CapMessageDirector::tryCheck(const CapMessageGameDataChecker* checker) const { + if (checker != nullptr) + return checker->check(this); + + return sDefaultCapMessageGameDataChecker.check(this); +} + +bool CapMessageDirector::tryShowMessageSystemLow(const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker) { + if (checker != nullptr) { + if (!checker->check(this)) + return false; + } else if (!sDefaultCapMessageGameDataChecker.check(this)) { + return false; + } + + if (!al::isNerve(this, &sCapMessageDirectorNrvGroup.Wait)) + return false; + + mLayout->start(showInfo); + al::setNerve(this, &sCapMessageDirectorNrvGroup.ShowSystemLow); + return true; +} + +bool CapMessageDirector::tryShowMessageSystemContinue(const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker) { + if (checker != nullptr) { + if (!checker->check(this)) + return false; + } else if (!sDefaultCapMessageGameDataChecker.check(this)) { + return false; + } + + mLayout->startContinue(showInfo); + al::setNerve(this, &sCapMessageDirectorNrvGroup.ShowSystemContinue); + return true; +} + +void CapMessageDirector::endCapMessageSystemContinue() { + if (al::isNerve(this, &sCapMessageDirectorNrvGroup.ShowSystemContinue)) { + mLayout->tryEnd(); + al::setNerve(this, &sCapMessageDirectorNrvGroup.End); + } +} + +void CapMessageDirector::invalidateAppearCapMessage() { + if (mLayout->tryEndExistContinueDemo()) { + if (al::isNerve(this, &sCapMessageDirectorNrvGroup.ShowPlacement) && + mCurrentPlacement != nullptr) { + mCurrentPlacement->showEnd(); + } + + al::setNerve(this, &sCapMessageDirectorNrvGroup.End); + } + + mIsAppearCapMessageValid = false; +} + +void CapMessageDirector::validateAppearCapMessage() { + mIsAppearCapMessageValid = true; +} + +void CapMessageDirector::forceEnd() { + mLayout->tryEnd(); + al::setNerve(this, &sCapMessageDirectorNrvGroup.End); +} diff --git a/src/MapObj/CapMessageDirector.h b/src/MapObj/CapMessageDirector.h new file mode 100644 index 00000000..d21b4d82 --- /dev/null +++ b/src/MapObj/CapMessageDirector.h @@ -0,0 +1,88 @@ +#pragma once + +#include + +#include "Library/LiveActor/LiveActor.h" +#include "Library/LiveActor/LiveActorGroup.h" +#include "Library/Scene/ISceneObj.h" + +#include "Scene/SceneObjFactory.h" + +namespace al { +struct ActorInitInfo; +class IUseSceneObjHolder; +} // namespace al + +class CapMessageGameDataChecker; +class CapMessageKeeper; +class CapMessageLayout; +class CapMessagePlacement; +class CapMessageShowInfo; + +class CapMessageDirector : public al::LiveActor, public al::ISceneObj { +public: + static constexpr s32 sSceneObjId = SceneObjID_CapMessageDirector; + + CapMessageDirector(); + ~CapMessageDirector() override; + + const char* getSceneObjName() const override; + void initAfterPlacementSceneObj(const al::ActorInitInfo& info) override; + + void exeWait(); + bool tryStartShowPlacement(); + void exeDelayPlacement(); + CapMessagePlacement* findPlacement() const; + void exeShowPlacement(); + void forceEndInner(); + void exeShowSystemLow(); + void exeShowSystem(); + void exeShowSystemContinue(); + void exeEnd(); + bool isShow(const char* labelName) const; + bool isDelay(const char* labelName) const; + bool isActive(const char* labelName) const; + s32 registerCapMessagePlacement(CapMessagePlacement* placement); + bool tryShowMessageSystem(const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker); + bool tryCheck(const CapMessageGameDataChecker* checker) const; + bool tryShowMessageSystemLow(const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker); + bool tryShowMessageSystemContinue(const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker); + void endCapMessageSystemContinue(); + void invalidateAppearCapMessage(); + void validateAppearCapMessage(); + void forceEnd(); + +private: + CapMessageLayout* mLayout; + al::DeriveActorGroup* mPlacementGroup; + CapMessagePlacement* mCurrentPlacement; + CapMessageKeeper* mMessageKeeper; + bool mIsAppearCapMessageValid; +}; + +static_assert(sizeof(CapMessageDirector) == 0x138, "CapMessageDirector"); + +namespace CapMessageDirectorFunction { +s32 registerCapMessagePlacement(CapMessagePlacement* placement); +bool tryShowCapMessageSystem(const al::IUseSceneObjHolder* sceneObjHolder, + const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker); +bool tryShowCapMessageSystemLow(const al::IUseSceneObjHolder* sceneObjHolder, + const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker); +bool tryShowCapMessageSystemContinue(const al::IUseSceneObjHolder* sceneObjHolder, + const CapMessageShowInfo* showInfo, + const CapMessageGameDataChecker* checker); +void endCapMessageSystemContinue(const al::IUseSceneObjHolder* sceneObjHolder); +void invalidateAppearCapMessageNew(const al::IUseSceneObjHolder* sceneObjHolder); +void validateAppearCapMessageNew(const al::IUseSceneObjHolder* sceneObjHolder); +void forceEndCapMessage(const al::IUseSceneObjHolder* sceneObjHolder); +bool tryCancelCapMessageNew(const al::IUseSceneObjHolder* sceneObjHolder, const char* labelName); +bool isShowCapMessage(const al::IUseSceneObjHolder* sceneObjHolder, const char* labelName); +bool isDelayCapMessage(const al::IUseSceneObjHolder* sceneObjHolder, const char* labelName); +bool isActiveCapMessage(const al::IUseSceneObjHolder* sceneObjHolder, const char* labelName); +CapMessageKeeper* getCapMessageKeeper(const al::IUseSceneObjHolder* sceneObjHolder); +} // namespace CapMessageDirectorFunction diff --git a/src/MapObj/CapMessageGameDataChecker.h b/src/MapObj/CapMessageGameDataChecker.h new file mode 100644 index 00000000..d4a694da --- /dev/null +++ b/src/MapObj/CapMessageGameDataChecker.h @@ -0,0 +1,31 @@ +#pragma once + +#include + +namespace al { +struct ActorInitInfo; +class IUseSceneObjHolder; +} // namespace al + +class CapMessageGameDataChecker { +public: + CapMessageGameDataChecker(); + + void initByPlacementInfo(const al::ActorInitInfo& info); + void invalidateKidsMode(); + void invalidatePlayerSeparate(); + void invalidateGameClear(); + void enableNoCap(); + void enableGiantWanderBoss(); + bool check(const al::IUseSceneObjHolder* sceneObjHolder) const; + +private: + bool mIsInvalidateKidsMode = false; + bool mIsInvalidatePlayerSeparate = false; + bool mIsInvalidateGameClear = false; + bool mIsEnableNoCap = false; + bool mIsEnableGiantWanderBoss = false; + u8 _5[3] = {}; +}; + +static_assert(sizeof(CapMessageGameDataChecker) == 0x8, "CapMessageGameDataChecker"); diff --git a/src/MapObj/CapMessageKeeper.h b/src/MapObj/CapMessageKeeper.h new file mode 100644 index 00000000..c89ad791 --- /dev/null +++ b/src/MapObj/CapMessageKeeper.h @@ -0,0 +1,61 @@ +#pragma once + +#include + +namespace al { +class IUseSceneObjHolder; +class Resource; +} // namespace al + +class CapMessageEnableChecker; + +class CapMessageKeeper { +public: + struct CapMsgType { + struct ValueArray { + ValueArray(); + }; + + static const char* text_(s32 value); + + s32 mValue = 0; + }; + + CapMessageKeeper(); + + void createAndReadYamlAll(); + bool isShowCapMsg(const al::IUseSceneObjHolder* sceneObjHolder, s32 id); + bool isShowCapMsgCurrentWorld(const al::IUseSceneObjHolder* sceneObjHolder, + const CapMsgType& type); + bool tryShowSaveCapMsg(const al::IUseSceneObjHolder* sceneObjHolder, const CapMsgType& type, + bool isSave); + bool tryShowCapMsgPrivate(const al::IUseSceneObjHolder* sceneObjHolder, const CapMsgType& type, + const char* messageName, s32 id, bool isDemo, bool isSave); + bool tryCheckShowCapMsg(const al::IUseSceneObjHolder* sceneObjHolder, const CapMsgType& type, + CapMessageEnableChecker* enableChecker, bool isSave); + void saveCapMsg(const al::IUseSceneObjHolder* sceneObjHolder, s32 id); + bool tryShowCapMsgPriorityLow(const al::IUseSceneObjHolder* sceneObjHolder, + const CapMsgType& type, s32 delayTime, s32 waitTime); + bool tryReadYamlOne(const al::Resource* resource, const char* messageName, s32* delayTime, + s32* waitTime); + bool tryShowCapMsgCurrentWorld(const al::IUseSceneObjHolder* sceneObjHolder, + const CapMsgType& type); + void saveCapMsgCurrentWorld(const al::IUseSceneObjHolder* sceneObjHolder, + const CapMsgType& type); + void saveCapMsg(const al::IUseSceneObjHolder* sceneObjHolder, const char* messageName); + s32* getCapMessageParam(const CapMsgType& type); + +private: + s32** mCapMessageParamTable = nullptr; + s32 mDefaultDelay = -1; + s32 mDefaultWaitFrame = -1; + void* mParamArray = nullptr; + s32 mUnused = 0; + u32 _1c = 0; +}; + +static_assert(sizeof(CapMessageKeeper) == 0x20, "CapMessageKeeper"); + +namespace CapMessageKeeperFuncrion { +CapMessageKeeper* getCapMsgKeeper(const al::IUseSceneObjHolder* sceneObjHolder); +} // namespace CapMessageKeeperFuncrion diff --git a/src/MapObj/CapMessagePlacement.h b/src/MapObj/CapMessagePlacement.h new file mode 100644 index 00000000..bcc39913 --- /dev/null +++ b/src/MapObj/CapMessagePlacement.h @@ -0,0 +1,59 @@ +#pragma once + +#include +#include + +#include "Library/LiveActor/LiveActor.h" + +namespace al { +struct ActorInitInfo; +} // namespace al + +class CapMessageAreaChecker; +class CapMessageEnableChecker; +class CapMessageGameDataChecker; +class CapMessageShowInfo; +struct SaveObjInfo; + +class CapMessagePlacement : public al::LiveActor { +public: + CapMessagePlacement(const char* name); + + void init(const al::ActorInitInfo& info); + void onKill(); + void onAppear(); + void initAfterPlacement(); + void showStart(); + void trySave(); + void showEnd(); + bool isActive() const; + bool checkEnbale() const; + + const CapMessageShowInfo* getShowInfo() const { return mShowInfo; } + + s32 getAppearPriority() const { return mAppearPriority; } + + s32 getDelayTime() const { return mDelayTime; } + + bool isDelayCancel() const { return mIsDelayCancel; } + + bool isKeepDisp() const { return mIsKeepDisp; } + +private: + CapMessageGameDataChecker* mGameDataChecker = nullptr; + CapMessageAreaChecker* mAreaChecker = nullptr; + CapMessageShowInfo* mShowInfo = nullptr; + sead::FixedSafeString<0x100> mMessageName; + sead::FixedSafeString<0x100> mLabelName; + bool mIsStageMessage = false; + u8 _351[7] = {}; + SaveObjInfo* mSaveObjInfo = nullptr; + s32 mAppearPriority = 0; + s32 mStartNum = 0; + s32 mDelayTime = 0; + bool mIsDelayCancel = false; + bool mIsSaveObjInfoOn = false; + bool mIsAppearSwitchOff = false; + bool mIsKilledBySwitch = false; + bool mIsKeepDisp = false; +}; diff --git a/src/Scene/SceneObjFactory.cpp b/src/Scene/SceneObjFactory.cpp index 5c457e24..f2e59bae 100644 --- a/src/Scene/SceneObjFactory.cpp +++ b/src/Scene/SceneObjFactory.cpp @@ -9,6 +9,7 @@ #include "Item/CoinCollectHolder.h" #include "Item/CoinCollectWatcher.h" #include "Layout/KidsModeLayoutAccessor.h" +#include "MapObj/CapMessageDirector.h" #include "MapObj/RouteGuideDirector.h" #include "Scene/HintPhotoLayoutHolder.h" @@ -24,7 +25,7 @@ static al::ISceneObj* sceneObjCreator(s32 id) { return nullptr; case SceneObjID_CapMessageDirector: - return nullptr; + return new CapMessageDirector(); case SceneObjID_CapMessageMoonNotifier: return nullptr;