| 1 | #include "Npc/ShineTowerNpc.h" |
| 2 | |
| 3 | #include <prim/seadSafeString.h> |
| 4 | |
| 5 | #include "Library/LiveActor/ActorInitUtil.h" |
| 6 | #include "Library/LiveActor/ActorModelFunction.h" |
| 7 | #include "Library/LiveActor/ActorMovementFunction.h" |
| 8 | #include "Library/Math/MathUtil.h" |
| 9 | #include "Library/Message/MessageHolder.h" |
| 10 | #include "Library/Message/MessageTagDataHolder.h" |
| 11 | #include "Library/Nerve/NerveSetupUtil.h" |
| 12 | #include "Library/Nerve/NerveUtil.h" |
| 13 | #include "Library/Player/PlayerUtil.h" |
| 14 | |
| 15 | #include "System/GameDataFunction.h" |
| 16 | #include "Util/NpcEventFlowUtil.h" |
| 17 | |
| 18 | namespace { |
| 19 | NERVE_IMPL(ShineTowerNpc, Wait); |
| 20 | NERVE_IMPL(ShineTowerNpc, GoKoopa); |
| 21 | NERVE_IMPL(ShineTowerNpc, NoBalloon); |
| 22 | |
| 23 | NERVES_MAKE_STRUCT(ShineTowerNpc, Wait, GoKoopa); |
| 24 | NERVES_MAKE_NOSTRUCT(ShineTowerNpc, NoBalloon); |
| 25 | } // namespace |
| 26 | |
| 27 | ShineTowerNpc::ShineTowerNpc(const char* name) : al::LiveActor(name) {} |
| 28 | |
| 29 | void ShineTowerNpc::init(const al::ActorInitInfo& actorInitInfo) { |
| 30 | al::initActorWithArchiveName(actor: this, initInfo: actorInitInfo, archiveName: "NpcCap" , suffix: nullptr); |
| 31 | al::initNerve(actor: this, nerve: &NrvShineTowerNpc.Wait, maxStates: 0); |
| 32 | mEventFlowExecutor = rs::initEventFlow(this, actorInitInfo, "HomeMechanicNpc" , nullptr); |
| 33 | al::MessageTagDataHolder* msgTagDataHolder = al::initMessageTagDataHolder(1); |
| 34 | al::registerMessageTagDataScore(msgTagDataHolder, "Score" , &mRemainingShineCount); |
| 35 | rs::initEventMessageTagDataHolder(mEventFlowExecutor, msgTagDataHolder); |
| 36 | |
| 37 | makeActorAlive(); |
| 38 | al::hideModel(actor: this); |
| 39 | mRemainingShineCount = getRemainingShineCount(actor: this); |
| 40 | if (mRemainingShineCount == 0) |
| 41 | al::setNerve(user: this, nerve: &NrvShineTowerNpc.GoKoopa); |
| 42 | } |
| 43 | |
| 44 | s32 getRemainingShineCount(al::LiveActor* actor) { |
| 45 | bool isGameClear = false; |
| 46 | s32 unlockShine = GameDataFunction::findUnlockShineNum(isGameClear: &isGameClear, accessor: actor); |
| 47 | s32 payShine = GameDataFunction::getPayShineNum(accessor: actor); |
| 48 | if (isGameClear) |
| 49 | payShine = GameDataFunction::getTotalPayShineNum(accessor: actor); |
| 50 | |
| 51 | return sead::Mathi::max(a: 0, b: unlockShine - payShine); |
| 52 | } |
| 53 | |
| 54 | void ShineTowerNpc::noBalloon() { |
| 55 | al::setNerve(user: this, nerve: &NoBalloon); |
| 56 | } |
| 57 | |
| 58 | void ShineTowerNpc::startBalloon() { |
| 59 | mRemainingShineCount = getRemainingShineCount(actor: this); |
| 60 | if (mRemainingShineCount == 0) |
| 61 | al::setNerve(user: this, nerve: &NrvShineTowerNpc.GoKoopa); |
| 62 | else |
| 63 | al::setNerve(user: this, nerve: &NrvShineTowerNpc.Wait); |
| 64 | } |
| 65 | |
| 66 | void ShineTowerNpc::exeWait() { |
| 67 | if (al::isFirstStep(user: this)) { |
| 68 | sead::FixedSafeString<0x40> string; |
| 69 | string.format(formatStr: "RestShineNum" ); |
| 70 | rs::startEventFlow(mEventFlowExecutor, string.cstr()); |
| 71 | } |
| 72 | |
| 73 | al::turnToTarget(actor: this, target: al::getPlayerActor(this, 0), deg: 2.0f); |
| 74 | mRemainingShineCount = getRemainingShineCount(actor: this); |
| 75 | if (mRemainingShineCount == 0) { |
| 76 | al::setNerve(user: this, nerve: &NrvShineTowerNpc.GoKoopa); |
| 77 | return; |
| 78 | } |
| 79 | rs::updateEventFlow(mEventFlowExecutor); |
| 80 | } |
| 81 | |
| 82 | void ShineTowerNpc::exeGoKoopa() { |
| 83 | if (al::isFirstStep(user: this)) |
| 84 | rs::startEventFlow(mEventFlowExecutor, "GoKoopa" ); |
| 85 | |
| 86 | al::turnToTarget(actor: this, target: al::getPlayerActor(this, 0), deg: 2.0f); |
| 87 | rs::updateEventFlow(mEventFlowExecutor); |
| 88 | } |
| 89 | |
| 90 | void ShineTowerNpc::exeNoBalloon() { |
| 91 | mRemainingShineCount = getRemainingShineCount(actor: this); |
| 92 | } |
| 93 | |