1#include "Enemy/EnemyStateHackStart.h"
2
3#include "Library/LiveActor/ActorActionFunction.h"
4#include "Library/LiveActor/ActorAnimFunction.h"
5#include "Library/LiveActor/ActorFlagFunction.h"
6#include "Library/LiveActor/ActorMovementFunction.h"
7#include "Library/LiveActor/LiveActorFunction.h"
8#include "Library/Nerve/NerveSetupUtil.h"
9#include "Library/Nerve/NerveUtil.h"
10#include "Library/Shadow/ActorShadowUtil.h"
11
12#include "Player/PlayerHackStartShaderCtrl.h"
13#include "Util/Hack.h"
14#include "Util/SensorMsgFunction.h"
15
16namespace {
17NERVE_IMPL(EnemyStateHackStart, DiveIn);
18NERVE_IMPL(EnemyStateHackStart, HackStart);
19
20NERVES_MAKE_NOSTRUCT(EnemyStateHackStart, DiveIn, HackStart);
21} // namespace
22
23EnemyStateHackStartParam::EnemyStateHackStartParam(const char* actionName, const char* visAnimName,
24 const char* mtpAnimName, bool hasSubActors,
25 bool updateSubActorShadowMap)
26 : actionName(actionName), visAnimName(visAnimName), mtpAnimName(mtpAnimName),
27 hasSubActors(hasSubActors), updateSubActorShadowMap(updateSubActorShadowMap) {}
28
29static EnemyStateHackStartParam sEnemyStateHackStartParam("HackStart", 0, 0, 0, 0);
30
31EnemyStateHackStart::EnemyStateHackStart(al::LiveActor* rootActor,
32 const EnemyStateHackStartParam* param,
33 PlayerHackStartShaderParam* shaderParam)
34 : al::ActorStateBase("憑依開始", rootActor), mParam(param) {
35 if (!param)
36 mParam = &sEnemyStateHackStartParam;
37 initNerve(nerve: &DiveIn, stateCount: 0);
38 mPlayerHackStartShaderCtrl = new PlayerHackStartShaderCtrl(rootActor, shaderParam);
39}
40
41IUsePlayerHack* EnemyStateHackStart::tryStart(const al::SensorMsg* msg, al::HitSensor* other,
42 al::HitSensor* self) {
43 if (!rs::isMsgStartHack(msg))
44 return nullptr;
45 al::setVelocityZero(mActor);
46 mHackActor = rs::startHack(self, other, 0);
47 rs::startHackStartDemo(mHackActor, mActor);
48 al::setNerve(user: this, nerve: &DiveIn);
49 return mHackActor;
50}
51
52void EnemyStateHackStart::kill() {
53 al::NerveStateBase::kill();
54 if (!mHackActor)
55 return;
56 rs::endHackStartDemo(mHackActor, mActor);
57 mHackActor = nullptr;
58}
59
60bool EnemyStateHackStart::isHackStart() const {
61 return al::isNerve(user: this, nerve: &HackStart);
62}
63
64f32 EnemyStateHackStart::calcHackStartNerveRate() const {
65 if (!isHackStart())
66 return 0.0f;
67
68 s32 frameMax = al::getActionFrameMax(actor: mActor, actionName: mParam->actionName);
69 return al::calcNerveRate(user: this, max: frameMax);
70}
71
72void EnemyStateHackStart::exeDiveIn() {
73 if (!rs::isHackStartDemoEnterMario(mHackActor))
74 return;
75 if (mParam->actionName)
76 al::setNerve(user: this, nerve: &HackStart);
77 else
78 kill();
79}
80
81void EnemyStateHackStart::exeHackStart() {
82 if (al::isFirstStep(user: this)) {
83 mPlayerHackStartShaderCtrl->start();
84 al::startAction(actor: mActor, actionName: mParam->actionName);
85
86 if (mParam->hasSubActors) {
87 s32 subActorNum = al::getSubActorNum(actor: mActor);
88 for (s32 i = 0; i < subActorNum; i++)
89 if (al::isExistAction(actor: al::getSubActor(actor: mActor, index: i), actionName: mParam->actionName))
90 al::startAction(actor: al::getSubActor(actor: mActor, index: i), actionName: mParam->actionName);
91 }
92 if (mParam->visAnimName)
93 al::startVisAnim(mActor, mParam->visAnimName);
94 if (mParam->mtpAnimName)
95 al::startMtpAnim(mActor, mParam->mtpAnimName);
96 al::LiveActor* actor = mActor;
97 if (al::isExistDepthShadowMapCtrl(actor)) {
98 al::invalidateShadow(actor);
99 al::offDepthShadowModel(actor);
100 al::validateDepthShadowMap(actor);
101 }
102 if (mParam->updateSubActorShadowMap) {
103 s32 subActorNum = al::getSubActorNum(actor: mActor);
104 for (s32 i = 0; i < subActorNum; i++) {
105 al::LiveActor* subActor = al::getSubActor(actor: mActor, index: i);
106 if (al::isExistDepthShadowMapCtrl(actor: subActor)) {
107 al::invalidateShadow(actor: subActor);
108 al::offDepthShadowModel(actor: subActor);
109 al::validateDepthShadowMap(actor: subActor);
110 }
111 }
112 }
113 }
114 mPlayerHackStartShaderCtrl->update();
115 if (al::isActionEnd(actor: mActor)) {
116 mPlayerHackStartShaderCtrl->end();
117 kill();
118 }
119}
120
121namespace EnemyStateHackFunction {
122void startHackSwitchShadow(al::LiveActor* actor, const EnemyStateHackStartParam* param) {
123 if (al::isExistDepthShadowMapCtrl(actor)) {
124 al::invalidateShadow(actor);
125 al::offDepthShadowModel(actor);
126 al::validateDepthShadowMap(actor);
127 }
128 if (param && param->updateSubActorShadowMap) {
129 s32 subActorNum = al::getSubActorNum(actor);
130 for (s32 i = 0; i < subActorNum; i++) {
131 al::LiveActor* subActor = al::getSubActor(actor, index: i);
132 if (al::isExistDepthShadowMapCtrl(actor: subActor)) {
133 al::invalidateShadow(actor: subActor);
134 al::offDepthShadowModel(actor: subActor);
135 al::validateDepthShadowMap(actor: subActor);
136 }
137 }
138 }
139}
140
141void endHackSwitchShadow(al::LiveActor* actor, const EnemyStateHackStartParam* param) {
142 if (al::isExistDepthShadowMapCtrl(actor)) {
143 al::validateShadow(actor);
144 al::onDepthShadowModel(actor);
145 al::invalidateDepthShadowMap(actor);
146 }
147 if (param && param->updateSubActorShadowMap) {
148 s32 subActorNum = al::getSubActorNum(actor);
149 for (s32 i = 0; i < subActorNum; i++) {
150 al::LiveActor* subActor = al::getSubActor(actor, index: i);
151 if (al::isExistDepthShadowMapCtrl(actor: subActor)) {
152 al::validateShadow(actor: subActor);
153 al::onDepthShadowModel(actor: subActor);
154 al::invalidateDepthShadowMap(actor: subActor);
155 }
156 }
157 }
158}
159
160} // namespace EnemyStateHackFunction
161