1#include "Item/Coin2DCityDirector.h"
2
3#include "Library/Bgm/BgmBeatCounter.h"
4#include "Library/Bgm/BgmLineFunction.h"
5#include "Library/LiveActor/ActorClippingFunction.h"
6#include "Library/LiveActor/ActorInitFunction.h"
7#include "Library/LiveActor/ActorInitUtil.h"
8#include "Library/LiveActor/ActorPoseUtil.h"
9#include "Library/Nerve/NerveSetupUtil.h"
10#include "Library/Nerve/NerveUtil.h"
11#include "Library/Placement/PlacementFunction.h"
12#include "Library/Placement/PlacementInfo.h"
13
14#include "Item/Coin2DCity.h"
15
16namespace {
17NERVE_IMPL(Coin2DCityDirector, Wait);
18
19NERVES_MAKE_STRUCT(Coin2DCityDirector, Wait);
20} // namespace
21
22Coin2DCityDirector::Coin2DCityDirector(const char* name) : al::LiveActor(name) {}
23
24void Coin2DCityDirector::init(const al::ActorInitInfo& initInfo) {
25 al::initActorWithArchiveName(actor: this, initInfo, archiveName: "Coin2DCityDirector", suffix: nullptr);
26 if (!al::isExistLinkChild(initInfo, linkName: "FirstCoin", index: 0)) {
27 kill();
28 return;
29 }
30
31 al::tryGetArg(arg: &mNextCoinLightTime, initInfo, key: "NextCoinLightTime");
32 al::tryGetArg(arg: &mLightTime, initInfo, key: "LightTime");
33 al::tryGetArg(arg: &mLightInterval, initInfo, key: "LightInterval");
34 al::tryGetArg(arg: &mDelayTime, initInfo, key: "DelayTime");
35 if (mNextCoinLightTime <= -1 || mLightTime <= -1 || mLightInterval <= -1 || mDelayTime <= -1) {
36 kill();
37 return;
38 }
39
40 mCoinHolder.allocBuffer(ptrNumMax: 100, heap: nullptr);
41
42 al::PlacementInfo placementInfo;
43 al::getLinksInfo(linkPlacementInfo: &placementInfo, initInfo, linkName: "FirstCoin");
44 s32 linkNestNum = al::calcLinkNestNum(placementInfo, linkName: "NextCoin");
45
46 Coin2DCity* coin = new Coin2DCity("コイン2D都市", this);
47 al::initCreateActorWithPlacementInfo(actor: coin, initInfo, placementInfo);
48 al::initSubActorKeeperNoFile(this, initInfo, linkNestNum + 1);
49
50 mBgmBeatCounter = new al::BgmBeatCounter(this, -0.28f);
51 al::initNerve(actor: this, nerve: &NrvCoin2DCityDirector.Wait, maxStates: 0);
52 makeActorAlive();
53}
54
55void Coin2DCityDirector::initAfterPlacement() {
56 sead::Vector3f minPos = sead::Vector3f::zero;
57 sead::Vector3f maxPos = sead::Vector3f::zero;
58
59 s32 size = mCoinHolder.size();
60 for (s32 i = 0; i < size; i++) {
61 al::registerSubActorSyncClipping(this, mCoinHolder[i]);
62 const sead::Vector3f& trans = al::getTrans(actor: mCoinHolder[i]);
63
64 if (i == 0) {
65 minPos = trans;
66 maxPos = trans;
67 continue;
68 }
69
70 minPos.x = sead::Mathf::min(a: minPos.x, b: trans.x);
71 minPos.y = sead::Mathf::min(a: minPos.y, b: trans.y);
72 minPos.z = sead::Mathf::min(a: minPos.z, b: trans.z);
73
74 maxPos.x = sead::Mathf::max(a: maxPos.x, b: trans.x);
75 maxPos.y = sead::Mathf::max(a: maxPos.y, b: trans.y);
76 maxPos.z = sead::Mathf::max(a: maxPos.z, b: trans.z);
77 }
78
79 mClippingPos = (maxPos + minPos) * 0.5f;
80 f32 clippingSize = (maxPos - minPos).length() * 0.5f + 500.0f;
81 al::setClippingInfo(actor: this, clippingSize, &mClippingPos);
82}
83
84void Coin2DCityDirector::control() {
85 return mBgmBeatCounter->update();
86}
87
88void Coin2DCityDirector::registerCoin(Coin2DCity* coin) {
89 mCoinHolder.pushBack(ptr: coin);
90}
91
92void Coin2DCityDirector::getCoin() {
93 if (++mCoinsCollected < mCoinHolder.size())
94 return;
95
96 s32 size = mCoinHolder.size();
97 for (s32 i = 0; i < size; i++)
98 mCoinHolder[i]->kill();
99
100 kill();
101}
102
103bool Coin2DCityDirector::isTriggerBeat() const {
104 return mBgmBeatCounter->isOnBeat();
105}
106
107void Coin2DCityDirector::exeWait() {
108 if (al::isEnableRhythmAnim(this, nullptr)) {
109 if (mBgmBeatCounter->isTriggerBeat(interval: mLightInterval, delayTime: mDelayTime))
110 mCoinHolder.front()->startLight();
111 return;
112 }
113
114 if (al::isFirstStep(user: this))
115 return;
116
117 if (al::getNerveStep(user: this) % mLightInterval == 0)
118 mCoinHolder.front()->startLight();
119}
120