1#include "MapObj/TrampleBush.h"
2
3#include "Library/LiveActor/ActorActionFunction.h"
4#include "Library/LiveActor/ActorInitUtil.h"
5#include "Library/LiveActor/ActorMovementFunction.h"
6#include "Library/LiveActor/ActorPoseUtil.h"
7#include "Library/LiveActor/ActorSensorUtil.h"
8#include "Library/Math/MathUtil.h"
9#include "Library/Nerve/NerveSetupUtil.h"
10#include "Library/Nerve/NerveUtil.h"
11
12#include "Util/ItemGenerator.h"
13#include "Util/SensorMsgFunction.h"
14
15namespace {
16NERVE_IMPL(TrampleBush, Wait);
17NERVE_IMPL(TrampleBush, Reaction);
18NERVE_IMPL(TrampleBush, Trample);
19
20NERVES_MAKE_STRUCT(TrampleBush, Wait, Reaction, Trample);
21} // namespace
22
23TrampleBush::TrampleBush(const char* actorName) : al::LiveActor(actorName) {}
24
25void TrampleBush::init(const al::ActorInitInfo& info) {
26 al::initMapPartsActor(actor: this, initInfo: info, suffix: nullptr);
27 mItemGenerator = new ItemGenerator(this, info);
28 al::initNerve(actor: this, nerve: &NrvTrampleBush.Wait, maxStates: 0);
29 makeActorAlive();
30}
31
32void TrampleBush::initAfterPlacement() {
33 if (mItemGenerator->isNone()) {
34 sead::Quatf randomRotation;
35 al::calcQuat(quat: &randomRotation, actor: this);
36 al::rotateQuatYDirDegree(&randomRotation, randomRotation, al::getRandomDegree());
37 al::updatePoseQuat(actor: this, quat: randomRotation);
38 }
39}
40
41void TrampleBush::attackSensor(al::HitSensor* self, al::HitSensor* other) {
42 rs::sendMsgPushToPlayer(source: other, target: self) || al::sendMsgPush(receiver: other, sender: self);
43}
44
45inline bool TrampleBush::isReady() {
46 return al::isNerve(user: this, nerve: &NrvTrampleBush.Wait) && al::isGreaterEqualStep(user: this, step: 10);
47}
48
49inline bool TrampleBush::isSensorOnSwitch(const al::SensorMsg* message, al::HitSensor* other) {
50 sead::Vector3f prevTrans = mAttackerTrans;
51 sead::Vector3f actorTrans = al::getActorTrans(other);
52 mAttackerTrans.set(actorTrans);
53
54 return !al::isNear(value: prevTrans, target: actorTrans, tolerance: 3.0f) && isReady();
55}
56
57bool TrampleBush::receiveMsg(const al::SensorMsg* message, al::HitSensor* other,
58 al::HitSensor* self) {
59 if (rs::isMsgPlayerDisregardHomingAttack(message))
60 return true;
61 if (rs::isMsgPlayerDisregardTargetMarker(message))
62 return true;
63 if (al::isMsgPlayerDisregard(msg: message))
64 return true;
65
66 if (al::isNerve(user: this, nerve: &NrvTrampleBush.Wait) || al::isNerve(user: this, nerve: &NrvTrampleBush.Reaction)) {
67 if (rs::isMsgFrogHackTrample(message)) {
68 al::setNerve(user: this, nerve: &NrvTrampleBush.Reaction);
69 al::startAction(actor: this, actionName: "Reaction");
70 return true;
71 }
72
73 if (rs::isMsgCapAttack(message) && isReady()) {
74 al::setNerve(user: this, nerve: &NrvTrampleBush.Reaction);
75 al::startAction(actor: this, actionName: "Reaction");
76 return true;
77 }
78
79 if (al::isMsgEnemyTouch(msg: message) || al::isMsgPlayerTouch(msg: message) ||
80 al::isMsgPlayerObjTouch(msg: message)) {
81 if (isSensorOnSwitch(message, other)) {
82 al::setNerve(user: this, nerve: &NrvTrampleBush.Reaction);
83 al::startAction(actor: this, actionName: "Reaction");
84 return true;
85 }
86 }
87
88 if (rs::isMsgPressDown(message)) {
89 al::setNerve(user: this, nerve: &NrvTrampleBush.Trample);
90 return true;
91 }
92 }
93 return false;
94}
95
96void TrampleBush::exeWait() {}
97
98void TrampleBush::exeReaction() {
99 if (al::isActionEnd(actor: this))
100 al::setNerve(user: this, nerve: &NrvTrampleBush.Wait);
101}
102
103void TrampleBush::exeTrample() {
104 if (al::isFirstStep(user: this)) {
105 al::startAction(actor: this, actionName: "Trample");
106 al::invalidateHitSensors(this);
107 return;
108 }
109 if (al::isActionEnd(actor: this)) {
110 al::startHitReaction(actor: this, name: "消滅");
111 if (!mItemGenerator->isNone()) {
112 sead::Vector3f frontDir;
113 al::calcFrontDir(front: &frontDir, actor: this);
114 mItemGenerator->generate(pos: al::getTrans(actor: this), vec: frontDir);
115 }
116 kill();
117 }
118}
119