1#include "Library/Obj/EffectObjFollowCameraLimit.h"
2
3#include "Library/Camera/CameraUtil.h"
4#include "Library/Effect/EffectKeeper.h"
5#include "Library/Effect/EffectSystemInfo.h"
6#include "Library/LiveActor/ActorClippingFunction.h"
7#include "Library/LiveActor/ActorFlagFunction.h"
8#include "Library/LiveActor/ActorInitUtil.h"
9#include "Library/LiveActor/ActorPoseUtil.h"
10#include "Library/Math/MathUtil.h"
11#include "Library/Matrix/MatrixUtil.h"
12#include "Library/Nerve/NerveSetupUtil.h"
13#include "Library/Nerve/NerveUtil.h"
14#include "Library/Obj/EffectObjFunction.h"
15#include "Library/Placement/PlacementFunction.h"
16#include "Library/Se/SeFunction.h"
17#include "Library/Stage/StageSwitchUtil.h"
18#include "Library/Thread/FunctorV0M.h"
19
20namespace al {
21namespace {
22NERVE_IMPL(EffectObjFollowCameraLimit, Wait)
23NERVE_IMPL(EffectObjFollowCameraLimit, Disappear)
24
25NERVES_MAKE_NOSTRUCT(EffectObjFollowCameraLimit, Wait, Disappear)
26} // namespace
27
28EffectObjFollowCameraLimit::EffectObjFollowCameraLimit(const char* name) : LiveActor(name) {}
29
30void EffectObjFollowCameraLimit::init(const ActorInitInfo& info) {
31 using EffectObjFollowCameraLimitFunctor =
32 FunctorV0M<EffectObjFollowCameraLimit*, void (EffectObjFollowCameraLimit::*)()>;
33
34 EffectObjFunction::initActorEffectObj(actor: this, info);
35 invalidateClipping(actor: this);
36 setEffectNamedMtxPtr(this, "Wait", &mBaseMtx);
37 initNerve(actor: this, nerve: &Wait, maxStates: 0);
38
39 listenStageSwitchOnOffAppear(
40 user: this, actionOn: EffectObjFollowCameraLimitFunctor(this, &EffectObjFollowCameraLimit::startAppear),
41 actionOff: EffectObjFollowCameraLimitFunctor(this, &EffectObjFollowCameraLimit::startDisappear)) ?
42 makeActorDead() :
43 makeActorAlive();
44
45 tryGetArg(arg: &mLimitBottom, initInfo: info, key: "LimitBottom");
46 tryGetArg(arg: &mLimitTop, initInfo: info, key: "LimitTop");
47
48 listenStageSwitchOnOffAppear(
49 user: this, actionOn: EffectObjFollowCameraLimitFunctor(this, &EffectObjFollowCameraLimit::startAppear),
50 actionOff: EffectObjFollowCameraLimitFunctor(this, &EffectObjFollowCameraLimit::startDisappear));
51
52 listenStageSwitchOnOff(
53 user: this, eventName: "OnKillOffAppearSwitch",
54 actionOn: EffectObjFollowCameraLimitFunctor(this, &EffectObjFollowCameraLimit::kill),
55 actionOff: EffectObjFollowCameraLimitFunctor(this, &EffectObjFollowCameraLimit::startAppear));
56
57 listenStageSwitchOnKill(
58 user: this, action: EffectObjFollowCameraLimitFunctor(this, &EffectObjFollowCameraLimit::startDisappear));
59}
60
61void EffectObjFollowCameraLimit::startAppear() {
62 if (isDead(actor: this))
63 appear();
64
65 setNerve(user: this, nerve: &Wait);
66}
67
68void EffectObjFollowCameraLimit::startDisappear() {
69 setNerve(user: this, nerve: &Disappear);
70}
71
72void EffectObjFollowCameraLimit::control() {
73 sead::Vector3f front;
74 sead::Vector3f pos;
75
76 calcCameraFront(&front, user: this, viewIdx: 0);
77 pos.set(getCameraPos(user: this, viewIdx: 0));
78
79 pos.y = sead::Mathf::max(a: pos.y, b: mLimitBottom);
80
81 if (!isNearZero(value: mLimitTop + 1))
82 pos.y = sead::Mathf::min(a: pos.y, b: mLimitTop);
83
84 if (!isParallelDirection(a: sead::Vector3f::ey, b: front, tolerance: 0.01f))
85 makeMtxUpFrontPos(outMtx: &mBaseMtx, up: sead::Vector3f::ey, front, pos);
86}
87
88void EffectObjFollowCameraLimit::kill() {
89 LiveActor::kill();
90}
91
92void EffectObjFollowCameraLimit::appear() {
93 LiveActor::appear();
94}
95
96void EffectObjFollowCameraLimit::exeWait() {
97 if (isFirstStep(user: this)) {
98 tryEmitEffect(this, "Wait", nullptr);
99 tryStartSe(this, "Wait");
100 }
101}
102
103void EffectObjFollowCameraLimit::exeDisappear() {
104 if (isFirstStep(user: this))
105 deleteEffect(this, "Wait");
106
107 if (isStep(user: this, step: 180))
108 kill();
109}
110} // namespace al
111