mirror of
https://github.com/MonsterDruide1/OdysseyDecomp
synced 2026-05-10 01:09:26 +00:00
121 lines
4.2 KiB
C++
121 lines
4.2 KiB
C++
#include "Item/CoinCirclePlacement.h"
|
|
|
|
#include "Library/LiveActor/ActorClippingFunction.h"
|
|
#include "Library/LiveActor/ActorFlagFunction.h"
|
|
#include "Library/LiveActor/ActorInitUtil.h"
|
|
#include "Library/LiveActor/ActorPoseUtil.h"
|
|
#include "Library/Math/MathUtil.h"
|
|
#include "Library/Nerve/NerveSetupUtil.h"
|
|
#include "Library/Nerve/NerveUtil.h"
|
|
#include "Library/Placement/PlacementFunction.h"
|
|
#include "Library/Stage/StageSwitchUtil.h"
|
|
#include "Library/Thread/FunctorV0M.h"
|
|
|
|
#include "Item/Coin.h"
|
|
#include "Util/ShadowUtil.h"
|
|
|
|
namespace {
|
|
NERVE_IMPL(CoinCirclePlacement, Move);
|
|
|
|
NERVES_MAKE_STRUCT(CoinCirclePlacement, Move);
|
|
} // namespace
|
|
|
|
CoinCirclePlacement::CoinCirclePlacement(const char* name) : al::LiveActor(name) {}
|
|
|
|
void CoinCirclePlacement::init(const al::ActorInitInfo& info) {
|
|
using CoinCirclePlacementFunctor =
|
|
al::FunctorV0M<CoinCirclePlacement*, void (CoinCirclePlacement::*)()>;
|
|
|
|
al::initActor(this, info);
|
|
al::initNerve(this, &NrvCoinCirclePlacement.Move, 0);
|
|
al::getArg(&mCoinNum, info, "CoinNum");
|
|
|
|
if (mCoinNum <= 0) {
|
|
kill();
|
|
return;
|
|
}
|
|
|
|
al::getArg(&mRotateVelocity, info, "RotateVelocity");
|
|
al::tryGetArg(&mCircleXWidth, info, "CircleXWidth");
|
|
al::tryGetArg(&mCircleZWidth, info, "CircleZWidth");
|
|
al::tryGetSide(&mSide, info);
|
|
al::tryGetUp(&mUp, info);
|
|
al::tryGetFront(&mFront, info);
|
|
|
|
s32 coinNum = mCoinNum;
|
|
mCoinArray = new Coin*[mCoinNum];
|
|
for (s32 i = 0; i < mCoinNum; i++) {
|
|
Coin* coin = new Coin("コイン", false);
|
|
al::initCreateActorWithPlacementInfo(coin, info);
|
|
mCoinArray[i] = coin;
|
|
|
|
f32 coinAngle = sead::Mathf::deg2rad((360.0f / coinNum) * i);
|
|
f32 xWidth = mCircleXWidth * sead::Mathf::cos(coinAngle) * 100.0f;
|
|
f32 zWidth = mCircleZWidth * sead::Mathf::sin(coinAngle) * 100.0f;
|
|
|
|
const sead::Vector3f& centerPos = al::getTrans(this);
|
|
sead::Vector3f coinPos = centerPos + xWidth * mSide + zWidth * mFront;
|
|
|
|
al::setTrans(mCoinArray[i], coinPos);
|
|
al::setScale(mCoinArray[i], {1.0f, 1.0f, 1.0f});
|
|
al::tryAddDisplayOffset(mCoinArray[i], info);
|
|
al::expandClippingRadiusByShadowLength(
|
|
this, &_154, rs::setShadowDropLength(mCoinArray[i], info, "本体"));
|
|
mCoinArray[i]->appearCirclePlacement();
|
|
}
|
|
|
|
f32 clippingRadius = 0.0f;
|
|
const sead::Vector3f& centerPosition = al::getTrans(this);
|
|
for (s32 i = 0; i < mCoinNum; i++) {
|
|
sead::Vector3f distanceToCenter = al::getTrans(mCoinArray[i]) - centerPosition;
|
|
f32 coinRadius = distanceToCenter.length() + al::getClippingRadius(mCoinArray[i]);
|
|
clippingRadius = sead::Mathf::max(coinRadius, clippingRadius);
|
|
}
|
|
al::setClippingInfo(this, clippingRadius, al::getTransPtr(this));
|
|
|
|
if (!al::listenStageSwitchOnAppear(
|
|
this, CoinCirclePlacementFunctor(this, &CoinCirclePlacement::listenAppear))) {
|
|
makeActorAlive();
|
|
} else {
|
|
makeActorDead();
|
|
for (s32 i = 0; i < mCoinNum; i++)
|
|
mCoinArray[i]->makeActorDead();
|
|
}
|
|
}
|
|
|
|
void CoinCirclePlacement::listenAppear() {
|
|
for (s32 i = 0; i < mCoinNum; i++)
|
|
mCoinArray[i]->makeActorAlive();
|
|
makeActorAlive();
|
|
}
|
|
|
|
void CoinCirclePlacement::exeMove() {
|
|
if (al::isNearZero(mRotateVelocity))
|
|
return;
|
|
|
|
mCurrentAngle = al::wrapAngle(mCurrentAngle + mRotateVelocity);
|
|
|
|
s32 coinNum = mCoinNum;
|
|
bool isNoCoinAlive = true;
|
|
for (s32 i = 0; i < mCoinNum; i++) {
|
|
if (al::isDead(mCoinArray[i]) || !mCoinArray[i]->isWait())
|
|
continue;
|
|
f32 prevY = al::getTrans(mCoinArray[i]).y;
|
|
f32 coinAngle = sead::Mathf::deg2rad(al::wrapAngle(mCurrentAngle + (360.0f / coinNum) * i));
|
|
f32 xWidth = mCircleXWidth * sead::Mathf::cos(coinAngle) * 100.0f;
|
|
f32 zWidth = mCircleZWidth * sead::Mathf::sin(coinAngle) * 100.0f;
|
|
|
|
const sead::Vector3f& centerPos = al::getTrans(this);
|
|
// The coin's new position is inverted on the X axis from the spawn point.
|
|
// This is likely a game bug with no adverse effects.
|
|
sead::Vector3f newCoinPos = -xWidth * mSide + centerPos + zWidth * mFront;
|
|
newCoinPos.y = prevY;
|
|
|
|
al::setTrans(mCoinArray[i], newCoinPos);
|
|
isNoCoinAlive = false;
|
|
}
|
|
|
|
if (isNoCoinAlive)
|
|
kill();
|
|
}
|