From b442b4587d643946f706859de19dd16338f14e3f Mon Sep 17 00:00:00 2001 From: guymakinggames <66076221+guymakinggames@users.noreply.github.com> Date: Tue, 14 Apr 2026 12:27:58 +0100 Subject: [PATCH] MapObj: Implement PoleClimbParts --- data/file_list.yml | 26 +++---- src/MapObj/PoleClimbParts.cpp | 119 ++++++++++++++++++++++++++++++ src/MapObj/PoleClimbParts.h | 32 ++++++++ src/Scene/ProjectActorFactory.cpp | 3 +- src/Util/BreakJudgeUtil.h | 5 +- 5 files changed, 169 insertions(+), 16 deletions(-) create mode 100644 src/MapObj/PoleClimbParts.cpp create mode 100644 src/MapObj/PoleClimbParts.h diff --git a/data/file_list.yml b/data/file_list.yml index 09c8130c..c402adb4 100644 --- a/data/file_list.yml +++ b/data/file_list.yml @@ -79886,53 +79886,53 @@ MapObj/PoleClimbParts.o: - offset: 0x2e5824 size: 128 label: _ZN14PoleClimbPartsC2EPKc - status: NotDecompiled + status: Matching - offset: 0x2e58a4 size: 140 label: _ZN14PoleClimbPartsC1EPKc - status: NotDecompiled + status: Matching - offset: 0x2e5930 size: 228 label: _ZN14PoleClimbParts4initERKN2al13ActorInitInfoE - status: NotDecompiled + status: Matching - offset: 0x2e5a14 size: 208 label: _ZN14PoleClimbParts10receiveMsgEPKN2al9SensorMsgEPNS0_9HitSensorES5_ - status: NotDecompiled + status: Matching - offset: 0x2e5ae4 size: 60 label: _ZN14PoleClimbParts8movementEv - status: NotDecompiled + status: Matching - offset: 0x2e5b20 size: 60 label: _ZN14PoleClimbParts8calcAnimEv - status: NotDecompiled + status: Matching - offset: 0x2e5b5c size: 4 label: _ZN14PoleClimbParts7exeWaitEv - status: NotDecompiled + status: Matching - offset: 0x2e5b60 size: 156 label: _ZN14PoleClimbParts8exeBreakEv - status: NotDecompiled + status: Matching - offset: 0x2e5bfc size: 120 label: _ZN14PoleClimbParts11exeReactionEv - status: NotDecompiled + status: Matching - offset: 0x2e5c74 size: 4 label: _ZNK12_GLOBAL__N_121PoleClimbPartsNrvWait7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x2e5c78 size: 8 label: _ZNK12_GLOBAL__N_122PoleClimbPartsNrvBreak7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true - offset: 0x2e5c80 size: 124 label: _ZNK12_GLOBAL__N_125PoleClimbPartsNrvReaction7executeEPN2al11NerveKeeperE - status: NotDecompiled + status: Matching guess: true MapObj/PoleGrabCeil.o: '.text': @@ -135096,7 +135096,7 @@ Scene/ProjectActorFactory.o: - offset: 0x4ba504 size: 52 label: _ZN2al19createActorFunctionI14PoleClimbPartsEEPNS_9LiveActorEPKc - status: NotDecompiled + status: Matching lazy: true - offset: 0x4ba538 size: 52 diff --git a/src/MapObj/PoleClimbParts.cpp b/src/MapObj/PoleClimbParts.cpp new file mode 100644 index 00000000..e6ff8b58 --- /dev/null +++ b/src/MapObj/PoleClimbParts.cpp @@ -0,0 +1,119 @@ +#include "MapObj/PoleClimbParts.h" + +#include "Library/LiveActor/ActorActionFunction.h" +#include "Library/LiveActor/ActorCollisionFunction.h" +#include "Library/LiveActor/ActorInitUtil.h" +#include "Library/LiveActor/LiveActorFunction.h" +#include "Library/Nerve/NerveSetupUtil.h" +#include "Library/Nerve/NerveUtil.h" +#include "Library/Placement/PlacementFunction.h" + +#include "Util/PlayerUtil.h" +#include "Util/SensorMsgFunction.h" + +namespace { +NERVE_IMPL(PoleClimbParts, Wait); +NERVE_IMPL(PoleClimbParts, Break); +NERVE_IMPL(PoleClimbParts, Reaction); + +NERVES_MAKE_STRUCT(PoleClimbParts, Wait, Break, Reaction); +} // namespace + +PoleClimbParts::PoleClimbParts(const char* name) : al::LiveActor(name) {} + +void PoleClimbParts::init(const al::ActorInitInfo& info) { + const char* suffix = nullptr; + al::tryGetStringArg(&suffix, info, "Suffix"); + al::initMapPartsActor(this, info, suffix); + + if (!al::isExistAction(this, "Reaction")) { + makeActorDead(); + return; + } + + mIsBreak = al::isClassName(info, "PoleClimbPartsBreak"); + al::initNerve(this, &NrvPoleClimbParts.Wait, 0); + + if (mIsBreak) { + if (!al::isExistAction(this, "Break")) + makeActorDead(); + + mBreakJudgeFunction = rs::getBreakJudgeFunction("標準攻撃"); + } + + al::trySyncStageSwitchAppearAndKill(this); +} + +bool PoleClimbParts::receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) { + if (al::isNerve(this, &NrvPoleClimbParts.Break)) + return false; + + if (rs::isMsgPlayerPoleClimbReaction(message)) { + if (!al::isNerve(this, &NrvPoleClimbParts.Wait)) + return true; + + al::setNerve(this, &NrvPoleClimbParts.Reaction); + return true; + } + + if (mIsBreak && mBreakJudgeFunction(message, other, self)) { + rs::requestHitReactionToAttacker(message, self, other); + rs::sendMsgBreakFloorToPlayer(this); + al::invalidateCollisionParts(this); + al::setNerve(this, &NrvPoleClimbParts.Break); + return true; + } + + return false; +} + +void PoleClimbParts::movement() { + if (al::isNerve(this, &NrvPoleClimbParts.Wait)) + return; + + al::LiveActor::movement(); +} + +void PoleClimbParts::calcAnim() { + if (al::isNerve(this, &NrvPoleClimbParts.Wait)) + return; + + al::LiveActor::calcAnim(); +} + +void PoleClimbParts::exeWait() {} + +void PoleClimbParts::exeBreak() { + if (!al::isFirstStep(this)) { + kill(); + return; + } + + al::LiveActor* subActor = al::tryGetSubActor(this, "壊れモデル"); + if (subActor) + subActor->appear(); + + subActor = al::tryGetSubActor(this, "残留モデル"); + if (subActor) + subActor->appear(); + + if (al::isExistAction(this, "Break")) { + al::startAction(this, "Break"); + return; + } + + kill(); +} + +void PoleClimbParts::exeReaction() { + if (al::isFirstStep(this)) { + al::startAction(this, "Reaction"); + return; + } + + if (al::isIntervalStep(this, al::getActionFrameMax(this, "Reaction"), 0)) { + al::stopAction(this); + al::setNerve(this, &NrvPoleClimbParts.Wait); + } +} diff --git a/src/MapObj/PoleClimbParts.h b/src/MapObj/PoleClimbParts.h new file mode 100644 index 00000000..ac67169b --- /dev/null +++ b/src/MapObj/PoleClimbParts.h @@ -0,0 +1,32 @@ +#pragma once + +#include "Library/LiveActor/LiveActor.h" + +#include "Util/BreakJudgeUtil.h" + +namespace al { +struct ActorInitInfo; +class HitSensor; +class SensorMsg; +} // namespace al + +class PoleClimbParts : public al::LiveActor { +public: + PoleClimbParts(const char* name); + + void init(const al::ActorInitInfo& info) override; + void movement() override; + void calcAnim() override; + bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other, + al::HitSensor* self) override; + + void exeWait(); + void exeBreak(); + void exeReaction(); + +private: + bool mIsBreak = false; + rs::break_judge_function_t mBreakJudgeFunction = nullptr; +}; + +static_assert(sizeof(PoleClimbParts) == 0x118); diff --git a/src/Scene/ProjectActorFactory.cpp b/src/Scene/ProjectActorFactory.cpp index cdb644fa..c76a1fb3 100644 --- a/src/Scene/ProjectActorFactory.cpp +++ b/src/Scene/ProjectActorFactory.cpp @@ -87,6 +87,7 @@ #include "MapObj/MoonBasementSlideObj.h" #include "MapObj/MoonWorldCaptureParadeLift.h" #include "MapObj/PeachWorldTree.h" +#include "MapObj/PoleClimbParts.h" #include "MapObj/PoleGrabCeil.h" #include "MapObj/RiseMapPartsHolder.h" #include "MapObj/RouletteSwitch.h" @@ -461,7 +462,7 @@ const al::NameToCreator sProjectActorFactoryEntries[] {"PlayerStartObjNoLink", nullptr}, {"PochiHintPhoto", nullptr}, {"Poetter", nullptr}, - {"PoleClimbParts", nullptr}, + {"PoleClimbParts", al::createActorFunction}, {"PoleClimbPartsBreak", nullptr}, {"PoleGrabCeil", al::createActorFunction}, {"PoleGrabCeilKeyMoveParts", nullptr}, diff --git a/src/Util/BreakJudgeUtil.h b/src/Util/BreakJudgeUtil.h index b15ba6b1..bd0cd652 100644 --- a/src/Util/BreakJudgeUtil.h +++ b/src/Util/BreakJudgeUtil.h @@ -2,10 +2,11 @@ namespace al { class SensorMsg; -} +class HitSensor; +} // namespace al namespace rs { -typedef bool (*break_judge_function_t)(const al::SensorMsg*); +typedef bool (*break_judge_function_t)(const al::SensorMsg*, al::HitSensor*, al::HitSensor*); break_judge_function_t getBreakJudgeFunction(const char* name); } // namespace rs