This commit is contained in:
guymakinggames 2026-04-23 06:38:27 +01:00 committed by GitHub
commit 0fa0f1a78a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
7 changed files with 300 additions and 17 deletions

View file

@ -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

View file

@ -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;

View file

@ -0,0 +1,155 @@
#include "MapObj/BlockQuestion2D.h"
#include <math/seadVector.h>
#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<al::StageSyncCounter>(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();
}
}

View file

@ -0,0 +1,49 @@
#pragma once
#include <basis/seadTypes.h>
#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);

View file

@ -0,0 +1,35 @@
#pragma once
#include <basis/seadTypes.h>
#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);

View file

@ -0,0 +1,41 @@
#pragma once
#include <basis/seadTypes.h>
#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);

View file

@ -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<al::ActorCreatorFunction> sProjectActorFactoryEntries[]
{"ClashWorldBlockHard", nullptr},
{"BlockQuestion", nullptr},
{"CityBlockQuestion", nullptr},
{"BlockQuestion2D", nullptr},
{"BlockQuestion2D", al::createActorFunction<BlockQuestion2D>},
{"BlockTransparent", nullptr},
{"BlockTransparent2D", nullptr},
{"BlowObjBeans", nullptr},