#include "Library/MapObj/WobbleMapParts.h" #include "Library/LiveActor/ActorActionFunction.h" #include "Library/LiveActor/ActorAreaFunction.h" #include "Library/LiveActor/ActorInitUtil.h" #include "Library/LiveActor/ActorModelFunction.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" namespace { using namespace al; NERVE_ACTION_IMPL(WobbleMapParts, Wait) NERVE_ACTION_IMPL(WobbleMapParts, Move) NERVE_ACTION_IMPL(WobbleMapParts, AssistStop) NERVE_ACTIONS_MAKE_STRUCT(WobbleMapParts, Wait, Move, AssistStop) } // namespace namespace al { WobbleMapParts::WobbleMapParts(const char* name) : LiveActor(name) {} void WobbleMapParts::init(const ActorInitInfo& info) { tryInitSubActorKeeperChildStep(this, info); initNerveAction(this, "Wait", &NrvWobbleMapParts.collector, 0); initMapPartsActor(this, info, nullptr); tryGetQuatPtr(this); registerAreaHostMtx(this, info); mInitialQuat = getQuat(this); mCurrentQuat = mInitialQuat; calcQuatUp(&mInitialUp, mInitialQuat); mTargetUp.set(mInitialUp); tryGetArg(&mMaxRotate, info, "MaxRotate"); initMaterialCode(this, info); createChildStep(info, this, true); trySyncStageSwitchAppear(this); } bool WobbleMapParts::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) { if (isMsgTouchAssist(message)) { mAssistStopTimer = 45; if (!isNerve(this, NrvWobbleMapParts.AssistStop.data())) startNerveAction(this, "AssistStop"); return true; } if (isMsgFloorTouch(message)) { sead::Vector3f pos; if (isMySensor(self, this)) pos.set(getSensorPos(other)); else pos.set(getActorTrans(self)); sead::Vector3f currentHorizontal; sead::Vector3f currentUp; calcQuatUp(¤tUp, mCurrentQuat); verticalizeVec(¤tHorizontal, currentUp, pos - getTrans(this)); f32 hDist = currentHorizontal.length(); f32 normHDist = normalize(hDist, 0.0f, 100.0f); if (isNearZero(hDist)) currentHorizontal = sead::Vector3f::zero; else currentHorizontal *= sead::Mathf::sin(sead::Mathf::deg2rad(normHDist * mMaxRotate)) / hDist; f32 cos = sead::Mathf::cos(sead::Mathf::deg2rad(normHDist * mMaxRotate)); mTargetUp.set(cos * mInitialUp + currentHorizontal); return true; } if (isMsgShowModel(message)) { showModelIfHide(this); return true; } if (isMsgHideModel(message)) { hideModelIfShow(this); return true; } if (isMsgRestart(message)) { appearAndSetStart(); return true; } return false; } void WobbleMapParts::appearAndSetStart() { mIsStop = false; mTiltSpeed = 0.0f; mAssistStopTimer = 0; mMoment.set(sead::Vector3f::zero); mCurrentQuat.set(mInitialQuat); mTargetUp.set(mInitialUp); setQuat(this, mInitialQuat); startNerveAction(this, "Wait"); makeActorAlive(); } void WobbleMapParts::exeWait() { updateMove(); if (mTiltSpeed > 0.1f) startNerveAction(this, "Move"); } void WobbleMapParts::updateMove() { sead::Vector3f currentHorizontal; sead::Vector3f currentUp; calcQuatUp(¤tUp, mCurrentQuat); currentHorizontal.setCross(currentUp, mTargetUp); currentHorizontal *= 180.0f / sead::Mathf::pi(); limitLength(¤tHorizontal, currentHorizontal, mMaxRotate * (1.0f / 750.0f)); mMoment = (mMoment + currentHorizontal) * 0.92f; rotateQuatMomentDegree(&mCurrentQuat, mCurrentQuat, mMoment); sead::Vector3f currentUp2; calcQuatUp(¤tUp2, mCurrentQuat); sead::Vector3f newUp; bool isStop = !turnVecToVecDegree(&newUp, mInitialUp, currentUp2, mMaxRotate); turnQuatYDirRate(getQuatPtr(this), mInitialQuat, newUp, 1.0f); if (isStop) mCurrentQuat = getQuat(this); mTargetUp.set(mInitialUp); mTiltSpeed = mMoment.length(); if (mIsStop != isStop) tryStartSeWithParam(this, "Stop", mTiltSpeed, ""); mIsStop = isStop; } void WobbleMapParts::exeMove() { updateMove(); tryHoldSeWithParam(this, "Rotate", mTiltSpeed, ""); if (mTiltSpeed < 0.1f) startNerveAction(this, "Wait"); } void WobbleMapParts::exeAssistStop() { mAssistStopTimer--; if (mAssistStopTimer <= 0) { mAssistStopTimer = 0; if (mTiltSpeed > 0.1f) startNerveAction(this, "Move"); else startNerveAction(this, "Wait"); } } } // namespace al