1#include "Enemy/EnemyStateWander.h"
2
3#include "Library/LiveActor/ActorActionFunction.h"
4#include "Library/LiveActor/ActorCollisionFunction.h"
5#include "Library/LiveActor/ActorMovementFunction.h"
6#include "Library/LiveActor/ActorPoseUtil.h"
7#include "Library/Math/MathUtil.h"
8#include "Library/Nerve/NerveSetupUtil.h"
9#include "Library/Nerve/NerveUtil.h"
10
11namespace {
12NERVE_IMPL(EnemyStateWander, Wait);
13NERVE_IMPL(EnemyStateWander, Walk);
14NERVE_IMPL(EnemyStateWander, Fall);
15
16NERVES_MAKE_STRUCT(EnemyStateWander, Wait, Walk, Fall);
17} // namespace
18
19EnemyStateWander::EnemyStateWander(al::LiveActor* actor, const char* stateName)
20 : al::ActorStateBase("さんぽ状態", actor), mStateName(stateName) {
21 initNerve(nerve: &NrvEnemyStateWander.Wait, stateCount: 0);
22}
23
24void EnemyStateWander::appear() {
25 al::NerveStateBase::appear();
26 al::setNerve(user: this, nerve: &NrvEnemyStateWander.Walk);
27}
28
29void EnemyStateWander::exeWait() {
30 if (al::isFirstStep(user: this)) {
31 al::startAction(actor: mActor, actionName: "Wait");
32 mMaxWaitTime = al::getRandom(max: 60);
33 }
34 if (al::isGreaterEqualStep(user: this, step: mMaxWaitTime + 120)) {
35 al::setNerve(user: this, nerve: &NrvEnemyStateWander.Walk);
36 return;
37 }
38 if (!al::isOnGround(mActor, 0)) {
39 al::setNerve(user: this, nerve: &NrvEnemyStateWander.Fall);
40 return;
41 }
42 if (al::isFallNextMove(actor: mActor, velocity: al::getVelocity(actor: mActor), gravity: 50.0f, searchDist: 200.0f)) {
43 al::scaleVelocity(actor: mActor, factor: -1.0f);
44 al::setVelocityY(actor: mActor, y: 0.0f);
45 }
46 al::scaleVelocity(actor: mActor, factor: 0.7f);
47 al::addVelocityToGravityFittedGround(actor: mActor, force: 2.0f, maxAirTime: 0);
48}
49
50void EnemyStateWander::exeWalk() {
51 if (al::isFirstStep(user: this)) {
52 al::startAction(actor: mActor, actionName: mStateName);
53 mMaxWaitTime = al::getRandom(max: 50);
54 mIsSwapRotation = al::isHalfProbability();
55 }
56 if (al::isGreaterEqualStep(user: this, step: mMaxWaitTime + 100)) {
57 al::setNerve(user: this, nerve: &NrvEnemyStateWander.Wait);
58 return;
59 }
60 if (!al::isOnGround(mActor, 0)) {
61 al::setNerve(user: this, nerve: &NrvEnemyStateWander.Fall);
62 return;
63 }
64
65 if (mIsSwapRotation)
66 al::rotateQuatYDirDegree(actor: mActor, deg: 1.0f);
67 else
68 al::rotateQuatYDirDegree(actor: mActor, deg: -1.0f);
69
70 sead::Vector3f frontDir = sead::Vector3f::zero;
71 al::calcFrontDir(front: &frontDir, actor: mActor);
72
73 f32 walkSpeed = mWalkSpeed > 0.0f ? mWalkSpeed : 1.0f;
74
75 auto* actor = mActor;
76
77 const sead::Vector3f& velocity = al::getVelocity(actor);
78
79 if (al::isFallNextMove(actor, velocity: walkSpeed * frontDir + velocity, gravity: 50.0f, searchDist: 200.0f)) {
80 al::scaleVelocity(actor: mActor, factor: -1.0f);
81 al::setVelocityY(actor: mActor, y: 0.0f);
82 } else {
83 al::addVelocityToDirection(actor: mActor, dir: frontDir, force: walkSpeed);
84 }
85 al::scaleVelocity(actor: mActor, factor: 0.7f);
86 al::addVelocityToGravityFittedGround(actor: mActor, force: 2.0f, maxAirTime: 0);
87}
88
89void EnemyStateWander::exeFall() {
90 if (al::isFirstStep(user: this))
91 al::startAction(actor: mActor, actionName: "Fall");
92 if (!al::isOnGround(mActor, 0)) {
93 al::scaleVelocity(actor: mActor, factor: 0.98f);
94 al::addVelocityToGravity(actor: mActor, force: 2.0f);
95 } else
96 al::setNerve(user: this, nerve: &NrvEnemyStateWander.Wait);
97}
98
99bool EnemyStateWander::isWait() const {
100 return al::isNerve(user: this, nerve: &NrvEnemyStateWander.Wait);
101}
102
103bool EnemyStateWander::isWalk() const {
104 return al::isNerve(user: this, nerve: &NrvEnemyStateWander.Walk);
105}
106
107bool EnemyStateWander::isFall() const {
108 return al::isNerve(user: this, nerve: &NrvEnemyStateWander.Fall);
109}
110
111void EnemyStateWander::changeWalkAnim(const char* animName) {
112 if (al::isActionPlaying(actor: mActor, actionName: mStateName))
113 al::startAction(actor: mActor, actionName: animName);
114 mStateName = animName;
115}
116