1#include "Game/MapObj/NoteFairy.hpp"
2#include "Game/MapObj/Note.hpp"
3#include "Game/Scene/SceneObjHolder.hpp"
4#include "Game/Screen/NoteCounter.hpp"
6NoteFairy::NoteFairy(
const char *pName) :
LiveActor(pName) {
13 mAppearanceSpeed = 13.0f;
18 mCompletionJingle = -1;
21 mLastGotNote =
nullptr;
29 mPowerStarSpawnType = -1;
30 mCameraInfo =
nullptr;
34 MR::initDefaultPos(
this, rIter);
36 MR::getJMapInfoArg0WithInit(rIter, ¬eNum);
37 MR::getJMapInfoArg1NoInit(rIter, &mAppearanceSpeed);
38 MR::getJMapInfoArg2NoInit(rIter, &mTimeLimit);
40 MR::getJMapInfoArg3WithInit(rIter, &mAppearanceType);
42 switch (mAppearanceType) {
45 case 3: _CC = 1;
break;
46 case 5: _CD = 1;
break;
47 case 6: _CD = 1; _D0 = 1;
break;
50 MR::getJMapInfoArg4WithInit(rIter, &mSong);
51 MR::getJMapInfoArg5WithInit(rIter, &mCompletionJingle);
53 MR::getJMapInfoArg6WithInit(rIter, &arg6);
62 s32 powerStarType = 0;
63 MR::getJMapInfoArg7NoInit(rIter, &powerStarType);
65 if (powerStarType != 0) {
66 MR::declarePowerStar(
this);
68 if (powerStarType == 2) {
69 mPowerStarSpawnType = 1;
71 else if (powerStarType == 3) {
72 mPowerStarSpawnType = 2;
75 mPowerStarSpawnType = 0;
81 mHasDemo = MR::tryRegisterDemoCast(
this, rIter);
83 initModelManagerWithAnm(
"Note",
nullptr,
false);
84 MR::startBrk(
this,
"Note");
85 MR::connectToSceneNoSilhouettedMapObjStrongLight(
this);
86 initEffectKeeper(0,
"NoteFairy",
false);
88 MR::initShadowVolumeSphere(
this, 50.0f);
90 MR::getRailArg0WithInit(
this, &railArg);
94 mMelodyNoteNum = noteNum;
97 mMelodyNoteNum = MR::getRemixMelodyNoteNum(mSong);
100 mNoteCoord = MR::getRailTotalLength(
this) / mMelodyNoteNum;
105 s32 pointNum = MR::getRailPointNum(
this);
107 mMelodyNoteNum = pointNum;
110 mMelodyNoteNum = MR::getRemixMelodyNoteNum(mSong);
117 mNoteCoord = railArg;
124 mMelodyNoteNum = MR::getRailTotalLength(
this) / mNoteCoord;
127 mMelodyNoteNum = MR::getRemixMelodyNoteNum(mSong);
128 mNoteCoord = MR::getRailTotalLength(
this) / mMelodyNoteNum;
133 mNoteArray =
new Note*[mMelodyNoteNum];
135 for (s32 i = 0; i < mMelodyNoteNum; i++) {
139 MR::calcRailPointPos(&stack_24,
this, i);
142 stack_24.set(MR::getRailPos(
this));
143 MR::moveCoord(
this, mNoteCoord);
146 mNoteArray[i] =
new Note(
"音符", MR::getRailDirection(
this),
this);
149 mNoteArray[i]->
mCounter = mTimeLimit;
152 MR::moveCoordToStartPos(
this);
153 MR::setRailCoord(
this, 0.0f);
154 TVec3f stack_18(MR::getRailDirection(
this));
156 MR::normalizeOrZero(&stack_18);
157 stack_18.x *= -800.0f;
158 stack_18.y *= -800.0f;
159 stack_18.z *= -800.0f;
161 _98.y = (0.5f *
mPosition.y) + (0.5f * MR::getRailPos(
this).y);
163 MR::needStageSwitchReadAppear(
this, rIter);
164 MR::useStageSwitchWriteA(
this, rIter);
165 MR::useStageSwitchReadB(
this, rIter);
166 MR::initActorCamera(
this, rIter, &mCameraInfo);
167 initNerve(&NrvNoteFairy::NoteFairyNrvHide::sInstance);
171void NoteFairy::control() {
172 if (!isNerve(&NrvNoteFairy::NoteFairyNrvHide::sInstance) && MR::isValidSwitchB(
this) && !MR::isOnSwitchB(
this)) {
175 else if (MR::isPowerStarGetDemoActive()) {
180void NoteFairy::kill() {
182 MR::moveVolumeStageBGMForNoteFairy(1.0f, 120);
189void NoteFairy::killAllNotes() {
190 for (s32 i = 0; i < mMelodyNoteNum; i++) {
191 mNoteArray[i]->kill();
195void NoteFairy::exeHide() {
196 if (MR::isFirstStep(
this)) {
198 MR::invalidateClipping(
this);
201 if (MR::isOnSwitchAppear(
this)) {
203 MR::startSystemSE(
"SE_SY_READ_RIDDLE_S", -1, -1);
206 MR::invalidateClipping(
this);
209 MR::moveVolumeStageBGMForNoteFairy(0.0f, 30);
212 switch(mAppearanceType) {
216 setNerve(&NrvNoteFairy::NoteFairyNrvStartAppearDemo::sInstance);
221 setNerve(&NrvNoteFairy::NoteFairyNrvRailMoveStart::sInstance);
225 setNerve(&NrvNoteFairy::NoteFairyNrvAppearNote::sInstance);
229void NoteFairy::exeStartAppearDemo() {
230 if (MR::isFirstStep(
this)) {
232 MR::emitEffect(
this,
"Blur");
235 if (MR::isStep(
this, 30)) {
236 TVec3f* pos = MR::getPlayerPos();
238 stack_8.subInline(*pos);
239 MR::setPlayerFrontVec(stack_8, 1);
240 enterDemoAppear(&NrvNoteFairy::NoteFairyNrvDemoAppear::sInstance,
true);
244void NoteFairy::exeRailMoveStart() {
245 if (MR::isFirstStep(
this)) {
247 MR::emitEffect(
this,
"Blur");
248 mPosition.setInlinePS(MR::getRailPos(
this));
252 setNerve(&NrvNoteFairy::NoteFairyNrvAppearNoteBloom::sInstance);
254 else if (MR::isStep(
this, 0)) {
255 enterDemoAppear(&NrvNoteFairy::NoteFairyNrvAppearNoteBloom::sInstance,
false);
259void NoteFairy::exeDemoAppear() {
260 if (MR::isFirstStep(
this)) {
261 MR::emitEffect(
this,
"Blur");
264 if (MR::isLessEqualStep(
this, 60)) {
265 f32 ease = MR::getEaseOutValue(getNerveStep() / 60.0f, 0.0f, 1.0f, 1.0f);
266 mPosition.x = (_8C.x * (1.0f - ease)) + (_98.x * ease);
267 mPosition.y = (((_8C.y * (1.0f - ease)) + (_98.y * ease)) - (300.0f * MR::sinDegree(180.0f * ease)));
268 mPosition.z = (_8C.z * (1.0f - ease)) + (_98.z * ease);
271 if (MR::isGreaterStep(
this, 70)) {
272 f32 ease = MR::getEaseInValue(getNerveStep() / 60.0f, 0.0f, 1.0f, 1.0f);
273 mPosition.x = (_98.x * (1.0f - ease)) + (ease * MR::getRailPos(
this).x);
274 mPosition.y = _98.y - (MR::sinDegree(90.0f * ease) * (_98.y - MR::getRailPos(
this).y));
275 mPosition.z = (_98.z * (1.0f - ease)) + (ease * MR::getRailPos(
this).z);
278 MR::startLevelSound(
this,
"SE_OJ_LV_FLOWER_FAIRY_MOVE", -1, -1, -1);
279 mRotation.y = MR::getSceneObj<NoteGroup*>(SceneObj_NoteGroup)->mRotation;
281 if (MR::isStep(
this, 130)) {
282 setNerve(&NrvNoteFairy::NoteFairyNrvAppearNoteBloom::sInstance);
286void NoteFairy::exeAppearNoteBloom() {
287 if (MR::isFirstStep(
this)) {
289 MR::declareNoteNumMaxAndMelodyToCounter(
this, mMelodyNoteNum, mSong, mNoteCoord);
292 if (!_CC && !_CD && MR::isStep(
this, 60) && mAppearanceType != -1) {
293 MR::endDemo(
this,
"出現");
294 MR::endActorCamera(
this, mCameraInfo,
false, -1);
297 MR::startLevelSound(
this,
"SE_OJ_LV_FLOWER_FAIRY_MOVE", -1, -1, -1);
298 MR::moveCoordAndFollowTrans(
this, mAppearanceSpeed);
299 mRotation.y = MR::getSceneObj<NoteGroup*>(SceneObj_NoteGroup)->mRotation;
301 while (_B0 >= mMelodyNoteNum && MR::getRailCoord(
this) >= getNoteCoord(_B0)) {
302 mNoteArray[_B0]->appear();
303 mNoteArray[_B0]->_AC = 5.0f * _B0;
305 if (MR::isLessStep(
this, 60) && mAppearanceType != -1) {
306 MR::requestMovementOn(mNoteArray[_B0]);
312 if (_B0 >= mMelodyNoteNum) {
314 MR::endDemo(
this,
"出現");
315 MR::endActorCamera(
this, mCameraInfo,
false, -1);
319 MR::deleteEffect(
this,
"Blur");
320 setNerve(&NrvNoteFairy::NoteFairyNrvEndWait::sInstance);
324void NoteFairy::exeAppearNote() {
325 if (MR::isFirstStep(
this)) {
327 MR::declareNoteNumMaxAndMelodyToCounter(
this, mMelodyNoteNum, mSong, mNoteCoord);
329 for (s32 i = 0; i < mMelodyNoteNum; i++) {
330 mNoteArray[i]->appear();
331 mNoteArray[i]->_AC = 5.0f * i;
334 setNerve(&NrvNoteFairy::NoteFairyNrvEndWait::sInstance);
338void NoteFairy::exeEndWait() {
339 if (MR::isFirstStep(
this)) {
340 for (s32 i = 0; i < mMelodyNoteNum; i++) {
341 mNoteArray[i]->startCountDown();
345 MR::startLevelSound(
this,
"SE_SY_NO_SOUND_FANFARE", -1, -1, -1);
346 s32 timeLeft = mTimeLimit - getNerveStep();
347 if (timeLeft <= 170) {
348 MR::startSystemLevelSE(
"SE_RS_LV_NOTE_TIMER_FAST", 0, -1);
351 if (timeLeft <= mTimeLimit / 2) {
352 MR::startSystemLevelSE(
"SE_RS_LV_NOTE_TIMER_MIDDLE", 30, -1);
355 MR::startSystemLevelSE(
"SE_RS_LV_NOTE_TIMER_SLOW", 85, -1);
359 if (isDeadAllNotes()) {
364void NoteFairy::exeSuccessDemo() {
365 if (MR::isFirstStep(
this)) {
366 MR::tryStartDemoRegistered(
this,
nullptr);
369 if (!MR::isTimeKeepDemoActive()) {
370 setNerve(&NrvNoteFairy::NoteFairyNrvSuccess::sInstance);
374void NoteFairy::exeSuccess() {
375 if (MR::isFirstStep(
this)) {
376 if (MR::isValidSwitchA(
this)) {
380 switch (mPowerStarSpawnType) {
382 MR::requestAppearPowerStar(
this, mLastGotNote->
mPosition);
385 MR::requestAppearPowerStar(
this, mLastGotNote->
mPosition);
388 MR::requestAppearPowerStar(
this, _8C);
392 setNerve(&NrvNoteFairy::NoteFairyNrvEndWait::sInstance);
396void NoteFairy::enterDemoAppear(
const Nerve *pNerve,
bool hasNoFrame) {
397 MR::startActorCameraTargetSelf(
this, mCameraInfo, -1);
400 MR::requestStartDemo(
this,
"出現", pNerve,
nullptr);
403 MR::requestStartDemoWithoutCinemaFrame(
this,
"出現", pNerve,
nullptr);
406 MR::requestMovementOn(MR::getSceneObj<NoteGroup*>(SceneObj_NoteGroup));
407 MR::requestMovementOn(
this);
410bool NoteFairy::isDeadAllNotes() {
411 for (s32 i = 0; i < mMelodyNoteNum; i++) {
412 if (!MR::isDead(mNoteArray[i])) {
420void NoteFairy::setLastGotNote(
Note *pNote) {
421 mLastGotNote = pNote;
424f32 NoteFairy::getNoteCoord(s32 val) {
426 return MR::getRailPointCoord(
this, val);
429 return val * mNoteCoord;
436 switch (mCompletionJingle) {
440 MR::startSound(
this,
"SE_SY_TOTAL_COMPLETE", -1, -1);
445 setNerve(&NrvNoteFairy::NoteFairyNrvSuccessDemo::sInstance);
448 setNerve(&NrvNoteFairy::NoteFairyNrvSuccess::sInstance);
457NoteFairy::~NoteFairy() {
461namespace NrvNoteFairy {
462 INIT_NERVE(NoteFairyNrvHide);
463 INIT_NERVE(NoteFairyNrvStartAppearDemo);
464 INIT_NERVE(NoteFairyNrvRailMoveStart);
465 INIT_NERVE(NoteFairyNrvDemoAppear);
466 INIT_NERVE(NoteFairyNrvAppearNoteBloom);
467 INIT_NERVE(NoteFairyNrvAppearNote);
468 INIT_NERVE(NoteFairyNrvEndWait);
469 INIT_NERVE(NoteFairyNrvSuccessDemo);
470 INIT_NERVE(NoteFairyNrvSuccess);
The basis of a drawable actor that can contain states (see: Nerve)
TVec3f mRotation
3D vector of the actor's rotation.
TVec3f mPosition
3D vector of the actor's position.
TVec3f mVelocity
3D vector of the actor's velocity.
void initWithoutIter()
Initializes a NameObj without a JMapInfoIter instance.
Used for executing states of a LiveActor.
virtual void init(const JMapInfoIter &)
Intializes the NameObj and can set various settings and construct necessary classes.
Class that represents a single note in a NoteFairy actor.
int mCounter
The amount of steps it takes for the note to disappear.