mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-04-26 10:34:30 +00:00
327 lines
9.8 KiB
C++
327 lines
9.8 KiB
C++
#include "Library/MapObj/RollingCubeMapParts.h"
|
|
|
|
#include "Library/Base/StringUtil.h"
|
|
#include "Library/Effect/EffectSystemInfo.h"
|
|
#include "Library/LiveActor/ActorActionFunction.h"
|
|
#include "Library/LiveActor/ActorClippingFunction.h"
|
|
#include "Library/LiveActor/ActorInitFunction.h"
|
|
#include "Library/LiveActor/ActorInitUtil.h"
|
|
#include "Library/LiveActor/ActorMovementFunction.h"
|
|
#include "Library/LiveActor/ActorPoseUtil.h"
|
|
#include "Library/LiveActor/ActorResourceFunction.h"
|
|
#include "Library/LiveActor/ActorSensorUtil.h"
|
|
#include "Library/Math/MathUtil.h"
|
|
#include "Library/Nerve/NerveSetupUtil.h"
|
|
#include "Library/Nerve/NerveUtil.h"
|
|
#include "Library/Obj/PartsModel.h"
|
|
#include "Library/Placement/PlacementFunction.h"
|
|
#include "Library/Yaml/ByamlIter.h"
|
|
#include "Library/Yaml/ByamlUtil.h"
|
|
#include "Project/Joint/RollingCubePoseKeeper.h"
|
|
#include "Project/Joint/RollingCubePoseKeeperUtil.h"
|
|
|
|
namespace {
|
|
using namespace al;
|
|
|
|
NERVE_ACTION_IMPL(RollingCubeMapParts, Wait)
|
|
NERVE_ACTION_IMPL(RollingCubeMapParts, Start)
|
|
NERVE_ACTION_IMPL(RollingCubeMapParts, Rotate)
|
|
NERVE_ACTION_IMPL(RollingCubeMapParts, Fall)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, SlideX, Slide)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, SlideY, Slide)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, SlideZ, Slide)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, LandX, Land)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, LandY, Land)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, LandZ, Land)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, FallLandX, FallLand)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, FallLandY, FallLand)
|
|
NERVE_ACTION_IMPL_(RollingCubeMapParts, FallLandZ, FallLand)
|
|
NERVE_ACTION_IMPL(RollingCubeMapParts, Stop)
|
|
|
|
NERVE_ACTIONS_MAKE_STRUCT(RollingCubeMapParts, Wait, Start, Rotate, Fall, SlideX, SlideY, SlideZ,
|
|
LandX, LandY, LandZ, FallLandX, FallLandY, FallLandZ, Stop)
|
|
} // namespace
|
|
|
|
namespace al {
|
|
RollingCubeMapParts::RollingCubeMapParts(const char* name) : LiveActor(name) {}
|
|
|
|
void RollingCubeMapParts::init(const ActorInitInfo& info) {
|
|
initNerveAction(this, "Wait", &NrvRollingCubeMapParts.collector, 0);
|
|
initMapPartsActor(this, info, nullptr);
|
|
tryGetQuatPtr(this);
|
|
|
|
mInitialPoseQuat = getQuat(this);
|
|
mInitialPoseTrans = getTrans(this);
|
|
|
|
bool isUseMoveLimit = false;
|
|
tryGetArg(&isUseMoveLimit, info, "IsUseMoveLimit");
|
|
if (isUseMoveLimit) {
|
|
mMoveLimitMtx = new sead::Matrix34f();
|
|
mMoveLimitMtx->makeQT(mInitialPoseQuat, mInitialPoseTrans);
|
|
|
|
mMoveLimitPartsModel = new PartsModel("");
|
|
StringTmp<256> model;
|
|
StringTmp<256> archive;
|
|
makeMapPartsModelName(&model, &archive, info);
|
|
mMoveLimitPartsModel->initPartsSuffix(this, info, model.cstr(), "MoveLimit", mMoveLimitMtx,
|
|
false);
|
|
}
|
|
|
|
sead::BoundBox3f boundBox;
|
|
if (isExistModelResourceYaml(this, "BoxInfo", nullptr) &&
|
|
tryGetByamlBox3f(&boundBox, ByamlIter(getModelResourceYaml(this, "BoxInfo", nullptr))))
|
|
mRollingCubePoseKeeper = createRollingCubePoseKeeper(boundBox, info);
|
|
else
|
|
mRollingCubePoseKeeper = createRollingCubePoseKeeper(this, info);
|
|
|
|
bool isFloorTouchStart = true;
|
|
tryGetArg(&isFloorTouchStart, info, "IsFloorTouchStart");
|
|
if (!isFloorTouchStart)
|
|
startNerveAction(this, "Start");
|
|
|
|
trySetEffectNamedMtxPtr(this, "Land", &mLandEffectMtx);
|
|
initMaterialCode(this, info);
|
|
|
|
f32 clippingRadius = 0.0f;
|
|
calcRollingCubeClippingInfo(&mClippingTrans, &clippingRadius, mRollingCubePoseKeeper, 0.0f);
|
|
setClippingInfo(this, clippingRadius, &mClippingTrans);
|
|
|
|
tryListenStageSwitchKill(this);
|
|
makeActorAlive();
|
|
}
|
|
|
|
void RollingCubeMapParts::kill() {
|
|
startHitReaction(this, "消滅");
|
|
|
|
LiveActor::kill();
|
|
}
|
|
|
|
bool RollingCubeMapParts::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) {
|
|
if (isMsgPlayerFloorTouch(message) && isNerve(this, NrvRollingCubeMapParts.Wait.data())) {
|
|
startNerveAction(this, "Start");
|
|
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
void RollingCubeMapParts::control() {
|
|
if (mMoveLimitMtx)
|
|
mMoveLimitMtx->makeQT(mInitialPoseQuat, getTrans(this));
|
|
|
|
calcMtxLandEffect(&mLandEffectMtx, mRollingCubePoseKeeper, getQuat(this), getTrans(this));
|
|
}
|
|
|
|
void RollingCubeMapParts::appearAndSetStart() {
|
|
mRollingCubePoseKeeper->setStart();
|
|
setQuat(this, mInitialPoseQuat);
|
|
setTrans(this, mInitialPoseTrans);
|
|
resetPosition(this);
|
|
setNerveNextMovement(isNextFallKey());
|
|
|
|
appear();
|
|
}
|
|
|
|
void RollingCubeMapParts::setNerveNextMovement(bool isNextFallKey) {
|
|
if (isMovementCurrentKeyRotate(mRollingCubePoseKeeper)) {
|
|
startNerveAction(this, "Rotate");
|
|
|
|
return;
|
|
}
|
|
|
|
if (isNextFallKey) {
|
|
startNerveAction(this, "Fall");
|
|
|
|
return;
|
|
}
|
|
|
|
Axis axis = (Axis)sead::Mathi::abs(
|
|
(s32)calcNearVecFromAxis3(nullptr, sead::Vector3f::ey, getQuat(this)));
|
|
switch (axis) {
|
|
default:
|
|
return;
|
|
case Axis::X:
|
|
startNerveAction(this, "SlideX");
|
|
|
|
return;
|
|
case Axis::Y:
|
|
startNerveAction(this, "SlideY");
|
|
|
|
return;
|
|
case Axis::Z:
|
|
startNerveAction(this, "SlideZ");
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
bool RollingCubeMapParts::isNextFallKey() const {
|
|
bool isNextFall = false;
|
|
tryGetArg(&isNextFall, getCurrentKeyPlacementInfo(mRollingCubePoseKeeper), "isNextFall");
|
|
|
|
return isNextFall;
|
|
}
|
|
|
|
void RollingCubeMapParts::exeWait() {}
|
|
|
|
void RollingCubeMapParts::exeStart() {
|
|
if (isGreaterEqualStep(this, 40))
|
|
setNerveNextMovement(isNextFallKey());
|
|
}
|
|
|
|
void RollingCubeMapParts::exeRotate() {
|
|
if (isFirstStep(this)) {
|
|
fittingToCurrentKeyBoundingBox(getQuatPtr(this), getTransPtr(this), mRollingCubePoseKeeper);
|
|
mCurrentPoseQuat = getQuat(this);
|
|
mCurrentPoseTrans = getTrans(this);
|
|
mMovementTime = getMovementTime() - 1;
|
|
}
|
|
|
|
calcCurrentKeyQT(getQuatPtr(this), getTransPtr(this), mRollingCubePoseKeeper, mCurrentPoseQuat,
|
|
mCurrentPoseTrans, calcNerveSquareInRate(this, mMovementTime));
|
|
|
|
if (isGreaterEqualStep(this, mMovementTime)) {
|
|
if (nextRollingCubeKey(mRollingCubePoseKeeper)) {
|
|
if (!isNextFallKey())
|
|
setNerveNextLand();
|
|
else if (isMovementCurrentKeyRotate(mRollingCubePoseKeeper))
|
|
startNerveAction(this, "Rotate");
|
|
else
|
|
startNerveAction(this, "Fall");
|
|
} else {
|
|
startNerveAction(this, "Stop");
|
|
}
|
|
}
|
|
}
|
|
|
|
s32 RollingCubeMapParts::getMovementTime() const {
|
|
s32 movementTime = 40;
|
|
tryGetArg(&movementTime, getCurrentKeyPlacementInfo(mRollingCubePoseKeeper), "MovementTime");
|
|
|
|
return movementTime;
|
|
}
|
|
|
|
void RollingCubeMapParts::setNerveNextLand() {
|
|
Axis axis = (Axis)sead::Mathi::abs(
|
|
(s32)calcNearVecFromAxis3(nullptr, sead::Vector3f::ey, getQuat(this)));
|
|
switch (axis) {
|
|
default:
|
|
return;
|
|
case Axis::X:
|
|
startNerveAction(this, "LandX");
|
|
|
|
return;
|
|
case Axis::Y:
|
|
startNerveAction(this, "LandY");
|
|
|
|
return;
|
|
case Axis::Z:
|
|
startNerveAction(this, "LandZ");
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
void RollingCubeMapParts::exeSlide() {
|
|
if (updateSlide()) {
|
|
if (nextRollingCubeKey(mRollingCubePoseKeeper)) {
|
|
if (!isNextFallKey())
|
|
setNerveNextLand();
|
|
else if (isMovementCurrentKeyRotate(mRollingCubePoseKeeper))
|
|
startNerveAction(this, "Rotate");
|
|
else
|
|
startNerveAction(this, "Fall");
|
|
} else {
|
|
startNerveAction(this, "Stop");
|
|
}
|
|
}
|
|
}
|
|
|
|
bool RollingCubeMapParts::updateSlide() {
|
|
if (isFirstStep(this)) {
|
|
fittingToCurrentKeyBoundingBox(getQuatPtr(this), getTransPtr(this), mRollingCubePoseKeeper);
|
|
mCurrentPoseQuat = getQuat(this);
|
|
mCurrentPoseTrans = getTrans(this);
|
|
mMovementTime = getMovementTime() - 1;
|
|
}
|
|
|
|
calcCurrentKeyQT(getQuatPtr(this), getTransPtr(this), mRollingCubePoseKeeper, mCurrentPoseQuat,
|
|
mCurrentPoseTrans, calcNerveSquareInRate(this, mMovementTime));
|
|
|
|
return isGreaterEqualStep(this, mMovementTime);
|
|
}
|
|
|
|
void RollingCubeMapParts::exeFall() {
|
|
if (updateSlide()) {
|
|
if (nextRollingCubeKey(mRollingCubePoseKeeper)) {
|
|
if (!isNextFallKey())
|
|
setNerveNextFallLand();
|
|
else if (isMovementCurrentKeyRotate(mRollingCubePoseKeeper))
|
|
startNerveAction(this, "Rotate");
|
|
else
|
|
startNerveAction(this, "Fall");
|
|
} else {
|
|
startNerveAction(this, "Stop");
|
|
}
|
|
}
|
|
}
|
|
|
|
void RollingCubeMapParts::setNerveNextFallLand() {
|
|
Axis axis = (Axis)sead::Mathi::abs(
|
|
(s32)calcNearVecFromAxis3(nullptr, sead::Vector3f::ey, getQuat(this)));
|
|
switch (axis) {
|
|
default:
|
|
return;
|
|
case Axis::X:
|
|
startNerveAction(this, "FallLandX");
|
|
|
|
return;
|
|
case Axis::Y:
|
|
startNerveAction(this, "FallLandY");
|
|
|
|
return;
|
|
case Axis::Z:
|
|
startNerveAction(this, "FallLandZ");
|
|
|
|
return;
|
|
}
|
|
}
|
|
|
|
void RollingCubeMapParts::exeLand() {
|
|
if (isGreaterEqualStep(this, getLandTime() - 1))
|
|
setNerveNextMovement(false);
|
|
}
|
|
|
|
s32 RollingCubeMapParts::getLandTime() const {
|
|
s32 landTime = 40;
|
|
tryGetArg(&landTime, getCurrentKeyPlacementInfo(mRollingCubePoseKeeper), "LandTime");
|
|
|
|
return landTime;
|
|
}
|
|
|
|
void RollingCubeMapParts::exeFallLand() {
|
|
if (isGreaterEqualStep(this, getLandTime()))
|
|
setNerveNextMovement(false);
|
|
}
|
|
|
|
void RollingCubeMapParts::exeStop() {
|
|
if (mIsStoppable) {
|
|
if (isFirstStep(this))
|
|
startHitReaction(this, "消滅");
|
|
|
|
if (isStep(this, 1)) {
|
|
setQuat(this, mInitialPoseQuat);
|
|
setTrans(this, mInitialPoseTrans);
|
|
resetPosition(this);
|
|
|
|
makeActorDead();
|
|
}
|
|
}
|
|
}
|
|
|
|
bool RollingCubeMapParts::isStop() const {
|
|
return isNerve(this, NrvRollingCubeMapParts.Stop.data());
|
|
}
|
|
} // namespace al
|