diff --git a/data/file_list.yml b/data/file_list.yml index 57275543..656ba621 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -64014,92 +64014,92 @@ MapObj/CheckpointFlag.o: - offset: 0x2495b8 size: 188 label: _ZN14CheckpointFlagC2EPKc - status: NotDecompiled + status: Matching - offset: 0x249674 size: 184 label: _ZN14CheckpointFlagC1EPKc - status: NotDecompiled + status: Matching - offset: 0x24972c size: 792 label: _ZN14CheckpointFlag4initERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x249a44 size: 4 label: _ZN14CheckpointFlag18initAfterPlacementEv - status: NotDecompiled + status: Matching - offset: 0x249a48 size: 44 label: _ZN14CheckpointFlag7controlEv - status: NotDecompiled + status: Matching - offset: 0x249a74 size: 108 label: _ZN14CheckpointFlag12attackSensorEPN2al9HitSensorES2_ - status: NotDecompiled + status: Matching - offset: 0x249ae0 size: 688 label: _ZN14CheckpointFlag10receiveMsgEPKN2al9SensorMsgEPNS0_9HitSensorES5_ - status: NotDecompiled + status: Matching - offset: 0x249d90 size: 8 label: _ZNK14CheckpointFlag20getPlayerRestartInfoEv - status: NotDecompiled + status: Matching - offset: 0x249d98 size: 80 label: _ZN14CheckpointFlag8setAfterEv - status: NotDecompiled + status: Matching - offset: 0x249de8 size: 16 label: _ZN14CheckpointFlag17startArriveByWarpEv - status: NotDecompiled + status: Matching - offset: 0x249df8 size: 20 label: _ZN14CheckpointFlag12initHomeFlagERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x249e0c size: 148 label: _ZN14CheckpointFlag9exeBeforeEv - status: NotDecompiled + status: Matching - offset: 0x249ea0 size: 132 label: _ZN14CheckpointFlag6exeGetEv - status: NotDecompiled + status: Matching - offset: 0x249f24 size: 124 label: _ZN14CheckpointFlag8exeAfterEv - status: NotDecompiled + status: Matching - offset: 0x249fa0 size: 168 label: _ZN14CheckpointFlag8exeShakeEv - status: NotDecompiled + status: Matching - offset: 0x24a048 size: 8 label: _ZNK14CheckpointFlag16getMessageSystemEv - status: NotDecompiled + status: Matching lazy: true - offset: 0x24a050 size: 8 label: _ZThn264_NK14CheckpointFlag16getMessageSystemEv - status: NotDecompiled + status: Matching lazy: true - offset: 0x24a058 size: 8 label: _ZNK12_GLOBAL__N_123CheckpointFlagNrvBefore7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x24a060 size: 128 label: _ZNK12_GLOBAL__N_122CheckpointFlagNrvAfter7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x24a0e0 size: 8 label: _ZNK12_GLOBAL__N_120CheckpointFlagNrvGet7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x24a0e8 size: 8 label: _ZNK12_GLOBAL__N_122CheckpointFlagNrvShake7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true MapObj/CheckpointFlagWatcher.o: '.text': @@ -133918,7 +133918,7 @@ Scene/ProjectActorFactory.o: - offset: 0x4b71f0 size: 52 label: _ZN2al19createActorFunctionI14CheckpointFlagEEPNS_9LiveActorEPKc - status: NotDecompiled + status: Matching lazy: true - offset: 0x4b7224 size: 52 diff --git a/src/MapObj/AirBubble.h b/src/MapObj/AirBubble.h new file mode 100644 index 00000000..3b1b20c1 --- /dev/null +++ b/src/MapObj/AirBubble.h @@ -0,0 +1,33 @@ +#pragma once + +#include "Library/LiveActor/LiveActor.h" + +class AirBubble : public al::LiveActor { +public: + AirBubble(const char*, bool); + + void init(const al::ActorInitInfo& info) override; + void endClipped() override; + void startClipped() override; + void appear() override; + void appearPopup(); + void control() override; + bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) override; + + void exeCreate(); + void exeWait(); + void exeReaction(); + void exeMove(); + void exeGot(); + + void getItem(); + + void exeCapGet(); + void exeBreak(); + +private: + char _108[0x20]; +}; + +static_assert(sizeof(AirBubble) == 0x128); diff --git a/src/MapObj/CheckpointFlag.cpp b/src/MapObj/CheckpointFlag.cpp new file mode 100644 index 00000000..a83347bc --- /dev/null +++ b/src/MapObj/CheckpointFlag.cpp @@ -0,0 +1,255 @@ +#include "MapObj/CheckpointFlag.h" + +#include + +#include "Library/Layout/LayoutInitInfo.h" +#include "Library/LiveActor/ActorActionFunction.h" +#include "Library/LiveActor/ActorAnimFunction.h" +#include "Library/LiveActor/ActorFlagFunction.h" +#include "Library/LiveActor/ActorInitUtil.h" +#include "Library/LiveActor/ActorModelFunction.h" +#include "Library/LiveActor/ActorPoseUtil.h" +#include "Library/LiveActor/ActorSensorUtil.h" +#include "Library/Message/MessageHolder.h" +#include "Library/Nature/NatureUtil.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" +#include "Library/Placement/PlacementFunction.h" + +#include "MapObj/AirBubble.h" +#include "MapObj/CheckpointFlagWatcher.h" +#include "MapObj/PlayerStartInfoHolder.h" +#include "Npc/BirdMtxGlideCtrl.h" +#include "System/GameDataFunction.h" +#include "Util/ItemUtil.h" +#include "Util/PlayerUtil.h" +#include "Util/SensorMsgFunction.h" +#include "Util/StageLayoutFunction.h" + +namespace { +NERVE_IMPL(CheckpointFlag, Before); +NERVE_IMPL(CheckpointFlag, After); +NERVE_IMPL(CheckpointFlag, Get); +NERVE_IMPL(CheckpointFlag, Shake); + +NERVES_MAKE_STRUCT(CheckpointFlag, Before, After, Get, Shake); +} // namespace + +CheckpointFlag::CheckpointFlag(const char* name) : al::LiveActor(name) {} + +const sead::Vector3f gBirdOffset = {75.0f, 0.0f, 0.0f}; +const sead::Vector3f gAirBubbleOffset = {0.0f, 100.0f, 0.0f}; +const sead::Vector3f gBalloonOffset = {0.0f, 75.0f, 0.0f}; + +void CheckpointFlag::init(const al::ActorInitInfo& info) { + al::initActorWithArchiveName(this, info, "CheckpointFlag", nullptr); + al::initNerve(this, &NrvCheckpointFlag.Before, 0); + rs::registerCheckpointFlagToWatcher(this); + mMessageSystem = al::getLayoutInitInfo(info).getMessageSystem(); + mPlayerRestartInfo = al::createLinksPlayerActorInfo(this, info); + mPlacementId = al::createPlacementId(info); + al::tryGetArg(&mIsZeroGravity, info, "IsZeroGravity"); + if (al::isInWater(this)) { + if (al::isInWaterPos(this, al::getSensorPos(this, "BodyTop"))) { + mAirBubble = new AirBubble("中間ポイントの空気泡", false); + al::initCreateActorNoPlacementInfo(mAirBubble, info); + } + } + if (mIsHome) { + rs::registerLinkedPlayerStartInfoToHolder(this, info, nullptr, nullptr, nullptr); + mFlagName = al::getSystemMessageString(this, "GlossaryObject", "Home"); + setAfter(); + makeActorAlive(); + return; + } + f32 frame = rs::getStageShineAnimFrame(this); + if (frame < 0.0f) + frame = 0.0f; + al::startMclAnimAndSetFrameAndStop(this, "Color", frame); + al::StringTmp<128> messageLabel(""); + rs::makeActorMessageLabel(&messageLabel, info, rs::getCheckpointLabelPrefix()); + const char* stageName = rs::getPlacementStageName(this, info); + if (al::isExistLabelInStageMessage(this, stageName, messageLabel.cstr())) + mFlagName = al::getStageMessageString(this, stageName, messageLabel.cstr()); + if (GameDataFunction::isGotCheckpoint(this, mPlacementId)) + setAfter(); + rs::registerLinkedPlayerStartInfoToHolder(this, info, nullptr, nullptr, nullptr); + GameDataFunction::registerCheckpointTrans(this, mPlacementId, al::getTrans(this)); + mBirdMtxGlideCtrl = BirdMtxGlideCtrl::tryCreateAliveWaitByLinksBird( + al::getJointMtxPtr(this, "Pole2"), gBirdOffset, info, "Bird"); + al::trySyncStageSwitchAppear(this); +} + +void CheckpointFlag::initAfterPlacement() {} + +void CheckpointFlag::control() { + mHitCooldown--; + if (mAirBubbleTimer > -1) + mAirBubbleTimer--; + if (mBirdMtxGlideCtrl) + mBirdMtxGlideCtrl->update(); +} + +void CheckpointFlag::attackSensor(al::HitSensor* self, al::HitSensor* other) { + if (al::isNerve(this, &NrvCheckpointFlag.After) && al::isSensorName(self, "Push")) + rs::sendMsgPushToPlayer(other, self) || al::sendMsgPush(other, self); +} + +bool CheckpointFlag::receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) { + if (al::isNerve(this, &NrvCheckpointFlag.Get)) + return false; + if (al::isMsgPlayerDisregard(message)) + return !al::isSensorName(self, "BodyTop"); + if (rs::isMsgPlayerDisregardTargetMarker(message)) + return true; + if (mIsGot) { + if (rs::isMsgItemGet(message) || al::isMsgPlayerKick(message) || + al::isMsgPlayerObjTouch(message) || rs::isMsgYoshiTongueAttack(message)) { + bool isGot = mIsGot; + AirBubble* airBubble = mAirBubble; + s32 hitCooldown = mHitCooldown; + mHitCooldown = 10; + if (hitCooldown > 0) + return false; + if (isGot) + rs::setTouchCheckpointFlagToWatcher(this); + if (airBubble && !al::isAlive(airBubble) && mAirBubbleTimer < 0) { + al::calcTransLocalOffset(al::getTransPtr(airBubble), this, gAirBubbleOffset); + airBubble->appear(); + mAirBubbleTimer = 180; + } + al::setNerve(this, &NrvCheckpointFlag.Shake); + return al::isMsgPlayerObjTouch(message); + } + } else { + bool isAcquired = false; + if (rs::isMsgItemGet(message)) { + if (rs::isPlayerHack(this) || rs::isPlayerBinding(this)) + isAcquired = true; + } else if (rs::isMsgCapReflect(message) || al::isMsgPlayerKick(message) || + al::isMsgPlayerItemGet(message) || rs::isMsgYoshiTongueAttack(message)) + isAcquired = true; + if (isAcquired) { + al::startHitReaction(this, "取得"); + rs::setTouchCheckpointFlagToWatcher(this); + AirBubble* airBubble = mAirBubble; + if (airBubble && !al::isAlive(airBubble) && mAirBubbleTimer < 0) { + al::calcTransLocalOffset(al::getTransPtr(airBubble), this, gAirBubbleOffset); + airBubble->appear(); + mAirBubbleTimer = 180; + } + GameDataFunction::recoveryPlayerMax(this); + rs::sendMsgAckCheckpoint(other, self); + al::setNerve(this, &NrvCheckpointFlag.Get); + return al::isMsgPlayerKick(message); + } + } + if (rs::isMsgCapReflect(message) || rs::isMsgHosuiAttack(message) || + rs::isMsgHammerBrosHammerHackAttack(message) || al::isMsgPlayerFireBallAttack(message) || + rs::isMsgTankBullet(message)) { + bool isGot = mIsGot; + AirBubble* airBubble = mAirBubble; + s32 hitCooldown = mHitCooldown; + mHitCooldown = 10; + if (hitCooldown > 0) + return false; + if (isGot) + rs::setTouchCheckpointFlagToWatcher(this); + if (airBubble && !al::isAlive(airBubble) && mAirBubbleTimer < 0) { + al::calcTransLocalOffset(al::getTransPtr(airBubble), this, gAirBubbleOffset); + airBubble->appear(); + mAirBubbleTimer = 180; + } + al::setNerve(this, &NrvCheckpointFlag.Shake); + return al::isMsgPlayerObjTouch(message); + } + return false; +} + +const al::PlacementInfo* CheckpointFlag::getPlayerRestartInfo() const { + return &al::getPlacementInfo(*mPlayerRestartInfo); +} + +void CheckpointFlag::setAfter() { + bool isZeroGravity = mIsZeroGravity; + al::startAction(this, "After"); + if (isZeroGravity) + al::setActionFrameRate(this, 0.2f); + al::setNerve(this, &NrvCheckpointFlag.After); +} + +void CheckpointFlag::startArriveByWarp() { + if (mBirdMtxGlideCtrl) + mBirdMtxGlideCtrl->makeActorDeadBirdIfAlive(); +} + +void CheckpointFlag::initHomeFlag(const al::ActorInitInfo& info) { + mIsHome = true; + init(info); +} + +void CheckpointFlag::exeBefore() { + if (al::isFirstStep(this)) { + bool isZeroGravity = mIsZeroGravity; + al::startAction(this, "Before"); + if (isZeroGravity) + al::setActionFrameRate(this, 0.2f); + if (mBirdMtxGlideCtrl) + mBirdMtxGlideCtrl->validateGlide(); + } + if (!mIsHome) { + if (mBirdMtxGlideCtrl && mBirdMtxGlideCtrl->isWaitBird()) + rs::requestShowCheckpointFlagBalloon(this, gBalloonOffset); + else + rs::requestShowCheckpointFlagBalloon(this, sead::Vector3f::zero); + } +} + +void CheckpointFlag::exeGet() { + if (al::isFirstStep(this)) { + bool isZeroGravity = mIsZeroGravity; + al::startAction(this, "Get"); + if (isZeroGravity) + al::setActionFrameRate(this, 0.2f); + rs::requestShowCheckpointFlagNameLayout(this, mFlagName); + rs::requestHideCheckpointFlagBalloon(this); + if (mBirdMtxGlideCtrl) + mBirdMtxGlideCtrl->invalidateGlide(); + mIsGot = true; + } + al::setNerveAtActionEnd(this, &NrvCheckpointFlag.After); +} + +void CheckpointFlag::exeAfter() { + if (al::isFirstStep(this)) { + bool isZeroGravity = mIsZeroGravity; + mIsGot = true; + if (!al::isActionPlaying(this, "After")) { + al::startAction(this, "After"); + if (isZeroGravity) + al::setActionFrameRate(this, 0.2f); + } + if (mBirdMtxGlideCtrl) + mBirdMtxGlideCtrl->validateGlide(); + } +} + +void CheckpointFlag::exeShake() { + if (al::isFirstStep(this)) { + bool isZeroGravity = mIsZeroGravity; + al::startAction(this, "Shake"); + if (isZeroGravity) + al::setActionFrameRate(this, 0.2f); + if (mBirdMtxGlideCtrl) + mBirdMtxGlideCtrl->invalidateGlide(); + if (mIsGot) + rs::requestShowCheckpointFlagNameLayout(this, mFlagName); + } + if (al::isActionEnd(this)) { + if (mIsGot) + al::setNerve(this, &NrvCheckpointFlag.After); + else + al::setNerve(this, &NrvCheckpointFlag.Before); + } +} diff --git a/src/MapObj/CheckpointFlag.h b/src/MapObj/CheckpointFlag.h new file mode 100644 index 00000000..d15c8bd2 --- /dev/null +++ b/src/MapObj/CheckpointFlag.h @@ -0,0 +1,50 @@ +#pragma once + +#include "Library/LiveActor/LiveActor.h" +#include "Library/Message/IUseMessageSystem.h" + +namespace al { +class PlacementId; +class PlacementInfo; +} // namespace al +class AirBubble; +class BirdMtxGlideCtrl; + +class CheckpointFlag : public al::LiveActor, public al::IUseMessageSystem { +public: + CheckpointFlag(const char* name); + + void init(const al::ActorInitInfo& info) override; + void initAfterPlacement() override; + void control() override; + void attackSensor(al::HitSensor* self, al::HitSensor* other) override; + bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) override; + + const al::PlacementInfo* getPlayerRestartInfo() const; + void setAfter(); + void startArriveByWarp(); + void initHomeFlag(const al::ActorInitInfo& info); + + void exeBefore(); + void exeGet(); + void exeAfter(); + void exeShake(); + + const al::MessageSystem* getMessageSystem() const override { return mMessageSystem; } + +private: + al::MessageSystem* mMessageSystem = nullptr; + al::ActorInitInfo* mPlayerRestartInfo = nullptr; + al::PlacementId* mPlacementId = nullptr; + const char16* mFlagName = u"/////////////////"; + s32 mHitCooldown = 0; + bool mIsGot = false; + bool mIsHome = false; + bool mIsZeroGravity = false; + AirBubble* mAirBubble = nullptr; + s32 mAirBubbleTimer = -1; + BirdMtxGlideCtrl* mBirdMtxGlideCtrl = nullptr; +}; + +static_assert(sizeof(CheckpointFlag) == 0x150); diff --git a/src/MapObj/CheckpointFlagWatcher.h b/src/MapObj/CheckpointFlagWatcher.h new file mode 100644 index 00000000..4de78872 --- /dev/null +++ b/src/MapObj/CheckpointFlagWatcher.h @@ -0,0 +1,86 @@ +#pragma once + +#include +#include + +#include "Library/Camera/IUseCamera.h" +#include "Library/Execute/IUseExecutor.h" +#include "Library/HostIO/HioNode.h" +#include "Library/LiveActor/LiveActorGroup.h" +#include "Library/Scene/ISceneObj.h" + +#include "Scene/SceneObjFactory.h" + +namespace al { +class LiveActor; +class PlacementInfo; +class Scene; +class SimpleLayoutAppearWaitEnd; +} // namespace al + +class CheckpointFlag; + +class CheckpointFlagWatcher : public al::HioNode, + public al::ISceneObj, + public al::IUseCamera, + public al::IUseExecutor { +public: + static constexpr s32 sSceneObjId = SceneObjID_CheckpointFlagWatcher; + + CheckpointFlagWatcher(al::CameraDirector* director); + + void initStageInfo(const char* stageName, s32 scenarioNum); + void initAfterPlacementSceneObj(const al::ActorInitInfo& info) override; + void execute() override; + + void registerCheckpointFlag(CheckpointFlag* checkpoint); + void setTouchCheckpointFlag(CheckpointFlag* checkpoint); + void setTouchAfterCheckpointFlag(const char* checkpointName); + CheckpointFlag* findCheckpointFlag(const char* checkpointName) const; + CheckpointFlag* tryFindCheckpointFlag(const char* checkpointName) const; + bool tryFindCheckpointFlagTrans(sead::Vector3f* trans, const char* checkpointName) const; + void requestShowNameLayout(const char16*); + void requestCancelNameLayoutByShineGetDemo(); + void requestShowBalloon(const CheckpointFlag*, const sead::Vector3f&); + void requestHideBalloon(); + void hideBalloonAllAtBossSequence(const al::LiveActor*); + void showBalloonAllAfterBossSequence(const al::LiveActor*); + + const char* getSceneObjName() const override { return "中間ポイント監視"; } + + al::CameraDirector* getCameraDirector() const override { return mCameraDirector; } + +private: + CheckpointFlag* mLastCheckpoint = nullptr; + al::DeriveActorGroup* mCheckpointTable; + char _28[0x8]; + al::SimpleLayoutAppearWaitEnd* mNameLayout = nullptr; + bool mIsCancelNameLayout = false; + char _40[0x30]; + const char* mStageName = nullptr; + s32 mScenarioNum = 1; + al::CameraDirector* mCameraDirector = nullptr; + al::LiveActor* _88 = nullptr; +}; + +static_assert(sizeof(CheckpointFlagWatcher) == 0x90); + +namespace rs { +void registerCheckpointFlagToWatcher(CheckpointFlag*); +void setTouchCheckpointFlagToWatcher(CheckpointFlag*); +void setTouchAfterCheckpointFlagToWatcher(const al::IUseSceneObjHolder* sceneObjHolder, + const char* checkpointName); +const al::PlacementInfo* +tryFindCheckpointFlagPlayerRestartInfo(const al::IUseSceneObjHolder* sceneObjHolder, + const char* checkpointName); +CheckpointFlag* tryFindCheckpointFlag(const al::IUseSceneObjHolder* sceneObjHolder, + const char* checkpointName); +bool tryFindCheckpointFlagTrans(sead::Vector3f*, const al::IUseSceneObjHolder* sceneObjHolder, + const char* checkpointName); +void requestShowCheckpointFlagNameLayout(const CheckpointFlag* checkpoint, const char16* name); +void requestShowCheckpointFlagBalloon(const CheckpointFlag*, const sead::Vector3f&); +void requestHideCheckpointFlagBalloon(const CheckpointFlag*); +void requestCancelCheckpointFlagNameLayoutByShineGetDemo(const al::Scene*); +void hideCheckpointFlagBalloonAllAtBossSequence(const al::LiveActor*); +void showCheckpointFlagBalloonAllAfterBossSequence(const al::LiveActor*); +} // namespace rs diff --git a/src/MapObj/PlayerStartInfoHolder.h b/src/MapObj/PlayerStartInfoHolder.h new file mode 100644 index 00000000..d3e88629 --- /dev/null +++ b/src/MapObj/PlayerStartInfoHolder.h @@ -0,0 +1,67 @@ +#pragma once + +#include +#include +#include + +#include "Library/Camera/IUseCamera.h" +#include "Library/HostIO/HioNode.h" +#include "Library/Scene/ISceneObj.h" + +namespace al { +struct ActorInitInfo; +class AreaObjGroup; +class CameraTicket; +class IUseSceneObjHolder; +class LiveActor; +class PlacementInfo; +class Scene; +} // namespace al +class PlayerStartInfo; +class PlayerStartObj; + +class PlayerStartInfoHolder : public al::ISceneObj, public al::IUseCamera, public al::HioNode { +public: + PlayerStartInfoHolder(); + + void init(al::CameraDirector*, s32); + void registerPlayerStartInfo(const al::PlacementInfo*, const char*, al::CameraTicket*, + PlayerStartObj*, const sead::Vector3f*, const sead::Quatf*); + bool isRegistered(const al::PlacementInfo*, const char*) const; + void registerChangeStageAreaGroup(al::AreaObjGroup*, const al::ActorInitInfo&); + void registerWarpAreaGroup(al::AreaObjGroup*, const al::ActorInitInfo&); + void registerRestartAreaGroup(al::AreaObjGroup*); + PlayerStartInfo* tryFindInitInfoByStartId(const char*) const; + PlayerStartInfo* tryFindInitInfoByPlacementIdString(const char*) const; + + const char* getSceneObjName() const override; + + al::CameraDirector* getCameraDirector() const override; + +private: + char _10[0x18]; +}; + +static_assert(sizeof(PlayerStartInfoHolder) == 0x28); + +namespace rs { +void registerLinkedPlayerStartInfoToHolder(const al::IUseSceneObjHolder*, const al::ActorInitInfo&, + const char*, const sead::Vector3f*, const sead::Quatf*); +void registerPlayerStartInfoToHolder(const al::IUseSceneObjHolder*, const al::PlacementInfo&, + const char*, PlayerStartObj*, const sead::Vector3f*, + const sead::Quatf*); +void registerPlayerStartInfoToHolder(const al::IUseSceneObjHolder*, const al::ActorInitInfo&, + const char*, PlayerStartObj*, const sead::Vector3f*, + const sead::Quatf*); +void registerPlayerStartInfoToHolderWithCamera(al::CameraTicket*, const al::IUseSceneObjHolder*, + const al::ActorInitInfo&, const char*, + PlayerStartObj*, const sead::Vector3f*, + const sead::Quatf*); +void registerPlayerStartInfoToHolderForTimeBalloon(const al::IUseSceneObjHolder*, + const al::ActorInitInfo&); +void registerPlayerStartInfoToHolderForCloset(const al::IUseSceneObjHolder*, + const al::ActorInitInfo&, const sead::Vector3f&, + const sead::Quatf&); +void tryStartEntranceCamera(const al::Scene*, const char*); +bool isPlayerStartCloset(const al::LiveActor*); +} // namespace rs diff --git a/src/Npc/BirdMtxGlideCtrl.h b/src/Npc/BirdMtxGlideCtrl.h new file mode 100644 index 00000000..a8912806 --- /dev/null +++ b/src/Npc/BirdMtxGlideCtrl.h @@ -0,0 +1,36 @@ +#pragma once + +#include +#include + +#include "Library/Nerve/NerveExecutor.h" + +namespace al { +struct ActorInitInfo; +} // namespace al + +class Bird; + +class BirdMtxGlideCtrl : public al::NerveExecutor { +public: + static BirdMtxGlideCtrl* tryCreateAliveWaitByLinksBird(const sead::Matrix34f*, + const sead::Vector3f&, + const al::ActorInitInfo&, const char*); + + BirdMtxGlideCtrl(Bird*); + + void update(); + void makeActorDeadBirdIfAlive(); + + void exeInvalid(); + void exeValid(); + + void validateGlide(); + void invalidateGlide(); + bool isWaitBird() const; + +private: + char _10[0x8]; +}; + +static_assert(sizeof(BirdMtxGlideCtrl) == 0x18); diff --git a/src/Scene/ProjectActorFactory.cpp b/src/Scene/ProjectActorFactory.cpp index 7316a553..87a7d3a6 100644 --- a/src/Scene/ProjectActorFactory.cpp +++ b/src/Scene/ProjectActorFactory.cpp @@ -70,6 +70,7 @@ #include "MapObj/CapBomb.h" #include "MapObj/CapHanger.h" #include "MapObj/CapSwitch.h" +#include "MapObj/CheckpointFlag.h" #include "MapObj/ChurchDoor.h" #include "MapObj/CitySignal.h" #include "MapObj/CoinCollectHintObj.h" @@ -210,7 +211,7 @@ const al::NameToCreator sProjectActorFactoryEntries[] {"CardboardBox", nullptr}, {"CatchBomb", al::createActorFunction}, {"Chair", nullptr}, - {"CheckpointFlag", nullptr}, + {"CheckpointFlag", al::createActorFunction}, {"ChorobonHolder", nullptr}, {"ChurchDoor", al::createActorFunction}, {"CityBuilding", nullptr},