1#include "MapObj/ShineTowerBackDoor.h"
2
3#include "Library/Collision/PartsConnector.h"
4#include "Library/LiveActor/ActorActionFunction.h"
5#include "Library/LiveActor/ActorClippingFunction.h"
6#include "Library/LiveActor/ActorInitUtil.h"
7#include "Library/LiveActor/ActorModelFunction.h"
8#include "Library/LiveActor/ActorMovementFunction.h"
9#include "Library/LiveActor/ActorPoseUtil.h"
10#include "Library/LiveActor/ActorSensorUtil.h"
11#include "Library/Math/MathUtil.h"
12#include "Library/Nerve/NerveSetupUtil.h"
13#include "Library/Nerve/NerveUtil.h"
14
15#include "Sequence/ChangeStageInfo.h"
16#include "System/GameDataFunction.h"
17#include "Util/PlayerPuppetFunction.h"
18#include "Util/SensorMsgFunction.h"
19
20namespace {
21NERVE_IMPL(ShineTowerBackDoor, Wait);
22NERVE_IMPL(ShineTowerBackDoor, Enter);
23NERVE_IMPL(ShineTowerBackDoor, Reaction);
24NERVE_IMPL(ShineTowerBackDoor, ReactionWait);
25NERVES_MAKE_STRUCT(ShineTowerBackDoor, Wait, Enter, ReactionWait, Reaction);
26} // namespace
27
28ShineTowerBackDoor::ShineTowerBackDoor(const char* name) : LiveActor(name) {}
29
30void ShineTowerBackDoor::init(const al::ActorInitInfo& info) {
31 al::initActorWithArchiveName(actor: this, initInfo: info, archiveName: "ShineTowerBackDoor", suffix: nullptr);
32 al::initNerve(actor: this, nerve: &NrvShineTowerBackDoor.Wait, maxStates: 0);
33 mMtxConnector = al::createMtxConnector(actor: this);
34 makeActorAlive();
35}
36
37void ShineTowerBackDoor::control() {
38 mBindTimer = sead::Mathi::clampMin(val: mBindTimer - 1, min_: 0);
39 al::connectPoseQT(actor: this, mtxConnector: mMtxConnector);
40}
41
42bool ShineTowerBackDoor::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
43 al::HitSensor* self) {
44 if (rs::isMsgKoopaRingBeamInvalidTouch(message) ||
45 rs::isMsgPlayerDisregardTargetMarker(message) ||
46 rs::isMsgPlayerDisregardHomingAttack(message))
47 return true;
48
49 if (al::isSensorMapObj(self)) {
50 if (_118)
51 return false;
52
53 if (al::isMsgPlayerHipDropAll(msg: message)) {
54 mBindTimer = 3;
55 return false;
56 }
57 }
58
59 if (al::isSensorBindable(self)) {
60 if (al::isMsgBindStart(msg: message))
61 return mBindTimer > 0;
62
63 if (al::isMsgBindInit(msg: message)) {
64 al::invalidateClipping(actor: this);
65 mPlayerPuppet = rs::startPuppet(actorHitSensor: self, playerHitSensor: other);
66 rs::setPuppetVelocity(playerPuppet: mPlayerPuppet, velocity: sead::Vector3f::ex * -45.0f);
67 rs::invalidatePuppetCollider(playerPuppet: mPlayerPuppet);
68 rs::hidePuppetSilhouette(playerPuppet: mPlayerPuppet);
69 al::setNerve(user: this, nerve: &NrvShineTowerBackDoor.Enter);
70 return true;
71 }
72
73 if (al::isMsgBindCancel(msg: message)) {
74 mPlayerPuppet = nullptr;
75 mBindTimer = 100;
76 al::setNerve(user: this, nerve: &NrvShineTowerBackDoor.Wait);
77 return true;
78 }
79
80 return false;
81 }
82
83 if (al::isNerve(user: this, nerve: &NrvShineTowerBackDoor.Enter))
84 return false;
85
86 if (al::isMsgFloorTouch(msg: message)) {
87 if (al::isNerve(user: this, nerve: &NrvShineTowerBackDoor.ReactionWait)) {
88 al::setNerve(user: this, nerve: &NrvShineTowerBackDoor.ReactionWait);
89 return true;
90 }
91
92 if (al::isNerve(user: this, nerve: &NrvShineTowerBackDoor.Wait)) {
93 al::setNerve(user: this, nerve: &NrvShineTowerBackDoor.Reaction);
94 return true;
95 }
96 }
97
98 return false;
99}
100
101void ShineTowerBackDoor::attachToHostJoint(const al::LiveActor* actor, const char* jointName) {
102 al::attachMtxConnectorToJoint(mtxConnector: mMtxConnector, actor, jointName);
103 al::resetMtxPosition(actor: this, mtx: *al::getJointMtxPtr(actor, jointName));
104}
105
106bool ShineTowerBackDoor::isEnter() const {
107 return al::isNerve(user: this, nerve: &NrvShineTowerBackDoor.Enter);
108}
109
110void ShineTowerBackDoor::exeWait() {
111 if (al::isFirstStep(user: this))
112 al::startAction(actor: this, actionName: "Wait");
113}
114
115void ShineTowerBackDoor::exeEnter() {
116 if (al::isFirstStep(user: this)) {
117 al::startAction(actor: this, actionName: "ReactionEnter");
118 al::startHitReaction(actor: this, name: "入る");
119 }
120
121 rs::setPuppetVelocity(playerPuppet: mPlayerPuppet, velocity: sead::Vector3f::ex * -45.0f);
122 sead::Vector3f puppetTrans = rs::getPuppetTrans(playerPuppet: mPlayerPuppet);
123 sead::Vector3f trans = al::getTrans(actor: this);
124 trans.y = puppetTrans.y;
125
126 f32 bottom = al::getTrans(actor: this).y - 300.0f;
127 if (puppetTrans.y < bottom) {
128 trans.y = bottom;
129 puppetTrans.y = bottom;
130 rs::setPuppetVelocity(playerPuppet: mPlayerPuppet, velocity: sead::Vector3f::zero);
131 rs::hidePuppet(playerPuppet: mPlayerPuppet);
132 }
133
134 al::lerpVec(&puppetTrans, puppetTrans, trans, 0.5f);
135 rs::setPuppetTrans(playerPuppet: mPlayerPuppet, trans: puppetTrans);
136
137 if (al::isGreaterEqualStep(user: this, step: 75)) {
138 GameDataHolder* gameDataHolder = GameDataFunction::getGameDataHolder(holder: this);
139 ChangeStageInfo changeStageInfo = ChangeStageInfo(gameDataHolder, "HomeBackDoor",
140 GameDataFunction::getHomeShipStageName());
141 GameDataFunction::tryChangeNextStage(writer: this, stageInfo: &changeStageInfo);
142 }
143}
144
145void ShineTowerBackDoor::exeReaction() {
146 if (al::isFirstStep(user: this))
147 al::startAction(actor: this, actionName: "ReactionLand");
148
149 if (al::isActionEnd(actor: this))
150 al::setNerve(user: this, nerve: &NrvShineTowerBackDoor.ReactionWait);
151}
152
153void ShineTowerBackDoor::exeReactionWait() {
154 if (al::isGreaterEqualStep(user: this, step: 3))
155 al::setNerve(user: this, nerve: &NrvShineTowerBackDoor.Wait);
156}
157