1#include "Library/Obj/EffectObj.h"
2
3#include "Library/Base/StringUtil.h"
4#include "Library/Collision/PartsConnector.h"
5#include "Library/Effect/EffectKeeper.h"
6#include "Library/Effect/EffectSystemInfo.h"
7#include "Library/LiveActor/ActorInitUtil.h"
8#include "Library/LiveActor/ActorPoseUtil.h"
9#include "Library/Matrix/MatrixUtil.h"
10#include "Library/Nerve/NerveSetupUtil.h"
11#include "Library/Obj/EffectObjFunction.h"
12#include "Library/Placement/PlacementFunction.h"
13#include "Library/Rail/RailUtil.h"
14#include "Library/Se/SeFunction.h"
15#include "Library/Stage/StageSwitchUtil.h"
16#include "Library/Thread/FunctorV0M.h"
17
18namespace al {
19EffectObj::EffectObj(const char* name) : LiveActor(name) {}
20
21void EffectObj::init(const ActorInitInfo& info) {
22 using EffectObjFunctor = FunctorV0M<EffectObj*, void (EffectObj::*)()>;
23
24 EffectObjFunction::initActorEffectObj(actor: this, info);
25
26 const char* className = nullptr;
27 getClassName(name: &className, initInfo: info);
28
29 if (isEqualString(str1: "EffectObjScale", str2: className)) {
30 mIsEffectObjScale = true;
31
32 setEffectEmitterVolumeScale(this, "Wait", getScale(actor: this));
33 }
34
35 trySyncStageSwitchAppear(actor: this);
36 tryListenStageSwitchKill(actor: this);
37
38 listenStageSwitchOnOff(user: this, eventName: "OnKillOffAppearSwitch", actionOn: EffectObjFunctor(this, &EffectObj::kill),
39 actionOff: EffectObjFunctor(this, &EffectObj::appear));
40
41 if (isExistRail(initInfo: info, linkName: "Rail")) {
42 tryGetArg(arg: (s32*)&mMoveType, initInfo: info, key: "MoveType");
43 tryGetArg(arg: &mRailMoveSpeed, initInfo: info, key: "RailMoveSpeed");
44 setRailPosToStart(this);
45 setRailClippingInfo(&mRailPos, actor: this, 100.0f, 100.0f);
46 tryGetArg(arg: &mIsSyncRailPose, initInfo: info, key: "IsSyncRailPose");
47 }
48
49 mMtxConnector = tryCreateMtxConnector(actor: this, info);
50}
51
52void EffectObj::initAfterPlacement() {
53 if (mMtxConnector == nullptr)
54 return;
55
56 attachMtxConnectorToCollision(mtxConnector: mMtxConnector, actor: this, false);
57}
58
59void EffectObj::control() {
60 if (isExistRail(railHolder: this)) {
61 switch (mMoveType) {
62 case MoveType::Turn:
63 moveSyncRailTurn(actor: this, speed: mRailMoveSpeed);
64 break;
65 case MoveType::Loop:
66 moveSyncRailLoop(actor: this, speed: mRailMoveSpeed);
67 break;
68 default:
69 moveSyncRail(actor: this, mRailMoveSpeed);
70 break;
71 }
72
73 if (mIsSyncRailPose) {
74 sead::Vector3f railUp;
75 sead::Matrix34f poseMtx;
76
77 const sead::Vector3f& railDir = getRailDir(railHolder: this);
78 calcRailUp(&railUp, railHolder: this);
79 const sead::Vector3f& railTrans = getTrans(actor: this);
80 makeMtxFrontUpPos(outMtx: &poseMtx, front: railDir, up: railUp, pos: railTrans);
81 updatePoseMtx(actor: this, mtx: &poseMtx);
82 }
83 } else if (mMtxConnector != nullptr)
84 connectPoseQT(actor: this, mtxConnector: mMtxConnector);
85
86 makeMtxRT(mtx: &mBaseMtx, actor: this);
87 tryEmitStart();
88}
89
90void EffectObj::appear() {
91 mIsStarted = false;
92
93 LiveActor::appear();
94}
95
96void EffectObj::kill() {
97 mIsStarted = false;
98
99 LiveActor::kill();
100}
101
102bool EffectObj::tryEmitStart() {
103 if (mIsStarted)
104 return false;
105
106 emitEffect(this, "Wait", nullptr);
107 alEffectFunction::emitEffectIfExist(effectKeeperHolder: this, effectName: "Wait2", pos: nullptr);
108 tryStartSe(this, "Wait");
109 mIsStarted = true;
110
111 return true;
112}
113} // namespace al
114