1#include "Library/Movement/EnemyStateBlowDown.h"
2
3#include "Library/LiveActor/ActorActionFunction.h"
4#include "Library/LiveActor/ActorClippingFunction.h"
5#include "Library/LiveActor/ActorCollisionFunction.h"
6#include "Library/LiveActor/ActorFlagFunction.h"
7#include "Library/LiveActor/ActorMovementFunction.h"
8#include "Library/LiveActor/ActorPoseUtil.h"
9#include "Library/LiveActor/ActorSensorUtil.h"
10#include "Library/Math/MathUtil.h"
11
12const al::EnemyStateBlowDownParam sEnemyStateBlowDownParam = al::EnemyStateBlowDownParam();
13
14namespace al {
15EnemyStateBlowDown::EnemyStateBlowDown(LiveActor* actor, const EnemyStateBlowDownParam* param,
16 const char* name)
17 : ActorStateBase(name, actor), mParam(param) {
18 if (!mParam)
19 mParam = &sEnemyStateBlowDownParam;
20}
21
22void EnemyStateBlowDown::start(const HitSensor* sensor) {
23 sead::Vector3f dir = getSensorPos(sensor) - getTrans(actor: mActor);
24
25 verticalizeVec(out: &dir, vertical: getGravity(actor: mActor), vec: dir);
26
27 if (!tryNormalizeOrZero(out: &dir))
28 calcFrontDir(front: &dir, actor: mActor);
29
30 start(-dir);
31}
32
33void EnemyStateBlowDown::start(const sead::Vector3f& dir) {
34 if (mParam->faceAwayFromActor)
35 faceToDirection(actor: mActor, dir: -dir);
36
37 auto* actor = mActor;
38 sead::Vector3f direction = dir * mParam->velocityStrength;
39 sead::Vector3f gravity = getGravity(actor);
40 sead::Vector3f velocity = gravity * mParam->gravityStrength;
41 setVelocity(actor, vel: direction - velocity);
42}
43
44void EnemyStateBlowDown::start(const HitSensor* sensor1, const HitSensor* sensor2) {
45 sead::Vector3f dir = getSensorPos(sensor1) - getSensorPos(sensor2);
46
47 verticalizeVec(out: &dir, vertical: getGravity(actor: mActor), vec: dir);
48
49 if (!tryNormalizeOrZero(out: &dir))
50 calcFrontDir(front: &dir, actor: mActor);
51
52 start(dir: -dir);
53}
54
55void EnemyStateBlowDown::start(const LiveActor* actor) {
56 sead::Vector3f dir;
57 calcFrontDir(front: &dir, actor);
58
59 start(dir: -dir);
60}
61
62void EnemyStateBlowDown::appear() {
63 al::NerveStateBase::appear();
64 if (isInvalidClipping(mActor))
65 mIsInvalidClipping = true;
66 else {
67 invalidateClipping(actor: mActor);
68 mIsInvalidClipping = false;
69 }
70 mBlowDownTimer = 0;
71}
72
73void EnemyStateBlowDown::kill() {
74 al::NerveStateBase::kill();
75 if (!mIsInvalidClipping)
76 validateClipping(actor: mActor);
77}
78
79void EnemyStateBlowDown::control() {
80 if (mBlowDownTimer == 0) {
81 if (mParam->actionName)
82 startAction(actor: mActor, actionName: mParam->actionName);
83 if (isExistActorCollider(mActor))
84 onCollide(actor: mActor);
85 }
86 if ((mParam->blowDownLength <= mBlowDownTimer) ||
87 (mParam->actionName && isActionOneTime(actor: mActor, actionName: mParam->actionName) &&
88 isActionEnd(actor: mActor)) ||
89 (isExistActorCollider(mActor) && isOnGround(mActor, 0))) {
90 kill();
91 return;
92 }
93 addVelocityToGravity(actor: mActor, force: mParam->velocityMultiplier);
94 scaleVelocity(actor: mActor, factor: mParam->velocityScale);
95 mBlowDownTimer++;
96}
97
98EnemyStateBlowDownParam::EnemyStateBlowDownParam() {}
99
100EnemyStateBlowDownParam::EnemyStateBlowDownParam(const char* actionName) : actionName(actionName) {}
101
102EnemyStateBlowDownParam::EnemyStateBlowDownParam(const char* actionName, f32 velocityStrength,
103 f32 gravityStrength, f32 velocityMultiplier,
104 f32 velocityScale, s32 blowDownLength,
105 bool faceAwayFromActor)
106 : actionName(actionName), velocityStrength(velocityStrength), gravityStrength(gravityStrength),
107 velocityMultiplier(velocityMultiplier), velocityScale(velocityScale),
108 blowDownLength(blowDownLength), faceAwayFromActor(faceAwayFromActor) {}
109} // namespace al
110