#include "Library/Play/Camera/CameraVerticalAbsorber.h" #include "Library/Camera/CameraPoser.h" #include "Library/Camera/CameraStartInfo.h" #include "Library/Math/MathUtil.h" #include "Library/Nerve/NerveSetupUtil.h" #include "Library/Nerve/NerveUtil.h" #include "Library/Yaml/ByamlUtil.h" namespace { using namespace al; NERVE_IMPL(CameraVerticalAbsorber, FollowGround); NERVE_IMPL(CameraVerticalAbsorber, FollowAbsolute); NERVE_IMPL_(CameraVerticalAbsorber, FollowClimbPoleNoInterp, Follow); NERVE_IMPL_(CameraVerticalAbsorber, FollowSlow, Absorb); NERVE_IMPL(CameraVerticalAbsorber, Absorb); NERVE_IMPL(CameraVerticalAbsorber, Follow); NERVE_IMPL(CameraVerticalAbsorber, FollowClimbPole); NERVES_MAKE_STRUCT(CameraVerticalAbsorber, FollowGround, FollowAbsolute, FollowClimbPoleNoInterp, FollowSlow, Absorb, Follow, FollowClimbPole); } // namespace namespace al { void CameraVerticalAbsorber::exeFollowAbsolute() { mTargetInterp *= 0.8f; } void CameraVerticalAbsorber::invalidate() { mIsInvalidated = true; if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute)) setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute); } // NON_MATCHING: https://decomp.me/scratch/Zhx9Y void CameraVerticalAbsorber::start(const sead::Vector3f& pos, const CameraStartInfo& info) { alCameraPoserFunction::calcTargetFront(&mPrevTargetFront, mCameraPoser); mTargetInterp.x = 0.0f; mTargetInterp.y = 0.0f; mTargetInterp.z = 0.0f; mPrevTargetTrans = pos; if (_1aa || mIsInvalidated || alCameraPoserFunction::isPlayerTypeNotTouchGround(mCameraPoser)) return setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute); if (alCameraPoserFunction::isTargetClimbPole(mCameraPoser)) return setNerve(this, &NrvCameraVerticalAbsorber.FollowClimbPoleNoInterp); if (alCameraPoserFunction::isTargetGrabCeil(mCameraPoser)) return setNerve(this, &NrvCameraVerticalAbsorber.FollowSlow); if (!info.isGrounded || alCameraPoserFunction::isTargetCollideGround(mCameraPoser)) return setNerve(this, &NrvCameraVerticalAbsorber.FollowGround); mPrevTargetTrans = alCameraPoserFunction::getPreLookAtPos(mCameraPoser); sead::Vector3f target; alCameraPoserFunction::calcTargetGravity(&target, mCameraPoser); mTargetInterp = pos - mPrevTargetTrans; parallelizeVec(&mTargetInterp, target, mTargetInterp); setNerve(this, &NrvCameraVerticalAbsorber.Absorb); } void CameraVerticalAbsorber::load(const ByamlIter& iter) { ByamlIter it; if (!iter.tryGetIterByKey(&it, "VerticalAbsorb")) return; tryGetByamlF32(&mAbsorbScreenPosUp, it, "AbsorbScreenPosUp"); tryGetByamlF32(&mAbsorbScreenPosDown, it, "AbsorbScreenPosDown"); tryGetByamlF32(&mHighJumpJudgeSpeedV, it, "HighJumpJudgeSpeedV"); ByamlIter it2; if (!it.tryGetIterByKey(&it2, "AdvanceAbsorbUp")) return; mIsAdvanceAbsorbUp = true; mAdvanceAbsorbScreenPosUp = getByamlKeyFloat(it2, "AdvanceAbsorbScreenPosUp"); } // NON_MATCHING: https://decomp.me/scratch/JdemU void CameraVerticalAbsorber::update() { if (mIsStopUpdate) return; sead::Vector3f gravity{}; alCameraPoserFunction::calcTargetGravity(&gravity, mCameraPoser); mTargetInterp = mCameraPoser->getPosition() - mPrevTargetTrans; parallelizeVec(&mTargetInterp, gravity, mTargetInterp); mLookAtCamera.getPos() = mCameraPoser->getPosition(); mLookAtCamera.getAt() = mCameraPoser->getTargetTrans(); mLookAtCamera.getUp() = mCameraPoser->getCameraUp(); if (mLookAtCamera.getUp().length() > 0.0f) mLookAtCamera.getUp().normalize(); if (!_1aa && !mIsInvalidated) { mLookAtCamera.getAt() -= mTargetInterp; if (!mIsNoCameraPosAbsorb) mLookAtCamera.getPos() -= mTargetInterp; } mLookAtCamera.doUpdateMatrix(&mLookAtCamera.getMatrix()); mProjection.set(alCameraPoserFunction::getNear(mCameraPoser), alCameraPoserFunction::getFar(mCameraPoser), sead::Mathf::deg2rad(mCameraPoser->getFovyDegree()), alCameraPoserFunction::getAspect(mCameraPoser)); alCameraPoserFunction::calcTargetFront(&mTargetFront, mCameraPoser); if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowGround) && alCameraPoserFunction::isTargetCollideGround(mCameraPoser)) setNerve(this, &NrvCameraVerticalAbsorber.FollowGround); if (!isNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute) && alCameraPoserFunction::isPlayerTypeNotTouchGround(mCameraPoser)) setNerve(this, &NrvCameraVerticalAbsorber.FollowAbsolute); updateNerve(); sead::Vector3f prevTargetTrans = sead::Vector3f::zero; if (!mIsKeepInFrame) { prevTargetTrans = mTargetInterp; } else { sead::Vector3f offsetTrans = sead::Vector3f::zero; alCameraPoserFunction::calcTargetTransWithOffset(&offsetTrans, mCameraPoser); alCameraPoserFunction::calcOffsetCameraKeepInFrameV( &gravity, &mLookAtCamera, offsetTrans, mCameraPoser, mKeepInFrameOffsetUp, alCameraPoserFunction::isPlayerTypeHighJump(mCameraPoser) ? 300.0f : mKeepInFrameOffsetDown); prevTargetTrans = mTargetInterp - gravity; } mPrevTargetTrans = mCameraPoser->getTargetTrans() - prevTargetTrans; mPrevTargetFront = mTargetFront; } } // namespace al