d_lyt_drop_line almost OK

This commit is contained in:
robojumper
2025-12-07 20:56:05 +01:00
parent 551fc3d154
commit 4bc36051dc
6 changed files with 533 additions and 102 deletions
+347
View File
@@ -0,0 +1,347 @@
#include "d/lyt/d_lyt_drop_line.h"
#include "common.h"
#include "d/a/d_a_item.h"
#include "d/lyt/meter/d_lyt_meter.h"
#include "d/snd/d_snd_small_effect_mgr.h"
#include "d/snd/d_snd_wzsound.h"
#include "f/f_base.h"
#include "m/m_color.h"
#include "m/m_vec.h"
#include "nw4r/math/math_types.h"
#include "toBeSorted/d_d3d.h"
#include "toBeSorted/d_emitter.h"
class dLytDropLine_HIO_c {
public:
dLytDropLine_HIO_c();
virtual ~dLytDropLine_HIO_c();
/* 0x04 */ f32 field_0x04;
/* 0x08 */ s32 mMoveDuration;
/* 0x0C */ u8 field_0x0C;
};
static dLytDropLine_HIO_c sHio;
dLytDropLine_HIO_c::dLytDropLine_HIO_c() : field_0x04(5.0f), mMoveDuration(10), field_0x0C(0) {}
dLytDropLine_HIO_c::~dLytDropLine_HIO_c() {}
STATE_DEFINE(dLytDropLineParts_c, Wait);
STATE_DEFINE(dLytDropLineParts_c, Move);
int dLytDropLineParts_c::create(dLytDropLine_c *main) {
mEmitter.init(main);
mpTargetPane = nullptr;
reset();
mStateMgr.changeState(StateID_Wait);
return fBase_c::SUCCEEDED;
}
int dLytDropLineParts_c::doDelete() {
// no-op
return fBase_c::SUCCEEDED;
}
int dLytDropLineParts_c::execute() {
mStateMgr.executeState();
return fBase_c::SUCCEEDED;
}
int dLytDropLineParts_c::draw() {
// no-op
return fBase_c::SUCCEEDED;
}
void dLytDropLineParts_c::startPickup(mVec3_c tearWorldPos, s32 trial) {
d3d::worldToScreen(mStartPos, tearWorldPos);
mStartPos.z = 0.0f;
mEffectPos = mStartPos;
mEffectPos.z = 0.0f;
mTrial = trial;
mMoveRequest = true;
mIsDone = false;
mLeftRight = false;
mIsChangeAnim = false;
}
void dLytDropLineParts_c::startChange(mVec3_c startPos, s32 trial, bool leftRight) {
mStartPos = startPos;
mEffectPos = mStartPos;
mTrial = trial;
mMoveRequest = true;
mIsDone = false;
mLeftRight = leftRight;
mIsChangeAnim = true;
}
void dLytDropLineParts_c::reset() {
mStartPos.setZero();
mEffectPos.setZero();
field_0x8C.setZero();
mMoveTimer = 0;
mTrial = 4;
mMoveRequest = false;
mIsDone = false;
mLeftRight = false;
mIsChangeAnim = false;
}
void dLytDropLineParts_c::initializeState_Wait() {}
void dLytDropLineParts_c::executeState_Wait() {
if (mMoveRequest) {
mStateMgr.changeState(StateID_Move);
}
}
void dLytDropLineParts_c::finalizeState_Wait() {}
void dLytDropLineParts_c::initializeState_Move() {
mMoveTimer = 0;
if (mpTargetPane != nullptr) {
nw4r::math::MTX34 mtx = mpTargetPane->GetGlobalMtx();
// TODO
mVec2_c v1 = mVec2_c(mtx._03, mtx._13);
v1 -= mVec2_c(mStartPos.x, mStartPos.y);
field_0x8C.x =
(v1.x + ((f32)sHio.mMoveDuration * sHio.field_0x04 * (f32)sHio.mMoveDuration)) / (f32)sHio.mMoveDuration;
field_0x8C.y = v1.y / (f32)sHio.mMoveDuration;
if (!mIsChangeAnim) {
dSndSmallEffectMgr_c::GetInstance()->playSound(SE_S_SIREN_SHIZUKU_GET_MOVE);
}
}
}
void dLytDropLineParts_c::executeState_Move() {
bool isDone = false;
if (mpTargetPane != nullptr) {
nw4r::math::MTX34 mtx = mpTargetPane->GetGlobalMtx();
mVec3_c panePos(mtx._03, mtx._13, 0.0f);
if (!mIsChangeAnim) {
if (dLytMeter_c::getfn_800C9FE0()) {
mEffectPos = panePos;
mStateMgr.changeState(StateID_Wait);
mMoveRequest = false;
mIsDone = true;
return;
}
}
if (mMoveTimer < sHio.mMoveDuration) {
// Quadratic parabola
if (mLeftRight) {
mEffectPos.x = mStartPos.x -
(field_0x8C.x * (f32)mMoveTimer - sHio.field_0x04 * (f32)mMoveTimer * (f32)mMoveTimer);
} else {
mEffectPos.x =
mStartPos.x + field_0x8C.x * (f32)mMoveTimer - sHio.field_0x04 * (f32)mMoveTimer * (f32)mMoveTimer;
}
mEffectPos.y = mStartPos.y + field_0x8C.y * (f32)mMoveTimer;
mEffectPos.z = 0.0f;
mMoveTimer++;
} else {
isDone = true;
mEffectPos = panePos;
}
static const mColor sColors1[] = {
mColor(0xA0, 0xFF, 0xB4, 0xFF), // #A0FFB4FF
mColor(0xFF, 0x80, 0xB4, 0xFF), // #FF80B4FF
mColor(0xFF, 0xFF, 0x80, 0xFF), // #FFFF80FF
mColor(0x80, 0xC8, 0xFF, 0xFF), // #80C8FFFF
};
static const mColor sColors2[] = {
mColor(0x00, 0xFF, 0x30, 0xFF), // #00FF30FF
mColor(0xFF, 0x40, 0x80, 0xFF), // #FF4080FF
mColor(0xFF, 0xFF, 0x00, 0xFF), // #FFFF00FF
mColor(0x60, 0x96, 0xFF, 0xFF), // #6096FFFF
};
mColor c1 = 0xFFFFFFFF;
mColor c2 = 0xFFFFFFFF;
switch (mTrial) {
case dAcItem_c::TRIAL_SKYLOFT:
c1 = sColors1[0];
c2 = sColors2[0];
break;
case dAcItem_c::TRIAL_FARON:
c1 = sColors1[1];
c2 = sColors2[1];
break;
case dAcItem_c::TRIAL_ELDIN:
c1 = sColors1[2];
c2 = sColors2[2];
break;
case dAcItem_c::TRIAL_LANAYRU:
c1 = sColors1[3];
c2 = sColors2[3];
break;
}
mEmitter.holdUIEffect(PARTICLE_RESOURCE_ID_MAPPING_138_, mEffectPos, nullptr, nullptr, &c1, &c2);
} else {
isDone = true;
}
if (isDone) {
mStateMgr.changeState(StateID_Wait);
mMoveRequest = false;
mIsDone = true;
mIsChangeAnim = false;
}
}
void dLytDropLineParts_c::finalizeState_Move() {}
SPECIAL_BASE_PROFILE(LYT_DROP_LINE, dLytDropLine_c, fProfile::LYT_DROP_LINE, 0x2B0, 0x6FD);
dLytDropLine_c *dLytDropLine_c::sInstance;
int dLytDropLine_c::create() {
sInstance->createInternal();
return SUCCEEDED;
}
int dLytDropLine_c::doDelete() {
sInstance->doDeleteInternal();
return SUCCEEDED;
}
int dLytDropLine_c::execute() {
if (sInstance != nullptr) {
sInstance->executeInternal();
}
return SUCCEEDED;
}
int dLytDropLine_c::draw() {
if (sInstance != nullptr) {
sInstance->drawInternal();
}
return SUCCEEDED;
}
void dLytDropLine_c::startPickup(mVec3_c tearWorldPos, dAcItem_c::Trial_e trial) {
if (sInstance != nullptr) {
sInstance->startPickupInternal(tearWorldPos, trial);
}
}
void dLytDropLine_c::startChange(
nw4r::lyt::Pane *tearSlotPane, nw4r::lyt::Pane *flowerPane, dAcItem_c::Trial_e trial, bool leftRight
) {
if (sInstance != nullptr) {
sInstance->startChangeInternal(tearSlotPane, flowerPane, trial, leftRight);
}
}
bool dLytDropLine_c::finishPart() {
if (sInstance != nullptr) {
return sInstance->finishPartInternal();
}
return false;
}
void dLytDropLine_c::setPane(nw4r::lyt::Pane *pane) {
if (sInstance != nullptr) {
sInstance->setPaneInternal(pane);
}
}
nw4r::lyt::Pane *dLytDropLine_c::getActivePane() {
if (sInstance != nullptr) {
return sInstance->getActivePaneInternal();
}
return nullptr;
}
int dLytDropLine_c::createInternal() {
for (int i = 0; i < NUM_PARTS; i++) {
mParts[i].create(this);
}
return true;
}
int dLytDropLine_c::doDeleteInternal() {
for (int i = 0; i < NUM_PARTS; i++) {
mParts[i].doDelete();
}
return SUCCEEDED;
}
int dLytDropLine_c::executeInternal() {
for (int i = 0; i < NUM_PARTS; i++) {
mParts[i].execute();
}
return SUCCEEDED;
}
int dLytDropLine_c::drawInternal() {
for (int i = 0; i < NUM_PARTS; i++) {
mParts[i].draw();
}
return SUCCEEDED;
}
void dLytDropLine_c::startPickupInternal(mVec3_c tearWorldPos, dAcItem_c::Trial_e trial) {
for (int i = 0; i < NUM_PARTS; i++) {
if (!mParts[i].isMoveRequest()) {
mParts[i].startPickup(tearWorldPos, trial);
return;
}
}
}
void dLytDropLine_c::startChangeInternal(
nw4r::lyt::Pane *tearSlotPane, nw4r::lyt::Pane *flowerPane, dAcItem_c::Trial_e trial, bool leftRight
) {
for (int i = 0; i < NUM_PARTS; i++) {
if (!mParts[i].isMoveRequest()) {
mParts[i].setTargetPane(flowerPane);
if (tearSlotPane != nullptr) {
nw4r::math::MTX34 mtx = tearSlotPane->GetGlobalMtx();
mVec3_c startPos(mtx._03, mtx._13, 0.0f);
mParts[i].startChange(startPos, trial, leftRight);
} else {
mVec3_c startPos(0.0f, -200.0f, 0.0f);
mParts[i].startChange(startPos, trial, leftRight);
}
return;
}
}
}
bool dLytDropLine_c::finishPartInternal() {
for (int i = 0; i < NUM_PARTS; i++) {
if (mParts[i].isDone()) {
mParts[i].finish();
return true;
}
}
return false;
}
void dLytDropLine_c::setPaneInternal(nw4r::lyt::Pane *pane) {
for (int i = 0; i < NUM_PARTS; i++) {
mParts[i].setTargetPane(pane);
}
}
nw4r::lyt::Pane *dLytDropLine_c::getActivePaneInternal() {
for (int i = 0; i < NUM_PARTS; i++) {
if (mParts[i].getTargetPane() != nullptr) {
return mParts[i].getTargetPane();
}
}
return nullptr;
}
+19 -19
View File
@@ -243,7 +243,7 @@ void LytMeterTimerPart1_c::startNextFruitAnim() {
}
void LytMeterTimerPart1_c::startFruitAnim(s32 index) {
if (field_0x780 < TIMER_01_NUM_TEARS && !mAnm[index + TIMER_01_ANIM_BOWL_NUT_OFFSET].isEnabled()) {
if (mChangeFruitIndex < TIMER_01_NUM_TEARS && !mAnm[index + TIMER_01_ANIM_BOWL_NUT_OFFSET].isEnabled()) {
mAnm[index + TIMER_01_ANIM_BOWL_NUT_OFFSET].setAnimEnable(true);
}
}
@@ -264,7 +264,7 @@ void LytMeterTimerPart1_c::disableCurrentFruitAnim() {
}
void LytMeterTimerPart1_c::stopFinishedFruit() {
for (s32 i = 0; i <= field_0x780; i++) {
for (s32 i = 0; i <= mChangeFruitIndex; i++) {
if (mAnm[i + TIMER_01_ANIM_BOWL_NUT_OFFSET].isEnabled() && mAnm[i + TIMER_01_ANIM_BOWL_NUT_OFFSET].isStop2()) {
mAnm[i + TIMER_01_ANIM_BOWL_NUT_OFFSET].setAnimEnable(false);
return;
@@ -292,7 +292,7 @@ bool LytMeterTimerPart1_c::isCurrentFruitAnimFinished() {
}
bool LytMeterTimerPart1_c::isAnyFruitAnimFinished() {
for (s32 i = 0; i <= field_0x780; i++) {
for (s32 i = 0; i <= mChangeFruitIndex; i++) {
if (mAnm[i + TIMER_01_ANIM_BOWL_NUT_OFFSET].isEnabled() && mAnm[i + TIMER_01_ANIM_BOWL_NUT_OFFSET].isStop2()) {
return true;
}
@@ -312,7 +312,7 @@ bool LytMeterTimerPart1_c::isOutAnimFinished() {
}
bool LytMeterTimerPart1_c::isAnyFruitAnimAtFrame(f32 f) const {
for (int i = 0; i <= field_0x780; i++) {
for (int i = 0; i <= mChangeFruitIndex; i++) {
if (mAnm[i + TIMER_01_ANIM_BOWL_NUT_OFFSET].isEnabled() &&
f - 1.0f < mAnm[i + TIMER_01_ANIM_BOWL_NUT_OFFSET].getFrame() &&
mAnm[i + TIMER_01_ANIM_BOWL_NUT_OFFSET].getFrame() <= f) {
@@ -324,7 +324,7 @@ bool LytMeterTimerPart1_c::isAnyFruitAnimAtFrame(f32 f) const {
bool LytMeterTimerPart1_c::incrementTearCount() {
mActualTearCount = ItemflagManager::sInstance->getFlagDirect(500);
if (mDisplayedTearCount < mActualTearCount && dLytDropLine_c::finishPartMaybe()) {
if (mDisplayedTearCount < mActualTearCount && dLytDropLine_c::finishPart()) {
startNextFruitAnim();
if (!dLytMeter_c::getfn_800C9FE0()) {
startEffect(mActualTearCount - 1);
@@ -402,9 +402,9 @@ void LytMeterTimerPart1_c::startEffect(s32 fruitIndex) {
);
}
void LytMeterTimerPart1_c::updateDropLine(nw4r::lyt::Pane *pane) {
u8 idx = field_0x780;
dLytDropLine_c::update(mpPanes[idx], pane, mTrial, field_0x780 % 2 != 0);
void LytMeterTimerPart1_c::startDropLineChange(nw4r::lyt::Pane *pane) {
u8 idx = mChangeFruitIndex;
dLytDropLine_c::startChange(mpPanes[idx], pane, mTrial, mChangeFruitIndex % 2 != 0);
}
static const d2d::LytBrlanMapping brlanMapPart2[] = {
@@ -1226,7 +1226,7 @@ void dLytMeterTimer_c::executeState_ChangeFruits() {
mpPart2->resetSingleAnim(TIMER_02_ANIM_FLOWER_LOOP);
}
if (dLytDropLine_c::finishPartMaybe()) {
if (dLytDropLine_c::finishPart()) {
if (mpPart1->isLastFruitAnimFinished()) {
mpPart2->realizeFruitsColor();
mpPart2->enableChangeFruitAnim();
@@ -1238,10 +1238,10 @@ void dLytMeterTimer_c::executeState_ChangeFruits() {
}
if (mpPart1->isAnyFruitAnimAtFrame(4.0f)) {
s32 fruit = mpPart1->getField0x780() + 1;
mpPart1->setField0x780(fruit);
if (mpPart1->getField0x780() < TIMER_01_NUM_TEARS) {
mpPart1->updateDropLine(mpPart2->i_getPane());
s32 fruit = mpPart1->getChangeFruitIndex() + 1;
mpPart1->setChangeFruitIndex(fruit);
if (mpPart1->getChangeFruitIndex() < TIMER_01_NUM_TEARS) {
mpPart1->startDropLineChange(mpPart2->i_getPane());
mpPart1->startFruitAnim(fruit);
mpPart1->startEffect(fruit);
}
@@ -1456,9 +1456,9 @@ void dLytMeterTimer_c::gotoSafe() {
void dLytMeterTimer_c::gotoChangeFruits6() {
if (mStateMgr.isState(StateID_Siren) || mStateMgr.isState(StateID_Safe)) {
mpPart1->resetBowlNuts();
mpPart1->updateDropLine(mpPart2->i_getPane());
mpPart1->startFruitAnim(mpPart1->getField0x780());
mpPart1->startEffect(mpPart1->getField0x780());
mpPart1->startDropLineChange(mpPart2->i_getPane());
mpPart1->startFruitAnim(mpPart1->getChangeFruitIndex());
mpPart1->startEffect(mpPart1->getChangeFruitIndex());
field_0x54 = false;
field_0x56 = 6;
mStateMgr.changeState(StateID_ChangeFruits);
@@ -1504,9 +1504,9 @@ void dLytMeterTimer_c::startSafe() {
void dLytMeterTimer_c::doPickup() {
mpPart1->resetBowlNuts();
mpPart1->updateDropLine(mpPart2->i_getPane());
mpPart1->startFruitAnim(mpPart1->getField0x780());
mpPart1->startEffect(mpPart1->getField0x780());
mpPart1->startDropLineChange(mpPart2->i_getPane());
mpPart1->startFruitAnim(mpPart1->getChangeFruitIndex());
mpPart1->startEffect(mpPart1->getChangeFruitIndex());
field_0x56 = 6;
}