1#include "Item/Coin2D.h"
2
3#include <math/seadQuat.h>
4#include <math/seadVector.h>
5
6#include "Library/Collision/PartsConnector.h"
7#include "Library/Controller/PadRumbleFunction.h"
8#include "Library/LiveActor/ActorActionFunction.h"
9#include "Library/LiveActor/ActorClippingFunction.h"
10#include "Library/LiveActor/ActorInitUtil.h"
11#include "Library/LiveActor/ActorMovementFunction.h"
12#include "Library/LiveActor/ActorPoseUtil.h"
13#include "Library/LiveActor/ActorSensorUtil.h"
14#include "Library/Math/MathUtil.h"
15#include "Library/Nerve/NerveSetupUtil.h"
16#include "Library/Nerve/NerveUtil.h"
17#include "Library/Placement/PlacementFunction.h"
18#include "Library/Stage/StageSwitchUtil.h"
19#include "Library/Thread/FunctorV0M.h"
20
21#include "System/GameDataFunction.h"
22#include "Util/ActorDimensionKeeper.h"
23#include "Util/ActorDimensionUtil.h"
24#include "Util/AreaUtil.h"
25#include "Util/ItemUtil.h"
26#include "Util/SensorMsgFunction.h"
27
28namespace {
29NERVE_IMPL(Coin2D, Appear);
30NERVE_IMPL(Coin2D, Wait);
31NERVE_IMPL(Coin2D, Got);
32NERVE_IMPL_(Coin2D, GotNoCoin, Got);
33NERVE_IMPL(Coin2D, CountUp);
34
35NERVES_MAKE_NOSTRUCT(Coin2D, GotNoCoin);
36NERVES_MAKE_STRUCT(Coin2D, Wait, Appear, CountUp, Got);
37} // namespace
38
39Coin2D::Coin2D(const char* name) : al::LiveActor(name) {}
40
41void Coin2D::init(const al::ActorInitInfo& initInfo) {
42 using Coin2DFunctor = al::FunctorV0M<Coin2D*, void (Coin2D::*)()>;
43
44 al::initActorWithArchiveName(actor: this, initInfo, archiveName: "CoinDot", suffix: nullptr);
45 mMtxConnector = al::tryCreateMtxConnector(actor: this, info: initInfo);
46 if (mMtxConnector != nullptr)
47 al::tryGetArg(arg: &mIsConnectToCollisionBack, initInfo, key: "IsConnectToCollisionBack");
48
49 al::initNerve(actor: this, nerve: &NrvCoin2D.Wait, maxStates: 0);
50 al::tryAddDisplayOffset(actor: this, initInfo);
51 mDimensionKeeper = rs::createDimensionKeeper(actor: this);
52 rs::updateDimensionKeeper(keeper: mDimensionKeeper);
53
54 mIsPlaced = al::isPlaced(initInfo);
55 if (mIsPlaced)
56 rs::snap2DParallelizeFront(this, this, 500.0f);
57
58 if (al::listenStageSwitchOnAppear(user: this, action: Coin2DFunctor(this, &Coin2D::listenAppear)))
59 makeActorDead();
60 else
61 makeActorAlive();
62
63 al::startAction(actor: this, actionName: "Wait");
64}
65
66void Coin2D::initAfterPlacement() {
67 if (mMtxConnector != nullptr) {
68 if (!mIsConnectToCollisionBack) {
69 al::attachMtxConnectorToCollision(mtxConnector: mMtxConnector, actor: this, 50.0f, 400.0f);
70 return;
71 }
72 sead::Vector3f frontDir = sead::Vector3f::zero;
73 al::calcFrontDir(front: &frontDir, actor: this);
74 al::attachMtxConnectorToCollision(
75 mtxConnector: mMtxConnector, actor: this, al::getTrans(actor: this) + frontDir * 50.0f, frontDir * -400.0f);
76 }
77}
78
79void Coin2D::appear() {
80 al::LiveActor::appear();
81 if (mMtxConnector != nullptr)
82 al::connectPoseQT(actor: this, mtxConnector: mMtxConnector);
83}
84
85void Coin2D::control() {
86 if (mMtxConnector != nullptr)
87 al::connectPoseQT(actor: this, mtxConnector: mMtxConnector);
88}
89
90void Coin2D::endClipped() {
91 rs::syncCoin2DAnimFrame(actor: this, name: "Wait");
92 al::LiveActor::endClipped();
93}
94
95bool Coin2D::receiveMsg(const al::SensorMsg* message, al::HitSensor* other, al::HitSensor* self) {
96 if (al::isMsgPlayerDisregard(msg: message))
97 return true;
98
99 if (rs::isMsgBlockUpperPunch2D(message)) {
100 if (al::isNerve(user: this, nerve: &NrvCoin2D.Wait) || al::isNerve(user: this, nerve: &NrvCoin2D.Appear)) {
101 al::invalidateClipping(actor: this);
102 sead::Vector3f up = sead::Vector3f::zero;
103 al::calcQuatUp(up: &up, actor: this);
104 al::setVelocityToDirection(actor: this, dir: up, speed: 16.0f);
105 al::setNerve(user: this, nerve: &NrvCoin2D.CountUp);
106 return true;
107 }
108 return false;
109 }
110
111 if (rs::isMsgItemGet2D(message) &&
112 (al::isNerve(user: this, nerve: &NrvCoin2D.Wait) || al::isNerve(user: this, nerve: &NrvCoin2D.Appear))) {
113 al::startHitReaction(actor: this, name: "取得");
114 al::setNerve(user: this, nerve: &NrvCoin2D.Got);
115 return true;
116 }
117
118 return false;
119}
120
121void Coin2D::listenAppear() {
122 appear();
123 al::invalidateClipping(actor: this);
124 al::setNerve(user: this, nerve: &NrvCoin2D.Appear);
125}
126
127void Coin2D::appearCountUp() {
128 appear();
129 al::invalidateClipping(actor: this);
130 sead::Vector3f up = sead::Vector3f::zero;
131 al::calcQuatUp(up: &up, actor: this);
132 al::setVelocityToDirection(actor: this, dir: up, speed: 16.0f);
133
134 al::AreaObj* areaObj = rs::tryFind2DAreaObj(actor: this, nullptr, nullptr);
135 if (areaObj != nullptr) {
136 sead::Vector3f lockDir = sead::Vector3f::zero;
137 rs::calc2DAreaLockDir(lockDir: &lockDir, area: areaObj, trans: al::getTrans(actor: this));
138 sead::Quatf quat = sead::Quatf::unit;
139 al::makeQuatFrontUp(outQuat: &quat, front: -lockDir, up);
140 al::setQuat(actor: this, quat);
141 }
142
143 al::setNerve(user: this, nerve: &NrvCoin2D.CountUp);
144}
145
146void Coin2D::get() {
147 al::startHitReaction(actor: this, name: "取得");
148 al::setNerve(user: this, nerve: &NrvCoin2D.Got);
149}
150
151bool Coin2D::isGot() const {
152 return al::isNerve(user: this, nerve: &NrvCoin2D.Got);
153}
154
155void Coin2D::exeAppear() {
156 if (al::isFirstStep(user: this))
157 al::startAction(actor: this, actionName: "Appear");
158
159 if (al::isActionEnd(actor: this)) {
160 al::startAction(actor: this, actionName: "Wait");
161 rs::syncCoin2DAnimFrame(actor: this, name: "Wait");
162 al::setNerve(user: this, nerve: &NrvCoin2D.Wait);
163 }
164}
165
166void Coin2D::exeWait() {}
167
168void Coin2D::exeGot() {
169 if (al::isFirstStep(user: this)) {
170 al::startAction(actor: this, actionName: "Got");
171 al::onStageSwitch(user: this, linkName: "SwitchGetOn");
172 alPadRumbleFunction::startPadRumble(actor: this, name: "コッ(微弱)", near: 1000.0f, far: 3000.0f);
173 if (!al::isNerve(user: this, nerve: &GotNoCoin))
174 GameDataFunction::addCoin(writer: this, count: 1);
175 }
176 if (al::isActionEnd(actor: this))
177 kill();
178}
179
180void Coin2D::exeCountUp() {
181 if (al::isFirstStep(user: this)) {
182 al::startAction(actor: this, actionName: "Got");
183 GameDataFunction::addCoin(writer: this, count: 1);
184 al::startHitReaction(actor: this, name: "自動取得[開始]");
185 }
186
187 sead::Vector3f gravityDir = {0.0f, 0.0f, 0.0f};
188 al::calcQuatGravity(out: &gravityDir, quat: al::getQuat(actor: this));
189 al::addVelocityToDirection(actor: this, dir: gravityDir, force: 0.6f);
190 al::scaleVelocity(actor: this, factor: 0.99f);
191 al::getVelocity(actor: this);
192 al::getQuat(actor: this);
193
194 if (al::isGreaterEqualStep(user: this, step: 32)) {
195 al::startHitReaction(actor: this, name: "自動取得[終了]");
196 al::setNerve(user: this, nerve: &GotNoCoin);
197 }
198}
199