#include "Library/MapObj/GateMapParts.h" #include "Library/Audio/System/SimpleAudioUser.h" #include "Library/Base/StringUtil.h" #include "Library/LiveActor/ActorActionFunction.h" #include "Library/LiveActor/ActorClippingFunction.h" #include "Library/LiveActor/ActorInitFunction.h" #include "Library/LiveActor/ActorInitUtil.h" #include "Library/LiveActor/ActorPoseUtil.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" namespace { using namespace al; NERVE_ACTION_IMPL(GateMapParts, Wait) NERVE_ACTION_IMPL(GateMapParts, Open) NERVE_ACTION_IMPL(GateMapParts, Bound) NERVE_ACTION_IMPL(GateMapParts, End) NERVE_ACTIONS_MAKE_STRUCT(GateMapParts, Wait, Open, Bound, End) } // namespace namespace al { GateMapParts::GateMapParts(const char* name) : LiveActor(name) {} void GateMapParts::init(const ActorInitInfo& info) { using GateMapPartsFunctor = FunctorV0M; initNerveAction(this, "Wait", &NrvGateMapParts.collector, 0); initMapPartsActor(this, info, nullptr); tryGetQuatPtr(this); mTrans = getTrans(this); mQuat = getQuat(this); tryGetLinksTrans(&mMoveNextTrans, info, "MoveNext"); tryGetLinksQuat(&mMoveNextQuat, info, "MoveNext"); tryGetArg(&mOpenTime, info, "OpenTime"); tryGetArg(&mBoundRate, info, "BoundRate"); tryGetArg(&mHitReactionCount, info, "HitReactionCount"); listenStageSwitchOnStart(this, GateMapPartsFunctor(this, &GateMapParts::start)); bool isPlaySuccessSe = false; tryGetArg(&isPlaySuccessSe, info, "IsPlaySuccessSe"); if (isPlaySuccessSe) mSuccessSeObj = new SimpleAudioUser("SuccessSeObj", info); makeActorAlive(); } void GateMapParts::start() { if (!isNerve(this, NrvGateMapParts.Wait.data())) return; appearAndSetStart(); } void GateMapParts::appearAndSetStart() { invalidateClipping(this); startNerveAction(this, "Open"); } void GateMapParts::exeWait() { if (isFirstStep(this)) validateClipping(this); } void GateMapParts::exeOpen() { updatePose(calcNerveSquareInRate(this, mOpenTime - 1)); if (isGreaterEqualStep(this, mOpenTime - 1)) { mCurrentBoundRate = mBoundRate; mCurrentBoundSteps = (s32)(mBoundRate * (f32)mOpenTime * 2); mHitReactionCurrent = 0; if (mMaxHitReactions > mHitReactionCurrent && mCurrentBoundSteps > 1) { startNerveAction(this, "Bound"); return; } if (mSuccessSeObj) startSe(mSuccessSeObj, "Riddle"); startNerveAction(this, "End"); if (mHitReactionCount < 2) startHitReaction(this, "バウンド1回目"); } } void GateMapParts::updatePose(f32 rate) { rate = sead::Mathf::clamp(rate, 0.0f, 1.0f); lerpVec(getTransPtr(this), mTrans, mMoveNextTrans, rate); slerpQuat(getQuatPtr(this), mQuat, mMoveNextQuat, rate); } void GateMapParts::exeBound() { if (isFirstStep(this)) { if (mHitReactionCurrent++ < mHitReactionCount) startHitReaction(this, StringTmp<32>("バウンド%d回目", mHitReactionCurrent).cstr()); tryStartSeWithParam(this, "BoundStart", (f32)(mMaxHitReactions - mHitReactionCurrent), ""); } f32 rate = calcNerveRate(this, mCurrentBoundSteps - 1); rate = sead::Mathf::pow(mCurrentBoundRate * (rate * 2 - 1.0f), 2); rate += (1.0f - sead::Mathf::pow(mCurrentBoundRate, 2)); updatePose(rate); if (isGreaterEqualStep(this, mCurrentBoundSteps - 1)) { mCurrentBoundRate *= mBoundRate; mCurrentBoundSteps = (s32)(mBoundRate * (f32)mCurrentBoundSteps); if (mMaxHitReactions > mHitReactionCurrent && mCurrentBoundSteps > 1) { startNerveAction(this, "Bound"); return; } if (mSuccessSeObj) startSe(mSuccessSeObj, "Riddle"); startNerveAction(this, "End"); } } void GateMapParts::exeEnd() { if (isFirstStep(this)) { validateClipping(this); updatePose(1.0f); } } } // namespace al