diff --git a/data/file_list.yml b/data/file_list.yml index f5f6c5b477..b055a929e5 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -129883,69 +129883,69 @@ Player/YoshiEgg.o: - offset: 0x495e84 size: 152 label: _ZN8YoshiEggC2EPKN2al9LiveActorEPK19IUsePlayerCollision - status: NotDecompiled + status: Matching - offset: 0x495f1c size: 156 label: _ZN8YoshiEggC1EPKN2al9LiveActorEPK19IUsePlayerCollision - status: NotDecompiled + status: Matching - offset: 0x495fb8 size: 244 label: _ZN8YoshiEgg4initERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x4960ac size: 16 label: _ZN8YoshiEgg18initAfterPlacementEv - status: NotDecompiled + status: Matching - offset: 0x4960bc size: 64 label: _ZN8YoshiEgg16initPlacementEggEv - status: NotDecompiled + status: Matching - offset: 0x4960fc size: 72 label: _ZN8YoshiEgg9appearEggEv - status: NotDecompiled + status: Matching - offset: 0x496144 size: 36 label: _ZNK8YoshiEgg11isEndAppearEv - status: NotDecompiled + status: Matching - offset: 0x496168 size: 16 label: _ZNK8YoshiEgg7isBreakEv - status: NotDecompiled + status: Matching - offset: 0x496178 size: 108 label: _ZN8YoshiEgg9exeAppearEv - status: NotDecompiled + status: Matching - offset: 0x4961e4 size: 72 label: _ZN8YoshiEgg7exeWaitEv - status: NotDecompiled + status: Matching - offset: 0x49622c size: 88 label: _ZN8YoshiEgg8exeBreakEv - status: NotDecompiled + status: Matching - offset: 0x496284 size: 112 label: _ZN8YoshiEgg12attackSensorEPN2al9HitSensorES2_ - status: NotDecompiled + status: Matching - offset: 0x4962f4 size: 188 label: _ZN8YoshiEgg10receiveMsgEPKN2al9SensorMsgEPNS0_9HitSensorES5_ - status: NotDecompiled + status: Matching - offset: 0x4963b0 size: 76 label: _ZNK12_GLOBAL__N_115YoshiEggNrvWait7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x4963fc size: 112 label: _ZNK12_GLOBAL__N_117YoshiEggNrvAppear7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x49646c size: 92 label: _ZNK12_GLOBAL__N_116YoshiEggNrvBreak7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true Player/YoshiJointControlHeadCorrection.o: '.text': diff --git a/src/MapObj/FukankunZoomCapMessage.h b/src/MapObj/FukankunZoomCapMessage.h new file mode 100644 index 0000000000..70b15c3573 --- /dev/null +++ b/src/MapObj/FukankunZoomCapMessage.h @@ -0,0 +1,44 @@ +#pragma once + +#include +#include +#include + +namespace al { +struct ActorInitInfo; +class LiveActor; +} // namespace al + +class FukankunZoomCapMessage { +public: + FukankunZoomCapMessage(const al::LiveActor* actor); + + void init(const al::ActorInitInfo& info, const char* capMessageName, + const char* fukankunZoomMessageName); + void initAfterPlacement(); + void update(); + + void setFukankunZoomWatchTimeThreshold(s32 threshold) { + mFukankunZoomWatchTimeThreshold = threshold; + } + + void resetZoomTypes() { + mFukankunZoomType = 0; + mCapMessageShowType = 0; + } + +private: + const al::LiveActor* mActor; + s32 mFukankunZoomType; + s32 mCapMessageShowType; + s32 mFukankunZoomWatchTimeThreshold; + bool mIsDisableAfterEnding; + sead::Vector3f mFukankunZoomOffset; + const char* mFukankunZoomTargetJointName; + bool mIsDisabled; + sead::FixedSafeString<256>* mCapMessageName; + sead::FixedSafeString<256>* mFukankunZoomMessageName; + bool mIsCapMessageShown; +}; + +static_assert(sizeof(FukankunZoomCapMessage) == 0x50); diff --git a/src/Player/YoshiEgg.cpp b/src/Player/YoshiEgg.cpp new file mode 100644 index 0000000000..3a461b82e0 --- /dev/null +++ b/src/Player/YoshiEgg.cpp @@ -0,0 +1,124 @@ +#include "Player/YoshiEgg.h" + +#include "Library/LiveActor/ActorActionFunction.h" +#include "Library/LiveActor/ActorClippingFunction.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 "MapObj/FukankunZoomCapMessage.h" +#include "MapObj/FukankunZoomTargetFunction.h" +#include "Util/SensorMsgFunction.h" + +namespace { +NERVE_IMPL(YoshiEgg, Wait); +NERVE_IMPL(YoshiEgg, Appear); +NERVE_IMPL(YoshiEgg, Break); + +NERVES_MAKE_STRUCT(YoshiEgg, Wait, Break); +NERVES_MAKE_NOSTRUCT(YoshiEgg, Appear); +} // namespace + +YoshiEgg::YoshiEgg(const al::LiveActor* parent, const IUsePlayerCollision* playerCollision) + : al::LiveActor("卵"), mParent(parent), mPlayerCollision(playerCollision) {} + +void YoshiEgg::init(const al::ActorInitInfo& info) { + al::initChildActorWithArchiveNameNoPlacementInfo(this, info, "YoshiEgg", nullptr); + al::initNerve(this, &NrvYoshiEgg.Wait, 0); + + if (!al::isPlaced(info)) { + makeActorDead(); + return; + } + + bool isFukankunZoomCapMessage = false; + if (al::tryGetArg(&isFukankunZoomCapMessage, info, "IsFukankunZoomCapMessage") && + isFukankunZoomCapMessage) { + mFukankunZoomCapMessage = new FukankunZoomCapMessage(this); + mFukankunZoomCapMessage->init(info, "CapMessage", "FukankunZoomYoshiEgg"); + FukankunZoomCapMessage* capMessage = mFukankunZoomCapMessage; + capMessage->setFukankunZoomWatchTimeThreshold( + FukankunZoomTargetFunction::getFukankunWatchCountDefault()); + capMessage->resetZoomTypes(); + } + + makeActorDead(); +} + +void YoshiEgg::initAfterPlacement() { + if (mFukankunZoomCapMessage) + mFukankunZoomCapMessage->initAfterPlacement(); +} + +void YoshiEgg::initPlacementEgg() { + al::copyPose(this, mParent); + appear(); + al::setNerve(this, &NrvYoshiEgg.Wait); +} + +void YoshiEgg::appearEgg() { + al::copyPose(this, mParent); + appear(); + al::invalidateClipping(this); + al::setNerve(this, &Appear); +} + +bool YoshiEgg::isEndAppear() const { + return !al::isNerve(this, &Appear); +} + +bool YoshiEgg::isBreak() const { + return al::isNerve(this, &NrvYoshiEgg.Break); +} + +void YoshiEgg::exeAppear() { + if (al::isFirstStep(this)) + al::startAction(this, "Appear"); + + al::copyPose(this, mParent); + if (al::isActionEnd(this)) { + al::validateClipping(this); + al::setNerve(this, &NrvYoshiEgg.Wait); + } +} + +void YoshiEgg::exeWait() { + al::tryStartActionIfNotPlaying(this, "Wait"); + al::copyPose(this, mParent); + if (mFukankunZoomCapMessage) + mFukankunZoomCapMessage->update(); +} + +void YoshiEgg::exeBreak() { + if (al::isFirstStep(this)) + al::startAction(this, "Break"); + + if (al::isActionEnd(this)) + kill(); +} + +void YoshiEgg::attackSensor(al::HitSensor* self, al::HitSensor* other) { + if (!al::isSensorName(self, "Push") || YoshiEgg::isBreak()) + return; + + rs::sendMsgPushToPlayer(other, self); +} + +bool YoshiEgg::receiveMsg(const al::SensorMsg* message, al::HitSensor* other, al::HitSensor* self) { + if (al::isSensorName(self, "Push")) + return al::isMsgPlayerDisregard(message); + + if (!al::isMsgPlayerTrample(message) && !rs::isMsgPlayerAndCapObjHipDropReflectAll(message) && + !rs::isMsgCapAttack(message) && !rs::isMsgThrowObjHitReflect(message) && + !rs::isMsgTankBullet(message) && !rs::isMsgMotorcycleAttack(message)) + return false; + + if (!al::isNerve(this, &NrvYoshiEgg.Wait)) + return false; + + al::setNerve(this, &NrvYoshiEgg.Break); + return true; +} diff --git a/src/Player/YoshiEgg.h b/src/Player/YoshiEgg.h new file mode 100644 index 0000000000..9e5cb1bfc3 --- /dev/null +++ b/src/Player/YoshiEgg.h @@ -0,0 +1,39 @@ +#pragma once + +#include "Library/LiveActor/LiveActor.h" + +namespace al { +struct ActorInitInfo; +class HitSensor; +class SensorMsg; +} // namespace al + +class IUsePlayerCollision; +class FukankunZoomCapMessage; + +class YoshiEgg : public al::LiveActor { +public: + YoshiEgg(const al::LiveActor* parent, const IUsePlayerCollision* playerCollision); + + void init(const al::ActorInitInfo& info) override; + void initAfterPlacement() override; + void attackSensor(al::HitSensor* self, al::HitSensor* other) override; + bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) override; + + void initPlacementEgg(); + void appearEgg(); + bool isEndAppear() const; + bool isBreak() const; + + void exeAppear(); + void exeWait(); + void exeBreak(); + +private: + const al::LiveActor* mParent; + const IUsePlayerCollision* mPlayerCollision; + FukankunZoomCapMessage* mFukankunZoomCapMessage = nullptr; +}; + +static_assert(sizeof(YoshiEgg) == 0x120);