diff --git a/data/file_list.yml b/data/file_list.yml index f5f6c5b477..9fa676b3c9 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -130135,45 +130135,45 @@ Player/YoshiStateEgg.o: label: - _ZN13YoshiStateEggC1ERKN2al13ActorInitInfoEPNS0_9LiveActorEPK19IUsePlayerCollisionPK11PlayerConstPKNS0_18WaterSurfaceFinderEP23PlayerModelChangerYoshi - _ZN13YoshiStateEggC2ERKN2al13ActorInitInfoEPNS0_9LiveActorEPK19IUsePlayerCollisionPK11PlayerConstPKNS0_18WaterSurfaceFinderEP23PlayerModelChangerYoshi - status: NotDecompiled + status: Matching - offset: 0x49775c size: 104 label: _ZN13YoshiStateEgg6appearEv - status: NotDecompiled + status: Matching - offset: 0x4977c4 size: 16 label: _ZN13YoshiStateEgg4killEv - status: NotDecompiled + status: Matching - offset: 0x4977d4 size: 92 label: _ZN13YoshiStateEgg9exeAppearEv - status: NotDecompiled + status: Matching - offset: 0x497830 size: 260 - label: '' - status: NotDecompiled + label: _ZL18updateFallVelocityPN2al9LiveActorEPK19IUsePlayerCollisionPK11PlayerConst + status: Matching - offset: 0x497934 size: 100 label: _ZN13YoshiStateEgg7exeWaitEv - status: NotDecompiled + status: Matching - offset: 0x497998 size: 128 label: _ZN13YoshiStateEgg29reactionCollidedCollisionCodeEv - status: NotDecompiled + status: Matching - offset: 0x497a18 size: 36 label: _ZN13YoshiStateEggD0Ev - status: NotDecompiled + status: Matching lazy: true - offset: 0x497a3c size: 104 label: _ZNK12_GLOBAL__N_120YoshiStateEggNrvWait7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x497aa4 size: 96 label: _ZNK12_GLOBAL__N_122YoshiStateEggNrvAppear7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true Player/YoshiStateHack.o: '.text': diff --git a/src/Player/PlayerModelChangerYoshi.h b/src/Player/PlayerModelChangerYoshi.h new file mode 100644 index 0000000000..0faadf0c07 --- /dev/null +++ b/src/Player/PlayerModelChangerYoshi.h @@ -0,0 +1,53 @@ +#pragma once + +#include "Library/HostIO/HioNode.h" + +#include "Player/IPlayerModelChanger.h" + +namespace al { +class LiveActor; +} // namespace al + +class PlayerModelHolder; + +class PlayerModelChangerYoshi : public al::HioNode, public IPlayerModelChanger { +public: + PlayerModelChangerYoshi(const al::LiveActor*, PlayerModelHolder*); + + void resetPosition() override; + void hideModel() override; + void hideSilhouette() override; + void showModel() override; + void showSilhouette() override; + bool isHiddenModel() const override; + + bool isFireFlower() const override { return false; } + + bool isMini() const override { return false; } + + bool isChange() const override { return false; } + + bool is2DModel() const override { return false; } + + bool isHiddenShadowMask() const override { return false; } + + void hideShadowMask() override {} + + void showShadowMask() override {} + + void syncHost(); + void syncModelFlag(al::LiveActor*); + void appearModel(); + void killModel(); + void changeModel(al::LiveActor*); + +private: + al::LiveActor* mActor; + al::LiveActor* mModelActor; + PlayerModelHolder* mModelHolder; + bool _20; + bool _21; + bool _22; +}; + +static_assert(sizeof(PlayerModelChangerYoshi) == 0x28); diff --git a/src/Player/YoshiEgg.h b/src/Player/YoshiEgg.h new file mode 100644 index 0000000000..44d982d2cc --- /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; +}; + +static_assert(sizeof(YoshiEgg) == 0x120); diff --git a/src/Player/YoshiStateEgg.cpp b/src/Player/YoshiStateEgg.cpp new file mode 100644 index 0000000000..3e73a697c9 --- /dev/null +++ b/src/Player/YoshiStateEgg.cpp @@ -0,0 +1,111 @@ +#include "Player/YoshiStateEgg.h" + +#include "Library/LiveActor/ActorActionFunction.h" +#include "Library/LiveActor/ActorAreaFunction.h" +#include "Library/LiveActor/ActorClippingFunction.h" +#include "Library/LiveActor/ActorMovementFunction.h" +#include "Library/LiveActor/ActorPoseUtil.h" +#include "Library/LiveActor/ActorSensorUtil.h" +#include "Library/Nature/NatureUtil.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" + +#include "Player/PlayerConst.h" +#include "Player/PlayerModelChangerYoshi.h" +#include "Player/YoshiEgg.h" +#include "Util/ObjUtil.h" +#include "Util/PlayerCollisionUtil.h" +#include "Util/PlayerHackFunction.h" + +namespace { +NERVE_IMPL(YoshiStateEgg, Appear) +NERVE_IMPL(YoshiStateEgg, Wait) + +NERVES_MAKE_STRUCT(YoshiStateEgg, Wait, Appear) +} // namespace + +YoshiStateEgg::YoshiStateEgg(const al::ActorInitInfo& info, al::LiveActor* actor, + const IUsePlayerCollision* playerCollision, + const PlayerConst* playerConst, + const al::WaterSurfaceFinder* waterSurfaceFinder, + PlayerModelChangerYoshi* playerModelChanger) + : al::ActorStateBase("卵", actor), mPlayerCollision(playerCollision), mPlayerConst(playerConst), + mWaterSurfaceFinder(waterSurfaceFinder), mPlayerModelChangerYoshi(playerModelChanger) { + mYoshiEgg = new YoshiEgg(actor, playerCollision); + mYoshiEgg->init(info); + initNerve(&NrvYoshiStateEgg.Wait, 0); +} + +void YoshiStateEgg::appear() { + al::ActorStateBase::appear(); + mYoshiEgg->kill(); + al::invalidateHitSensors(mActor); + if (_48) { + _48 = false; + mYoshiEgg->initPlacementEgg(); + al::setNerve(this, &NrvYoshiStateEgg.Wait); + return; + } + + al::setNerve(this, &NrvYoshiStateEgg.Appear); +} + +void YoshiStateEgg::kill() { + al::ActorStateBase::kill(); + al::validateHitSensors(mActor); +} + +bool YoshiStateEgg::reactionCollidedCollisionCode() { + if (isDead()) + return false; + + al::LiveActor* actor = mActor; + + if (al::isInDeathArea(actor)) { + al::startHitReaction(actor, "[ヨッシー]死亡"); + return true; + } + + if (al::isNerve(this, &NrvYoshiStateEgg.Wait) && + (rs::isTouchHackCancelCollisionCode(actor, mPlayerCollision) || al::isInWater(actor))) { + al::startHitReaction(actor, "[ヨッシー]死亡"); + return true; + } + + return false; +} + +static void updateFallVelocity(al::LiveActor* actor, const IUsePlayerCollision* playerCollision, + const PlayerConst* playerConst) { + if (rs::isCollidedGround(playerCollision)) { + rs::waitGround(actor, playerCollision, playerConst->getGravity(), + playerConst->getFallSpeedMax(), playerConst->getSlerpQuatGrav(), 0.0f); + return; + } + + al::tryAddVelocityLimit(actor, al::getGravity(actor) * playerConst->getGravity(), + playerConst->getFallSpeedMax()); +} + +void YoshiStateEgg::exeAppear() { + if (al::isFirstStep(this)) + mYoshiEgg->appearEgg(); + + updateFallVelocity(mActor, mPlayerCollision, mPlayerConst); + + if (mYoshiEgg->isEndAppear()) { + al::setNerve(this, &NrvYoshiStateEgg.Wait); + return; + } +} + +void YoshiStateEgg::exeWait() { + if (al::isFirstStep(this)) + al::validateClipping(mActor); + + updateFallVelocity(mActor, mPlayerCollision, mPlayerConst); + if (mYoshiEgg->isBreak()) { + mPlayerModelChangerYoshi->appearModel(); + kill(); + } +} diff --git a/src/Player/YoshiStateEgg.h b/src/Player/YoshiStateEgg.h new file mode 100644 index 0000000000..9f846a9afa --- /dev/null +++ b/src/Player/YoshiStateEgg.h @@ -0,0 +1,37 @@ +#pragma once + +#include "Library/Nerve/NerveStateBase.h" + +namespace al { +struct ActorInitInfo; +class WaterSurfaceFinder; +} // namespace al + +class IUsePlayerCollision; +class PlayerConst; +class PlayerModelChangerYoshi; +class YoshiEgg; + +class YoshiStateEgg : public al::ActorStateBase { +public: + YoshiStateEgg(const al::ActorInitInfo&, al::LiveActor*, const IUsePlayerCollision*, + const PlayerConst*, const al::WaterSurfaceFinder*, PlayerModelChangerYoshi*); + + void appear() override; + void kill() override; + + bool reactionCollidedCollisionCode(); + + void exeAppear(); + void exeWait(); + +private: + const IUsePlayerCollision* mPlayerCollision; + const PlayerConst* mPlayerConst; + const al::WaterSurfaceFinder* mWaterSurfaceFinder; + YoshiEgg* mYoshiEgg = nullptr; + PlayerModelChangerYoshi* mPlayerModelChangerYoshi; + bool _48 = true; +}; + +static_assert(sizeof(YoshiStateEgg) == 0x50);