#include "Library/MapObj/ClockMapParts.h" #include "Library/Fluid/RippleCtrl.h" #include "Library/LiveActor/ActorActionFunction.h" #include "Library/LiveActor/ActorAreaFunction.h" #include "Library/LiveActor/ActorInitFunction.h" #include "Library/LiveActor/ActorInitUtil.h" #include "Library/LiveActor/ActorModelFunction.h" #include "Library/LiveActor/ActorMovementFunction.h" #include "Library/LiveActor/ActorPoseUtil.h" #include "Library/LiveActor/ActorSensorUtil.h" #include "Library/MapObj/ChildStep.h" #include "Library/Math/MathUtil.h" #include "Library/Nerve/NerveSetupUtil.h" #include "Library/Nerve/NerveUtil.h" #include "Library/Placement/PlacementFunction.h" #include "Library/Se/SeFunction.h" #include "Library/Stage/StageSwitchUtil.h" #include "Library/Thread/FunctorV0M.h" #include "MapObj/SubActorLodFixPartsScenarioAction.h" namespace { using namespace al; NERVE_ACTION_IMPL(ClockMapParts, StandBy) NERVE_ACTION_IMPL(ClockMapParts, Delay) NERVE_ACTION_IMPL(ClockMapParts, RotateSign) NERVE_ACTION_IMPL(ClockMapParts, Rotate) NERVE_ACTION_IMPL(ClockMapParts, Wait) NERVE_ACTION_IMPL(ClockMapParts, AssistStop) NERVE_ACTION_IMPL(ClockMapParts, AssistStopSync) NERVE_ACTION_IMPL(ClockMapParts, AssistStopEndWait) NERVE_ACTIONS_MAKE_STRUCT(ClockMapParts, StandBy, Delay, RotateSign, Rotate, Wait, AssistStop, AssistStopSync, AssistStopEndWait) } // namespace namespace al { ClockMapParts::ClockMapParts(const char* name) : LiveActor(name) {} void ClockMapParts::init(const ActorInitInfo& info) { using ClockMapPartsFunctor = FunctorV0M; tryInitSubActorKeeperChildStep(this, info); initNerveAction(this, "Rotate", &NrvClockMapParts.collector, 0); initMapPartsActor(this, info, nullptr); tryGetQuatPtr(this); registerAreaHostMtx(this, info); registSupportFreezeSyncGroup(this, info); mQuat.set(getQuat(this)); tryGetArg(&mClockAngleDegree, info, "ClockAngleDegree"); if (mClockAngleDegree == 0) { mTurnStepCount = 1; } else { s32 lcm = sead::Mathi::lcm(sead::Mathi::abs(mClockAngleDegree), 360); s32 clockAngleDegree = sead::Mathi::abs(mClockAngleDegree); mTurnStepCount = lcm / clockAngleDegree; } tryGetArg(&mRotateAxis, info, "RotateAxis"); createChildStep(info, this, true); tryGetArg(&mDelayTime, info, "DelayTime"); tryGetArg(&mWaitTime, info, "WaitTime"); tryGetArg(&mRotateTime, info, "RotateTime"); initMaterialCode(this, info); if (isExistAction(this, "MiddleSign")) { mRotateSignTime = (s32)getActionFrameMax(this, "MiddleSign"); } else { mRotateSignTime = 36; tryGetArg(&mRotateSignTime, info, "RotateSignTime"); } mRotateTimer = mRotateSignTime + mRotateTime + 1; mActiveTimer = mRotateTimer + mWaitTime + 1; if (mDelayTime >= 1) { mTimer = 0; startNerveAction(this, "Delay"); } else { mTimer = mRotateSignTime; } if (listenStageSwitchOnStart(this, ClockMapPartsFunctor(this, &ClockMapParts::start))) startNerveAction(this, "StandBy"); if (isExistModel(this)) { mRippleCtrl = RippleCtrl::tryCreate(this); if (mRippleCtrl) mRippleCtrl->init(info); } listenStageSwitchOn(this, "SwitchStop", ClockMapPartsFunctor(this, &ClockMapParts::standBy)); trySyncStageSwitchAppear(this); } void ClockMapParts::start() { if (!isNerve(this, NrvClockMapParts.StandBy.data())) return; if (mDelayTime >= 1) { startNerveAction(this, "Delay"); return; } setRotateStartNerve(); } void ClockMapParts::standBy() { startNerveAction(this, "StandBy"); } bool ClockMapParts::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) { if (isNerve(this, NrvClockMapParts.StandBy.data())) return false; if (isMsgTouchAssist(message)) { mAssistStopTimer = 45; if (isNerve(this, NrvClockMapParts.AssistStop.data())) return true; if (isExistAction(this)) stopAction(this); startNerveAction(this, "AssistStop"); return true; } if (isMsgShowModel(message)) { showModelIfHide(this); return true; } if (isMsgHideModel(message)) { hideModelIfShow(this); return true; } if (isMsgRestart(message)) { appearAndSetStart(); return true; } if (isMsgIsNerveSupportFreeze(message)) return isNerve(this, NrvClockMapParts.AssistStop.data()); if (isMsgOnSyncSupportFreeze(message)) { if (isNerve(this, NrvClockMapParts.AssistStop.data())) return true; if (isExistAction(this)) stopAction(this); startNerveAction(this, "AssistStopSync"); return true; } if (isMsgOffSyncSupportFreeze(message)) { if (!isNerve(this, NrvClockMapParts.AssistStopSync.data())) return true; setRestartNerve(); return true; } return false; } void ClockMapParts::appearAndSetStart() { mCurrentStep = 0; mTimer = 0; mAssistStopTimer = 0; setQuat(this, mQuat); if (mDelayTime >= 1) startNerveAction(this, "Delay"); else setRotateStartNerve(); makeActorAlive(); } void ClockMapParts::setRestartNerve() { if (isExistAction(this)) restartAction(this); if (mTimer >= mRotateTimer) startNerveAction(this, "AssistStopEndWait"); else if (mTimer >= mRotateSignTime) startNerveAction(this, "Rotate"); else startNerveAction(this, "RotateSign"); } void ClockMapParts::control() { if (!mRippleCtrl) return; mRippleCtrl->update(); } void ClockMapParts::setRotateStartNerve() { if (mRotateSignTime > 0) startNerveAction(this, "RotateSign"); else startNerveAction(this, "Rotate"); } void ClockMapParts::exeStandBy() {} void ClockMapParts::exeDelay() { if (isGreaterEqualStep(this, mDelayTime - 1)) setRotateStartNerve(); } void ClockMapParts::exeRotateSign() { if (isFirstStep(this)) tryStartAction(this, "MiddleSign"); f32 angle = wrapAngle(mCurrentStep * mClockAngleDegree); rotateQuatLocalDirDegree(this, mQuat, mRotateAxis, angle + sead::Mathf::sin((f32)mTimer * sead::Mathf::pi2() / 18.0f)); mTimer++; if (mTimer >= mRotateSignTime) startNerveAction(this, "Rotate"); } void ClockMapParts::exeRotate() { f32 time = (f32)(mTimer - mRotateSignTime) / (f32)(mRotateTimer + ~mRotateSignTime); f32 angle = wrapAngle((time + mCurrentStep) * mClockAngleDegree); rotateQuatLocalDirDegree(this, mQuat, mRotateAxis, angle); mTimer++; if (mTimer >= mRotateTimer) { mCurrentStep = wrapValue(mCurrentStep + 1, mTurnStepCount); startNerveAction(this, "Wait"); tryStartSe(this, "RotateEnd"); } } void ClockMapParts::exeWait() { mTimer++; if (mTimer >= mActiveTimer) { mTimer -= mActiveTimer; setRotateStartNerve(); } } void ClockMapParts::exeAssistStop() { mAssistStopTimer--; if (mAssistStopTimer <= 0) { mAssistStopTimer = 0; setRestartNerve(); } } void ClockMapParts::exeAssistStopSync() {} void ClockMapParts::exeAssistStopEndWait() { exeWait(); } } // namespace al