1#include "Library/MapObj/BreakMapPartsBase.h"
2
3#include "Library/Audio/System/SimpleAudioUser.h"
4#include "Library/Base/StringUtil.h"
5#include "Library/Collision/PartsConnector.h"
6#include "Library/Effect/EffectKeeper.h"
7#include "Library/Item/ItemUtil.h"
8#include "Library/LiveActor/ActorActionFunction.h"
9#include "Library/LiveActor/ActorClippingFunction.h"
10#include "Library/LiveActor/ActorCollisionFunction.h"
11#include "Library/LiveActor/ActorInitFunction.h"
12#include "Library/LiveActor/ActorInitUtil.h"
13#include "Library/LiveActor/ActorModelFunction.h"
14#include "Library/LiveActor/ActorMovementFunction.h"
15#include "Library/LiveActor/ActorResourceFunction.h"
16#include "Library/LiveActor/LiveActorFunction.h"
17#include "Library/Math/MathUtil.h"
18#include "Library/Nerve/NerveSetupUtil.h"
19#include "Library/Nerve/NerveUtil.h"
20#include "Library/Obj/PartsFunction.h"
21#include "Library/Placement/PlacementFunction.h"
22#include "Library/Se/SeFunction.h"
23#include "Library/Stage/StageSwitchUtil.h"
24#include "Library/Thread/FunctorV0M.h"
25#include "Library/Yaml/ByamlIter.h"
26#include "Library/Yaml/ByamlUtil.h"
27
28namespace {
29using namespace al;
30
31NERVE_IMPL(BreakMapPartsBase, Wait)
32NERVE_IMPL(BreakMapPartsBase, Break)
33
34NERVES_MAKE_STRUCT(BreakMapPartsBase, Wait, Break)
35} // namespace
36
37namespace al {
38static void syncStageSwitchMakeActorDead(LiveActor* actor) {
39 using LiveActorFunctor = FunctorV0M<LiveActor*, void (LiveActor::*)()>;
40
41 listenStageSwitchOnOffKill(user: actor, actionOn: LiveActorFunctor(actor, &LiveActor::makeActorDead),
42 actionOff: LiveActorFunctor(actor, &LiveActor::makeActorAlive));
43 actor->makeActorAlive();
44}
45
46BreakMapPartsBase::BreakMapPartsBase(const char* name) : LiveActor(name) {}
47
48void BreakMapPartsBase::init(const ActorInitInfo& info) {
49 const char* suffix = nullptr;
50 tryGetStringArg(arg: &suffix, initInfo: info, key: "SuffixName");
51
52 if (suffix != nullptr && isEqualString(str1: suffix, str2: "None"))
53 suffix = nullptr;
54
55 initMapPartsActor(actor: this, initInfo: info, suffix);
56 initNerve(actor: this, nerve: &NrvBreakMapPartsBase.Wait, maxStates: 0);
57
58 ByamlIter iter;
59 bool isExistInitFile = tryGetActorInitFileIter(&iter, this, "InitBreakMapParts", nullptr);
60 const char* breakType = nullptr;
61 if (isExistInitFile) {
62 breakType = tryGetByamlKeyStringOrNULL(iter, "BreakType");
63 tryGetByamlV3f(&mItemOffset, iter, "ItemOffset");
64 tryGetByamlBool(&mIsExistHitReactionBreak, iter, "IsExistHitReactionBreak");
65 }
66
67 mJudgeFunction = getJudgeFunction(name: breakType);
68 mMtxConnector = tryCreateMtxConnector(actor: this, info);
69
70 syncStageSwitchMakeActorDead(actor: this);
71
72 if (isExistItemKeeper(actor: this))
73 setAppearItemOffset(actor: this, offset: mItemOffset);
74
75 bool isPlaySuccessSe = false;
76 if (tryGetArg(arg: &isPlaySuccessSe, initInfo: info, key: "IsPlaySuccessSe") && isPlaySuccessSe)
77 mAudioKeeper = new SimpleAudioUser("SuccessSeObj", info);
78}
79
80void BreakMapPartsBase::initAfterPlacement() {
81 if (mMtxConnector == nullptr)
82 return;
83
84 attachMtxConnectorToCollision(mtxConnector: mMtxConnector, actor: this, false);
85}
86
87void BreakMapPartsBase::kill() {
88 LiveActor::kill();
89
90 tryOnSwitchDeadOn(user: this);
91}
92
93void BreakMapPartsBase::movement() {
94 if (!isNerve(user: this, nerve: &NrvBreakMapPartsBase.Wait) || mMtxConnector != nullptr) {
95 LiveActor::movement();
96
97 return;
98 }
99
100 if (getEffectKeeper() != nullptr && getEffectKeeper()->get_21())
101 getEffectKeeper()->update();
102}
103
104void BreakMapPartsBase::calcAnim() {
105 if (isNerve(user: this, nerve: &NrvBreakMapPartsBase.Wait) && mMtxConnector == nullptr)
106 return;
107
108 LiveActor::calcAnim();
109}
110
111void BreakMapPartsBase::exeWait() {
112 if (mMtxConnector != nullptr)
113 connectPoseQT(actor: this, mtxConnector: mMtxConnector);
114}
115
116void BreakMapPartsBase::exeBreak() {
117 if (isFirstStep(user: this)) {
118 LiveActor* subActor = tryGetSubActor(actor: this, subActorName: "壊れモデル");
119 if (subActor != nullptr)
120 subActor->appear();
121
122 subActor = tryGetSubActor(actor: this, subActorName: "残留モデル");
123 if (subActor != nullptr) {
124 subActor->appear();
125
126 if (isTraceModelRandomRotate(actor: subActor))
127 addRotateAndRepeatY(actor: subActor, deg: getRandomDegree());
128 }
129
130 if (mIsExistHitReactionBreak)
131 startHitReaction(actor: this, name: "破壊");
132
133 if (mAudioKeeper != nullptr)
134 startSe(mAudioKeeper, "Riddle");
135
136 if (!isExistAction(actor: this, actionName: "Break")) {
137 kill();
138 } else {
139 startAction(actor: this, actionName: "Break");
140 hideModelIfShow(actor: this);
141 }
142
143 return;
144 }
145
146 kill();
147}
148
149void BreakMapPartsBase::startBreakByProgram() {
150 invalidateClipping(actor: this);
151 invalidateCollisionParts(this);
152
153 setNerve(user: this, nerve: &NrvBreakMapPartsBase.Break);
154}
155
156bool BreakMapPartsBase::receiveMsg(const SensorMsg* message, HitSensor* other, HitSensor* self) {
157 if (isNerve(user: this, nerve: &NrvBreakMapPartsBase.Wait) && mJudgeFunction(message, other, self)) {
158 startBreakByProgram();
159
160 return true;
161 }
162
163 return false;
164}
165} // namespace al
166