1#include "Library/LiveActor/ActorActionFunction.h"
2
3#include "Library/Action/ActorActionKeeper.h"
4#include "Library/Base/StringUtil.h"
5#include "Library/LiveActor/ActorAnimFunction.h"
6#include "Library/LiveActor/HitReactionKeeper.h"
7#include "Library/LiveActor/LiveActor.h"
8#include "Library/Math/MathUtil.h"
9#include "Library/Nerve/NerveAction.h"
10#include "Library/Nerve/NerveActionCtrl.h"
11#include "Library/Nerve/NerveKeeper.h"
12#include "Library/Nerve/NerveUtil.h"
13#include "Project/Action/ActionAnimCtrl.h"
14#include "Project/Action/ActionSeCtrl.h"
15
16namespace al {
17
18void startAction(LiveActor* actor, const char* actionName) {
19 if (!actor->getActorActionKeeper() || !actor->getActorActionKeeper()->startAction(actionName)) {
20 tryStartSklAnimIfExist(actor, actionName);
21 tryStartMtpAnimIfExist(actor, actionName);
22 tryStartMclAnimIfExist(actor, actionName);
23 tryStartMtsAnimIfExist(actor, actionName);
24 tryStartVisAnimIfExistForAction(actor, actionName);
25 }
26}
27
28s32 startActionAtRandomFrame(LiveActor* actor, const char* actionName) {
29 startAction(actor, actionName);
30 s32 frame = getRandom(min: 0.0f, max: getSklAnimFrameMax(actor, 0));
31 setSklAnimFrame(actor, frame, 0);
32 return frame;
33}
34
35bool tryStartAction(LiveActor* actor, const char* actionName) {
36 if (actor->getActorActionKeeper() && actor->getActorActionKeeper()->getAnimCtrl() &&
37 actor->getActorActionKeeper()->getAnimCtrl()->isExistAction(actionName)) {
38 actor->getActorActionKeeper()->startAction(actionName);
39 return true;
40 }
41
42 bool sklStarted = tryStartSklAnimIfExist(actor, actionName);
43 bool mtpStarted = tryStartMtpAnimIfExist(actor, actionName);
44 bool mclStarted = tryStartMclAnimIfExist(actor, actionName);
45 bool mtsStarted = tryStartMtsAnimIfExist(actor, actionName);
46 bool visStarted = tryStartVisAnimIfExistForAction(actor, actionName);
47
48 if (!sklStarted && !mtpStarted && !mclStarted && !mtsStarted && !visStarted)
49 return false;
50 if (actor->getActorActionKeeper())
51 actor->getActorActionKeeper()->startAction(actionName);
52 return true;
53}
54
55bool tryStartActionIfNotPlaying(LiveActor* actor, const char* actionName) {
56 if (isActionPlaying(actor, actionName))
57 return false;
58
59 startAction(actor, actionName);
60 return true;
61}
62
63bool isActionPlaying(const LiveActor* actor, const char* actionName) {
64 const char* playingActionName = nullptr;
65 ActorActionKeeper* keeper = actor->getActorActionKeeper();
66 if (keeper && keeper->getAnimCtrl())
67 playingActionName = keeper->getAnimCtrl()->getPlayingActionName();
68 if (!playingActionName)
69 playingActionName = alAnimFunction::getAllAnimName(actor);
70 return playingActionName && isEqualString(str1: playingActionName, str2: actionName);
71}
72
73bool tryStartActionIfActionEnd(LiveActor* actor, const char* actionName) {
74 if (isActionPlaying(actor, actionName) && !isActionEnd(actor))
75 return false;
76
77 startAction(actor, actionName);
78 return true;
79}
80
81bool isActionEnd(const LiveActor* actor) {
82 const ActorActionKeeper* keeper = actor->getActorActionKeeper();
83 if (keeper && keeper->getAnimCtrl())
84 return keeper->getAnimCtrl()->isActionEnd();
85 return alAnimFunction::isAllAnimEnd(actor, -1);
86}
87
88bool isExistAction(const LiveActor* actor) {
89 return isSklAnimExist(actor) || isMtpAnimExist(actor) || isMclAnimExist(actor) ||
90 isMtsAnimExist(actor) || isVisAnimExist(actor);
91}
92
93bool isExistAction(const LiveActor* actor, const char* actionName) {
94 const ActorActionKeeper* keeper = actor->getActorActionKeeper();
95 if (keeper && keeper->getAnimCtrl() && keeper->getAnimCtrl()->isExistAction(actionName))
96 return true;
97 return isSklAnimExist(actor, actionName) || isMtpAnimExist(actor, actionName) ||
98 isMclAnimExist(actor, actionName) || isMtsAnimExist(actor, actionName) ||
99 isVisAnimExist(actor, actionName);
100}
101
102bool isActionOneTime(const LiveActor* actor) {
103 return isActionOneTime(actor, actionName: getActionName(actor));
104}
105
106bool isActionOneTime(const LiveActor* actor, const char* actionName) {
107 if (actor->getActorActionKeeper() && actor->getActorActionKeeper()->getAnimCtrl() &&
108 actor->getActorActionKeeper()->getAnimCtrl()->isExistAction(actionName))
109 return actor->getActorActionKeeper()->getAnimCtrl()->isActionOneTime(actionName);
110
111 if (isSklAnimExist(actor, actionName))
112 return isSklAnimOneTime(actor, actionName);
113 if (isMtpAnimExist(actor, actionName))
114 return isMtpAnimOneTime(actor, actionName);
115 if (isMclAnimExist(actor, actionName))
116 return isMclAnimOneTime(actor, actionName);
117 if (isMtsAnimExist(actor, actionName))
118 return isMtsAnimOneTime(actor, actionName);
119 if (isVisAnimExist(actor, actionName))
120 return isVisAnimOneTime(actor, actionName);
121 return false;
122}
123
124const char* getActionName(const LiveActor* actor) {
125 const ActorActionKeeper* keeper = actor->getActorActionKeeper();
126 if (keeper && keeper->getAnimCtrl()) {
127 const char* actionName = keeper->getAnimCtrl()->getPlayingActionName();
128 if (actionName)
129 return actionName;
130 }
131 return alAnimFunction::getAllAnimName(actor);
132}
133
134f32 getActionFrame(const LiveActor* actor) {
135 const ActorActionKeeper* keeper = actor->getActorActionKeeper();
136 if (keeper && keeper->getAnimCtrl())
137 return keeper->getAnimCtrl()->getFrame();
138 return alAnimFunction::getAllAnimFrame(actor, -1);
139}
140
141f32 getActionFrameMax(const LiveActor* actor) {
142 return getActionFrameMax(actor, actionName: getActionName(actor));
143}
144
145f32 getActionFrameMax(const LiveActor* actor, const char* actionName) {
146 const ActorActionKeeper* keeper = actor->getActorActionKeeper();
147 if (keeper && keeper->getAnimCtrl())
148 return keeper->getAnimCtrl()->getActionFrameMax(actionName);
149 return alAnimFunction::getAllAnimFrameMax(actor, actionName, -1);
150}
151
152f32 getActionFrameRate(const LiveActor* actor) {
153 const ActorActionKeeper* keeper = actor->getActorActionKeeper();
154 if (keeper && keeper->getAnimCtrl())
155 return keeper->getAnimCtrl()->getFrameRate();
156 return alAnimFunction::getAllAnimFrameRate(actor, -1);
157}
158
159void setActionFrame(LiveActor* actor, f32 frame) {
160 if (isSklAnimExist(actor))
161 setSklAnimFrame(actor, frame, 0);
162}
163
164void setActionFrameRate(LiveActor* actor, f32 rate) {
165 if (isSklAnimExist(actor))
166 setSklAnimFrameRate(actor, rate, 0);
167}
168
169void stopAction(LiveActor* actor) {
170 if (isSklAnimExist(actor))
171 setSklAnimFrameRate(actor, 0.0f, 0);
172 if (isMtpAnimExist(actor))
173 setMtpAnimFrameRate(actor, 0.0f);
174 if (isMclAnimExist(actor))
175 setMclAnimFrameRate(actor, 0.0f);
176 if (isMtsAnimExist(actor))
177 setMtsAnimFrameRate(actor, 0.0f);
178 if (isVisAnimExist(actor) && isVisAnimPlayingForAction(actor))
179 setVisAnimFrameRateForAction(actor, 0.0f);
180
181 if (actor->getActorActionKeeper() && actor->getActorActionKeeper()->getSeCtrl())
182 actor->getActorActionKeeper()->getSeCtrl()->resetAction(true);
183}
184
185void restartAction(LiveActor* actor) {
186 if (isSklAnimExist(actor))
187 setSklAnimFrameRate(actor, 1.0f, 0);
188 if (isMtpAnimExist(actor))
189 setMtpAnimFrameRate(actor, 1.0f);
190 if (isMclAnimExist(actor))
191 setMclAnimFrameRate(actor, 1.0f);
192 if (isMtsAnimExist(actor))
193 setMtsAnimFrameRate(actor, 1.0f);
194 if (isVisAnimExist(actor) && isVisAnimPlayingForAction(actor))
195 setVisAnimFrameRateForAction(actor, 1.0f);
196
197 if (actor->getActorActionKeeper() && actor->getActorActionKeeper()->getSeCtrl())
198 actor->getActorActionKeeper()->getSeCtrl()->restartAction();
199}
200
201void copyAction(LiveActor* actor, const LiveActor* sourceActor) {
202 startAction(actor, actionName: getActionName(actor: sourceActor));
203 if (isSklAnimExist(sourceActor) && isSklAnimExist(actor))
204 copySklAnim(actor, sourceActor);
205}
206
207void startNerveAction(LiveActor* actor, const char* actionName) {
208 if (actor->getActorActionKeeper())
209 actor->getActorActionKeeper()->tryStartActionNoAnim(actionName);
210 alNerveFunction::setNerveAction(user: actor, action: actionName);
211}
212
213void setNerveAtActionEnd(LiveActor* actor, const Nerve* nerve) {
214 if (isActionEnd(actor))
215 setNerve(user: actor, nerve);
216}
217
218void resetNerveActionForInit(LiveActor* actor) {
219 NerveActionCtrl* actionCtrl = actor->getNerveKeeper()->getActionCtrl();
220 const Nerve* currentNerve = actor->getNerveKeeper()->getCurrentNerve();
221 if (actionCtrl->getNumActions() <= 0)
222 return;
223
224 s32 index = 0;
225 ;
226 for (index = 0; index < actionCtrl->getNumActions(); index++) {
227 if (actionCtrl->getAction(idx: index) == currentNerve) {
228 startNerveAction(actor, actionName: actionCtrl->getAction(idx: index)->getActionName());
229 break;
230 }
231 }
232}
233
234void startHitReaction(const LiveActor* actor, const char* name) {
235 if (actor->getHitReactionKeeper())
236 actor->getHitReactionKeeper()->start(name, nullptr, nullptr, nullptr);
237}
238
239void startHitReactionHitEffect(const LiveActor* actor, const char* name, const HitSensor* other,
240 const HitSensor* self) {
241 if (actor->getHitReactionKeeper())
242 actor->getHitReactionKeeper()->start(name, nullptr, other, self);
243}
244
245void startHitReactionHitEffect(const LiveActor* actor, const char* name,
246 const sead::Vector3f& pos) {
247 if (actor->getHitReactionKeeper())
248 actor->getHitReactionKeeper()->start(name, &pos, nullptr, nullptr);
249}
250
251void startHitReactionHitEffect(const LiveActor* actor, const char* name,
252 const sead::Matrix34f* mtx) {
253 if (actor->getHitReactionKeeper()) {
254 sead::Vector3f pos = mtx->getBase(axis: 3);
255
256 // copying around again to force more compact stp codegen
257 sead::Vector3f x;
258 x.set(pos);
259 actor->getHitReactionKeeper()->start(name, &x, nullptr, nullptr);
260 }
261}
262
263void startHitReactionBlowHit(const LiveActor* actor, const HitSensor* other,
264 const HitSensor* self) {
265 startHitReactionHitEffect(actor, name: "吹き飛びヒット", other, self);
266}
267
268void startHitReactionBlowHit(const LiveActor* actor, const sead::Vector3f& pos) {
269 startHitReactionHitEffect(actor, name: "吹き飛びヒット", pos);
270}
271
272void startHitReactionBlowHit(const LiveActor* actor) {
273 startHitReaction(actor, name: "吹き飛びヒット");
274}
275
276void startHitReactionBlowHitDirect(const LiveActor* actor, const HitSensor* other,
277 const HitSensor* self) {
278 startHitReactionHitEffect(actor, name: "吹き飛びヒット[直接ヒット]", other, self);
279}
280
281void startHitReactionBlowHitDirect(const LiveActor* actor, const sead::Vector3f& pos) {
282 startHitReactionHitEffect(actor, name: "吹き飛びヒット[直接ヒット]", pos);
283}
284
285void startHitReactionBlowHitDirect(const LiveActor* actor) {
286 startHitReaction(actor, name: "吹き飛びヒット[直接ヒット]");
287}
288
289} // namespace al
290