1#include "Library/MapObj/FallMapParts.h"
2
3#include "Library/LiveActor/ActorActionFunction.h"
4#include "Library/LiveActor/ActorAreaFunction.h"
5#include "Library/LiveActor/ActorClippingFunction.h"
6#include "Library/LiveActor/ActorCollisionFunction.h"
7#include "Library/LiveActor/ActorInitUtil.h"
8#include "Library/LiveActor/ActorModelFunction.h"
9#include "Library/LiveActor/ActorMovementFunction.h"
10#include "Library/LiveActor/ActorPoseUtil.h"
11#include "Library/LiveActor/ActorSensorUtil.h"
12#include "Library/Nerve/NerveSetupUtil.h"
13#include "Library/Nerve/NerveUtil.h"
14#include "Library/Placement/PlacementFunction.h"
15
16namespace {
17using namespace al;
18
19NERVE_ACTION_IMPL(FallMapParts, Appear)
20NERVE_ACTION_IMPL(FallMapParts, Wait)
21NERVE_ACTION_IMPL(FallMapParts, FallSign)
22NERVE_ACTION_IMPL(FallMapParts, Fall)
23NERVE_ACTION_IMPL(FallMapParts, End)
24
25NERVE_ACTIONS_MAKE_STRUCT(FallMapParts, Appear, Wait, FallSign, Fall, End)
26} // namespace
27
28namespace al {
29FallMapParts::FallMapParts(const char* name) : LiveActor(name) {}
30
31void FallMapParts::init(const ActorInitInfo& info) {
32 initNerveAction(actor: this, actionName: "Wait", collector: &NrvFallMapParts.collector, maxStates: 0);
33 initMapPartsActor(actor: this, initInfo: info, suffix: nullptr);
34 registerAreaHostMtx(actor: this, initInfo: info);
35
36 mPos = getTrans(actor: this);
37
38 tryGetArg(arg: &mFallTime, initInfo: info, key: "FallTime");
39 tryGetArg(arg: &mIsInvalidAutoRestart, initInfo: info, key: "IsInvalidAutoRestart");
40
41 trySyncStageSwitchAppear(actor: this);
42}
43
44bool FallMapParts::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) {
45 if (isMsgFloorTouch(msg: message) && isNerve(user: this, nerve: NrvFallMapParts.Wait.data())) {
46 startNerveAction(actor: this, actionName: "FallSign");
47 invalidateClipping(actor: this);
48
49 return true;
50 }
51
52 if (isMsgShowModel(msg: message)) {
53 if (!isNerve(user: this, nerve: NrvFallMapParts.End.data()))
54 showModelIfHide(actor: this);
55
56 return true;
57 }
58
59 if (isMsgHideModel(msg: message)) {
60 if (!isNerve(user: this, nerve: NrvFallMapParts.End.data()))
61 hideModelIfShow(actor: this);
62
63 return true;
64 }
65
66 if (isMsgRestart(msg: message)) {
67 appearAndSetStart();
68
69 return true;
70 }
71
72 return false;
73}
74
75void FallMapParts::appearAndSetStart() {
76 setTrans(actor: this, trans: mPos);
77 resetPosition(actor: this);
78 showModelIfHide(actor: this);
79 startNerveAction(actor: this, actionName: "Appear");
80 setVelocityZero(this);
81
82 makeActorAlive();
83}
84
85void FallMapParts::exeAppear() {
86 if (isFirstStep(user: this)) {
87 validateCollisionParts(this);
88 if (!tryStartAction(actor: this, actionName: "Appear")) {
89 startNerveAction(actor: this, actionName: "Wait");
90
91 return;
92 }
93 }
94
95 if (!isExistAction(actor: this) || isActionEnd(actor: this))
96 startNerveAction(actor: this, actionName: "Wait");
97}
98
99void FallMapParts::exeWait() {
100 if (isFirstStep(user: this)) {
101 tryStartAction(actor: this, actionName: "Wait");
102 validateClipping(actor: this);
103 }
104}
105
106void FallMapParts::exeFallSign() {
107 if (isFirstStep(user: this))
108 mIsStartAction = tryStartAction(actor: this, actionName: "FallSign");
109
110 if (!mIsStartAction) {
111 f32 offset = sead::Mathf::sin(t: calcNerveValue(user: this, max: 20, start: 0.0f, end: sead::Mathf::pi() * 3)) * 3;
112 setTrans(actor: this, trans: offset * sead::Vector3f::ey + mPos);
113 }
114
115 if (isEndFallSign())
116 startNerveAction(actor: this, actionName: "Fall");
117}
118
119bool FallMapParts::isEndFallSign() const {
120 return mIsStartAction ? isActionEnd(actor: this) : isGreaterEqualStep(user: this, step: 20);
121}
122
123void FallMapParts::exeFall() {
124 if (isFirstStep(user: this)) {
125 tryStartAction(actor: this, actionName: "Fall");
126 setTrans(actor: this, trans: mPos);
127 }
128
129 addVelocityToGravity(actor: this, force: 0.3f);
130 scaleVelocity(actor: this, factor: 0.9f);
131
132 if (isGreaterStep(user: this, step: mFallTime))
133 startNerveAction(actor: this, actionName: "End");
134}
135
136void FallMapParts::exeEnd() {
137 if (isFirstStep(user: this)) {
138 tryStartAction(actor: this, actionName: "End");
139 hideModelIfShow(actor: this);
140 invalidateCollisionParts(this);
141 setVelocityZero(this);
142
143 if (mIsInvalidAutoRestart) {
144 kill();
145
146 return;
147 }
148 }
149
150 if (isGreaterStep(user: this, step: 120)) {
151 setTrans(actor: this, trans: mPos);
152 resetPosition(actor: this);
153 showModelIfHide(actor: this);
154 startNerveAction(actor: this, actionName: "Appear");
155 }
156}
157} // namespace al
158