diff --git a/data/file_list.yml b/data/file_list.yml index 0e7a7041..5304518f 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -59090,66 +59090,66 @@ MapObj/BlockQuestion2D.o: - offset: 0x21eaac size: 168 label: _ZN15BlockQuestion2DC2EPKc - status: NotDecompiled + status: Matching - offset: 0x21eb54 size: 164 label: _ZN15BlockQuestion2DC1EPKc - status: NotDecompiled + status: Matching - offset: 0x21ebf8 size: 588 label: _ZN15BlockQuestion2D4initERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x21ee44 size: 224 label: _ZN15BlockQuestion2D18initAfterPlacementEv - status: NotDecompiled + status: Matching - offset: 0x21ef24 size: 56 label: _ZN15BlockQuestion2D6appearEv - status: NotDecompiled + status: Matching - offset: 0x21ef5c size: 16 label: _ZN15BlockQuestion2D7controlEv - status: NotDecompiled + status: Matching - offset: 0x21ef6c size: 132 label: _ZN15BlockQuestion2D12attackSensorEPN2al9HitSensorES2_ - status: NotDecompiled + status: Matching - offset: 0x21eff0 size: 240 label: _ZN15BlockQuestion2D10receiveMsgEPKN2al9SensorMsgEPNS0_9HitSensorES5_ - status: NotDecompiled + status: Matching - offset: 0x21f0e0 size: 100 label: _ZN15BlockQuestion2D10endClippedEv - status: NotDecompiled + status: Matching - offset: 0x21f144 size: 88 label: _ZN15BlockQuestion2D13exeSingleItemEv - status: NotDecompiled + status: Matching - offset: 0x21f19c size: 76 label: _ZN15BlockQuestion2D10exeTenCoinEv - status: NotDecompiled + status: Matching - offset: 0x21f1e8 size: 8 label: _ZNK15BlockQuestion2D23getActorDimensionKeeperEv - status: NotDecompiled + status: Matching lazy: true - offset: 0x21f1f0 size: 8 label: _ZThn264_NK15BlockQuestion2D23getActorDimensionKeeperEv - status: NotDecompiled + status: Matching lazy: true - offset: 0x21f1f8 size: 80 label: _ZNK12_GLOBAL__N_125BlockQuestion2DNrvTenCoin7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x21f248 size: 92 label: _ZNK12_GLOBAL__N_128BlockQuestion2DNrvSingleItem7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true MapObj/BlockStateNoItem.o: '.text': @@ -133626,7 +133626,7 @@ Scene/ProjectActorFactory.o: - offset: 0x4b63a8 size: 52 label: _ZN2al19createActorFunctionI15BlockQuestion2DEEPNS_9LiveActorEPKc - status: NotDecompiled + status: Matching lazy: true - offset: 0x4b63dc size: 52 diff --git a/src/MapObj/BlockEmpty2D.h b/src/MapObj/BlockEmpty2D.h index 9b9202df..221af446 100644 --- a/src/MapObj/BlockEmpty2D.h +++ b/src/MapObj/BlockEmpty2D.h @@ -20,6 +20,8 @@ public: bool receiveMsg(const al::SensorMsg* msg, al::HitSensor* other, al::HitSensor* self) override; ActorDimensionKeeper* getActorDimensionKeeper() const override; + void setMtxConnector(al::MtxConnector* mtxConnector) { mMtxConnector = mtxConnector; } + private: bool mIsConnectToCollisionBack = false; al::MtxConnector* mMtxConnector = nullptr; diff --git a/src/MapObj/BlockQuestion2D.cpp b/src/MapObj/BlockQuestion2D.cpp new file mode 100644 index 00000000..86315df2 --- /dev/null +++ b/src/MapObj/BlockQuestion2D.cpp @@ -0,0 +1,155 @@ +#include "MapObj/BlockQuestion2D.h" + +#include + +#include "Library/Collision/PartsConnectorUtil.h" +#include "Library/LiveActor/ActorActionFunction.h" +#include "Library/LiveActor/ActorAnimFunction.h" +#include "Library/LiveActor/ActorInitUtil.h" +#include "Library/LiveActor/ActorPoseUtil.h" +#include "Library/LiveActor/ActorSensorUtil.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" +#include "Library/Placement/PlacementFunction.h" +#include "Library/Placement/PlacementId.h" +#include "Library/Scene/SceneObjUtil.h" +#include "Library/Stage/StageRhythm.h" + +#include "MapObj/BlockEmpty2D.h" +#include "MapObj/BlockStateSingleItem.h" +#include "MapObj/BlockStateTenCoin.h" +#include "Util/ActorDimensionKeeper.h" +#include "Util/ActorDimensionUtil.h" +#include "Util/ItemUtil.h" +#include "Util/SensorMsgFunction.h" + +namespace { +NERVE_IMPL(BlockQuestion2D, TenCoin); +NERVE_IMPL(BlockQuestion2D, SingleItem); + +NERVES_MAKE_STRUCT(BlockQuestion2D, TenCoin, SingleItem); +} // namespace + +BlockQuestion2D::BlockQuestion2D(const char* name) : al::LiveActor(name) {} + +void BlockQuestion2D::init(const al::ActorInitInfo& info) { + al::initActorWithArchiveName(this, info, "BlockQuestion2D", nullptr); + mItemType = rs::getItemType(info); + + if (mItemType < 0) { + mSingleItemState = new BlockStateSingleItem(this, mItemType, true); + al::initNerve(this, &NrvBlockQuestion2D.SingleItem, 1); + al::initNerveState(this, mSingleItemState, &NrvBlockQuestion2D.SingleItem, "アイテム"); + } else { + rs::initItem2DByPlacementInfo(this, info); + if (mItemType == rs::ItemType::Coin10) { + mTenCoinState = new BlockStateTenCoin(this, true); + al::initNerve(this, &NrvBlockQuestion2D.TenCoin, 1); + al::initNerveState(this, mTenCoinState, &NrvBlockQuestion2D.TenCoin, "10コイン"); + } else { + mSingleItemState = new BlockStateSingleItem(this, mItemType, true); + al::initNerve(this, &NrvBlockQuestion2D.SingleItem, 1); + al::initNerveState(this, mSingleItemState, &NrvBlockQuestion2D.SingleItem, "アイテム"); + } + } + + al::startAction(this, "Wait"); + mDimensionKeeper = rs::createDimensionKeeper(this); + rs::updateDimensionKeeper(mDimensionKeeper); + + if (!rs::isIn2DArea(this)) { + al::PlacementId placementId; + al::tryGetPlacementId(&placementId, info); + al::StringTmp<128> str; + placementId.makeString(&str); + kill(); + return; + } + + mMtxConnector = al::tryCreateMtxConnector(this, info); + if (mMtxConnector) + al::tryGetArg(&mIsConnectToCollisionBack, info, "IsConnectToCollisionBack"); + + rs::snap2DParallelizeFront(this, this, 500.0f); + mEmptyBlock2D = new BlockEmpty2D("空ブロック2D"); + al::initCreateActorWithPlacementInfo(mEmptyBlock2D, info); + mEmptyBlock2D->makeActorDead(); + makeActorAlive(); +} + +void BlockQuestion2D::initAfterPlacement() { + if (!mMtxConnector) + return; + + if (mIsConnectToCollisionBack) { + sead::Vector3f frontDir = {0.0f, 0.0f, 0.0f}; + al::calcFrontDir(&frontDir, this); + al::attachMtxConnectorToCollision( + mMtxConnector, this, al::getTrans(this) + 50.0f * frontDir, -400.0f * frontDir); + } else { + al::attachMtxConnectorToCollision(mMtxConnector, this, 50.0f, 400.0f); + } +} + +void BlockQuestion2D::appear() { + al::LiveActor::appear(); + if (mMtxConnector) + al::connectPoseQT(this, mMtxConnector); +} + +void BlockQuestion2D::control() { + if (mMtxConnector) + al::connectPoseQT(this, mMtxConnector); +} + +void BlockQuestion2D::attackSensor(al::HitSensor* self, al::HitSensor* other) { + if (al::isNerve(this, &NrvBlockQuestion2D.SingleItem) && mSingleItemState->isReaction()) { + rs::sendMsgBlockUpperPunch2D(other, self); + return; + } + + if (al::isNerve(this, &NrvBlockQuestion2D.TenCoin) && mTenCoinState->isReaction()) + rs::sendMsgBlockUpperPunch2D(other, self); +} + +bool BlockQuestion2D::receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) { + if (al::isMsgPlayerDisregard(message)) + return true; + + if (rs::isMsgBlockReaction2D(message) && !al::isSensorName(self, "UpperPunch")) { + if (al::isNerve(this, &NrvBlockQuestion2D.SingleItem)) { + mSingleItemState->setItemOffsetY(200.0f); + return mSingleItemState->receiveMsg(message, other, self); + } + + if (al::isNerve(this, &NrvBlockQuestion2D.TenCoin)) { + mTenCoinState->setItemOffsetY(200.0f); + return mTenCoinState->receiveMsg(message, other, self); + } + } + return false; +} + +void BlockQuestion2D::endClipped() { + s32 syncCounter = al::getSceneObj(this)->getCounter(); + s32 frameMax = al::getVisAnimFrameMax(this, "Wait"); + al::setVisAnimFrameForAction(this, syncCounter % frameMax); + al::LiveActor::endClipped(); +} + +void BlockQuestion2D::exeSingleItem() { + if (al::updateNerveState(this)) { + mEmptyBlock2D->appear(); + mEmptyBlock2D->setMtxConnector(mMtxConnector); + kill(); + } +} + +void BlockQuestion2D::exeTenCoin() { + if (al::updateNerveState(this)) { + mEmptyBlock2D->appear(); + // BUG: missing `mEmptyBlock2D->setMtxConnector(mMtxConnector)` + kill(); + } +} diff --git a/src/MapObj/BlockQuestion2D.h b/src/MapObj/BlockQuestion2D.h new file mode 100644 index 00000000..172b86cd --- /dev/null +++ b/src/MapObj/BlockQuestion2D.h @@ -0,0 +1,49 @@ +#pragma once + +#include + +#include "Library/LiveActor/LiveActor.h" + +#include "Util/IUseDimension.h" + +namespace al { +struct ActorInitInfo; +class HitSensor; +class MtxConnector; +class SensorMsg; +} // namespace al + +class ActorDimensionKeeper; +class BlockEmpty2D; +class BlockStateSingleItem; +class BlockStateTenCoin; + +class BlockQuestion2D : public al::LiveActor, public IUseDimension { +public: + BlockQuestion2D(const char* name); + + void init(const al::ActorInitInfo& info) override; + void initAfterPlacement() override; + void appear() 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; + void endClipped() override; + + ActorDimensionKeeper* getActorDimensionKeeper() const override { return mDimensionKeeper; } + + void exeSingleItem(); + void exeTenCoin(); + +private: + s32 mItemType = -1; + BlockStateTenCoin* mTenCoinState = nullptr; + BlockStateSingleItem* mSingleItemState = nullptr; + BlockEmpty2D* mEmptyBlock2D = nullptr; + ActorDimensionKeeper* mDimensionKeeper = nullptr; + al::MtxConnector* mMtxConnector = nullptr; + bool mIsConnectToCollisionBack = false; +}; + +static_assert(sizeof(BlockQuestion2D) == 0x148); diff --git a/src/MapObj/BlockStateSingleItem.h b/src/MapObj/BlockStateSingleItem.h new file mode 100644 index 00000000..0740527b --- /dev/null +++ b/src/MapObj/BlockStateSingleItem.h @@ -0,0 +1,35 @@ +#pragma once + +#include + +#include "Library/Nerve/NerveStateBase.h" + +namespace al { +class HitSensor; +class LiveActor; +class SensorMsg; +} // namespace al + +class BlockStateSingleItem : public al::ActorStateBase { +public: + BlockStateSingleItem(al::LiveActor* actor, s32 itemType, bool isSkipStartWaitAction); + + void init() override; + + bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other, al::HitSensor* self); + bool isReaction() const; + bool isEnableAppearItem() const; + void setItemOffsetY(f32 itemOffsetY); + void autoGet(al::HitSensor* sensor); + void exeWait(); + void exeReaction(); + void exeReactionHipDrop(); + +private: + s32 mItemType = 0; + bool mIsNoWaitAction = false; + al::HitSensor* mAttackedSensor = nullptr; + f32 mItemOffsetY = 0.0f; +}; + +static_assert(sizeof(BlockStateSingleItem) == 0x38); diff --git a/src/MapObj/BlockStateTenCoin.h b/src/MapObj/BlockStateTenCoin.h new file mode 100644 index 00000000..39a14b89 --- /dev/null +++ b/src/MapObj/BlockStateTenCoin.h @@ -0,0 +1,41 @@ +#pragma once + +#include + +#include "Library/Nerve/NerveStateBase.h" + +namespace al { +class HitSensor; +class LiveActor; +class SensorMsg; +} // namespace al + +class BlockStateTenCoin : public al::ActorStateBase { +public: + BlockStateTenCoin(al::LiveActor* actor, bool isSkipStartWaitAction); + + void init() override; + void control() override; + + void autoGet(al::HitSensor* sensor); + bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other, al::HitSensor* self); + bool isReaction() const; + bool isEnableAppearItem() const; + + void setItemOffsetY(f32 itemOffsetY) { mItemOffsetY = itemOffsetY; } + + void exeWait(); + void exeReaction(); + void exeReactionHipDrop(); + void exeGetAuto(); + +private: + s32 mCoinCount = 10; + s32 mTimer = 130; + s32 mReactionCooldown = 0; + bool mIsWaitSyncStage = false; + al::HitSensor* mAttackedSensor = nullptr; + f32 mItemOffsetY = 0.0f; +}; + +static_assert(sizeof(BlockStateTenCoin) == 0x40); diff --git a/src/Scene/ProjectActorFactory.cpp b/src/Scene/ProjectActorFactory.cpp index 1bf74abc..f7801774 100644 --- a/src/Scene/ProjectActorFactory.cpp +++ b/src/Scene/ProjectActorFactory.cpp @@ -69,6 +69,7 @@ #include "MapObj/AllDeadWatcherWithShine.h" #include "MapObj/AnagramAlphabet.h" #include "MapObj/BlockEmpty2D.h" +#include "MapObj/BlockQuestion2D.h" #include "MapObj/BossKnuckleFix.h" #include "MapObj/CapBomb.h" #include "MapObj/CapHanger.h" @@ -153,7 +154,7 @@ const al::NameToCreator sProjectActorFactoryEntries[] {"ClashWorldBlockHard", nullptr}, {"BlockQuestion", nullptr}, {"CityBlockQuestion", nullptr}, - {"BlockQuestion2D", nullptr}, + {"BlockQuestion2D", al::createActorFunction}, {"BlockTransparent", nullptr}, {"BlockTransparent2D", nullptr}, {"BlowObjBeans", nullptr},