1#include "Library/MapObj/VisibleSwitchMapParts.h"
2
3#include "Library/Collision/PartsConnector.h"
4#include "Library/LiveActor/ActorActionFunction.h"
5#include "Library/LiveActor/ActorInitUtil.h"
6#include "Library/LiveActor/ActorModelFunction.h"
7#include "Library/LiveActor/ActorPoseUtil.h"
8#include "Library/LiveActor/ActorSensorUtil.h"
9#include "Library/Nerve/NerveSetupUtil.h"
10#include "Library/Nerve/NerveUtil.h"
11#include "Library/Placement/PlacementFunction.h"
12#include "Library/Stage/StageSwitchUtil.h"
13#include "Library/Thread/FunctorV0M.h"
14
15namespace al {
16namespace {
17NERVE_IMPL(VisibleSwitchMapParts, Show)
18NERVE_IMPL(VisibleSwitchMapParts, Hide)
19NERVE_IMPL(VisibleSwitchMapParts, Disappear)
20NERVE_IMPL(VisibleSwitchMapParts, DisappearDither)
21NERVE_IMPL(VisibleSwitchMapParts, Appear)
22NERVE_IMPL(VisibleSwitchMapParts, AppearDither)
23
24NERVES_MAKE_STRUCT(VisibleSwitchMapParts, Show, Hide, Disappear, DisappearDither, Appear,
25 AppearDither)
26} // namespace
27
28VisibleSwitchMapParts::VisibleSwitchMapParts(const char* name) : LiveActor(name) {}
29
30void VisibleSwitchMapParts::init(const ActorInitInfo& info) {
31 using VisibleSwitchMapPartsFunctor =
32 FunctorV0M<al::VisibleSwitchMapParts*, void (al::VisibleSwitchMapParts::*)()>;
33
34 initMapPartsActor(actor: this, initInfo: info, suffix: nullptr);
35 initNerve(actor: this, nerve: &NrvVisibleSwitchMapParts.Show, maxStates: 0);
36
37 makeActorAlive();
38
39 if (isValidStageSwitch(user: this, linkName: "SwitchAppear") && isValidStageSwitch(user: this, linkName: "SwitchDisappear"))
40 return;
41
42 if (isValidStageSwitch(user: this, linkName: "SwitchDisappear")) {
43 listenStageSwitchOnOff(
44 user: this, eventName: "SwitchDisappear",
45 actionOn: VisibleSwitchMapPartsFunctor(this, &VisibleSwitchMapParts::startDisappear),
46 actionOff: VisibleSwitchMapPartsFunctor(this, &VisibleSwitchMapParts::startAppear));
47 } else if (isValidStageSwitch(user: this, linkName: "SwitchAppear")) {
48 listenStageSwitchOnOff(
49 user: this, eventName: "SwitchAppear",
50 actionOn: VisibleSwitchMapPartsFunctor(this, &VisibleSwitchMapParts::startAppear),
51 actionOff: VisibleSwitchMapPartsFunctor(this, &VisibleSwitchMapParts::startDisappear));
52 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Hide);
53 } else {
54 return;
55 }
56
57 listenStageSwitchOn(
58 user: this, eventName: "SwitchSuddenDisappear",
59 action: VisibleSwitchMapPartsFunctor(this, &VisibleSwitchMapParts::startSuddenDisappear));
60
61 tryGetArg(arg: &mConnectMapCheckLength, initInfo: info, key: "ConnectMapCheckLength");
62 tryGetArg(arg: (s32*)&mConnectMapDirType, initInfo: info, key: "ConnectMapDirType");
63 tryGetArg(arg: &mDitherFrame, initInfo: info, key: "DitherFrame");
64 tryGetArg(arg: &mIsUsingAlphaMask, initInfo: info, key: "UseAlphaMask");
65
66 if (mConnectMapDirType != ConnectMapDirType::Invalid)
67 mMtxConnector = createMtxConnector(actor: this);
68}
69
70void VisibleSwitchMapParts::startDisappear() {
71 if (isNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Disappear) ||
72 isNerve(user: this, nerve: &NrvVisibleSwitchMapParts.DisappearDither) ||
73 isNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Hide))
74 return;
75
76 if (mIsUsingAlphaMask)
77 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.DisappearDither);
78 else
79 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Disappear);
80}
81
82void VisibleSwitchMapParts::startAppear() {
83 if (isNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Appear) ||
84 isNerve(user: this, nerve: &NrvVisibleSwitchMapParts.AppearDither))
85 return;
86
87 if (mIsUsingAlphaMask)
88 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.AppearDither);
89 else
90 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Appear);
91}
92
93void VisibleSwitchMapParts::startSuddenDisappear() {
94 if (isNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Hide))
95 return;
96
97 if (mIsUsingAlphaMask)
98 setModelAlphaMask(actor: this, 0.0f);
99
100 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Hide);
101}
102
103void VisibleSwitchMapParts::initAfterPlacement() {
104 if (mMtxConnector == nullptr)
105 return;
106
107 sead::Vector3f dir;
108 switch (mConnectMapDirType) {
109 case ConnectMapDirType::Side:
110 calcSideDir(side: &dir, actor: this);
111
112 break;
113 case ConnectMapDirType::Up:
114 calcUpDir(up: &dir, actor: this);
115
116 break;
117 case ConnectMapDirType::Front:
118 calcFrontDir(front: &dir, actor: this);
119
120 break;
121 default:
122 break;
123 }
124
125 if (mConnectMapDirType == ConnectMapDirType::NegSide ||
126 mConnectMapDirType == ConnectMapDirType::NegUp ||
127 mConnectMapDirType == ConnectMapDirType::NegFront)
128 dir = -dir;
129
130 attachMtxConnectorToCollision(mtxConnector: mMtxConnector, actor: this, getTrans(actor: this),
131 mConnectMapCheckLength * dir);
132}
133
134void VisibleSwitchMapParts::control() {
135 if (mMtxConnector == nullptr)
136 return;
137
138 connectPoseQT(actor: this, mtxConnector: mMtxConnector);
139}
140
141bool VisibleSwitchMapParts::receiveMsg(const SensorMsg* message, HitSensor* other,
142 HitSensor* self) {
143 if (isMsgScreenPointInvalidCollisionParts(msg: message) &&
144 isNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Hide))
145 return true;
146
147 return false;
148}
149
150void VisibleSwitchMapParts::exeShow() {
151 if (isFirstStep(user: this))
152 tryStartAction(actor: this, actionName: "Wait");
153}
154
155void VisibleSwitchMapParts::exeDisappear() {
156 if (isFirstStep(user: this)) {
157 if (!tryStartAction(actor: this, actionName: "Disappear")) {
158 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Hide);
159
160 return;
161 }
162 }
163
164 if (isActionEnd(actor: this))
165 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Hide);
166}
167
168void VisibleSwitchMapParts::exeDisappearDither() {
169 setModelAlphaMask(actor: this, 1.0f - calcNerveRate(user: this, max: mDitherFrame));
170
171 if (isGreaterEqualStep(user: this, step: mDitherFrame))
172 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Hide);
173}
174
175void VisibleSwitchMapParts::exeHide() {
176 if (isFirstStep(user: this))
177 hideModelIfShow(actor: this);
178}
179
180void VisibleSwitchMapParts::exeAppear() {
181 if (isFirstStep(user: this)) {
182 showModelIfHide(actor: this);
183
184 if (!tryStartAction(actor: this, actionName: "Appear")) {
185 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Show);
186
187 return;
188 }
189 }
190
191 if (isActionEnd(actor: this))
192 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Show);
193}
194
195void VisibleSwitchMapParts::exeAppearDither() {
196 if (isFirstStep(user: this))
197 showModelIfHide(actor: this);
198
199 setModelAlphaMask(actor: this, calcNerveRate(user: this, max: mDitherFrame));
200
201 if (isGreaterEqualStep(user: this, step: mDitherFrame))
202 setNerve(user: this, nerve: &NrvVisibleSwitchMapParts.Show);
203}
204} // namespace al
205