Merge branch 'master' into BlockQuestion2D

This commit is contained in:
guymakinggames 2026-04-23 06:38:23 +01:00 committed by GitHub
commit 90795457b1
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
87 changed files with 3002 additions and 361 deletions

View file

@ -67,7 +67,7 @@ jobs:
exit 1
fi
- name: Upload build artifact
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v7
with:
name: odyssey
path: build/odyssey

View file

@ -14,7 +14,7 @@ jobs:
if: github.event_name == 'pull_request_target' && github.event.action == 'opened'
steps:
- name: Label new PR as "status:waiting for review"
uses: actions/github-script@v8
uses: actions/github-script@v9
with:
script: |
github.rest.issues.addLabels({

View file

@ -15,7 +15,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Download artifact'
uses: actions/github-script@v8
uses: actions/github-script@v9
with:
script: |
let allArtifacts = await github.rest.actions.listWorkflowRunArtifacts({
@ -44,7 +44,7 @@ jobs:
run: unzip "${{ runner.temp }}/artifacts/review-event.zip" -d "${{ runner.temp }}/artifacts"
- name: Update status labels based on review
uses: actions/github-script@v8
uses: actions/github-script@v9
with:
script: |
const fs = require('fs');

View file

@ -13,7 +13,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Promote approved PRs to "ready to merge"
uses: actions/github-script@v8
uses: actions/github-script@v9
with:
script: |
const owner = context.repo.owner

File diff suppressed because it is too large Load diff

View file

@ -16,7 +16,7 @@ class AudioMic;
class SeKeeper;
class BgmKeeper;
class AudioKeeper : public IUseHioNode {
class AudioKeeper : public HioNode {
public:
AudioKeeper(const AudioDirector*);
virtual ~AudioKeeper();

View file

@ -4,6 +4,7 @@
namespace al {
class ByamlIter;
class CameraOffsetPreset;
class CameraOffsetCtrlPreset : public CameraOffsetCtrl {
public:
@ -11,5 +12,10 @@ public:
void load(const ByamlIter& iter) override;
f32 getOffset() const override;
private:
CameraOffsetPreset* mPreset;
};
static_assert(sizeof(CameraOffsetCtrlPreset) == 0x10);
} // namespace al

View file

@ -231,7 +231,7 @@ protected:
sead::Vector3f mTargetTrans = {0.0f, 0.0f, 500.0f};
sead::Vector3f mCameraUp = sead::Vector3f::ey;
f32 mFovyDegree = 35.0f;
f32 _64 = -1.0f;
f32 mNearClipDistance = -1.0f;
sead::Matrix34f mViewMtx = sead::Matrix34f::ident;
bool _98 = false;
CameraPoserSceneInfo* mSceneInfo = nullptr;

View file

@ -17,7 +17,11 @@ public:
void makeLookAtCamera(sead::LookAtCamera* lookAtCam) const override;
private:
char _140[24];
f32 mOffsetY;
sead::Vector3f mCameraPos;
bool mIsUsePrePoserPos;
bool mIsKeepDistanceFromLookAt;
f32 mKeepDistance;
};
static_assert(sizeof(CameraPoserFixPoint) == 0x158);

View file

@ -0,0 +1,245 @@
#include "Library/Clipping/FrustumRadar.h"
#include <math/seadMathCalcCommon.h>
#include "Library/Math/MathUtil.h"
#include "Library/Matrix/MatrixUtil.h"
namespace al {
FrustumRadar::FrustumRadar() = default;
void FrustumRadar::calcFrustumArea(const sead::Matrix34f& orthoMtx, f32 fovyAngle, f32 aspectRatio,
f32 near, f32 far) {
setLocalAxis(orthoMtx);
setFactor(fovyAngle, aspectRatio);
mNear = near;
mFar = far;
}
void FrustumRadar::setLocalAxis(const sead::Matrix34f& orthoMtx) {
sead::Matrix34f mtxInvertOrtho;
calcMxtInvertOrtho(&mtxInvertOrtho, orthoMtx);
mtxInvertOrtho.getBase(mOrthoSide, 0);
mtxInvertOrtho.getBase(mOrthoUp, 1);
mtxInvertOrtho.getBase(mOrthoFront, 2);
mOrthoFront.negate();
mtxInvertOrtho.getTranslation(mOrthoTrans);
mStereoEyeOffset = 0.0f;
}
void FrustumRadar::setFactor(f32 fovyAngle, f32 aspectRatio) {
mVerticalSlope = sead::Mathf::tan(sead::Mathf::deg2rad(fovyAngle * 0.5f));
mVerticalNormFactor = sead::Mathf::sqrt(mVerticalSlope * mVerticalSlope + 1.0f);
mHorizontalSlope = mVerticalSlope * aspectRatio;
mHorizontalNormFactor = sead::Mathf::sqrt(mHorizontalSlope * mHorizontalSlope + 1.0f);
}
void FrustumRadar::calcFrustumArea(const sead::Matrix34f& orthoMtx,
const sead::Matrix44f& projectionMtx, f32 near, f32 far) {
setLocalAxis(orthoMtx);
setFactor(projectionMtx);
mNear = near;
mFar = far;
}
void FrustumRadar::setFactor(const sead::Matrix44f& projectionMtx) {
mVerticalSlope = 1.0f / projectionMtx(1, 1);
mVerticalNormFactor = sead::Mathf::sqrt(mVerticalSlope * mVerticalSlope + 1.0f);
mHorizontalSlope = 1.0f / projectionMtx(0, 0);
mHorizontalNormFactor = sead::Mathf::sqrt(mHorizontalSlope * mHorizontalSlope + 1.0f);
}
void FrustumRadar::calcFrustumAreaStereo(const sead::Matrix34f& orthoMtxLeft,
const sead::Matrix34f& orthoMtxRight,
const sead::Matrix44f& projectionMtx, f32 near, f32 far) {
setLocalAxisStereo(orthoMtxLeft, orthoMtxRight);
setFactorStereo(projectionMtx);
mNear = near;
mFar = far;
}
void FrustumRadar::setLocalAxisStereo(const sead::Matrix34f& orthoMtxLeft,
const sead::Matrix34f& orthoMtxRight) {
sead::Matrix34f mtxInvertOrthoLeft;
sead::Matrix34f mtxInvertRight;
calcMxtInvertOrtho(&mtxInvertOrthoLeft, orthoMtxLeft);
mtxInvertOrthoLeft.getBase(mOrthoSide, 0);
mtxInvertOrthoLeft.getBase(mOrthoUp, 1);
mtxInvertOrthoLeft.getBase(mOrthoFront, 2);
mOrthoFront.negate();
calcMxtInvertOrtho(&mtxInvertRight, orthoMtxRight);
mOrthoTrans = (mtxInvertOrthoLeft.getTranslation() + mtxInvertRight.getTranslation()) * 0.5f;
mStereoEyeOffset = mOrthoSide.dot(mOrthoTrans - mtxInvertOrthoLeft.getTranslation());
}
void FrustumRadar::setFactorStereo(const sead::Matrix44f& projectionMtx) {
setFactor(projectionMtx);
f32 centerOffset = projectionMtx(0, 2);
mStereoSlopeLeft = mHorizontalSlope * (1.0f - centerOffset);
mStereoNormFactorLeft = sead::Mathf::sqrt(mStereoSlopeLeft * mStereoSlopeLeft + 1.0f);
mStereoSlopeRight = mHorizontalSlope * (1.0f + centerOffset);
mStereoNormFactorRight = sead::Mathf::sqrt(mStereoSlopeRight * mStereoSlopeRight + 1.0f);
}
bool FrustumRadar::judgeInLeft(const sead::Vector3f& pos, f32 radius) const {
f32 dotFront = mOrthoFront.dot(pos - mOrthoTrans);
f32 dotSide = mOrthoSide.dot(pos - mOrthoTrans);
return !(dotSide < -(dotFront * mHorizontalSlope + mHorizontalNormFactor * radius));
}
bool FrustumRadar::judgeInRight(const sead::Vector3f& pos, f32 radius) const {
f32 dotFront = mOrthoFront.dot(pos - mOrthoTrans);
f32 dotSide = mOrthoSide.dot(pos - mOrthoTrans);
return !(dotFront * mHorizontalSlope + mHorizontalNormFactor * radius < dotSide);
}
bool FrustumRadar::judgeInTop(const sead::Vector3f& pos, f32 radius) const {
f32 dotFront = mOrthoFront.dot(pos - mOrthoTrans);
f32 dotUp = mOrthoUp.dot(pos - mOrthoTrans);
return !(dotFront * mVerticalSlope + mVerticalNormFactor * radius < dotUp);
}
bool FrustumRadar::judgeInBottom(const sead::Vector3f& pos, f32 radius) const {
f32 dotFront = mOrthoFront.dot(pos - mOrthoTrans);
f32 dotUp = mOrthoUp.dot(pos - mOrthoTrans);
return !(dotUp < -(dotFront * mVerticalSlope + mVerticalNormFactor * radius));
}
bool FrustumRadar::judgeInArea(const sead::Vector3f& pos, f32 radius, f32 near, f32 far) const {
f32 dotFront = mOrthoFront.dot(pos - mOrthoTrans);
if (dotFront < near - radius)
return false;
if (far > 0.0f && radius + far < dotFront)
return false;
f32 dotUpAbs = sead::Mathf::abs(mOrthoUp.dot(pos - mOrthoTrans));
if (dotFront * mVerticalSlope + mVerticalNormFactor * radius < dotUpAbs)
return false;
f32 dotSide = mOrthoSide.dot(pos - mOrthoTrans);
if (isNearZero(mStereoEyeOffset)) {
if (dotFront * mHorizontalSlope + mHorizontalNormFactor * radius <
sead::Mathf::abs(dotSide))
return false;
} else {
f32 limitRight = dotFront * mStereoSlopeRight + mStereoNormFactorRight * radius;
f32 limitLeft = dotFront * mStereoSlopeLeft + mStereoNormFactorLeft * radius;
f32 relSideLeft = dotSide - mStereoEyeOffset;
f32 relSideRight = dotSide + mStereoEyeOffset;
if (relSideLeft > limitLeft && relSideRight > limitRight)
return false;
if (relSideLeft < -limitRight && relSideRight < -limitLeft)
return false;
}
return true;
}
bool FrustumRadar::judgeInArea(const sead::Vector3f& pos, f32 radius, f32 near) const {
return judgeInArea(pos, radius, near, mFar);
}
bool FrustumRadar::judgeInArea(const sead::Vector3f& pos, f32 radius) const {
return judgeInArea(pos, radius, mNear, mFar);
}
bool FrustumRadar::judgeInAreaNoFar(const sead::Vector3f& pos, f32 radius) const {
return judgeInArea(pos, radius, mNear, -1.0f);
}
FrustumRadar::PointFlag FrustumRadar::judgePointFlag(const sead::Vector3f& pos, f32 near,
f32 far) const {
u32 flag = PointFlag::None;
sead::Vector3f relPos = pos - mOrthoTrans;
f32 dotFront = mOrthoFront.dot(relPos);
if (dotFront < near)
flag |= PointFlag::Near;
if (far > 0.0f && dotFront > far)
flag |= PointFlag::Far;
f32 dotUp = mOrthoUp.dot(relPos);
if (dotUp < -(dotFront * mVerticalSlope))
flag |= PointFlag::Bottom;
if (dotFront * mVerticalSlope < dotUp)
flag |= PointFlag::Top;
f32 dotSide = mOrthoSide.dot(relPos);
if (isNearZero(mStereoEyeOffset)) {
if (dotSide < -(dotFront * mHorizontalSlope))
flag |= PointFlag::Left;
if (dotFront * mHorizontalSlope < dotSide)
flag |= PointFlag::Right;
return (PointFlag)flag;
}
f32 limitRight = dotFront * mStereoSlopeRight;
f32 limitLeft = dotFront * mStereoSlopeLeft;
f32 distSideLeftEye = dotSide - mStereoEyeOffset;
f32 distSideRightEye = dotSide + mStereoEyeOffset;
if (distSideLeftEye > limitLeft && distSideRightEye > limitRight)
flag |= PointFlag::Right;
if (distSideLeftEye < -limitRight && distSideRightEye < -limitLeft)
flag |= PointFlag::Left;
return (PointFlag)flag;
}
bool FrustumRadar::judgeInAreaObb(const sead::Matrix34f* mtx, const sead::BoundBox3f& boundBox,
f32 near, f32 far) const {
sead::Vector3f corners[8];
calcObbCorners(corners, *mtx, boundBox);
s32 mask = ~PointFlag::None;
for (s32 i = 0; i < 8; ++i) {
s32 pointFlags = judgePointFlag(corners[i], near, far);
if (pointFlags == PointFlag::None)
return true;
mask &= pointFlags;
}
return mask == PointFlag::None;
}
bool FrustumRadar::judgeInAreaObb(const sead::Matrix34f* mtx, const sead::BoundBox3f& boundBox,
f32 near) const {
return judgeInAreaObb(mtx, boundBox, near, mFar);
}
bool FrustumRadar::judgeInAreaObb(const sead::Matrix34f* mtx,
const sead::BoundBox3f& boundBox) const {
return judgeInAreaObb(mtx, boundBox, mNear, mFar);
}
bool FrustumRadar::judgeInAreaObbNoFar(const sead::Matrix34f* mtx,
const sead::BoundBox3f& boundBox) const {
return judgeInAreaObb(mtx, boundBox, mNear, -1.0f);
}
} // namespace al

View file

@ -3,34 +3,68 @@
#include <math/seadBoundBox.h>
#include <math/seadMatrix.h>
#include "Library/Matrix/MatrixUtil.h"
namespace al {
class FrustumRadar {
public:
enum PointFlag : u32 {
None = 0,
Near = 1,
Far = 2,
Bottom = 4,
Top = 8,
Left = 16,
Right = 32,
};
FrustumRadar();
void calcFrustumArea(const sead::Matrix34f&, f32, f32, f32, f32);
void setLocalAxis(const sead::Matrix34f&);
void setFactor(f32, f32);
void calcFrustumArea(const sead::Matrix34f&, const sead::Matrix44f&, f32, f32);
void setFactor(sead::Matrix44f);
void calcFrustumAreaStereo(const sead::Matrix34f&, const sead::Matrix34f&,
const sead::Matrix44f&, f32, f32);
void setLocalAxisStereo(const sead::Matrix34f&, const sead::Matrix34f&);
void setFactorStereo(const sead::Matrix44f&);
bool judgeInLeft(const sead::Vector3f&, f32) const;
bool judgeInRight(const sead::Vector3f&, f32) const;
bool judgeInTop(const sead::Vector3f&, f32) const;
bool judgeInBottom(const sead::Vector3f&, f32) const;
bool judgeInArea(const sead::Vector3f&, f32, f32, f32) const;
bool judgeInArea(const sead::Vector3f&, f32, f32) const;
bool judgeInAreaNoFar(const sead::Vector3f&, f32) const;
bool judgePointFlag(const sead::Vector3f&, f32, f32) const;
bool judgeInAreaObb(const sead::Matrix34f*, const sead::BoundBox3f&, f32, f32) const;
bool judgeInAreaObb(const sead::Matrix34f*, const sead::BoundBox3f&, f32) const;
bool judgeInAreaObbNoFar(const sead::Matrix34f*, const sead::BoundBox3f&) const;
void calcFrustumArea(const sead::Matrix34f& orthoMtx, f32 fovyAngle, f32 aspectRatio, f32 near,
f32 far);
void setLocalAxis(const sead::Matrix34f& orthoMtx);
void setFactor(f32 fovyAngle, f32 aspectRatio);
void calcFrustumArea(const sead::Matrix34f& orthoMtx, const sead::Matrix44f& projectionMtx,
f32 near, f32 far);
void setFactor(const sead::Matrix44f& projectionMtx);
void calcFrustumAreaStereo(const sead::Matrix34f& orthoMtxLeft,
const sead::Matrix34f& orthoMtxRight,
const sead::Matrix44f& projectionMtx, f32 near, f32 far);
void setLocalAxisStereo(const sead::Matrix34f& orthoMtxLeft,
const sead::Matrix34f& orthoMtxRight);
void setFactorStereo(const sead::Matrix44f& projectionMtx);
bool judgeInLeft(const sead::Vector3f& pos, f32 radius) const;
bool judgeInRight(const sead::Vector3f& pos, f32 radius) const;
bool judgeInTop(const sead::Vector3f& pos, f32 radius) const;
bool judgeInBottom(const sead::Vector3f& pos, f32 radius) const;
bool judgeInArea(const sead::Vector3f& pos, f32 radius, f32 near, f32 far) const;
bool judgeInArea(const sead::Vector3f& pos, f32 radius, f32 near) const;
bool judgeInArea(const sead::Vector3f& pos, f32 radius) const;
bool judgeInAreaNoFar(const sead::Vector3f& pos, f32 radius) const;
PointFlag judgePointFlag(const sead::Vector3f& pos, f32 near, f32 far) const;
bool judgeInAreaObb(const sead::Matrix34f* mtx, const sead::BoundBox3f& boundBox, f32 near,
f32 far) const;
bool judgeInAreaObb(const sead::Matrix34f* mtx, const sead::BoundBox3f& boundBox,
f32 near) const;
bool judgeInAreaObb(const sead::Matrix34f* mtx, const sead::BoundBox3f& boundBox) const;
bool judgeInAreaObbNoFar(const sead::Matrix34f* mtx, const sead::BoundBox3f& boundBox) const;
private:
unsigned char filler[0x5c];
sead::Vector3f mOrthoSide = sead::Vector3f::ex;
sead::Vector3f mOrthoUp = sead::Vector3f::ey;
sead::Vector3f mOrthoFront = sead::Vector3f::ez;
sead::Vector3f mOrthoTrans = sead::Vector3f::zero;
f32 mHorizontalSlope = 0.3f;
f32 mHorizontalNormFactor = 1.04403f;
f32 mVerticalSlope = 0.2f;
f32 mVerticalNormFactor = 1.0098f;
f32 mStereoEyeOffset = 0.0f;
f32 mStereoSlopeLeft = 0.3f;
f32 mStereoNormFactorLeft = 1.04403f;
f32 mStereoSlopeRight = 0.3f;
f32 mStereoNormFactorRight = 1.04403f;
f32 mNear = 100.0f;
f32 mFar = 10000.0f;
};
} // namespace al

View file

@ -45,7 +45,7 @@ public:
CollisionDirector* getCollisionDirector() const override;
sead::Vector3f* get_30() const { return _30; }
const sead::Vector3f* getActorGravityPtr() const { return mActorGravityPtr; }
f32 getRadius() { return mRadius; };
@ -55,9 +55,9 @@ public:
void setOffsetY(f32 offsetY) { mOffsetY = offsetY; };
s32 get_48() const { return _48; }
s32 getPlaneNum() const { return mPlaneNum; }
u32 getPlaneCount() const { return mPlaneCount; }
u32 getStoredPlaneNum() const { return mStoredPlaneNum; }
const sead::Vector3f& getFixReaction() const { return mFixReaction; }
@ -73,7 +73,7 @@ public:
f32 get_260() const { return _260; }
u32 get_264() const { return _264; }
u32 getNoGroundCounter() const { return mNoGroundCounter; }
void setReactMovePower(bool isEnabled) {
mFlag &= ~1;
@ -87,18 +87,18 @@ public:
bool isCollidedWallFace() { return mFlag >> 5 & 1; }
private:
CollisionDirector* _8;
TriangleFilterBase* _10;
CollisionPartsFilterBase* _18;
sead::Matrix34f* _20;
sead::Vector3f* _28;
sead::Vector3f* _30;
CollisionDirector* mCollisionDirector;
const TriangleFilterBase* mTriangleFilter;
const CollisionPartsFilterBase* mCollisionPartsFilter;
const sead::Matrix34f* mActorBaseMtxPtr;
const sead::Vector3f* mActorTransPtr;
const sead::Vector3f* mActorGravityPtr;
f32 mRadius;
f32 mOffsetY;
void* filler1;
u32 _48;
u32 mPlaneCount;
HitInfo* _50;
sead::Vector3f* _40;
u32 mPlaneNum;
u32 mStoredPlaneNum;
HitInfo* mPlanes;
sead::Vector3f mFixReaction;
sead::Vector3f _64;
HitInfo mFloorHit;
@ -109,12 +109,12 @@ private:
char filler4[0x4];
HitInfo mCeilingHit;
f32 _260;
u32 _264;
sead::Vector3f _268;
u32 mNoGroundCounter;
sead::Vector3f mRecentOnGroundNormal;
char _274;
char mFlag;
sead::Vector3f _278;
f32 _284;
sead::Vector3f mCurrentTrans;
f32 mCurrentRadius;
};
static_assert(sizeof(Collider) == 0x288);

View file

@ -9,6 +9,9 @@ class CameraTicket;
class LiveActor;
class EventFlowEventData;
class IUseCamera;
class EventFlowRequestInfo;
class EventFlowScareCtrlBase;
class BalloonOrderGroup;
class EventFlowDataHolder {
public:
@ -37,6 +40,24 @@ public:
void endAllEventCamera(IUseCamera*);
bool isEndInterpoleCamera(const IUseCamera*, const char*) const;
bool isPlayingEventAnimCamera(const char*) const;
private:
EventFlowRequestInfo* mRequestInfo;
void* filler_8[10];
void* _58;
void* filler_60[1];
EventFlowScareCtrlBase* mScareCtrl;
void* _70;
void* filler_78[2];
BalloonOrderGroup* mBalloonOrderGroup;
sead::WFixedSafeString<32> _90;
void* filler_e8[1];
const char* mTalkSubActorName;
s32 mItemTypeCapacity;
s32 mItemTypeCount;
const char** mItemTypes;
};
static_assert(sizeof(EventFlowDataHolder) == 0x108);
} // namespace al

View file

@ -6,6 +6,7 @@
#include "Library/HostIO/HioNode.h"
// BUG: outside of `al` namespace
class IJointController {
public:
virtual void calcJointCallback(s32, sead::Matrix34f*) = 0;

View file

@ -29,5 +29,15 @@ public:
s32 getGroupNum() const;
void calcAnim(bool);
void draw();
private:
CustomTagProcessor* mTagProcessor;
nn::ui2d::DrawInfo* mDrawInfo;
nn::ui2d::Layout* mLayout;
void* filler_18[2];
eui::Screen* mScreen;
void* filler_30;
};
static_assert(sizeof(LayoutKeeper) == 0x38);
} // namespace al

View file

@ -151,7 +151,7 @@ void PlaneParam::initialize(const sead::Vector3f& direction, ParameterObj* param
StringTmp<256> distance = {"%sDistance", planeName};
initializeDir(direction, parameterObj, normal.cstr(), "平面法線");
mDistanceFromOrigin = new ParameterF32(distance.cstr(), "原点からの距離",
mDistanceFromOrigin = new ParameterF32(0.0f, distance.cstr(), "原点からの距離",
"Min=-100000, Max=100000", parameterObj, true);
}
} // namespace al

View file

@ -117,7 +117,7 @@ void setSyncCollisionMtxPtr(LiveActor* actor, const sead::Matrix34f* mtx) {
bool isOnGround(const LiveActor* actor, u32 coyoteTime) {
Collider* collider = actor->getCollider();
if (!isCollidedGround(actor) && collider->get_264() > coyoteTime)
if (!isCollidedGround(actor) && collider->getNoGroundCounter() > coyoteTime)
return false;
return !(getVelocity(actor).dot(collider->getRecentOnGroundNormal(coyoteTime)) > 0.0f);
}
@ -137,15 +137,16 @@ bool isOnGroundNoVelocity(const LiveActor* actor, u32 coyoteTime) {
if (isCollidedGround(actor))
return true;
return actor->getCollider()->get_264() <= coyoteTime;
return actor->getCollider()->getNoGroundCounter() <= coyoteTime;
}
bool isOnGroundDegree(const LiveActor* actor, f32 angle, u32 coyoteTime) {
Collider* collider = actor->getCollider();
if (!(isCollidedGround(actor) || collider->get_264() <= coyoteTime))
if (!(isCollidedGround(actor) || collider->getNoGroundCounter() <= coyoteTime))
return false;
if (sead::Mathf::abs((*collider->get_30()).dot(collider->getRecentOnGroundNormal(coyoteTime))) <
if (sead::Mathf::abs(
(*collider->getActorGravityPtr()).dot(collider->getRecentOnGroundNormal(coyoteTime))) <
sead::Mathf::cos(sead::Mathf::deg2rad(angle)))
return false;
@ -161,10 +162,11 @@ bool isOnGroundNoVelocityDegree(const LiveActor* actor, f32 angle, u32 coyoteTim
if (!collider)
return getTrans(actor).y <= 0.0;
if (!(isCollidedGround(actor) || collider->get_264() <= coyoteTime))
if (!(isCollidedGround(actor) || collider->getNoGroundCounter() <= coyoteTime))
return false;
if (sead::Mathf::abs((*collider->get_30()).dot(collider->getRecentOnGroundNormal(coyoteTime))) <
if (sead::Mathf::abs(
(*collider->getActorGravityPtr()).dot(collider->getRecentOnGroundNormal(coyoteTime))) <
sead::Mathf::cos(sead::Mathf::deg2rad(angle)))
return false;
@ -451,7 +453,7 @@ bool isCollidedFloorCode(const LiveActor* actor, const char* name) {
bool isCollidedCollisionCode(const LiveActor* actor, const char* sensorName, const char* name) {
Collider* collider = actor->getCollider();
if (collider->get_48() == 0) {
if (collider->getPlaneNum() == 0) {
if (collider->get_110() >= 0.0f) {
if (isEqualString(name,
getCollisionCodeName(collider->getFloorHit().triangle, sensorName))) {
@ -473,7 +475,7 @@ bool isCollidedCollisionCode(const LiveActor* actor, const char* sensorName, con
return false;
}
u32 size = collider->getPlaneCount();
u32 size = collider->getStoredPlaneNum();
for (u32 i = 0; i < size; i++)
if (isEqualString(name, getCollisionCodeName(*collider->getPlane(i), sensorName)))
return true;

View file

@ -773,8 +773,8 @@ bool reboundVelocityFromCollision(LiveActor* actor, f32 reboundStrength, f32 reb
bool reboundVelocityFromTriangles(LiveActor* actor, f32 reboundStrength, f32 reboundMin) {
Collider* collider = getActorCollider(actor);
s32 planeCount = collider->getPlaneCount();
if (collider->get_48() == 0)
s32 planeCount = collider->getStoredPlaneNum();
if (collider->getPlaneNum() == 0)
return false;
bool isRebound = false;

View file

@ -250,7 +250,7 @@ void ClockMapParts::exeRotate() {
mTimer++;
if (mTimer >= mRotateTimer) {
mCurrentStep = modi(mCurrentStep + mTurnStepCount + 1, mTurnStepCount);
mCurrentStep = wrapValue(mCurrentStep + 1, mTurnStepCount);
startNerveAction(this, "Wait");
tryStartSe(this, "RotateEnd");
}

View file

@ -205,6 +205,10 @@ void makeBoxMullerRandomGauss(sead::Vector2f* outBox, f32 randA, f32 randB);
f32 modf(f32 a, f32 b);
s32 modi(s32 a, s32 b);
inline s32 wrapValue(s32 value, s32 maxRange) {
return modi(value + maxRange, maxRange);
}
inline f32 wrapValue(f32 value, f32 maxRange) {
return modf(value + maxRange, maxRange) + 0.0f;
}

View file

@ -0,0 +1,101 @@
#include "Library/Movement/ClockMovement.h"
#include "Library/Math/MathUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "Library/Placement/PlacementFunction.h"
namespace {
using namespace al;
NERVE_IMPL(ClockMovement, Delay);
NERVE_IMPL(ClockMovement, RotateSign);
NERVE_IMPL(ClockMovement, Rotate);
NERVE_IMPL(ClockMovement, Wait);
NERVES_MAKE_STRUCT(ClockMovement, Delay, RotateSign, Rotate);
NERVES_MAKE_NOSTRUCT(ClockMovement, Wait);
} // namespace
namespace al {
ClockMovement::ClockMovement(const ActorInitInfo& info) : NerveExecutor("クロックパーツ動作") {
getQuat(&mInitialQuat, info);
mCurrentQuat = mInitialQuat;
tryGetArg(&mClockAngleDegree, info, "ClockAngleDegree");
tryGetArg(&mRotateAxis, info, "RotateAxis");
tryGetArg(&mDelayTime, info, "DelayTime");
tryGetArg(&mRotateSignTime, info, "RotateSignTime");
tryGetArg(&mRotateTime, info, "RotateTime");
tryGetArg(&mWaitTime, info, "WaitTime");
if (mDelayTime == 0)
initNerve(&NrvClockMovement.RotateSign, 0);
else
initNerve(&NrvClockMovement.Delay, 0);
s32 stepsPerCycle = 1;
if (mClockAngleDegree != 0) {
stepsPerCycle = sead::Mathi::lcm(sead::Mathi::abs(mClockAngleDegree), 360) /
sead::Mathi::abs(mClockAngleDegree);
}
mMaxStepIndex = stepsPerCycle;
}
void ClockMovement::exeDelay() {
if (isGreaterEqualStep(this, mDelayTime - 1)) {
if (mRotateSignTime > 0)
setNerve(this, &NrvClockMovement.RotateSign);
else
setNerve(this, &NrvClockMovement.Rotate);
}
}
void ClockMovement::exeRotateSign() {
f32 rotateAngle = wrapValue(static_cast<f32>(mCurrentStepIndex * mClockAngleDegree), 360.0f);
rotateQuatLocalDirDegree(&mCurrentQuat, mInitialQuat, mRotateAxis,
rotateAngle +
sead::Mathf::sin(getNerveStep(this) * sead::Mathf::pi2() / 18.0f));
if (isGreaterEqualStep(this, mRotateSignTime - 1))
setNerve(this, &NrvClockMovement.Rotate);
}
void ClockMovement::exeRotate() {
f32 rotateAngle = wrapValue(
(calcNerveRate(this, mRotateTime) + mCurrentStepIndex) * mClockAngleDegree, 360.0f);
rotateQuatLocalDirDegree(&mCurrentQuat, mInitialQuat, mRotateAxis, rotateAngle);
if (isGreaterEqualStep(this, mRotateTime)) {
mCurrentStepIndex = wrapValue(mCurrentStepIndex + 1, mMaxStepIndex);
setNerve(this, &Wait);
}
}
void ClockMovement::exeWait() {
if (isGreaterEqualStep(this, mWaitTime)) {
if (mRotateSignTime > 0)
setNerve(this, &NrvClockMovement.RotateSign);
else
setNerve(this, &NrvClockMovement.Rotate);
}
}
bool ClockMovement::isFirstStepDelay() const {
return isNerve(this, &NrvClockMovement.Delay) && isFirstStep(this);
}
bool ClockMovement::isFirstStepRotateSign() const {
return isNerve(this, &NrvClockMovement.RotateSign) && isFirstStep(this);
}
bool ClockMovement::isFirstStepRotate() const {
return isNerve(this, &NrvClockMovement.Rotate) && isFirstStep(this);
}
bool ClockMovement::isFirstStepWait() const {
return isNerve(this, &Wait) && isFirstStep(this);
}
} // namespace al

View file

@ -0,0 +1,36 @@
#pragma once
#include <math/seadQuat.h>
#include "Library/Nerve/NerveExecutor.h"
namespace al {
struct ActorInitInfo;
class ClockMovement : public NerveExecutor {
public:
ClockMovement(const ActorInitInfo& info);
void exeDelay();
void exeRotateSign();
void exeRotate();
void exeWait();
bool isFirstStepDelay() const;
bool isFirstStepRotateSign() const;
bool isFirstStepRotate() const;
bool isFirstStepWait() const;
private:
sead::Quatf mCurrentQuat = sead::Quatf::unit;
sead::Quatf mInitialQuat = sead::Quatf::unit;
s32 mRotateAxis = 0;
s32 mClockAngleDegree = 90;
s32 mCurrentStepIndex = 0;
s32 mMaxStepIndex = 4;
s32 mDelayTime = 0;
s32 mRotateSignTime = 36;
s32 mRotateTime = 60;
s32 mWaitTime = 0;
};
static_assert(sizeof(ClockMovement) == 0x50);
} // namespace al

View file

@ -59,7 +59,7 @@ void SwingMovement::exeMove() {
if (updateRotate())
setNerve(this, &Stop);
mFrameInCycle = modi((mFrameInCycle + 1) + mSwingCycle, mSwingCycle);
mFrameInCycle = wrapValue(mFrameInCycle + 1, mSwingCycle);
}
void SwingMovement::exeStop() {

View file

@ -14,6 +14,7 @@ public:
private:
bool mIsAlive = true;
bool mIsKillIfEnter = false;
f32* mAngleH = nullptr;
f32* mAngleV = nullptr;
};

View file

@ -323,11 +323,8 @@ s32 getNextRailPointNo(const IUseRail* railHolder) {
s32 newIndex = getRailPointNo(railHolder) + modifier;
s32 railPointNum = getRailPointNum(railHolder);
if (isLoop) {
s32 sum = railPointNum + newIndex;
s32 railPointNumAgain = getRailPointNum(railHolder);
return modi(sum + railPointNumAgain, railPointNumAgain);
}
if (isLoop)
return wrapValue(railPointNum + newIndex, getRailPointNum(railHolder));
return sead::Mathi::clamp2(0, newIndex, railPointNum - 1);
}

View file

@ -24,7 +24,7 @@ ScreenPointKeeper::ScreenPointKeeper() {
mOptions = new ParameterObj();
mAddTargetNum =
new ParameterS32("AddTargetNum", "AddTargetNum", "Min=0, Max=10", mOptions, true);
new ParameterS32(0, "AddTargetNum", "AddTargetNum", "Min=0, Max=10", mOptions, true);
mParameterIo->addObj(mOptions, "Options");
mParameterIo->addArray(mTargets, "Targets");

View file

@ -54,5 +54,10 @@ public:
void setEmitterPoseMtxPtr(const sead::Matrix34f*, const char*);
void setEmitterPosePosPtr(const sead::Vector3f*, const char*);
void loadSe(IAudioResourceLoader*);
private:
void* _0[0x78 / 8];
};
static_assert(sizeof(SeKeeper) == 0x78);
} // namespace al

View file

@ -26,6 +26,8 @@ public:
virtual void drawMain() const;
virtual void drawSub() const;
AudioKeeper* getAudioKeeper() const override { return mAudioKeeper; }
virtual bool isDisposable() const;
virtual Scene* getCurrentScene() const { return nullptr; }
@ -34,8 +36,6 @@ public:
void setSceneCreator(SceneCreator* sceneCreator) override { mSceneCreator = sceneCreator; }
AudioKeeper* getAudioKeeper() const override { return mAudioKeeper; }
void initAudio(const GameSystemInfo&, const char*, s32, s32, s32, const char*);
void initAudioKeeper(const char*);
void initDrawSystemInfo(const SequenceInitInfo&);

View file

@ -40,19 +40,11 @@ SEAD_ENUM(YamlParamType,
#define PARAM_TYPE_DEF(Name, Type) \
class Parameter##Name : public Parameter<Type> { \
public: \
Parameter##Name(const sead::SafeString& name, const sead::SafeString& label, \
const sead::SafeString& meta, ParameterObj* obj, bool e) \
: Parameter(name, label, meta, obj, e) {} \
\
Parameter##Name(Type const& value, const sead::SafeString& name, \
const sead::SafeString& label, const sead::SafeString& meta, \
ParameterObj* obj, bool e) \
: Parameter(value, name, label, meta, obj, e) {} \
\
Parameter##Name(const sead::SafeString& name, const sead::SafeString& label, \
const sead::SafeString& meta, ParameterList* list, bool e) \
: Parameter(name, label, meta, list, e) {} \
\
Parameter##Name(Type const& value, const sead::SafeString& name, \
const sead::SafeString& label, const sead::SafeString& meta, \
ParameterList* list, bool e) \
@ -71,9 +63,9 @@ class ParameterBase {
public:
static u32 calcHash(const sead::SafeString& key);
// TODO: rename parameter bool e in all functions
ParameterBase(bool e) { initialize("default", "parameter", "", e); }
ParameterBase() { initialize("default", "parameter", "", true); }
// TODO: rename parameter bool e in all functions
ParameterBase(const sead::SafeString& name, const sead::SafeString& label,
const sead::SafeString& meta, ParameterObj* obj, bool e);
@ -139,39 +131,42 @@ template <typename T>
class Parameter : public ParameterBase {
public:
// TODO: rename parameter bool e in constructor
Parameter(const sead::SafeString& name, const sead::SafeString& label,
const sead::SafeString& meta, ParameterObj* obj, bool e)
: ParameterBase(e) {
Parameter(const T& value, const sead::SafeString& name, const sead::SafeString& label,
const sead::SafeString& meta, ParameterObj* obj, bool e) {
initializeListNode(name, label, meta, obj, e);
mValue = T();
setValue(value);
}
Parameter(const T& value, const sead::SafeString& name, const sead::SafeString& label,
const sead::SafeString& meta, ParameterObj* obj, bool e)
: ParameterBase(e) {
initializeListNode(name, label, meta, obj, e);
mValue = value;
}
Parameter(const sead::SafeString& name, const sead::SafeString& label,
const sead::SafeString& meta, ParameterList* list, bool e)
: ParameterBase(e) {
const sead::SafeString& meta, ParameterList* list, bool e) {
initializeListNode(name, label, meta, list, e);
mValue = T();
}
Parameter(const T& value, const sead::SafeString& name, const sead::SafeString& label,
const sead::SafeString& meta, ParameterList* list, bool e)
: ParameterBase(e) {
initializeListNode(name, label, meta, list, e);
mValue = value;
setValue(value);
}
const void* ptr() const override { return &mValue; };
void* ptr() override { return &mValue; };
s32 size() const override { return sizeof(T); }
s32 size() const override {
// BUG: sead::FixedSafeString<128> is excluded from this list
if constexpr (std::is_same<T, sead::FixedSafeString<32>>())
return 32;
else if constexpr (std::is_same<T, sead::FixedSafeString<64>>())
return 64;
else if constexpr (std::is_same<T, sead::FixedSafeString<256>>())
return 256;
// NOTE: from 512 onwards, no examples exist in the binary
else if constexpr (std::is_same<T, sead::FixedSafeString<512>>())
return 512;
else if constexpr (std::is_same<T, sead::FixedSafeString<1024>>())
return 1024;
else if constexpr (std::is_same<T, sead::FixedSafeString<2048>>())
return 2048;
else if constexpr (std::is_same<T, sead::FixedSafeString<4096>>())
return 4096;
else
return sizeof(T);
}
const char* getParamTypeStr() const override {
return YamlParamType::text(YamlParamType::Invalid);

View file

@ -23,5 +23,32 @@ public:
bool receiveRequestFromObject(const CameraObjectRequestInfo& info);
void setAngleV(f32 angleV);
private:
void* _0; // object of size 0x14
void* _8; // object of size 0x10
bool mIsValidRotateH;
s32 _14;
f32 _18;
f32 _1c;
f32 mMinAngleH;
f32 mMaxAngleH;
f32 _28;
f32 mAngleV;
f32 _30;
f32 mMinAngleV;
f32 mMaxAngleV;
f32 _3c;
f32 _40;
f32 _44;
f32 _48;
f32 _4c;
bool mIsKeepPreAngleV;
bool mIsSetResetAngleV;
f32 mResetAngleV;
bool mIsInvalidReceiveRequest;
};
static_assert(sizeof(CameraAngleCtrlInfo) == 0x60);
} // namespace al

View file

@ -17,8 +17,7 @@ void FlowMapCtrl::update() {
flowParameters.y =
calcRate01(halfInterval - sead::Mathi::abs(halfInterval - mFlowStep), 0.0f, halfInterval);
flowParameters.z = calcRate01(mFlowStep, 0.0f, mInterval);
flowParameters.w =
calcRate01(modi(mFlowStep + halfInterval + mInterval, mInterval), 0.0f, mInterval);
flowParameters.w = calcRate01(wrapValue(mFlowStep + halfInterval, mInterval), 0.0f, mInterval);
s32 materialCount = getMaterialCount(mParent);
for (s32 i = 0; i < materialCount; i++) {
@ -27,7 +26,7 @@ void FlowMapCtrl::update() {
}
mFlowStep++;
mFlowStep = modi(mFlowStep + mInterval, mInterval);
mFlowStep = wrapValue(mFlowStep, mInterval);
}
} // namespace al

View file

@ -0,0 +1,48 @@
#pragma once
#include <basis/seadTypes.h>
#include <math/seadQuat.h>
#include <math/seadVector.h>
#include "Library/Scene/ISceneObj.h"
#include "Scene/SceneObjFactory.h"
namespace al {
class LiveActor;
}
class KoopaHackStopCtrl : public al::ISceneObj {
public:
static constexpr s32 sSceneObjId = SceneObjID_KoopaStopHackCtrl;
KoopaHackStopCtrl();
const char* getSceneObjName() const override { return "崩落クッパの停止制御"; }
void startStop(const al::LiveActor* actor);
void endStop(const al::LiveActor* actor);
void resetPosture(const al::LiveActor* actor, const sead::Quatf& quat,
const sead::Vector3f& trans);
bool tryResetPosture(al::LiveActor* actor);
private:
const al::LiveActor* mStopActor = nullptr;
bool mIsNeedResetPosture = false;
sead::Quatf mResetQuat = sead::Quatf::unit;
sead::Vector3f mResetTrans = sead::Vector3f::zero;
bool mIsStatusDemoForSceneKoopaHack = false;
};
static_assert(sizeof(KoopaHackStopCtrl) == 0x38, "KoopaHackStopCtrl");
namespace KoopaHackFunction {
void startStopKoopaHack(al::LiveActor* actor);
void endStopKoopaHack(al::LiveActor* actor);
void resetPostureKoopaHack(al::LiveActor* actor, const sead::Quatf& quat,
const sead::Vector3f& trans);
bool isStopKoopaHack(const al::LiveActor* actor);
bool isStatusDemoForSceneKoopaHack(const al::LiveActor* actor);
void setStatusDemoForSceneKoopaHack(const al::LiveActor* actor);
void resetStatusDemoForSceneKoopaHack(const al::LiveActor* actor);
} // namespace KoopaHackFunction

View file

@ -0,0 +1,120 @@
#include "Boss/Koopa/KoopaLandPointHolder.h"
#include "Library/Math/MathUtil.h"
#include "Library/Placement/PlacementFunction.h"
#include "Library/Placement/PlacementInfo.h"
KoopaLandPointHolder::KoopaLandPointHolder(const al::ActorInitInfo& initInfo) {
al::getTrans(&mTrans, initInfo);
al::getQuat(&mQuat, initInfo);
mLandPoints = al::calcLinkChildNum(initInfo, "LandPoint");
if (mLandPoints <= 0)
return;
mPointsQuat = new sead::Quatf[mLandPoints];
mPointsTrans = new sead::Vector3f[mLandPoints];
mInvalidPoints = new bool[mLandPoints];
for (s32 i = 0; i < mLandPoints; i++) {
mInvalidPoints[i] = false;
al::PlacementInfo placementInfo;
al::getLinksInfoByIndex(&placementInfo, initInfo, "LandPoint", i);
al::getQuat(&mPointsQuat[i], placementInfo);
al::getTrans(&mPointsTrans[i], placementInfo);
}
}
inline f32 getKoopaLandPointDistance(const sead::Vector3f& posA, const sead::Vector3f& posB) {
sead::Vector3f distance = posA - posB;
return sead::Mathf::sqrt(distance.x * distance.x + distance.z * distance.z);
}
void KoopaLandPointHolder::decidePointFarFrom(const sead::Vector3f& pos) {
s32 selectedPoint = -1;
f32 maxDistance = 0.0f;
for (s32 i = 0; i < mLandPoints; i++) {
if (mInvalidPoints[i])
continue;
f32 dist = getKoopaLandPointDistance(mPointsTrans[i], pos);
if (selectedPoint < 0 || maxDistance < dist) {
selectedPoint = i;
maxDistance = dist;
}
}
invalidatePoint(selectedPoint);
mCurrentLandPoint = selectedPoint;
}
void KoopaLandPointHolder::invalidatePoint(s32 index) {
mInvalidPoints[index] = true;
if (mCurrentLandPoint > -1)
mInvalidPoints[mCurrentLandPoint] = false;
}
void KoopaLandPointHolder::decidePointEitherFarSide(const sead::Vector3f& pos) {
if (mCurrentLandPoint < 0) {
decidePointFarFrom(pos);
return;
}
mInvalidPoints[mCurrentLandPoint] = false;
s32 prevPoint = al::wrapValue(mCurrentLandPoint - 1, mLandPoints);
s32 nextPoint = al::wrapValue(mCurrentLandPoint + 1, mLandPoints);
f32 prevDist = getKoopaLandPointDistance(mPointsTrans[prevPoint], pos);
f32 nextDist = getKoopaLandPointDistance(mPointsTrans[nextPoint], pos);
if (prevDist < nextDist)
mCurrentLandPoint = nextPoint;
else
mCurrentLandPoint = prevPoint;
}
void KoopaLandPointHolder::decidePointNearFrom(const sead::Vector3f& pos) {
s32 selectedPoint = -1;
f32 minDistance = 0.0f;
for (s32 i = 0; i < mLandPoints; i++) {
if (mInvalidPoints[i])
continue;
f32 dist = getKoopaLandPointDistance(mPointsTrans[i], pos);
if (selectedPoint < 0 || dist < minDistance) {
selectedPoint = i;
minDistance = dist;
}
}
invalidatePoint(selectedPoint);
mCurrentLandPoint = selectedPoint;
}
void KoopaLandPointHolder::reset() {
for (s32 i = 0; i < mLandPoints; i++)
mInvalidPoints[i] = false;
}
// NOTE: does not care about `mInvalidPoints`
const sead::Vector3f& KoopaLandPointHolder::findNearestPointTrans(const sead::Vector3f& pos) const {
f32 minDistance = getKoopaLandPointDistance(mPointsTrans[0], pos);
s32 selectedPoint = 0;
for (s32 i = 1; i < mLandPoints; i++) {
f32 dist = getKoopaLandPointDistance(mPointsTrans[i], pos);
if (dist < minDistance) {
selectedPoint = i;
minDistance = dist;
}
}
return mPointsTrans[selectedPoint];
}

View file

@ -0,0 +1,32 @@
#pragma once
#include <basis/seadTypes.h>
#include <math/seadQuat.h>
#include <math/seadVector.h>
namespace al {
struct ActorInitInfo;
} // namespace al
class KoopaLandPointHolder {
public:
KoopaLandPointHolder(const al::ActorInitInfo& initInfo);
void decidePointFarFrom(const sead::Vector3f& pos);
void invalidatePoint(s32 index);
void decidePointEitherFarSide(const sead::Vector3f& pos);
void decidePointNearFrom(const sead::Vector3f& pos);
void reset();
const sead::Vector3f& findNearestPointTrans(const sead::Vector3f& pos) const;
private:
sead::Vector3f mTrans = {0.0f, 0.0f, 0.0f};
sead::Quatf mQuat = sead::Quatf::unit;
s32 mCurrentLandPoint = -1;
s32 mLandPoints = 0;
sead::Quatf* mPointsQuat = nullptr;
sead::Vector3f* mPointsTrans = nullptr;
bool* mInvalidPoints = nullptr;
};
static_assert(sizeof(KoopaLandPointHolder) == 0x40);

41
src/Enemy/Bros.cpp Normal file
View file

@ -0,0 +1,41 @@
#include "Enemy/Bros.h"
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorClippingFunction.h"
#include "Library/LiveActor/ActorFlagFunction.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/Math/MathUtil.h"
BrosWeaponBase::BrosWeaponBase(const char* name, const al::LiveActor* bros)
: al::LiveActor(name), mBros(bros) {}
void BrosWeaponBase::attach(const sead::Matrix34f* poseMtx, const sead::Vector3f& trans,
const sead::Vector3f& rotation, const char* actionName) {
mPoseMtx = poseMtx;
mTrans.set(trans);
mRotation.set(rotation);
sead::Matrix34f attachMtx;
calcAttachMtx(&attachMtx, poseMtx, trans, rotation);
al::updatePoseMtx(this, &attachMtx);
al::invalidateClipping(this);
al::offCollide(this);
if (actionName)
al::startAction(this, actionName);
appear();
}
void BrosWeaponBase::calcAttachMtx(sead::Matrix34f* attachMtx, const sead::Matrix34f* poseMtx,
const sead::Vector3f& trans, const sead::Vector3f& rotation) {
sead::Matrix34f translationMatrix;
translationMatrix.makeRT(sead::Vector3f::zero, trans);
sead::Matrix34f rotationMatrix;
rotationMatrix.makeRT(rotation, sead::Vector3f::zero);
sead::Matrix34f mtxRT = rotationMatrix * translationMatrix;
sead::Matrix34f poseMtxNorm = *poseMtx;
al::normalize(&poseMtxNorm);
attachMtx->setMul(poseMtxNorm, mtxRT);
}

43
src/Enemy/Bros.h Normal file
View file

@ -0,0 +1,43 @@
#pragma once
#include <basis/seadTypes.h>
#include <math/seadMatrix.h>
#include <math/seadVector.h>
#include "Library/LiveActor/LiveActor.h"
class BrosWeaponBase : public al::LiveActor {
public:
BrosWeaponBase(const char* name, const al::LiveActor* bros);
// TODO: Find what unknown does
virtual void shoot(const sead::Vector3f& trans, const sead::Quatf& quat,
const sead::Vector3f& force, bool isHack, s32 unknown, bool isFast) = 0;
virtual void killCollide(al::HitSensor* sensor, const sead::Vector3f& trans, bool isHack) = 0;
virtual void killEnemy() = 0;
virtual void attach(const sead::Matrix34f* poseMtx, const sead::Vector3f& trans,
const sead::Vector3f& rotation, const char* actionName);
void calcAttachMtx(sead::Matrix34f* attachMtx, const sead::Matrix34f* poseMtx,
const sead::Vector3f& trans, const sead::Vector3f& rotation);
virtual u32 getBreakStep() const { return 0; }
virtual bool isBreak() const { return false; }
const sead::Matrix34f* getPoseMtx() const { return mPoseMtx; }
const sead::Vector3f& getTrans() const { return mTrans; }
const sead::Vector3f& getRotation() const { return mRotation; }
const LiveActor* getBrosActor() const { return mBros; }
private:
const sead::Matrix34f* mPoseMtx = nullptr;
sead::Vector3f mTrans = sead::Vector3f::zero;
sead::Vector3f mRotation = sead::Vector3f::zero;
const al::LiveActor* mBros;
};
static_assert(sizeof(BrosWeaponBase) == 0x130);

View file

@ -638,7 +638,8 @@ void Bubble::control() {
if (!al::isNerve(this, &NrvBubble.StandBy) && !al::isNerve(this, &NrvBubble.Delay) &&
(!isHack() || !rs::isActiveHackStartDemo(mPlayerHack)) &&
!al::isClipped(mClippingProbeActor) && !mIsClipped) {
mReviveDelayCount = al::modi(mReviveDelayCount + 1 + mReviveDelayTime, mReviveDelayTime);
mReviveDelayCount =
al::wrapValue(static_cast<s32>(mReviveDelayCount + 1), mReviveDelayTime);
}
mIsClipped = al::isClipped(mClippingProbeActor);

174
src/Enemy/DonkeyKong2D.cpp Normal file
View file

@ -0,0 +1,174 @@
#include "Enemy/DonkeyKong2D.h"
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorClippingFunction.h"
#include "Library/LiveActor/ActorFlagFunction.h"
#include "Library/LiveActor/ActorInitInfo.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/LiveActor/ActorMovementFunction.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/LiveActor/ActorSensorUtil.h"
#include "Library/LiveActor/LiveActorGroup.h"
#include "Library/Math/MathUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "Library/Placement/PlacementFunction.h"
#include "Library/Stage/StageSwitchUtil.h"
#include "MapObj/Barrel2D.h"
#include "MapObj/BarrelStack2D.h"
#include "Util/ActorDimensionUtil.h"
#include "Util/SensorMsgFunction.h"
namespace {
NERVE_IMPL(DonkeyKong2D, Wait);
NERVE_IMPL(DonkeyKong2D, Down);
NERVE_IMPL(DonkeyKong2D, Damage);
NERVE_IMPL(DonkeyKong2D, Throw);
NERVES_MAKE_STRUCT(DonkeyKong2D, Down, Damage);
NERVES_MAKE_NOSTRUCT(DonkeyKong2D, Wait, Throw);
} // namespace
static const sead::Vector3f sThrowOffset = {0.0f, 0.0f, -320.0f};
DonkeyKong2D::DonkeyKong2D(const char* name) : al::LiveActor(name) {}
void DonkeyKong2D::init(const al::ActorInitInfo& info) {
al::initActor(this, info);
al::initNerve(this, &Wait, 0);
rs::createAndSetFilter2DOnly(this);
mDimensionKeeper = rs::createDimensionKeeper(this);
rs::updateDimensionKeeper(mDimensionKeeper);
if (!rs::isIn2DArea(this)) {
makeActorDead();
return;
}
rs::snap2D(this, this, 500.0f);
al::tryGetArg(&mWaitStep, info, "WaitStep");
al::tryGetArg(&mMoveSpeed, info, "MoveSpeed");
s32 barrelNum = 3;
al::tryGetArg(&barrelNum, info, "BarrelNum");
if (al::calcLinkChildNum(info, "BarrelStack") == 1) {
mBarrelStack = new BarrelStack2D("積まれたタル2D");
al::initLinksActor(mBarrelStack, info, "BarrelStack", 0);
}
al::DeriveActorGroup<Barrel2D>* barrelGroup =
new al::DeriveActorGroup<Barrel2D>("樽グループ", barrelNum);
mBarrelGroup = barrelGroup;
for (s32 i = 0; i < barrelGroup->getMaxActorCount(); i++) {
Barrel2D* barrel = new Barrel2D("樽2D");
al::initCreateActorWithPlacementInfo(barrel, info);
barrelGroup->registerActor(barrel);
}
mBarrelGroup->makeActorDeadAll();
al::onCollide(this);
makeActorAlive();
}
void DonkeyKong2D::attackSensor(al::HitSensor* self, al::HitSensor* other) {
if (!al::isNerve(this, &NrvDonkeyKong2D.Down) && al::isSensorEnemyAttack(self))
rs::sendMsgEnemyAttack2D(other, self) || rs::sendMsgPush2D(other, self);
}
bool DonkeyKong2D::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) {
if (al::isMsgPlayerDisregard(message))
return true;
if (al::isNerve(this, &NrvDonkeyKong2D.Down))
return false;
if (al::isNerve(this, &NrvDonkeyKong2D.Damage) && al::isLessEqualStep(this, 10))
return false;
if (rs::isMsgBlockUpperPunch2D(message)) {
mHitsTaken++;
rs::requestHitReactionToAttacker(message, self, other);
if (mHitsTaken >= 4) {
al::startHitReaction(this, "ダウン");
al::setNerve(this, &NrvDonkeyKong2D.Down);
} else {
al::startHitReaction(this, "ダメージ");
al::setNerve(this, &NrvDonkeyKong2D.Damage);
}
return true;
}
return false;
}
void DonkeyKong2D::exeWait() {
if (al::isFirstStep(this)) {
al::startAction(this, "Wait");
al::validateClipping(this);
}
if (al::isGreaterEqualStep(this, mWaitStep)) {
mHeldBarrel = mBarrelGroup->tryFindDeadDeriveActor();
if (mHeldBarrel)
al::setNerve(this, &Throw);
}
}
void DonkeyKong2D::exeThrow() {
if (al::isFirstStep(this)) {
al::startAction(this, "Throw");
al::invalidateClipping(this);
}
if (mHeldBarrel && al::isGreaterEqualStep(this, 59)) {
sead::Vector3f trans;
al::calcTransLocalOffset(&trans, this, sThrowOffset);
sead::Quatf quat = al::getQuat(this);
al::rotateQuatYDirDegree(&quat, quat, 180.0f);
mHeldBarrel->appearByGenerator(trans, quat, mMoveSpeed);
mHeldBarrel->startMove();
mHeldBarrel = nullptr;
}
if (al::isActionEnd(this))
al::setNerve(this, &Wait);
}
void DonkeyKong2D::exeDamage() {
if (al::isFirstStep(this))
al::startAction(this, "Damage");
if (al::isActionEnd(this))
al::setNerve(this, &Wait);
}
void DonkeyKong2D::exeDown() {
sead::Vector3f gravity;
rs::calcDimensionGravity(&gravity, this, al::getGravity(this));
if (al::isStep(this, 1)) {
al::startAction(this, "Down");
al::tryOnSwitchDeadOn(this);
al::offCollide(this);
al::invalidateClipping(this);
al::setVelocityToDirection(this, -gravity, 36.0f);
if (mBarrelStack)
mBarrelStack->doBreak();
}
if (al::isGreaterStep(this, 1)) {
al::addVelocityToDirection(this, gravity, 1.3f);
al::scaleVelocity(this, 0.98f);
}
if (al::isStep(this, 20))
al::startHitReaction(this, "落下開始");
if (al::isGreaterEqualStep(this, 270))
kill();
}

44
src/Enemy/DonkeyKong2D.h Normal file
View file

@ -0,0 +1,44 @@
#pragma once
#include <basis/seadTypes.h>
#include "Library/LiveActor/LiveActor.h"
#include "Util/IUseDimension.h"
namespace al {
struct ActorInitInfo;
template <typename T>
class DeriveActorGroup;
class HitSensor;
class SensorMsg;
} // namespace al
class ActorDimensionKeeper;
class Barrel2D;
class BarrelStack2D;
class DonkeyKong2D : public al::LiveActor, public IUseDimension {
public:
DonkeyKong2D(const char* name);
void init(const al::ActorInitInfo& info) override;
void attackSensor(al::HitSensor* self, al::HitSensor* other) override;
bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) override;
void exeWait();
void exeThrow();
void exeDamage();
void exeDown();
ActorDimensionKeeper* getActorDimensionKeeper() const override { return mDimensionKeeper; }
private:
ActorDimensionKeeper* mDimensionKeeper = nullptr;
al::DeriveActorGroup<Barrel2D>* mBarrelGroup = nullptr;
Barrel2D* mHeldBarrel = nullptr;
BarrelStack2D* mBarrelStack = nullptr;
s32 mWaitStep = 180;
f32 mMoveSpeed = 10.0f;
s32 mHitsTaken = 0;
};
static_assert(sizeof(DonkeyKong2D) == 0x140);

View file

@ -505,7 +505,8 @@ void Gamane::exeHack() {
mCoinsLeft--;
}
mHackCoinAppearCounter = al::modi((mHackCoinAppearCounter++ + 1) + 6, 6);
// NOTE: this is only one increment, as post-incrementing is used
mHackCoinAppearCounter = al::wrapValue(mHackCoinAppearCounter++ + 1, 6);
}
void Gamane::exeTrampled() {

View file

@ -25,7 +25,7 @@ HosuiTrailKeeper::HosuiTrailKeeper(const al::ActorInitInfo& initInfo) {
void HosuiTrailKeeper::appearTrail(const sead::Vector3f& pos, const sead::Vector3f& dir) {
s32 count = mTrails.size();
s32 prevIdx = al::modi(mIndex + count - 1 + count, count);
s32 prevIdx = al::wrapValue(mIndex + count - 1, count);
HosuiTrail* prevTrail = mTrails[prevIdx];
if (al::isAlive(prevTrail) && (pos - al::getTrans(prevTrail)).length() < 120.0f)
@ -56,12 +56,12 @@ void HosuiTrailKeeper::appearTrail(const sead::Vector3f& pos, const sead::Vector
trail->setFollowCollisionParts(triangle.getCollisionParts());
}
s32 disappearIdx = al::modi(mIndex + 5 + count, count);
s32 disappearIdx = al::wrapValue(mIndex + 5, count);
HosuiTrail* disappearTrail = mTrails[disappearIdx];
if (al::isAlive(disappearTrail))
disappearTrail->disappear();
mIndex = al::modi(mIndex + 1 + count, count);
mIndex = al::wrapValue(mIndex + 1, count);
}
void HosuiTrailKeeper::forceKillAll() {

View file

@ -2,6 +2,17 @@
#include "Library/LiveActor/LiveActor.h"
namespace al {
class EnemyStateBlowDown;
class CollisionPartsFilterBase;
} // namespace al
class ActorStateSandGeyser;
class EnemyStateReset;
class EnemyStateWander;
class PlayerPushReceiver;
class CollisionMultiShape;
class CollisionShapeKeeper;
class KuriboMini : public al::LiveActor {
public:
KuriboMini(const char* name);
@ -59,5 +70,27 @@ public:
void forceStartClipped();
private:
void* filler[22];
EnemyStateReset* mStateReset;
EnemyStateWander* mStateWander;
ActorStateSandGeyser* mStateSandGeyser;
al::EnemyStateBlowDown* mStateBlowDown;
s32 mCounterChase;
s32 _12c;
al::CollisionPartsFilterBase* mCollisionFilter;
void* _138;
s32 _140;
f32 mClippingRadius;
PlayerPushReceiver* mPlayerPushReceiver;
CollisionMultiShape* mCollisionMultiShape;
CollisionShapeKeeper* mCollisionShapeKeeper;
f32 mJumpSink;
s32 mFramesSpecialPush;
s32 mShiftTypeOnGround;
al::LiveActor* _170;
sead::Vector3f _178;
bool mIsPopBack;
bool mIsInvalidateClipping;
sead::Matrix34f mColliderMtx;
};
static_assert(sizeof(KuriboMini) == 0x1b8);

View file

@ -29,3 +29,5 @@ public:
private:
al::LayoutActor* mParBg = nullptr;
};
static_assert(sizeof(BootLayout) == 0x138);

View file

@ -243,8 +243,7 @@ void MenuSelectParts::exeSelect() {
s32 direction = mKeyRepeatCtrl->isUp() ? -1 : 1;
al::startAction(mLayoutArray[calcPartsIndex(mCursorItemIndex)], "Wait");
mCursorItemIndex =
al::modi(mCursorItemIndex + direction + mMenuItemAmount, mMenuItemAmount);
mCursorItemIndex = al::wrapValue(mCursorItemIndex + direction, mMenuItemAmount);
f32 pitch = ((1.0f - (f32)mCursorItemIndex / (mMenuItemAmount - 1)) * 0.375f) + 1.0f;
al::PadRumbleParam param;

View file

@ -161,15 +161,15 @@ void WindowConfirmData::exeWait() {
if (rs::isRepeatUiDown(mWindowConfirmLayout)) {
if (mSelectionCooldown == 0)
changeSelectingIdx(al::modi((mSelectionIndex + 1) + 2, 2));
mSelectionCooldown = al::modi((mSelectionCooldown + 1) + 10, 10);
changeSelectingIdx(al::wrapValue(mSelectionIndex + 1, 2));
mSelectionCooldown = al::wrapValue(mSelectionCooldown + 1, 10);
return;
}
if (rs::isRepeatUiUp(mWindowConfirmLayout)) {
if (mSelectionCooldown == 0)
changeSelectingIdx(al::modi((mSelectionIndex - 1) + 2, 2));
mSelectionCooldown = al::modi((mSelectionCooldown + 1) + 10, 10);
changeSelectingIdx(al::wrapValue(mSelectionIndex - 1, 2));
mSelectionCooldown = al::wrapValue(mSelectionCooldown + 1, 10);
return;
}

36
src/MapObj/Barrel2D.h Normal file
View file

@ -0,0 +1,36 @@
#pragma once
#include <basis/seadTypes.h>
#include <math/seadQuat.h>
#include <math/seadVector.h>
#include "Library/LiveActor/LiveActor.h"
#include "Util/IUseDimension.h"
class ActorDimensionKeeper;
class Barrel2D : public al::LiveActor, public IUseDimension {
public:
Barrel2D(const char* name);
void init(const al::ActorInitInfo& info) override;
void attackSensor(al::HitSensor* self, al::HitSensor* other) override;
bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) override;
void appearByGenerator(const sead::Vector3f&, const sead::Quatf&, f32);
void startMove();
void exeWait();
void exeMove();
ActorDimensionKeeper* getActorDimensionKeeper() const override { return mDimensionKeeper; }
private:
ActorDimensionKeeper* mDimensionKeeper;
f32 _118;
f32 mMoveSpeed;
f32 _120;
s32 _124;
s32 _128;
};
static_assert(sizeof(Barrel2D) == 0x130);

View file

@ -0,0 +1,89 @@
#include "MapObj/BossKnuckleFix.h"
#include <math/seadVector.h>
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorAnimFunction.h"
#include "Library/LiveActor/ActorCollisionFunction.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/LiveActor/ActorResourceFunction.h"
#include "Library/LiveActor/ActorSensorUtil.h"
#include "Library/LiveActor/LiveActorFunction.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "Library/Obj/CollisionObj.h"
#include "Library/Stage/StageSwitchUtil.h"
#include "Util/SensorMsgFunction.h"
namespace {
NERVE_IMPL(BossKnuckleFix, Wait);
NERVE_IMPL(BossKnuckleFix, ReactionLarge);
NERVE_IMPL(BossKnuckleFix, Reaction);
NERVES_MAKE_STRUCT(BossKnuckleFix, Wait, ReactionLarge, Reaction);
} // namespace
BossKnuckleFix::BossKnuckleFix(const char* name) : al::LiveActor(name) {}
void BossKnuckleFix::init(const al::ActorInitInfo& info) {
al::initActorWithArchiveName(this, info, "BossKnuckleBody", "Fix");
al::initNerve(this, &NrvBossKnuckleFix.Wait, 0);
// NOTE: color of embedded grand shine is hardcoded to 5 (Sand)
al::startMclAnimAndSetFrameAndStop(al::getSubActor(this, "グランドシャイン"), "Color", 5.0f);
al::trySyncStageSwitchKill(this);
makeActorAlive();
mCollisionObj = new al::CollisionObj(info, al::getModelResource(this), "MoveLimit",
al::getHitSensor(this, "Body"), nullptr, nullptr);
al::setCollisionPartsSpecialPurposeName(mCollisionObj, "MoveLimit");
al::setTrans(mCollisionObj, al::getTrans(this));
al::setRotate(mCollisionObj, {0.0f, 90.0f, 0.0f});
mCollisionObj->makeActorAlive();
}
bool BossKnuckleFix::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) {
if (rs::isMsgPlayerDisregardHomingAttack(message))
return true;
if (al::isNerve(this, &NrvBossKnuckleFix.Wait) &&
(rs::isMsgSphinxRideAttackTouch(message) || rs::isMsgPlayerAndCapHipDropAll(message))) {
rs::requestHitReactionToAttacker(message, self, other);
mReactionCount++;
if (mReactionCount >= 3) {
mReactionCount = 0;
al::setNerve(this, &NrvBossKnuckleFix.ReactionLarge);
} else
al::setNerve(this, &NrvBossKnuckleFix.Reaction);
return !rs::isMsgPlayerAndCapHipDropAll(message);
}
return false;
}
void BossKnuckleFix::exeWait() {
if (al::isFirstStep(this))
al::startAction(this, "MapWait");
}
void BossKnuckleFix::exeReaction() {
if (al::isFirstStep(this))
al::startAction(this, "MapReaction");
if (al::isActionEnd(this))
al::setNerve(this, &NrvBossKnuckleFix.Wait);
}
void BossKnuckleFix::exeReactionLarge() {
if (al::isFirstStep(this)) {
al::startAction(this, "MapReactionLarge");
al::tryOnStageSwitch(this, "ReactionOn");
}
if (al::isActionEnd(this))
al::setNerve(this, &NrvBossKnuckleFix.Wait);
}

View file

@ -0,0 +1,31 @@
#pragma once
#include <basis/seadTypes.h>
#include "Library/LiveActor/LiveActor.h"
namespace al {
struct ActorInitInfo;
class CollisionObj;
class HitSensor;
class SensorMsg;
} // namespace al
class BossKnuckleFix : public al::LiveActor {
public:
BossKnuckleFix(const char* name);
void init(const al::ActorInitInfo& info) override;
bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) override;
void exeWait();
void exeReaction();
void exeReactionLarge();
private:
al::CollisionObj* mCollisionObj = nullptr;
s32 mReactionCount = 0;
};
static_assert(sizeof(BossKnuckleFix) == 0x118);

View file

@ -9,6 +9,9 @@ struct ActorInitInfo;
class HitSensor;
class SensorMsg;
} // namespace al
class CapTargetInfo;
class ItemGenerator;
class SaveObjInfo;
class CapHanger : public al::LiveActor {
public:
@ -31,15 +34,15 @@ public:
void setPeachCastleCap(const sead::Vector3f&);
private:
void* _108;
CapTargetInfo* mCapTargetInfo;
void* _110;
s32 _118;
s32 _11c;
s32 mAppearItemNum;
s32 _120;
void* _128;
bool _130;
ItemGenerator* mItemGenerator;
bool mIsEmitEffect;
void* _138;
void* _140;
SaveObjInfo* _140;
sead::Matrix34f _148;
sead::Matrix34f _178;
bool _1a8;

77
src/MapObj/DoorCity.cpp Normal file
View file

@ -0,0 +1,77 @@
#include "MapObj/DoorCity.h"
#include "Library/Base/StringUtil.h"
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorCollisionFunction.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "Library/Placement/PlacementFunction.h"
#include "Library/Stage/StageSwitchUtil.h"
#include "Library/Thread/FunctorV0M.h"
#include "System/GameDataFunction.h"
namespace {
NERVE_IMPL(DoorCity, Open);
NERVE_IMPL(DoorCity, WaitOpen);
NERVE_IMPL(DoorCity, WaitClose);
NERVES_MAKE_NOSTRUCT(DoorCity, Open, WaitOpen, WaitClose);
} // namespace
DoorCity::DoorCity(const char* name) : al::LiveActor(name) {}
void DoorCity::init(const al::ActorInitInfo& info) {
using DoorCityFunctor = al::FunctorV0M<DoorCity*, void (DoorCity::*)()>;
al::initActor(this, info);
const char* initState = nullptr;
al::getStringArg(&initState, info, "InitState");
if (al::isEqualString(initState, "Open")) {
al::initNerve(this, &WaitOpen, 0);
al::invalidateCollisionParts(this);
} else if (al::isEqualString(initState, "Close")) {
al::initNerve(this, &WaitClose, 0);
al::listenStageSwitchOnStart(this, DoorCityFunctor(this, &DoorCity::onStageSwitch));
} else {
kill();
return;
}
makeActorAlive();
al::listenStageSwitchOn(this, "SwitchLightOff",
DoorCityFunctor(this, &DoorCity::listenSwitchOff));
}
void DoorCity::onStageSwitch() {
al::setNerve(this, &Open);
}
void DoorCity::listenSwitchOff() {}
void DoorCity::exeWaitOpen() {
if (al::isFirstStep(this))
al::startAction(this, "OpenWait");
}
void DoorCity::exeOpen() {
if (al::isFirstStep(this))
al::startAction(this, "Open");
if (al::isActionEnd(this)) {
al::invalidateCollisionParts(this);
al::setNerve(this, &WaitOpen);
}
}
void DoorCity::exeWaitClose() {
if (al::isFirstStep(this)) {
if (GameDataFunction::getScenarioNo(this) == 1)
al::tryStartAction(this, "Blink");
else
al::tryStartAction(this, "CloseWait");
}
}

18
src/MapObj/DoorCity.h Normal file
View file

@ -0,0 +1,18 @@
#pragma once
#include "Library/LiveActor/LiveActor.h"
class DoorCity : public al::LiveActor {
public:
DoorCity(const char* name);
void init(const al::ActorInitInfo& info) override;
void onStageSwitch();
void listenSwitchOff();
void exeWaitOpen();
void exeOpen();
void exeWaitClose();
};
static_assert(sizeof(DoorCity) == 0x108);

View file

@ -0,0 +1,44 @@
#include "MapObj/FastenerObjSpace.h"
#include "Library/LiveActor/ActorClippingFunction.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/LiveActor/ActorModelFunction.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
namespace {
NERVE_IMPL(FastenerObjSpace, Wait);
NERVE_IMPL(FastenerObjSpace, Disappear);
NERVES_MAKE_NOSTRUCT(FastenerObjSpace, Wait, Disappear);
} // namespace
FastenerObjSpace::FastenerObjSpace(const char* name) : al::LiveActor(name) {}
void FastenerObjSpace::init(const al::ActorInitInfo& info) {
al::initActorWithArchiveName(this, info, "FastenerSpace", nullptr);
al::initNerve(this, &Wait, 0);
makeActorAlive();
}
void FastenerObjSpace::appear() {
al::LiveActor::appear();
al::setModelAlphaMask(this, 1.0f);
al::setNerve(this, &Wait);
}
void FastenerObjSpace::disappear() {
al::invalidateClipping(this);
al::setNerve(this, &Disappear);
}
void FastenerObjSpace::exeWait() {
if (al::isFirstStep(this)) {
}
}
void FastenerObjSpace::exeDisappear() {
f32 rate = al::calcNerveRate(this, 60);
al::setModelAlphaMask(this, 1.0f - rate);
if (al::isGreaterStep(this, 60))
kill();
}

View file

@ -0,0 +1,18 @@
#pragma once
#include "Library/LiveActor/LiveActor.h"
class FastenerObjSpace : public al::LiveActor {
public:
FastenerObjSpace(const char* name);
void init(const al::ActorInitInfo& info) override;
void appear() override;
void disappear();
void exeWait();
void exeDisappear();
private:
al::LiveActor* mLinkActor = nullptr;
};
static_assert(sizeof(FastenerObjSpace) == 0x110);

View file

@ -0,0 +1,41 @@
#include "MapObj/MoonBasementBreakParts.h"
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
namespace {
NERVE_IMPL(MoonBasementBreakParts, Wait)
NERVE_IMPL(MoonBasementBreakParts, Break)
NERVES_MAKE_NOSTRUCT(MoonBasementBreakParts, Wait, Break)
} // namespace
MoonBasementBreakParts::MoonBasementBreakParts(const char* actorName) : al::LiveActor(actorName) {}
void MoonBasementBreakParts::init(const al::ActorInitInfo& info) {
al::initActorWithArchiveName(this, info, "MoonWorldBasementBreakParts000", nullptr);
al::initNerve(this, &Wait, 0);
makeActorAlive();
}
void MoonBasementBreakParts::appear() {
al::setNerve(this, &Wait);
al::LiveActor::appear();
}
void MoonBasementBreakParts::kill() {
al::startAction(this, "Break");
al::setNerve(this, &Break);
}
void MoonBasementBreakParts::exeWait() {
if (al::isFirstStep(this))
al::startAction(this, "Wait");
}
void MoonBasementBreakParts::exeBreak() {
if (al::isActionEnd(this))
al::LiveActor::kill();
}

View file

@ -0,0 +1,17 @@
#pragma once
#include "Library/LiveActor/LiveActor.h"
class MoonBasementBreakParts : public al::LiveActor {
public:
MoonBasementBreakParts(const char* actorName);
void init(const al::ActorInitInfo& info) override;
void appear() override;
void kill() override;
void exeWait();
void exeBreak();
};
static_assert(sizeof(MoonBasementBreakParts) == 0x108);

View file

@ -0,0 +1,165 @@
#include "MapObj/MoonBasementFloor.h"
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorClippingFunction.h"
#include "Library/LiveActor/ActorFlagFunction.h"
#include "Library/LiveActor/ActorInitFunction.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/LiveActor/ActorMovementFunction.h"
#include "Library/Math/MathUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "Library/Placement/PlacementFunction.h"
#include "Library/Stage/StageSwitchUtil.h"
#include "Library/Thread/FunctorV0M.h"
#include "Boss/Koopa/KoopaHackStopCtrl.h"
#include "Util/SensorMsgFunction.h"
namespace {
NERVE_IMPL(MoonBasementFloor, Wait)
NERVE_IMPL(MoonBasementFloor, FallSignStart)
NERVE_IMPL_(MoonBasementFloor, FallSignStartByMeteor, FallSignStart)
NERVE_IMPL_(MoonBasementFloor, FallSignStartBySwitch, FallSignStart)
NERVE_IMPL(MoonBasementFloor, FallSignBySwitch)
NERVE_IMPL_(MoonBasementFloor, FallByMeteor, Fall)
NERVE_IMPL(MoonBasementFloor, FallSign)
NERVE_IMPL(MoonBasementFloor, Fall)
NERVES_MAKE_STRUCT(MoonBasementFloor, Wait, FallSignStart, FallSignStartByMeteor,
FallSignStartBySwitch, FallSignBySwitch, FallByMeteor, FallSign, Fall)
const f32 sFallGravity = 0.2f;
const f32 sFallScale = 0.95f;
const f32 sFallGravityByMeteor = 0.2f;
const f32 sFallScaleByMeteor = 0.95f;
struct MoonFallParams {
const f32* gravity;
const f32* scale;
};
const MoonFallParams sFallParams{&sFallGravity, &sFallScale};
const MoonFallParams sFallParamsByMeteor{&sFallGravityByMeteor, &sFallScaleByMeteor};
inline const MoonFallParams& getMoonFallParams(al::LiveActor* actor) {
return al::isNerve(actor, &NrvMoonBasementFloor.FallByMeteor) ? sFallParamsByMeteor :
sFallParams;
}
} // namespace
MoonBasementFloor::MoonBasementFloor(const char* name) : al::LiveActor(name) {}
void MoonBasementFloor::init(const al::ActorInitInfo& info) {
using MoonBasementFloorFunctor =
al::FunctorV0M<MoonBasementFloor*, void (MoonBasementFloor::*)()>;
al::initActorChangeModel(this, info);
al::initNerve(this, &NrvMoonBasementFloor.Wait, 0);
f32 rotate = sead::Mathf::floor(al::getRandom(0.0f, 3.99f));
al::addRotateAndRepeatY(this, rotate * 90.0);
if (al::listenStageSwitchOn(
this, "SwitchFallStart",
MoonBasementFloorFunctor(this, &MoonBasementFloor::startFallBySwitch))) {
al::tryGetArg(&mFallSignStepBySwitch, info, "FallSignStepBySwitch");
}
al::trySyncStageSwitchKill(this);
}
void MoonBasementFloor::startFallBySwitch() {
if (!al::isAlive(this))
return;
if (al::isNerve(this, &NrvMoonBasementFloor.Fall))
return;
if (al::isNerve(this, &NrvMoonBasementFloor.FallByMeteor))
return;
s32 fallSignStepBySwitch = mFallSignStepBySwitch;
al::invalidateClipping(this);
if (fallSignStepBySwitch == 0)
al::setNerve(this, &NrvMoonBasementFloor.FallSignStart);
else
al::setNerve(this, &NrvMoonBasementFloor.FallSignStartBySwitch);
}
void MoonBasementFloor::movement() {
if (!KoopaHackFunction::isStopKoopaHack(this))
al::LiveActor::movement();
}
bool MoonBasementFloor::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) {
if (!al::isNerve(this, &NrvMoonBasementFloor.Wait))
return false;
if (rs::isMsgKoopaTouchFloor(message)) {
al::startHitReaction(this, "クッパ着地");
al::invalidateClipping(this);
al::setNerve(this, &NrvMoonBasementFloor.FallSignStart);
return true;
}
if (rs::isMsgMoonBasementAttackMeteor(message)) {
al::invalidateClipping(this);
al::setNerve(this, &NrvMoonBasementFloor.FallSignStartByMeteor);
return true;
}
return false;
}
void MoonBasementFloor::exeWait() {
if (al::isFirstStep(this))
al::startAction(this, "Wait");
}
void MoonBasementFloor::exeFallSignStart() {
if (al::isFirstStep(this))
al::startAction(this, "FallSignStart");
if (al::isActionEnd(this)) {
if (al::isNerve(this, &NrvMoonBasementFloor.FallSignStartBySwitch))
al::setNerve(this, &NrvMoonBasementFloor.FallSignBySwitch);
else if (al::isNerve(this, &NrvMoonBasementFloor.FallSignStartByMeteor))
al::setNerve(this, &NrvMoonBasementFloor.FallByMeteor);
else
al::setNerve(this, &NrvMoonBasementFloor.FallSign);
}
}
void MoonBasementFloor::exeFallSign() {
if (al::isFirstStep(this))
al::startAction(this, "FallSign");
al::setNerveAtActionEnd(this, &NrvMoonBasementFloor.Fall);
}
void MoonBasementFloor::exeFallSignBySwitch() {
if (al::isFirstStep(this))
al::startAction(this, "FallSignBySwitch");
s32 fallSignStep = mFallSignStepBySwitch;
if (fallSignStep < 0)
fallSignStep = 30;
al::setNerveAtGreaterEqualStep(this, &NrvMoonBasementFloor.Fall, fallSignStep);
}
void MoonBasementFloor::exeFall() {
if (al::isFirstStep(this))
al::startAction(this, "Fall");
al::addVelocityToGravity(this, *getMoonFallParams(this).gravity);
al::scaleVelocity(this, *getMoonFallParams(this).scale);
if (al::isGreaterEqualStep(this, 300)) {
al::startHitReaction(this, "消滅");
kill();
}
}

View file

@ -0,0 +1,34 @@
#pragma once
#include <basis/seadTypes.h>
#include "Library/LiveActor/LiveActor.h"
namespace al {
struct ActorInitInfo;
class HitSensor;
class SensorMsg;
} // namespace al
class MoonBasementFloor : public al::LiveActor {
public:
MoonBasementFloor(const char* name);
void init(const al::ActorInitInfo& info) override;
void movement() override;
bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) override;
void startFallBySwitch();
void exeWait();
void exeFallSignStart();
void exeFallSign();
void exeFallSignBySwitch();
void exeFall();
private:
s32 mFallSignStepBySwitch = -1;
};
static_assert(sizeof(MoonBasementFloor) == 0x110);

47
src/MapObj/PeachTrunk.cpp Normal file
View file

@ -0,0 +1,47 @@
#include "MapObj/PeachTrunk.h"
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/LiveActor/ActorSensorUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "Util/SensorMsgFunction.h"
namespace {
NERVE_IMPL(PeachTrunk, Wait)
NERVE_IMPL(PeachTrunk, ReactionCap)
NERVES_MAKE_NOSTRUCT(PeachTrunk, Wait, ReactionCap)
} // namespace
PeachTrunk::PeachTrunk(const char* actorName) : al::LiveActor(actorName) {}
void PeachTrunk::init(const al::ActorInitInfo& info) {
al::initActorWithArchiveName(this, info, "PeachTrunk", nullptr);
al::initNerve(this, &Wait, 0);
makeActorAlive();
}
bool PeachTrunk::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) {
if (al::isMsgPlayerDisregard(message))
return true;
if (rs::isMsgNpcCapReactionAll(message)) {
rs::requestHitReactionToAttacker(message, self, other);
al::setNerve(this, &ReactionCap);
return true;
}
return false;
}
void PeachTrunk::exeWait() {
if (al::isFirstStep(this))
al::startAction(this, "Wait");
}
void PeachTrunk::exeReactionCap() {
if (al::isFirstStep(this))
al::startAction(this, "ReactionCap");
al::setNerveAtActionEnd(this, &Wait);
}

17
src/MapObj/PeachTrunk.h Normal file
View file

@ -0,0 +1,17 @@
#pragma once
#include "Library/LiveActor/LiveActor.h"
class PeachTrunk : public al::LiveActor {
public:
PeachTrunk(const char* actorName);
void init(const al::ActorInitInfo& info) override;
bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) override;
void exeWait();
void exeReactionCap();
};
static_assert(sizeof(PeachTrunk) == 0x108);

View file

@ -1,6 +1,7 @@
#pragma once
#include <basis/seadTypes.h>
#include <container/seadPtrArray.h>
#include <math/seadQuat.h>
#include <math/seadVector.h>
@ -39,7 +40,8 @@ public:
al::CameraDirector* getCameraDirector() const override;
private:
char _10[0x18];
sead::PtrArray<PlayerStartInfo> mPlayerStartInfoList;
al::CameraDirector* mCameraDirector;
};
static_assert(sizeof(PlayerStartInfoHolder) == 0x28);

View file

@ -0,0 +1,44 @@
#include "MapObj/ReactionMapParts.h"
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "Util/SensorMsgFunction.h"
namespace {
NERVE_IMPL(ReactionMapParts, Wait)
NERVE_IMPL(ReactionMapParts, Reaction)
NERVES_MAKE_NOSTRUCT(ReactionMapParts, Wait, Reaction)
} // namespace
ReactionMapParts::ReactionMapParts(const char* actorName) : al::LiveActor(actorName) {}
void ReactionMapParts::init(const al::ActorInitInfo& info) {
al::initMapPartsActor(this, info, nullptr);
al::initNerve(this, &Wait, 0);
al::trySyncStageSwitchAppearAndKill(this);
}
bool ReactionMapParts::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) {
if (rs::isMsgCapTouchWall(message) || rs::isMsgPlayerRollingWallHitDown(message)) {
al::setNerve(this, &Reaction);
return true;
}
return false;
}
void ReactionMapParts::exeWait() {
if (al::isFirstStep(this))
al::startAction(this, "Wait");
}
void ReactionMapParts::exeReaction() {
if (al::isFirstStep(this))
al::startAction(this, "Reaction");
if (al::isActionEnd(this))
al::setNerve(this, &Wait);
}

View file

@ -0,0 +1,17 @@
#pragma once
#include "Library/LiveActor/LiveActor.h"
class ReactionMapParts : public al::LiveActor {
public:
ReactionMapParts(const char* actorName);
void init(const al::ActorInitInfo& info) override;
bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) override;
void exeWait();
void exeReaction();
};
static_assert(sizeof(ReactionMapParts) == 0x108);

237
src/MapObj/RocketFlower.cpp Normal file
View file

@ -0,0 +1,237 @@
#include "MapObj/RocketFlower.h"
#include "Library/Collision/PartsConnectorUtil.h"
#include "Library/Effect/EffectSystemInfo.h"
#include "Library/LiveActor/ActorActionFunction.h"
#include "Library/LiveActor/ActorAnimFunction.h"
#include "Library/LiveActor/ActorClippingFunction.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/LiveActor/ActorMovementFunction.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/LiveActor/ActorSensorUtil.h"
#include "Library/Math/MathUtil.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "MapObj/RocketFlowerFunction.h"
#include "Util/PlayerUtil.h"
#include "Util/SensorMsgFunction.h"
namespace {
NERVE_IMPL(RocketFlower, Wait);
NERVE_IMPL(RocketFlower, Attach);
NERVE_IMPL(RocketFlower, WaitFollow);
NERVE_IMPL(RocketFlower, Follow);
NERVE_IMPL(RocketFlower, WaitAttach);
NERVES_MAKE_STRUCT(RocketFlower, Wait, Attach, WaitFollow, Follow, WaitAttach);
} // namespace
RocketFlower::RocketFlower(const char* name) : al::LiveActor(name) {}
void RocketFlower::init(const al::ActorInitInfo& info) {
al::initActor(this, info);
al::initNerve(this, &NrvRocketFlower.Wait, 0);
makeActorAlive();
mMtxConnector = al::tryCreateMtxConnector(this, info);
mFlowerSub = new al::LiveActor("ロケットフラワーの花");
al::initChildActorWithArchiveNameNoPlacementInfo(mFlowerSub, info, "RocketFlowerDash", nullptr);
al::startAction(mFlowerSub, "Wait");
mFlowerSub->makeActorDead();
RocketFlowerFunction::createRocketFlowerEquipWatcherIfNotExist(this, info);
al::setHitSensorPosPtr(this, "Equip", al::getTransPtr(mFlowerSub));
al::startAction(this, "Wait");
}
void RocketFlower::initAfterPlacement() {
if (mMtxConnector)
al::attachMtxConnectorToCollision(mMtxConnector, this, false);
}
void RocketFlower::attackSensor(al::HitSensor* self, al::HitSensor* other) {
if (!al::isSensorName(self, "Equip"))
return;
if (isEnableEquip()) {
if (rs::sendMsgRocketFlowerExtension(other, self))
al::setNerve(this, &NrvRocketFlower.Attach);
}
}
bool RocketFlower::isEnableEquip() const {
if (al::isNerve(this, &NrvRocketFlower.Follow) && !al::isNewNerve(this))
return true;
return al::isNerve(this, &NrvRocketFlower.WaitAttach);
}
bool RocketFlower::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) {
if (al::isMsgPlayerSpinAttack(message)) {
if (al::isNerve(this, &NrvRocketFlower.Wait)) {
al::invalidateClipping(this);
al::setNerve(this, &NrvRocketFlower.WaitFollow);
}
} else if (rs::isMsgCapItemGet(message)) {
if (al::isNerve(this, &NrvRocketFlower.Wait)) {
al::invalidateClipping(this);
al::setNerve(this, &NrvRocketFlower.Follow);
return true;
}
} else if (al::isMsgPlayerObjTouch(message) || rs::isMsgBlowObjAttack(message) ||
rs::isMsgFireDamageAll(message) || rs::isMsgHammerBrosHammerEnemyAttack(message) ||
rs::isMsgHammerBrosHammerHackAttack(message) || rs::isMsgHosuiAttack(message) ||
al::isMsgEnemyAttack(message) || al::isMsgKickStoneAttack(message) ||
rs::isMsgRadishAttack(message) || rs::isMsgSeedAttack(message) ||
rs::isMsgTankBullet(message) || rs::isMsgGamaneBulletThrough(message) ||
rs::isMsgHackAttackPoison(message) || rs::isMsgYoshiTongueAttack(message)) {
if (al::isSensorMapObj(self)) {
if (mReactionFrame == 0)
al::startAction(this, "Reaction");
mReactionFrame = 30;
}
} else if (rs::isMsgCapAttack(message)) {
if (al::isSensorMapObj(self) && !al::isNerve(this, &NrvRocketFlower.Wait) &&
!al::isNerve(this, &NrvRocketFlower.WaitFollow)) {
if (mReactionFrame == 0)
al::startAction(this, "Reaction");
mReactionFrame = 30;
}
} else if (al::isMsgPlayerPutOnEquipment(message) && al::isSensorName(self, "Equip") &&
isEnableEquip()) {
if (RocketFlowerFunction::requestEquipRocketFlower(this, other)) {
al::setNerve(this, &NrvRocketFlower.Attach);
return true;
}
terminateFollow();
}
return false;
}
void RocketFlower::terminateFollow() {
al::invalidateHitSensor(this, "Equip");
al::validateClipping(this);
mFlowerSub->kill();
al::startAction(this, "Appear");
mReactionFrame = 30;
al::startHitReaction(this, "復帰");
al::setNerve(this, &NrvRocketFlower.Wait);
}
void RocketFlower::exeWait() {
if (al::isFirstStep(this)) {
al::startVisAnim(this, "Show");
al::invalidateHitSensor(this, "Equip");
}
}
void RocketFlower::exeWaitFollow() {
if (trySyncFlyingCapPos()) {
al::setNerve(this, &NrvRocketFlower.Follow);
return;
}
if (al::isGreaterEqualStep(this, 30)) {
al::validateClipping(this);
al::setNerve(this, &NrvRocketFlower.Wait);
}
}
bool RocketFlower::trySyncFlyingCapPos() {
sead::Vector3f flyingCapPos;
if (!rs::tryGetFlyingCapPos(&flyingCapPos, this))
return false;
flyingCapPos += 50.0f * sead::Vector3f::ey;
al::resetPosition(mFlowerSub, flyingCapPos);
sead::Vector3f toPlayerHead = rs::getPlayerHeadPos(this) - flyingCapPos;
if (al::tryNormalizeOrZero(&toPlayerHead)) {
sead::Quatf quat;
quat.makeVectorRotation(sead::Vector3f::ez, toPlayerHead);
al::setQuat(mFlowerSub, quat);
}
return true;
}
void RocketFlower::exeFollow() {
if (al::isFirstStep(this)) {
appearFlowerSub();
mFollowLostFrame = 0;
}
if (trySyncFlyingCapPos()) {
mFollowLostFrame = 0;
return;
}
if (rs::isEquipCapCatched(this)) {
al::validateHitSensor(this, "Equip");
al::setNerve(this, &NrvRocketFlower.WaitAttach);
return;
}
if (mFollowLostFrame >= 16)
terminateFollow();
mFollowLostFrame++;
}
void RocketFlower::appearFlowerSub() {
al::startVisAnim(this, "Hide");
mFlowerSub->appear();
al::startAction(mFlowerSub, "Wait");
al::startAction(this, "ReactionCap");
mReactionFrame = 30;
al::startHitReaction(this, "花が取れた");
}
void RocketFlower::exeWaitAttach() {
rs::tryCalcPlayerModelHeadJointPos(al::getTransPtr(mFlowerSub), this);
if (al::isGreaterEqualStep(this, 20))
terminateFollow();
}
void RocketFlower::exeAttach() {
if (al::isFirstStep(this))
al::startAction(mFlowerSub, "Dash");
}
void RocketFlower::setFollowFlowerPose(const sead::Quatf& quat, const sead::Vector3f& trans) {
al::setQuat(mFlowerSub, quat);
al::resetPosition(mFlowerSub, trans);
}
void RocketFlower::disappear() {
al::startHitReaction(mFlowerSub, "消滅");
}
void RocketFlower::disappearForce() {
al::tryKillEmitterAndParticleAll(mFlowerSub);
al::invalidateHitSensor(this, "Equip");
al::validateClipping(this);
mFlowerSub->kill();
al::startAction(this, "Wait");
mReactionFrame = 30;
al::setNerve(this, &NrvRocketFlower.Wait);
}
void RocketFlower::control() {
if (al::isActionOneTime(this) && al::isActionEnd(this))
al::startAction(this, "Wait");
if (mReactionFrame != 0)
mReactionFrame--;
if (mMtxConnector)
al::connectPoseQT(this, mMtxConnector);
}

48
src/MapObj/RocketFlower.h Normal file
View file

@ -0,0 +1,48 @@
#pragma once
#include <math/seadQuat.h>
#include <math/seadVector.h>
#include "Library/LiveActor/LiveActor.h"
namespace al {
struct ActorInitInfo;
class HitSensor;
class MtxConnector;
class SensorMsg;
} // namespace al
class RocketFlower : public al::LiveActor {
public:
RocketFlower(const char* name);
void init(const al::ActorInitInfo& info) override;
void initAfterPlacement() override;
void attackSensor(al::HitSensor* self, al::HitSensor* other) override;
bool receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
al::HitSensor* self) override;
void control() override;
bool isEnableEquip() const;
void terminateFollow();
void exeWait();
void exeWaitFollow();
bool trySyncFlyingCapPos();
void exeFollow();
void appearFlowerSub();
void exeWaitAttach();
void exeAttach();
void setFollowFlowerPose(const sead::Quatf& quat, const sead::Vector3f& trans);
void disappear();
void disappearForce();
private:
al::MtxConnector* mMtxConnector = nullptr;
al::LiveActor* mFlowerSub = nullptr;
s32 mReactionFrame = 0;
u32 mFollowLostFrame = 0;
};
static_assert(sizeof(RocketFlower) == 0x120);

View file

@ -0,0 +1,17 @@
#pragma once
namespace al {
struct ActorInitInfo;
class HitSensor;
class LiveActor;
} // namespace al
class RocketFlower;
namespace RocketFlowerFunction {
void createRocketFlowerEquipWatcherIfNotExist(const al::LiveActor* actor,
const al::ActorInitInfo& info);
bool requestEquipRocketFlower(RocketFlower* flower, al::HitSensor* sensor);
} // namespace RocketFlowerFunction

View file

@ -0,0 +1,35 @@
#pragma once
#include <basis/seadTypes.h>
#include <math/seadVector.h>
class ScreenPointAnalyzer {
public:
ScreenPointAnalyzer();
void reset();
void update();
void analyze(const sead::Vector2f& pos);
bool isHold() const;
bool isSlide() const;
const sead::Vector2f& getSlideDir() const { return mSlideDir; }
const sead::Vector2f& getMoveVec() const { return mMoveVec; }
f32 getRotateSpeedDegree() const { return mRotateSpeedDegree; }
private:
s32 _00 = 0;
s32 _04 = 0;
s32 _08 = 0;
s32 _0c = 0;
s32 _10 = 0;
s32 _14 = 0;
sead::Vector2f mSlideDir = {0.0f, 0.0f};
sead::Vector2f mMoveVec = {0.0f, 0.0f};
s32 _28 = 0;
s32 _2c = 0;
f32 mRotateSpeedDegree = 0.0f;
};
static_assert(sizeof(ScreenPointAnalyzer) == 0x34);

View file

@ -0,0 +1,71 @@
#include "MapObj/TouchActionMessageDirector.h"
#include "Library/LiveActor/ActorInitUtil.h"
#include "Library/LiveActor/LiveActor.h"
#include "Library/Math/MathUtil.h"
#include "Library/Scene/SceneObjUtil.h"
#include "Library/Screen/ScreenPointer.h"
#include "MapObj/ScreenPointAnalyzer.h"
TouchActionMessageDirector::TouchActionMessageDirector() = default;
void TouchActionMessageDirector::init(const al::ActorInitInfo& info) {
mCollisionDirector = al::getCollisionDirectorFromInfo(info);
mScreenPointAnalyzer = new ScreenPointAnalyzer();
mScreenPointer = new al::ScreenPointer(info, "No Owner");
}
void TouchActionMessageDirector::update() {
mScreenPointAnalyzer->update();
}
bool TouchActionMessageDirector::isTouchHold() const {
return mScreenPointAnalyzer->isHold();
}
f32 TouchActionMessageDirector::getRotateSpeedDegree() const {
return mScreenPointAnalyzer->getRotateSpeedDegree();
}
bool TouchActionMessageDirector::tryGetMoveVec(sead::Vector2f* out) const {
if (!isTouchHold())
return false;
const sead::Vector2f& moveVec = mScreenPointAnalyzer->getMoveVec();
if (al::isNearZero(moveVec))
return false;
out->set(moveVec);
return true;
}
bool TouchActionMessageDirector::tryGetSlideDir(sead::Vector2f* out) const {
if (!mScreenPointAnalyzer->isSlide())
return false;
out->set(mScreenPointAnalyzer->getSlideDir());
return true;
}
namespace rs {
bool isTimeHandled(const al::LiveActor* actor) {
TouchActionMessageDirector* director = al::getSceneObj<TouchActionMessageDirector>(actor);
return director->isTouchHold();
}
f32 getTimeHandleRotateSpeedDegree(const al::LiveActor* actor) {
TouchActionMessageDirector* director = al::getSceneObj<TouchActionMessageDirector>(actor);
return director->getRotateSpeedDegree();
}
bool tryGetTouchActionMoveVec(sead::Vector2f* out, const al::LiveActor* actor) {
TouchActionMessageDirector* director = al::getSceneObj<TouchActionMessageDirector>(actor);
return director->tryGetMoveVec(out);
}
bool tryGetTouchActionSlideDir(sead::Vector2f* out, const al::LiveActor* actor) {
TouchActionMessageDirector* director = al::getSceneObj<TouchActionMessageDirector>(actor);
return director->tryGetSlideDir(out);
}
} // namespace rs

View file

@ -0,0 +1,52 @@
#pragma once
#include <basis/seadTypes.h>
#include <math/seadVector.h>
#include "Library/Collision/IUseCollision.h"
#include "Library/HostIO/HioNode.h"
#include "Library/Scene/ISceneObj.h"
#include "Scene/SceneObjFactory.h"
class ScreenPointAnalyzer;
namespace al {
struct ActorInitInfo;
class CollisionDirector;
class LiveActor;
class ScreenPointer;
} // namespace al
class TouchActionMessageDirector : public al::HioNode,
public al::ISceneObj,
public al::IUseCollision {
public:
static constexpr s32 sSceneObjId = SceneObjID_TouchActionMessageDirector;
TouchActionMessageDirector();
void init(const al::ActorInitInfo& info);
void update();
bool isTouchHold() const;
f32 getRotateSpeedDegree() const;
bool tryGetMoveVec(sead::Vector2f* out) const;
bool tryGetSlideDir(sead::Vector2f* out) const;
const char* getSceneObjName() const override {
return "タッチアクションメッセージディレクター";
}
al::CollisionDirector* getCollisionDirector() const override { return mCollisionDirector; }
private:
al::CollisionDirector* mCollisionDirector = nullptr;
ScreenPointAnalyzer* mScreenPointAnalyzer = nullptr;
al::ScreenPointer* mScreenPointer = nullptr;
};
namespace rs {
bool isTimeHandled(const al::LiveActor* actor);
f32 getTimeHandleRotateSpeedDegree(const al::LiveActor* actor);
bool tryGetTouchActionMoveVec(sead::Vector2f* out, const al::LiveActor* actor);
bool tryGetTouchActionSlideDir(sead::Vector2f* out, const al::LiveActor* actor);
} // namespace rs

View file

@ -8,6 +8,7 @@ namespace al {
struct ActorInitInfo;
class HitSensor;
class SensorMsg;
class MtxConnector;
} // namespace al
class TreasureBoxKeyOpener : public al::LiveActor {
@ -27,7 +28,12 @@ public:
virtual void setHostForClipping(al::LiveActor*);
private:
void* filler[4];
al::LiveActor* mHostForClipping;
al::MtxConnector* mMtxConnector;
f32 _118;
f32 _11c;
s32 _120;
s32 _124;
};
static_assert(sizeof(TreasureBoxKeyOpener) == 0x128);

View file

@ -0,0 +1,25 @@
#pragma once
#include <basis/seadTypes.h>
#include "Library/Play/Layout/SimpleLayoutAppearWaitEnd.h"
class IBalloonFindMyAchievementHolder;
namespace al {
class LayoutInitInfo;
} // namespace al
class TimeBalloonAchievementLayout : public al::SimpleLayoutAppearWaitEnd {
public:
TimeBalloonAchievementLayout(const al::LayoutInitInfo& info);
void appear() override;
void update();
void setAchievement(const IBalloonFindMyAchievementHolder* holder);
private:
u8 _130[0x288 - 0x130];
};
static_assert(sizeof(TimeBalloonAchievementLayout) == 0x288);

View file

@ -0,0 +1,72 @@
#pragma once
#include <basis/seadTypes.h>
#include <math/seadVector.h>
class FriendsProfileDataHolder;
namespace al {
class FriendsProfileData;
} // namespace al
namespace nn::nex {
template <typename K, typename V>
class qMap;
template <typename T>
class qVector;
class qBuffer;
struct DataStoreRatingInfo;
struct DataStoreSearchBalloonResult;
} // namespace nn::nex
namespace TimeBalloon {
class BalloonDataServer {
public:
BalloonDataServer();
virtual ~BalloonDataServer();
};
class BalloonData {
public:
void setRatingInfo(const nn::nex::qMap<s8, nn::nex::DataStoreRatingInfo>& ratingInfoMap);
void setGotIdList(const nn::nex::qVector<nn::nex::qBuffer>& gotIdList);
void setPlayedIdList(const nn::nex::qVector<nn::nex::qBuffer>& playedIdList);
const nn::nex::qVector<nn::nex::qBuffer>& getGotIdList() const;
const nn::nex::qVector<nn::nex::qBuffer>& getPlayedIdList() const;
};
struct BalloonDataMetaBinary;
class RankAchievement {
public:
void end();
};
void initBalloonDataServer(BalloonDataServer* server);
bool isGotBalloon(const BalloonData& balloonData);
s32 getPlayerRank(const BalloonData& balloonData);
s64 getPlayedNum(const BalloonData& balloonData);
s32 calcGotCoin(const BalloonData& balloonData);
s32 calcProtectNum(const BalloonData& balloonData);
s64 calcProtectCoin(const BalloonData& balloonData);
s64 calcProtectCoin(s32 protectNum);
al::FriendsProfileData* tryGetProfileData(const BalloonData& balloonData);
void tryGetNickName(const char** outNickName, const BalloonData& balloonData);
const char* tryGetNickName(const BalloonData& balloonData);
void getBalloonPos(sead::Vector3f* outBalloonPos, const BalloonData& balloonData);
void setRatingInfo(BalloonData* balloonData,
const nn::nex::qMap<s8, nn::nex::DataStoreRatingInfo>& ratingInfoMap);
void createBalloonData(BalloonData* balloonData,
const nn::nex::DataStoreSearchBalloonResult& searchBalloonResult,
FriendsProfileDataHolder* profileDataHolder, bool isGotBalloon);
void createBalloonData(BalloonData* balloonData, u64 dataId, u64 ownerId, u16 playerRank,
const nn::nex::qMap<s8, nn::nex::DataStoreRatingInfo>& ratingInfoMap,
const BalloonDataMetaBinary* metaBinary,
FriendsProfileDataHolder* profileDataHolder, bool isGotBalloon);
s32 getBalloonGotSlotId();
s32 getBalloonPlayedSlotId();
} // namespace TimeBalloon

View file

@ -0,0 +1,59 @@
#include "ModeBalloon/TimeBalloonStateShowResult.h"
#include "Library/Nerve/NerveSetupUtil.h"
#include "Library/Nerve/NerveUtil.h"
#include "ModeBalloon/TimeBalloonAchievementLayout.h"
#include "Util/StageInputFunction.h"
namespace {
NERVE_IMPL(TimeBalloonStateShowResult, Appear)
NERVE_IMPL(TimeBalloonStateShowResult, Wait)
NERVE_IMPL(TimeBalloonStateShowResult, End)
NERVES_MAKE_NOSTRUCT(TimeBalloonStateShowResult, Appear, Wait, End)
} // namespace
TimeBalloonStateShowResult::TimeBalloonStateShowResult(
StageSceneStateTimeBalloon* timeBalloon, al::SimpleLayoutAppearWaitEnd* layout,
const IBalloonFindMyAchievementHolder* achievementHolder, const al::LayoutInitInfo& info)
: al::HostStateBase<StageSceneStateTimeBalloon>("結果を見る(風船割りゲーム)", timeBalloon),
mAchievementHolder(achievementHolder) {
mAchievementLayout = new TimeBalloonAchievementLayout(info);
}
void TimeBalloonStateShowResult::init() {
initNerve(&Appear, 0);
}
void TimeBalloonStateShowResult::appear() {
al::NerveStateBase::appear();
al::setNerve(this, &Appear);
}
void TimeBalloonStateShowResult::exeAppear() {
if (al::isFirstStep(this)) {
mAchievementLayout->setAchievement(mAchievementHolder);
mAchievementLayout->appear();
}
mAchievementLayout->update();
if (mAchievementLayout->isWait())
al::setNerve(this, &Wait);
}
void TimeBalloonStateShowResult::exeWait() {
mAchievementLayout->update();
if (rs::isTriggerUiCancel(mAchievementLayout))
al::setNerve(this, &End);
}
void TimeBalloonStateShowResult::exeEnd() {
if (al::isFirstStep(this))
mAchievementLayout->end();
if (!mAchievementLayout->isAlive())
kill();
}
void TimeBalloonStateShowResult::setNerveWait() {
al::setNerve(this, &Wait);
}

View file

@ -0,0 +1,35 @@
#pragma once
#include "Library/Nerve/NerveStateBase.h"
namespace al {
class LayoutInitInfo;
class SimpleLayoutAppearWaitEnd;
} // namespace al
class IBalloonFindMyAchievementHolder;
class StageSceneStateTimeBalloon;
class TimeBalloonAchievementLayout;
class TimeBalloonStateShowResult : public al::HostStateBase<StageSceneStateTimeBalloon> {
public:
TimeBalloonStateShowResult(StageSceneStateTimeBalloon* timeBalloon,
al::SimpleLayoutAppearWaitEnd* layout,
const IBalloonFindMyAchievementHolder* achievementHolder,
const al::LayoutInitInfo& info);
void init() override;
void appear() override;
void exeAppear();
void exeWait();
void exeEnd();
void setNerveWait();
private:
const IBalloonFindMyAchievementHolder* mAchievementHolder = nullptr;
TimeBalloonAchievementLayout* mAchievementLayout = nullptr;
};
static_assert(sizeof(TimeBalloonStateShowResult) == 0x30);

View file

@ -82,18 +82,18 @@ void SmallBirdStateFlyAway::exeFlyAway() {
mIsColliding = false;
startActionAtRandomFrameIfNotPlaying(mActor, "Fly");
if (rs::isModeE3MovieRom()) {
gVerticalAccelIndex = al::modi(gVerticalAccelIndex + 7, 6);
gVerticalAccelIndex = al::wrapValue(gVerticalAccelIndex + 1, 6);
mVerticalAccel = gE3MovieVerticalAccel[gVerticalAccelIndex];
gHorizontalAccelIndex = al::modi(gHorizontalAccelIndex + 5, 4);
gHorizontalAccelIndex = al::wrapValue(gHorizontalAccelIndex + 1, 4);
mHorizontalAccel = gE3MovieHorizontalAccel[gHorizontalAccelIndex];
} else {
gVerticalAccelIndex = al::modi(gVerticalAccelIndex + 5, 4);
gVerticalAccelIndex = al::wrapValue(gVerticalAccelIndex + 1, 4);
mVerticalAccel = gVerticalAccel[gVerticalAccelIndex];
mHorizontalAccel = gHorizontalAccel;
}
mTargetAccelDir = {0, mVerticalAccel, mHorizontalAccel};
al::normalize(&mTargetAccelDir);
gCollisionCheckOffsetStep = al::modi(gCollisionCheckOffsetStep + 11, 10);
gCollisionCheckOffsetStep = al::wrapValue(gCollisionCheckOffsetStep + 1, 10);
mCollisionCheckOffsetStep = gCollisionCheckOffsetStep;
}

View file

@ -1,7 +1,14 @@
#pragma once
#include <prim/seadSafeString.h>
#include "Library/LiveActor/LiveActor.h"
namespace al {
class ActorDitherAnimator;
class WaterSurfaceFinder;
class PadRumbleKeeper;
} // namespace al
class PlayerInput;
class PlayerAreaChecker;
class PlayerWallActionHistory;
@ -15,6 +22,15 @@ class PlayerJointControlKeeper;
class HackCapJudgePreInputSeparateThrow;
class HackCapJudgePreInputSeparateJump;
class CapTargetInfo;
class PlayerColliderHackCap;
class HackCapTrigger;
class HackCapAboveGroundChecker;
class HackCapThrowParam;
class HackCapJointControlKeeper;
class PlayerExternalVelocity;
class PlayerPushReceiver;
class HackCapStateThrowStay;
class HackCapStateHide;
class HackCap : public al::LiveActor {
public:
@ -184,16 +200,103 @@ public:
bool stayWallHit();
void endHackThrow();
CapTargetInfo* getCapTargetInfo() const { return mCapTargetInfo; }
CapTargetInfo* getCapTargetInfo() const { return mCapTargetInfo1; }
private:
unsigned char _108[0x10];
al::LiveActor* mActorA;
unsigned char _120[0x08];
al::LiveActor* mPlayerActor;
void* _130[0x1f];
CapTargetInfo* mCapTargetInfo;
void* _230[0x7c];
al::LiveActor* mEquipmentHat;
al::LiveActor* mEquipmentHatDepthShadow;
al::LiveActor* mLockOnCapEyes;
al::LiveActor* mThrowingHatEyes;
const al::LiveActor* mPlayerActor;
const IUsePlayerCollision* mPlayerCollision;
const char* mTypeName;
const PlayerAreaChecker* mPlayerAreaChecker;
const PlayerSeparateCapFlag* mPlayerSeparateCapFlag;
const IUsePlayerHeightCheck* mPlayerHeightCheck;
const PlayerWetControl* mPlayerWetControl;
const PlayerJointControlKeeper* mPlayerJointControlKeeper;
PlayerColliderHackCap* mPlayerColliderHackCap;
al::WaterSurfaceFinder* mWaterSurfaceFinder;
al::PadRumbleKeeper* mPadRumbleKeeper;
PlayerWetControl* mSelfPlayerWetControl;
HackCapTrigger* mHackCapTrigger;
al::ActorDitherAnimator* mActorDitherAnimator;
HackCapAboveGroundChecker* mHackCapAboveGroundChecker;
void* _1a0_arr;
u64 _1a0_capacity;
s32 _1a0_current;
void* _1b8_arr;
u64 _1b8_capacity;
s32 _1b8_current;
const al::HitSensor* _1d0;
al::HitSensor* mAttackSensor;
sead::Vector3f mSpiralTailPositions[5];
HackCapThrowParam* mHackCapThrowParam;
CapTargetInfo* mCapTargetInfo1;
CapTargetInfo* mCapTargetInfo2;
void* _238;
sead::Vector3f _240;
sead::Vector3f _24c;
sead::Vector3f _258;
f32 _264;
sead::Vector2f _268;
f32 _270;
s32 _274;
s32 _278;
s32 _27c;
f32 _280;
f32 _284;
f32 _288;
f32 _28c;
s32 _290;
s32 _298;
bool _2a0[17];
const PlayerWallActionHistory* mPlayerWallActionHistory;
const PlayerCapActionHistory* mPlayerCapActionHistory;
const PlayerInput* mInput;
PlayerEyeSensorHitHolder* mPlayerEyeSensorHitHolder;
PlayerEyeSensorHitHolder* mCapEyeSensorHitHolder;
f32 _2d8;
s32 _2dc;
HackCapJointControlKeeper* mHackCapJointControlKeeper;
void* _2e8[5];
sead::FixedSafeString<128> _310;
sead::FixedSafeString<128> _3a8;
sead::Matrix34f _440;
sead::Matrix34f _470;
sead::Matrix34f _4a0;
bool _4d0;
sead::Vector3f _4d4;
sead::Vector3f _4e0;
bool _4ec;
void* _4f0;
PlayerExternalVelocity* mCapExternalVelocity;
PlayerPushReceiver* mCapPushReceiver;
al::HitSensor* mPlayerBodySensor;
bool _510;
sead::Vector3f _514;
HackCapJudgePreInputSeparateThrow* mCapJudgePreInputSeparateThrow;
HackCapJudgePreInputSeparateJump* mCapJudgePreInputSeparateJump;
bool _530;
s32 _534;
sead::Vector3f mWallPos;
sead::Vector3f mWallNormal;
sead::Vector3f mWallVelocity;
void* _560[4];
s32 _580;
s32 mLockOnCounter;
sead::Matrix34f _588;
bool _5b8;
bool mIsHackDamageVisible;
bool _5ba;
bool _5bb;
s32 _5bc;
void* _5c0[7];
bool mIsPuppet;
bool _5f9;
bool mIsHidePuppetCapSilhouette;
HackCapStateThrowStay* mStateThrowStay;
HackCapStateHide* mStateHide;
};
static_assert(sizeof(HackCap) == 0x610);

View file

@ -84,14 +84,25 @@ public:
private:
PlayerModelHolder* mModelHolder;
al::LiveActor* mPlayerDeco;
void* _10;
al::LiveActor* mPlayer;
PlayerAnimFrameCtrl* mAnimFrameCtrl;
sead::FixedSafeString<64> mCurAnim;
sead::FixedSafeString<64> mCurSubAnim;
sead::FixedSafeString<64> mCurUpperBodyAnim;
sead::FixedSafeString<64> _128;
char padding_180[0x1A2 - 0x180];
al::ActorDitherAnimator* mDitherAnim;
f32* mSklAnimBlendWeights;
void* _190;
f32 mRunStartAnimRate;
s32 _19c;
bool mIsNeedFullFaceAnim;
bool _1a1;
bool mIsSubAnimPlaying;
bool _1a3;
bool mIsUpperBodyAnimHeadVisKeep;
bool _1a5;
bool _1a6;
bool mIsSubAnimOnlyAir;
};
static_assert(sizeof(PlayerAnimator) == 0x1a8);

View file

@ -1,14 +1,44 @@
#pragma once
#include <basis/seadTypes.h>
namespace al {
class HitSensor;
}
class SensorMsg;
} // namespace al
class PlayerBindableSensorList;
class IUsePlayerPuppet;
class PlayerBindKeeper {
public:
PlayerBindKeeper(al::HitSensor*, IUsePlayerPuppet*);
bool sendStartMsg();
void clearBindableSensor();
void cancelBind();
bool receiveEndMsg(const al::SensorMsg*);
void clearBindImpl();
void cancelBindByDemo();
bool sendMsgBindDamage();
bool receiveRequestDamage();
bool sendMsgCollidedGround();
bool sendMsgEnableMapCheckPointWarp();
bool sendMsgBindKeepDemoStart();
bool sendMsgBindKeepDemoExecute();
bool sendMsgBindKeepDemoEnd();
bool sendMsgBindRecoveryLife() const;
bool collectBindableSensor(al::HitSensor*, al::HitSensor*);
void appendBindRequest(al::HitSensor*);
void resetInvalidTimer();
al::HitSensor* getBindSensor() const { return mBindSensor; }
private:
char padding[8];
al::HitSensor* mBodyHitSensor;
al::HitSensor* mBindSensor;
PlayerBindableSensorList* mBindableSensorList;
IUsePlayerPuppet* mPuppet;
s32 _20;
bool _24;
};
static_assert(sizeof(PlayerBindKeeper) == 0x28);

View file

@ -1,5 +1,6 @@
#pragma once
#include <container/seadPtrArray.h>
#include <math/seadMatrix.h>
#include <prim/seadBitFlag.h>
@ -13,6 +14,7 @@ class SpherePoseInterpolator;
} // namespace al
class CollidedShapeResult;
class CollisionShapeKeeper;
class CollisionMultiShape;
class PlayerCollider : public al::HioNode, public al::IUseCollision {
public:
@ -58,12 +60,48 @@ public:
void set1b0(f32 value) { _1b0 = value; }
private:
void* filler[13];
al::CollisionDirector* mCollisionDirector;
const sead::Matrix34f* mMtxPtr;
const sead::Vector3f* mTransPtr;
const sead::Vector3f* mGravityPtr;
sead::Vector3f mTrans;
f32 mSize;
sead::Matrix34f mMtx;
al::HitInfo* _68;
f32 _70;
void* filler2[37];
s32 _1a0;
al::HitInfo* _78;
f32 _7c;
al::HitInfo* _88;
f32 _8c;
sead::Vector3f mCollidedFixReaction;
bool _a0;
bool _a1;
sead::Vector3f mCollisionHitNormal;
sead::Vector3f mCollisionHitPos;
s32 mTimeInAir;
sead::Matrix34f mCollidePosMtx;
CollisionShapeKeeper* mCollisionShapeKeeper;
f32 mCollisionShapeScale;
CollisionMultiShape* mCollisionMultiShape;
s32 _108;
bool mIsInFastMoveCollisionArea;
bool mIsValidGroundSupport;
bool mIsDuringRecovery;
sead::Vector3f mCutCollideAffectDir;
s32 mWallBorderCheckType;
const al::CollisionPartsFilterBase* mCollisionPartsFilter;
sead::PtrArray<al::HitInfo> _128[3];
al::HitInfo* _158;
u32 _160;
s32 _164;
sead::PtrArray<al::HitInfo> _168;
s32 _178;
f32* _180;
s32 _188;
f32* _190;
sead::Vector3f _198;
sead::Vector3f mCollidedGroundNormal;
f32 _1b0;
};
static_assert(sizeof(PlayerCollider) == 0x1B8);
static_assert(sizeof(PlayerCollider) == 0x1b8);

View file

@ -1,7 +1,33 @@
#pragma once
#include <math/seadVector.h>
namespace al {
class LiveActor;
}
class ExternalForceKeeper;
class IUsePlayerCollision;
class PlayerExternalVelocity {
public:
bool isExistForce() const;
bool isExistSnapForce() const;
private:
ExternalForceKeeper* mExternalForceKeeper;
sead::Vector3f _8;
sead::Vector3f _14;
sead::Vector3f _20;
const al::LiveActor* mActor;
const IUsePlayerCollision* mCollision;
const sead::Vector3f* _38;
bool _40;
sead::Vector3f _44;
f32 _50[6];
sead::Vector3f mSnapForce;
s32 mApplyLastGroundInertia;
sead::Vector3f _80;
sead::Vector3f _8c;
};
static_assert(sizeof(PlayerExternalVelocity) == 0x98);

View file

@ -40,6 +40,7 @@
#include "Camera/ScenarioStartCamera.h"
#include "Enemy/Bubble.h"
#include "Enemy/CatchBomb.h"
#include "Enemy/DonkeyKong2D.h"
#include "Enemy/Gamane.h"
#include "Enemy/KaronWing.h"
#include "Enemy/Kuribo2D.h"
@ -69,6 +70,7 @@
#include "MapObj/AnagramAlphabet.h"
#include "MapObj/BlockEmpty2D.h"
#include "MapObj/BlockQuestion2D.h"
#include "MapObj/BossKnuckleFix.h"
#include "MapObj/CapBomb.h"
#include "MapObj/CapHanger.h"
#include "MapObj/CapSwitch.h"
@ -76,6 +78,7 @@
#include "MapObj/ChurchDoor.h"
#include "MapObj/CitySignal.h"
#include "MapObj/CoinCollectHintObj.h"
#include "MapObj/DoorCity.h"
#include "MapObj/Doshi.h"
#include "MapObj/ElectricWire/ElectricWire.h"
#include "MapObj/FireDrum2D.h"
@ -85,11 +88,15 @@
#include "MapObj/KoopaShip.h"
#include "MapObj/LavaPan.h"
#include "MapObj/MeganeMapParts.h"
#include "MapObj/MoonBasementBreakParts.h"
#include "MapObj/MoonBasementFloor.h"
#include "MapObj/MoonBasementSlideObj.h"
#include "MapObj/MoonWorldCaptureParadeLift.h"
#include "MapObj/PeachWorldTree.h"
#include "MapObj/PoleGrabCeil.h"
#include "MapObj/ReactionMapParts.h"
#include "MapObj/RiseMapPartsHolder.h"
#include "MapObj/RocketFlower.h"
#include "MapObj/RouletteSwitch.h"
#include "MapObj/SaveFlagCheckObj.h"
#include "MapObj/ShineTowerRocket.h"
@ -161,7 +168,7 @@ const al::NameToCreator<al::ActorCreatorFunction> sProjectActorFactoryEntries[]
{"BossForestWander", al::createActorFunction<BossForestWander>},
{"BossKnuckle", nullptr},
{"BossKnuckleCounterGround", nullptr},
{"BossKnuckleFix", nullptr},
{"BossKnuckleFix", al::createActorFunction<BossKnuckleFix>},
{"BossMagma", nullptr},
{"BossRaid", nullptr},
{"BossRaidNpc", nullptr},
@ -268,12 +275,12 @@ const al::NameToCreator<al::ActorCreatorFunction> sProjectActorFactoryEntries[]
{"DokanMaze", nullptr},
{"DokanMazeDirector", nullptr},
{"DokanStageChange", nullptr},
{"DonkeyKong2D", nullptr},
{"DonkeyKong2D", al::createActorFunction<DonkeyKong2D>},
{"Donsuke", nullptr},
{"Doshi", al::createActorFunction<Doshi>},
{"DoorAreaChange", nullptr},
{"DoorAreaChangeCap", nullptr},
{"DoorCity", nullptr},
{"DoorCity", al::createActorFunction<DoorCity>},
{"DoorSnow", nullptr},
{"DoorWarp", nullptr},
{"DoorWarpStageChange", nullptr},
@ -403,12 +410,12 @@ const al::NameToCreator<al::ActorCreatorFunction> sProjectActorFactoryEntries[]
{"MeganeKeyMoveMapParts", nullptr},
{"MeganeMapParts", al::createActorFunction<MeganeMapParts>},
{"Mirror", nullptr},
{"MoonBasementBreakParts", nullptr},
{"MoonBasementBreakParts", al::createActorFunction<MoonBasementBreakParts>},
{"MoonBasementClimaxWatcher", nullptr},
{"MoonBasementFallObj", nullptr},
{"MoonBasementFinalGate", nullptr},
{"MoonBasementFallObjDecoration", nullptr},
{"MoonBasementFloor", nullptr},
{"MoonBasementFloor", al::createActorFunction<MoonBasementFloor>},
{"MoonBasementGate", nullptr},
{"MoonBasementMeteorAreaObj", nullptr},
{"MoonBasementPillar", nullptr},
@ -665,9 +672,9 @@ const al::NameToCreator<al::ActorCreatorFunction> sProjectActorFactoryEntries[]
{"RailCollision", nullptr},
{"RailMoveMapParts", al::createActorFunction<al::RailMoveMapParts>},
{"RiseMapParts", nullptr},
{"ReactionMapParts", nullptr},
{"ReactionMapParts", al::createActorFunction<ReactionMapParts>},
{"RiseMapPartsHolder", al::createActorFunction<RiseMapPartsHolder>},
{"RocketFlower", nullptr},
{"RocketFlower", al::createActorFunction<RocketFlower>},
{"RollingCubeMapParts", al::createActorFunction<al::RollingCubeMapParts>},
{"RippleFixMapParts", nullptr},
{"RotateMapParts", al::createActorFunction<al::RotateMapParts>},

View file

@ -74,7 +74,7 @@ enum SceneObjID : s32 {
SceneObjID_TalkNpcSceneEventSwitcher,
SceneObjID_TestStageTimeDirector,
SceneObjID_TimeBalloonDirector,
SceneObjID__42,
SceneObjID_TouchActionMessageDirector,
SceneObjID_alTrafficAreaDirector,
SceneObjID_TrafficRailWatcher,
SceneObjID_TRexScrollBreakMapPartsBreakJudge,

View file

@ -6,6 +6,7 @@
#include "Layout/KidsModeLayoutAccessor.h"
#include "Layout/StageSceneLayout.h"
#include "Scene/StageSceneStateSnapShot.h"
#include "System/GameDataFunction.h"
#include "System/GameDataHolderAccessor.h"
#include "Util/AmiiboUtil.h"
@ -83,6 +84,12 @@ NERVES_MAKE_STRUCT(StageScene, StartStageBgm, CollectBgm, CollectionList, MiniGa
WarpToCheckpoint, DemoAppearFromHome, DemoRisePyramid, WaitWarpToCheckpoint)
} // namespace
bool StageScene::isIgnoreAddPlayTime() const {
if (!mStateSnapShot->isDead())
return true;
return al::isNerve(this, &NrvStageScene.Pause);
}
void StageScene::exeDemoGetLifeMaxUpItem() {
if (mIsUpdateKitAndGraphics) {
al::updateKit(this);

View file

@ -0,0 +1,30 @@
#pragma once
#include "Library/Nerve/NerveStateBase.h"
namespace al {
class Scene;
} // namespace al
class ControllerGuideSnapShotCtrl;
class InputSeparator;
class NpcEventDirector;
class SceneAudioSystemPauseController;
class StageSceneStateSnapShot : public al::HostStateBase<al::Scene> {
public:
StageSceneStateSnapShot(const char*, al::Scene*, ControllerGuideSnapShotCtrl*,
SceneAudioSystemPauseController*, InputSeparator*, NpcEventDirector*);
void appear() override;
void kill() override;
bool tryStart();
void exeWait();
private:
ControllerGuideSnapShotCtrl* mControllerGuideSnapShotCtrl;
SceneAudioSystemPauseController* mAudioSystemPauseController;
InputSeparator* mInputSeparator;
NpcEventDirector* mNpcEventDirector;
};
static_assert(sizeof(StageSceneStateSnapShot) == 0x40);

View file

@ -106,6 +106,7 @@ private:
sead::FixedSafeString<128> mCostumeName;
al::SimpleAudioUser* mPlayerAudioUser;
bool mIsHackEnd;
bool mIsWarpCheckpoint;
TimeBalloonSequenceInfo* mBalloonSeqInfo;
CollectBgmPlayer* mCollectBgmPlayer;
sead::FixedSafeString<128> mLanguage;

View file

@ -217,7 +217,7 @@ bool isMissEndPrevStageForSceneDead(GameDataHolderAccessor accessor) {
}
void reenterStage(GameDataHolderWriter writer) {
writer->set_4a();
writer->setStageEnding();
}
s32 getNextWorldId(GameDataHolderAccessor accessor) {

View file

@ -211,9 +211,9 @@ public:
GameDataFile* getGameDataFile() const { return mPlayingFile; }
void set_49() { _49 = true; }
void setStageChanging() { mIsStageChanging = true; }
void set_4a() { _4a = true; }
void setStageEnding() { mIsStageEnding = true; }
s64 getPlayTimeAcrossFile() const { return mPlayTimeAcrossFile; }
@ -293,8 +293,8 @@ private:
bool mIsRequireSave;
u32 mRequireSaveFrame;
bool mIsInvalidSaveForMoonGet;
bool _49; // related to changeNextStage(WithWorldDemoWarp)
bool _4a; // related to endStage
bool mIsStageChanging;
bool mIsStageEnding;
sead::FixedSafeString<32> mLanguage;
u64 mPlayTimeAcrossFile;
sead::Heap* mSaveDataWriteThread;

View file

@ -23,7 +23,12 @@ public:
void read(const al::ByamlIter& save) override;
private:
void* _padding[0x6];
bool mIsShowDemoOpenMoonRockFirst;
bool* mIsShowDemoOpenMoonRockWorld;
bool* mIsAppearedMoonRockTalkMessage;
bool mIsShowDemoAfterOpenMoonRockFirst;
bool* mIsShowDemoMoonRockMapWorld;
s32 mWorldNum;
};
static_assert(sizeof(MoonRockData) == 0x38);