1#include "Item/CoinCollectEmpty.h"
2
3#include <math/seadVector.h>
4
5#include "Library/Collision/PartsConnector.h"
6#include "Library/Controller/PadRumbleFunction.h"
7#include "Library/Effect/EffectSystemInfo.h"
8#include "Library/LiveActor/ActorActionFunction.h"
9#include "Library/LiveActor/ActorClippingFunction.h"
10#include "Library/LiveActor/ActorInitFunction.h"
11#include "Library/LiveActor/ActorInitUtil.h"
12#include "Library/LiveActor/ActorModelFunction.h"
13#include "Library/LiveActor/ActorMovementFunction.h"
14#include "Library/LiveActor/ActorPoseUtil.h"
15#include "Library/Nature/NatureUtil.h"
16#include "Library/Nerve/NerveSetupUtil.h"
17#include "Library/Nerve/NerveUtil.h"
18
19#include "Item/CoinRotateCalculator.h"
20#include "Item/CoinStateCountUp.h"
21#include "System/GameDataFunction.h"
22#include "Util/ExternalForceKeeper.h"
23#include "Util/SensorMsgFunction.h"
24#include "Util/ShadowUtil.h"
25
26namespace {
27NERVE_IMPL(CoinCollectEmpty, Wait);
28NERVE_IMPL(CoinCollectEmpty, Got);
29NERVE_IMPL(CoinCollectEmpty, CountUp);
30
31NERVES_MAKE_STRUCT(CoinCollectEmpty, Wait, Got, CountUp);
32} // namespace
33
34CoinCollectEmpty::CoinCollectEmpty(const char* name, const char* archiveName)
35 : al::LiveActor(name), mArchiveName(archiveName) {}
36
37void CoinCollectEmpty::init(const al::ActorInitInfo& initInfo) {
38 al::initActorSceneInfo(actor: this, info: initInfo);
39 al::initActorWithArchiveName(actor: this, initInfo, archiveName: mArchiveName, suffix: nullptr);
40 al::initNerve(actor: this, nerve: &NrvCoinCollectEmpty.Wait, maxStates: 1);
41 mStateCountUp = new CoinStateCountUp(this);
42 al::initNerveState(user: this, state: mStateCountUp, nerve: &NrvCoinCollectEmpty.Got, hostName: "カウントアップ状態");
43 mRotateCalculator = new CoinRotateCalculator(this);
44 al::tryAddDisplayOffset(actor: this, initInfo);
45 mMtxConnector = al::tryCreateMtxConnector(actor: this, info: initInfo);
46 mExternalForceKeeper = new ExternalForceKeeper();
47 al::expandClippingRadiusByShadowLength(actor: this, nullptr,
48 radius: rs::setShadowDropLength(this, initInfo, "本体"));
49
50 if (al::isExistDitherAnimator(actor: this))
51 al::stopDitherAnimAutoCtrl(actor: this);
52
53 al::setModelAlphaMask(actor: this, 0.499f);
54 al::setEffectNamedMtxPtr(this, "WaterSurface", &mWaterSurfaceMatrix);
55 makeActorAlive();
56}
57
58void CoinCollectEmpty::initAfterPlacement() {
59 if (mMtxConnector != nullptr)
60 al::attachMtxConnectorToCollision(mtxConnector: mMtxConnector, actor: this, false);
61}
62
63bool CoinCollectEmpty::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
64 al::HitSensor* self) {
65 if (rs::isMsgFishingItemGet(message) && al::isNerve(user: this, nerve: &NrvCoinCollectEmpty.Wait)) {
66 al::invalidateClipping(actor: this);
67 al::setNerve(user: this, nerve: &NrvCoinCollectEmpty.Got);
68 return true;
69 }
70
71 if ((rs::isMsgCapAttack(message) || rs::isMsgItemGetAll(message)) &&
72 al::isNerve(user: this, nerve: &NrvCoinCollectEmpty.Wait)) {
73 al::invalidateClipping(actor: this);
74 al::setNerve(user: this, nerve: &NrvCoinCollectEmpty.CountUp);
75 return false;
76 }
77
78 if (rs::isMsgFishingLineTouch(message)) {
79 mRotateCalculator->addFishingLineTouch();
80 return true;
81 }
82
83 return false;
84}
85
86void CoinCollectEmpty::endClipped() {
87 mRotateCalculator->reset();
88 al::LiveActor::endClipped();
89}
90
91void CoinCollectEmpty::appear() {
92 mExternalForceKeeper->reset();
93 al::LiveActor::appear();
94}
95
96void CoinCollectEmpty::control() {
97 sead::Vector3f force = sead::Vector3f::zero;
98 mExternalForceKeeper->calcForce(force: &force);
99 mExternalForceKeeper->reset();
100 mRotateCalculator->update(force, checkWater: true);
101}
102
103void CoinCollectEmpty::rotate() {
104 if (mMtxConnector != nullptr)
105 al::connectPoseQT(actor: this, mtxConnector: mMtxConnector);
106
107 al::setQuat(actor: this, quat: sead::Quatf::unit);
108 al::rotateQuatYDirDegree(actor: this, deg: mRotateCalculator->getRotate());
109}
110
111void CoinCollectEmpty::exeWait() {
112 rotate();
113}
114
115void CoinCollectEmpty::exeGot() {
116 if (al::isFirstStep(user: this)) {
117 alPadRumbleFunction::startPadRumble(actor: this, name: "コッ(微弱)", near: 500.0f, far: 2000.0f);
118 al::startAction(actor: this, actionName: "Got");
119 GameDataFunction::addCoin(writer: this, count: 1);
120 GameDataFunction::addCoin(writer: this, count: 1);
121 al::hideModelIfShow(actor: this);
122 }
123 if (al::isGreaterEqualStep(user: this, step: 30))
124 kill();
125}
126
127void CoinCollectEmpty::exeCountUp() {
128 if (al::isFirstStep(user: this)) {
129 GameDataFunction::addCoin(writer: this, count: 1);
130 GameDataFunction::addCoin(writer: this, count: 1);
131 }
132
133 if (!mIsNotInWater && !al::isInWater(this)) {
134 sead::Vector3f waterSurface = sead::Vector3f::zero;
135 al::calcFindWaterSurface(&waterSurface, nullptr, this, al::getTrans(actor: this),
136 sead::Vector3f::ey, 200.0f);
137 mWaterSurfaceMatrix.setBase(axis: 3, v: waterSurface);
138 al::startHitReaction(actor: this, name: "水しぶき");
139 mIsNotInWater = true;
140 }
141
142 if (al::updateNerveState(user: this)) {
143 al::startHitReaction(actor: this, name: "釣り取得");
144 kill();
145 }
146}
147