1#include "Library/Controller/PadRumbleFunction.h"
2
3#include "Library/Controller/PadRumbleDirector.h"
4#include "Library/Layout/LayoutActor.h"
5#include "Library/Layout/LayoutSceneInfo.h"
6#include "Library/LiveActor/ActorPoseUtil.h"
7#include "Library/LiveActor/ActorSceneInfo.h"
8#include "Library/LiveActor/LiveActor.h"
9#include "Library/Math/MathUtil.h"
10#include "Library/Player/PlayerUtil.h"
11
12namespace al {
13void PadRumbleParam::setVolumeByBalance(f32 balance) {
14 f32 angle = sead::Mathf::deg2rad(deg: balance * 90.0f);
15 volumeLeft = sead::Mathf::cos(t: angle);
16 volumeRight = sead::Mathf::sin(t: angle);
17}
18} // namespace al
19
20namespace alPadRumbleFunction {
21al::PadRumbleDirector* getPadRumbleDirector(const al::LiveActor* actor) {
22 return actor->getSceneInfo()->padRumbleDirector;
23}
24
25al::PadRumbleDirector* getPadRumbleDirector(const al::LayoutActor* layoutActor) {
26 return layoutActor->getLayoutSceneInfo()->getPadRumbleDirector();
27}
28
29void startPadRumble(al::PadRumbleDirector* director, const sead::Vector3f& position,
30 const char* name, f32 near, f32 far, s32 port) {
31 al::PadRumbleParam rumbleParam(near, far);
32 director->startRumble(name, position, rumbleParam, port);
33}
34
35void startPadRumbleWithParam(al::PadRumbleDirector* director, const sead::Vector3f& position,
36 const char* name, const al::PadRumbleParam& rumbleParam, s32 port) {
37 director->startRumble(name, position, rumbleParam, port);
38}
39
40void startPadRumble(const al::LiveActor* actor, const char* name, f32 near, f32 far, s32 port) {
41 startPadRumblePos(actor, position: al::getTrans(actor), name, near, far, port);
42}
43
44void startPadRumblePos(const al::LiveActor* actor, const sead::Vector3f& position, const char* name,
45 f32 near, f32 far, s32 port) {
46 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
47 if (port >= 0) {
48 startPadRumble(director, position, name, near, far, port);
49 return;
50 }
51
52 s32 playerNum = al::getPlayerNumMax(actor);
53 for (s32 i = 0; i < playerNum; i++) {
54 if (al::isPlayerDead(actor, i))
55 continue;
56 al::PadRumbleParam rumbleParam(near, far);
57 s32 port = al::getPlayerPort(actor, i);
58 startPadRumbleWithParam(director, position, name, rumbleParam, port);
59 }
60}
61
62void startPadRumbleWithParam(const al::LiveActor* actor, const sead::Vector3f& position,
63 const char* name, const al::PadRumbleParam& rumbleParam, s32 port) {
64 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
65 startPadRumbleWithParam(director, position, name, rumbleParam, port);
66}
67
68void startPadRumbleNo3D(al::PadRumbleDirector* director, const char* name, s32 port) {
69 director->startRumbleNo3D(name, {}, port);
70}
71
72void startPadRumbleNo3DWithParam(al::PadRumbleDirector* director, const char* name,
73 const al::PadRumbleParam& rumbleParam, s32 port) {
74 director->startRumbleNo3D(name, rumbleParam, port);
75}
76
77void startPadRumbleNo3DWithParam(al::PadRumbleDirector* director, const char* name, f32 volumeLeft,
78 f32 volumeRight, f32 pitchLeft, f32 pitchRight, s32 port) {
79 al::PadRumbleParam rumbleParam(0.0f, 0.0f, volumeLeft, volumeRight, pitchLeft, pitchRight);
80 director->startRumbleNo3D(name, rumbleParam, port);
81}
82
83void startPadRumbleNo3D(const al::LiveActor* actor, const char* name, s32 port) {
84 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
85 if (port >= 0) {
86 startPadRumbleNo3D(director, name, port);
87 return;
88 }
89
90 s32 playerNum = al::getPlayerNumMax(actor);
91 for (s32 i = 0; i < playerNum; i++) {
92 if (al::isPlayerDead(actor, i))
93 continue;
94 al::PadRumbleParam rumbleParam;
95 s32 port = al::getPlayerPort(actor, i);
96 startPadRumbleNo3DWithParam(director, name, rumbleParam, port);
97 }
98}
99
100void startPadRumbleNo3DWithParam(const al::LiveActor* actor, const char* name,
101 const al::PadRumbleParam& rumbleParam, s32 port) {
102 getPadRumbleDirector(actor)->startRumbleNo3D(name, rumbleParam, port);
103}
104
105void startPadRumbleNo3DWithParam(const al::LiveActor* actor, const char* name, f32 volumeLeft,
106 f32 volumeRight, f32 pitchLeft, f32 pitchRight, s32 port) {
107 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
108 startPadRumbleNo3DWithParam(director, name, volumeLeft, volumeRight, pitchLeft, pitchRight,
109 port);
110}
111
112void stopPadRumbleOneTime(al::PadRumbleDirector* director, const char* name, s32 port) {
113 director->stopPadRumbleOneTime(name, port);
114}
115
116void stopPadRumbleOneTime(const al::LiveActor* actor, const char* name, s32 port) {
117 getPadRumbleDirector(actor)->stopPadRumbleOneTime(name, port);
118}
119
120void startPadRumbleLoop(al::PadRumbleDirector* director, const char* name,
121 const sead::Vector3f* position, f32 near, f32 far, s32 port) {
122 // BUG: ignores near and far parameters
123 director->startRumbleLoop(name, position, {}, port);
124}
125
126void startPadRumbleLoopWithParam(al::PadRumbleDirector* director, const char* name,
127 const sead::Vector3f* position,
128 const al::PadRumbleParam& rumbleParam, s32 port) {
129 director->startRumbleLoop(name, position, rumbleParam, port);
130}
131
132void startPadRumbleLoop(const al::LiveActor* actor, const char* name,
133 const sead::Vector3f* position, f32 near, f32 far, s32 port) {
134 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
135 if (port >= 0) {
136 al::PadRumbleParam rumbleParam(near, far);
137 director->startRumbleLoop(name, position, rumbleParam, port);
138 return;
139 }
140
141 s32 playerNum = al::getPlayerNumMax(actor);
142 for (s32 i = 0; i < playerNum; i++) {
143 if (al::isPlayerDead(actor, i))
144 continue;
145 al::PadRumbleParam rumbleParam(near, far);
146 s32 port = al::getPlayerPort(actor, i);
147 director->startRumbleLoop(name, position, rumbleParam, port);
148 }
149}
150
151void startPadRumbleLoopWithParam(const al::LiveActor* actor, const char* name,
152 const sead::Vector3f* position,
153 const al::PadRumbleParam& rumbleParam, s32 port) {
154 getPadRumbleDirector(actor)->startRumbleLoop(name, position, rumbleParam, port);
155}
156
157void startPadRumbleLoopNo3D(al::PadRumbleDirector* director, const char* name,
158 const sead::Vector3f* position, s32 port) {
159 director->startRumbleLoopNo3D(name, position, {}, port);
160}
161
162void startPadRumbleLoopNo3DWithParam(al::PadRumbleDirector* director, const char* name,
163 const sead::Vector3f* position,
164 const al::PadRumbleParam& rumbleParam, s32 port) {
165 director->startRumbleLoopNo3D(name, position, rumbleParam, port);
166}
167
168void startPadRumbleLoopNo3D(const al::LiveActor* actor, const char* name,
169 const sead::Vector3f* position, s32 port) {
170 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
171 if (port >= 0) {
172 director->startRumbleLoopNo3D(name, position, {}, port);
173 return;
174 }
175
176 s32 playerNum = al::getPlayerNumMax(actor);
177 for (s32 i = 0; i < playerNum; i++) {
178 if (al::isPlayerDead(actor, i))
179 continue;
180 al::PadRumbleParam rumbleParam;
181 s32 port = al::getPlayerPort(actor, i);
182 director->startRumbleLoopNo3D(name, position, rumbleParam, port);
183 }
184}
185
186void startPadRumbleLoopNo3DWithParam(const al::LiveActor* actor, const char* name,
187 const sead::Vector3f* position,
188 const al::PadRumbleParam& rumbleParam, s32 port) {
189 getPadRumbleDirector(actor)->startRumbleLoopNo3D(name, position, rumbleParam, port);
190}
191
192void stopPadRumbleLoop(al::PadRumbleDirector* director, const char* name,
193 const sead::Vector3f* position, s32 port) {
194 director->stopRumbleLoop(name, position, port);
195}
196
197void stopPadRumbleLoop(const al::LiveActor* actor, const char* name, const sead::Vector3f* position,
198 s32 port) {
199 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
200 if (port >= 0) {
201 director->stopRumbleLoop(name, position, port);
202 return;
203 }
204
205 s32 playerNum = al::getPlayerNumMax(actor);
206 for (s32 i = 0; i < playerNum; i++) {
207 if (al::isPlayerDead(actor, i))
208 continue;
209 s32 port = al::getPlayerPort(actor, i);
210 director->stopRumbleLoop(name, position, port);
211 }
212}
213
214bool checkIsAlivePadRumbleLoop(al::PadRumbleDirector* director, const char* name,
215 const sead::Vector3f* position, s32 port) {
216 return director->checkIsAliveRumbleLoop(name, position, port);
217}
218
219bool checkIsAlivePadRumbleLoop(const al::LiveActor* actor, const char* name,
220 const sead::Vector3f* position, s32 port) {
221 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
222 return director->checkIsAliveRumbleLoop(name, position, port);
223}
224
225void startPadRumbleLoopControlable(const al::LiveActor* actor, const char* name,
226 const sead::Vector3f* position, s32 port) {
227 startPadRumbleLoopNo3D(actor, name, position, port);
228}
229
230void changePadRumbleLoopVolmue(const al::LiveActor* actor, const char* name,
231 const sead::Vector3f* position, f32 volumeLeft, f32 volumeRight,
232 s32 port) {
233 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
234 if (port >= 0) {
235 director->changeRumbleLoopVolume(name, position, volumeLeft, volumeRight, port);
236 return;
237 }
238
239 s32 playerNum = al::getPlayerNumMax(actor);
240 for (s32 i = 0; i < playerNum; i++) {
241 if (al::isPlayerDead(actor, i))
242 continue;
243 s32 port = al::getPlayerPort(actor, i);
244 director->changeRumbleLoopVolume(name, position, volumeLeft, volumeRight, port);
245 }
246}
247
248void changePadRumbleLoopVolmueEaseInRange(const al::LiveActor* actor, const char* name,
249 const sead::Vector3f* position, f32 time, f32 startTime,
250 f32 stopTime, f32 volumeLeft, f32 volumeRight, s32 port) {
251 f32 easeIn = al::easeIn(t: al::calcRate01(time, startTime, stopTime));
252 changePadRumbleLoopVolmue(actor, name, position, volumeLeft: easeIn * volumeLeft, volumeRight: easeIn * volumeRight,
253 port);
254}
255
256void changePadRumbleLoopPitch(const al::LiveActor* actor, const char* name,
257 const sead::Vector3f* position, f32 pitchLeft, f32 pitchRight,
258 s32 port) {
259 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
260 if (port >= 0) {
261 director->changeRumbleLoopPitch(name, position, pitchLeft, pitchRight, port);
262 return;
263 }
264
265 s32 playerNum = al::getPlayerNumMax(actor);
266 for (s32 i = 0; i < playerNum; i++) {
267 if (al::isPlayerDead(actor, i))
268 continue;
269 s32 port = al::getPlayerPort(actor, i);
270 director->changeRumbleLoopPitch(name, position, pitchLeft, pitchRight, port);
271 }
272}
273
274// TODO: add proper names to a, b, c, d, e, f and in header
275void startPadRumbleDirectValue(const al::LiveActor* actor, f32 a, f32 b, f32 c, f32 d, f32 e, f32 f,
276 s32 port) {
277 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
278 if (port >= 0) {
279 director->startRumbleDirectValue(a, b, c, d, e, f, port);
280 return;
281 }
282
283 s32 playerNum = al::getPlayerNumMax(actor);
284 for (s32 i = 0; i < playerNum; i++) {
285 if (al::isPlayerDead(actor, i))
286 continue;
287 s32 port = al::getPlayerPort(actor, i);
288 director->startRumbleDirectValue(a, b, c, d, e, f, port);
289 }
290}
291
292void stopPadRumbleDirectValue(const al::LiveActor* actor, s32 port) {
293 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
294 if (port >= 0) {
295 director->stopRumbleDirectValue(port);
296 return;
297 }
298
299 s32 playerNum = al::getPlayerNumMax(actor);
300 for (s32 i = 0; i < playerNum; i++) {
301 if (al::isPlayerDead(actor, i))
302 continue;
303 s32 port = al::getPlayerPort(actor, i);
304 director->stopRumbleDirectValue(port);
305 }
306}
307
308void startPadRumbleWithVolume(const al::LiveActor* actor, const char* name, f32 volumeLeft,
309 f32 volumeRight, s32 port) {
310 al::PadRumbleDirector* director = getPadRumbleDirector(actor);
311 if (port >= 0) {
312 director->startRumbleWithVolume(name, volumeLeft, volumeRight, port);
313 return;
314 }
315
316 s32 playerNum = al::getPlayerNumMax(actor);
317 for (s32 i = 0; i < playerNum; i++) {
318 if (al::isPlayerDead(actor, i))
319 continue;
320 s32 port = al::getPlayerPort(actor, i);
321 director->startRumbleWithVolume(name, volumeLeft, volumeRight, port);
322 }
323}
324
325void startPadRumbleWithVolume(al::PadRumbleDirector* director, const char* name, f32 volumeLeft,
326 f32 volumeRight, s32 port) {
327 director->startRumbleWithVolume(name, volumeLeft, volumeRight, port);
328}
329
330void makePadRumbleParamNearFarVolume(al::PadRumbleParam* rumbleParam, f32 near, f32 far,
331 f32 volume) {
332 makePadRumbleParamNearFarVolumeLR(rumbleParam, near, far, volumeLeft: volume, volumeRight: volume);
333}
334
335void makePadRumbleParamNearFarVolumeLR(al::PadRumbleParam* rumbleParam, f32 near, f32 far,
336 f32 volumeLeft, f32 volumeRight) {
337 makePadRumbleParamNearFarVolumePitchLR(rumbleParam, near, far, volumeLeft, volumeRight, pitchLeft: 1.0f,
338 pitchRight: 1.0f);
339}
340
341void makePadRumbleParamNearFarVolumePitch(al::PadRumbleParam* rumbleParam, f32 near, f32 far,
342 f32 volume, f32 pitch) {
343 makePadRumbleParamNearFarVolumePitchLR(rumbleParam, near, far, volumeLeft: volume, volumeRight: volume, pitchLeft: pitch, pitchRight: pitch);
344}
345
346void makePadRumbleParamNearFarVolumePitchLR(al::PadRumbleParam* rumbleParam, f32 near, f32 far,
347 f32 volumeLeft, f32 volumeRight, f32 pitchLeft,
348 f32 pitchRight) {
349 rumbleParam->far = far;
350 rumbleParam->near = near;
351 rumbleParam->volumeLeft = volumeLeft;
352 rumbleParam->volumeRight = volumeRight;
353 rumbleParam->pitchLeft = pitchLeft;
354 rumbleParam->pitchRight = pitchRight;
355 rumbleParam->field_18 = 0;
356}
357} // namespace alPadRumbleFunction
358