1#include "Layout/CoinCounter.h"
2
3#include "Library/Layout/LayoutActionFunction.h"
4#include "Library/Layout/LayoutActorUtil.h"
5#include "Library/Layout/LayoutInitInfo.h"
6#include "Library/Nerve/NerveSetupUtil.h"
7#include "Library/Nerve/NerveUtil.h"
8#include "Library/Se/SeFunction.h"
9
10#include "System/GameDataFunction.h"
11#include "Util/StageLayoutFunction.h"
12
13namespace {
14NERVE_IMPL(CoinCounter, Appear);
15NERVE_IMPL(CoinCounter, Wait);
16NERVE_IMPL(CoinCounter, End);
17NERVE_IMPL(CoinCounter, Add);
18NERVE_IMPL(CoinCounter, Sub);
19NERVE_IMPL(CoinCounter, CountAnimAdd);
20NERVE_IMPL(CoinCounter, CountAnimSub);
21
22NERVES_MAKE_NOSTRUCT(CoinCounter, Wait);
23NERVES_MAKE_STRUCT(CoinCounter, Appear, End, Add, Sub, CountAnimAdd, CountAnimSub);
24} // namespace
25
26CoinCounter::CoinCounter(const char* name, const al::LayoutInitInfo& initInfo, bool isCoin)
27 : al::LayoutActor(name), mIsCoin(isCoin) {
28 if (mIsCoin) {
29 al::initLayoutActor(this, initInfo, "CounterCoin", nullptr);
30 mNumDigits = 4;
31 mPanelName = "Coin";
32 } else {
33 al::initLayoutActor(this, initInfo, "CounterCollectCoin", nullptr);
34 mNumDigits = 3;
35 mPanelName = "CollectCoin";
36 al::setPaneString(this, "TxtIcon", rs::getWorldCoinCollectPictureFont(this), 0);
37 al::setPaneString(this, "TxtIconSh", rs::getWorldCoinCollectPictureFont(this), 0);
38 }
39
40 initNerve(&NrvCoinCounter.Appear, 0);
41 kill();
42 updatePanel(coinCount: mCoinNum, numDigits: mNumDigits);
43}
44
45void CoinCounter::kill() {
46 al::setNerve(user: this, nerve: &NrvCoinCounter.Appear);
47 al::LayoutActor::kill();
48}
49
50void CoinCounter::updatePanel(u32 coinCount, s32 numDigits) {
51 if (numDigits == 4) {
52 al::IUseLayout* layout = static_cast<al::LayoutActor*>(this);
53 al::setPaneStringFormat(layout, "TxtCounter", "%04d", coinCount);
54 al::setPaneStringFormat(layout, "TxtCounterSh", "%04d", coinCount);
55 al::requestCaptureRecursive(this);
56 }
57 if (numDigits == 3) {
58 al::IUseLayout* layout = static_cast<al::LayoutActor*>(this);
59 al::setPaneStringFormat(layout, "TxtCounter", "%03d", coinCount);
60 al::setPaneStringFormat(layout, "TxtCounterSh", "%03d", coinCount);
61 al::requestCaptureRecursive(this);
62 }
63}
64
65bool CoinCounter::isWait() const {
66 return al::isNerve(user: this, nerve: &Wait);
67}
68
69void CoinCounter::tryStart() {
70 if (al::isNerve(user: this, nerve: &NrvCoinCounter.Appear)) {
71 al::startAction(layout: this, actionName: "Appear", paneName: nullptr);
72 updateCountImmidiate();
73 al::LayoutActor::appear();
74 al::setNerve(user: this, nerve: &NrvCoinCounter.End);
75 }
76}
77
78void CoinCounter::updateCountImmidiate() {
79 s32 newCoinNum = getCountFromData();
80 s32 newTotalCoins = getCountTotalFromData();
81
82 mTotalCoins = newTotalCoins;
83 mCoinNum = newCoinNum;
84 updatePanel(coinCount: mCoinNum, numDigits: mNumDigits);
85}
86
87void CoinCounter::tryEnd() {
88 if (!al::isNerve(user: this, nerve: &NrvCoinCounter.Appear))
89 al::setNerve(user: this, nerve: &NrvCoinCounter.Appear);
90}
91
92void CoinCounter::startCountAnim(s32 coinNum) {
93 s32 prevCoinCount = mCoinNum;
94 mCoinNum = coinNum;
95 mPrevCoinCount = prevCoinCount;
96 mTotalCoins = getCountTotalFromData();
97
98 if (coinNum < prevCoinCount)
99 al::setNerve(user: this, nerve: &NrvCoinCounter.Sub);
100 else
101 al::setNerve(user: this, nerve: &NrvCoinCounter.Add);
102}
103
104bool CoinCounter::tryUpdateCount() {
105 s32 newCoinNum = getCountFromData();
106 s32 newTotalCoins = getCountTotalFromData();
107
108 if (mTotalCoins == newTotalCoins) {
109 if (newCoinNum >= mCoinNum)
110 return false;
111 }
112
113 al::Nerve* nerve;
114 if (mTotalCoins < newTotalCoins)
115 nerve = &NrvCoinCounter.CountAnimAdd;
116 else
117 nerve = &NrvCoinCounter.CountAnimSub;
118
119 mTotalCoins = newTotalCoins;
120 mCoinNum = newCoinNum;
121 al::setNerve(user: this, nerve);
122 return true;
123}
124
125s32 CoinCounter::getCountFromData() const {
126 if (mIsCoin)
127 return GameDataFunction::getCoinNum(accessor: this);
128
129 return GameDataFunction::getCoinCollectNum(accessor: this);
130}
131
132s32 CoinCounter::getCountTotalFromData() const {
133 if (mIsCoin)
134 return GameDataFunction::getTotalCoinNum(accessor: this);
135
136 return GameDataFunction::getCoinCollectGotNum(accessor: this);
137}
138
139void CoinCounter::exeAppear() {
140 if (al::isActionEnd(layout: this, paneName: nullptr))
141 al::setNerve(user: this, nerve: &Wait);
142}
143
144void CoinCounter::exeWait() {
145 if (al::isFirstStep(user: this))
146 al::startAction(layout: this, actionName: "Wait", paneName: nullptr);
147 if (mIsUpdateCount)
148 tryUpdateCount();
149}
150
151void CoinCounter::exeEnd() {
152 if (al::isFirstStep(user: this))
153 al::startAction(layout: this, actionName: "End", paneName: nullptr);
154 if (al::isActionEnd(layout: this, paneName: nullptr))
155 kill();
156}
157
158void CoinCounter::exeAdd() {
159 if (al::isFirstStep(user: this)) {
160 al::startAction(layout: this, actionName: "Add", paneName: mPanelName);
161 updatePanel(coinCount: mCoinNum, numDigits: mNumDigits);
162 }
163 if (al::isActionEnd(layout: this, paneName: nullptr))
164 al::setNerve(user: this, nerve: &Wait);
165}
166
167void CoinCounter::exeSub() {
168 if (al::isFirstStep(user: this)) {
169 al::startAction(layout: this, actionName: "Add", paneName: mPanelName);
170 updatePanel(coinCount: mCoinNum, numDigits: mNumDigits);
171 }
172 if (al::isActionEnd(layout: this, paneName: nullptr))
173 al::setNerve(user: this, nerve: &Wait);
174}
175
176void CoinCounter::exeCountAnimAdd() {
177 if (al::isFirstStep(user: this))
178 mAnimationCount = mPrevCoinCount;
179
180 if (al::isGreaterEqualStep(user: this, step: 60)) {
181 updatePanel(coinCount: mCoinNum, numDigits: mNumDigits);
182 al::setNerve(user: this, nerve: &Wait);
183 return;
184 }
185
186 s32 animationCount = al::calcNerveValue(user: this, max: 60, start: mPrevCoinCount, end: mCoinNum);
187 updatePanel(coinCount: animationCount, numDigits: mNumDigits);
188
189 if (mAnimationCount != animationCount) {
190 al::startSe(this, mIsCoin ? "CoinCount" : "CoinCollectCount");
191 mAnimationCount = animationCount;
192 }
193
194 al::holdSe(this, "CoinCount_loop");
195}
196
197void CoinCounter::exeCountAnimSub() {
198 if (al::isFirstStep(user: this))
199 mAnimationCount = mPrevCoinCount;
200
201 if (al::isGreaterEqualStep(user: this, step: 60)) {
202 updatePanel(coinCount: mCoinNum, numDigits: mNumDigits);
203 al::setNerve(user: this, nerve: &Wait);
204 return;
205 }
206
207 s32 animationCount = al::calcNerveValue(user: this, max: 60, start: mPrevCoinCount, end: mCoinNum);
208 updatePanel(coinCount: animationCount, numDigits: mNumDigits);
209
210 if (mAnimationCount != animationCount) {
211 al::startSe(this, mIsCoin ? "CoinCount" : "CoinCollectCount");
212 mAnimationCount = animationCount;
213 }
214
215 al::holdSe(this, "CoinCount_loop");
216}
217