1#include "Player/Player.h"
2
3#include <math/seadVector.h>
4
5#include "Library/Controller/InputFunction.h"
6#include "Library/LiveActor/ActorActionFunction.h"
7#include "Library/LiveActor/ActorAnimFunction.h"
8#include "Library/LiveActor/ActorClippingFunction.h"
9#include "Library/LiveActor/ActorCollisionFunction.h"
10#include "Library/LiveActor/ActorInitUtil.h"
11#include "Library/LiveActor/ActorMovementFunction.h"
12#include "Library/LiveActor/ActorPoseUtil.h"
13#include "Library/LiveActor/ActorSensorUtil.h"
14#include "Library/Math/MathUtil.h"
15#include "Library/Nerve/NerveSetupUtil.h"
16#include "Library/Nerve/NerveUtil.h"
17#include "Library/Player/PlayerFunction.h"
18
19namespace {
20NERVE_IMPL(Player, Wait);
21NERVE_IMPL(Player, Run);
22NERVE_IMPL(Player, Jump);
23NERVE_IMPL(Player, Fall);
24NERVE_IMPL(Player, Damage);
25
26NERVES_MAKE_NOSTRUCT(Player, Damage);
27NERVES_MAKE_STRUCT(Player, Fall, Jump, Run, Wait);
28} // namespace
29
30Player::Player(const char* actorName, const char* archiveName, s32 port)
31 : al::LiveActor(actorName), mArchiveName(archiveName), mPort(port) {}
32
33void Player::init(const al::ActorInitInfo& info) {
34 al::initActorWithArchiveName(actor: this, initInfo: info, archiveName: mArchiveName, suffix: nullptr);
35 al::invalidateClipping(actor: this);
36 al::initNerve(actor: this, nerve: &NrvPlayer.Fall, maxStates: 0);
37 makeActorAlive();
38}
39
40void Player::exeWait() {
41 if (al::isFirstStep(user: this))
42 al::startAction(actor: this, actionName: "Wait");
43
44 al::scaleVelocity(actor: this, factor: 0.7f);
45
46 if (al::isPadTriggerA(port: mPort))
47 al::setNerve(user: this, nerve: &NrvPlayer.Jump);
48 else if (!al::isNearZero(vec: al::getLeftStick(port: mPort)))
49 al::setNerve(user: this, nerve: &NrvPlayer.Run);
50}
51
52void Player::exeRun() {
53 if (al::isFirstStep(user: this)) {
54 al::startAction(actor: this, actionName: "Run");
55 mAirTime = 0;
56 }
57 al::addVelocityToGravity(actor: this, force: 2.0f);
58 al::scaleVelocity(actor: this, factor: 0.7f);
59 al::addPlayerAccelStickGravity(this, al::getFrontPtr(actor: this), 3.0f,
60 sead::Vector3f{0.0f, 1.0f, 0.0f}, mPort, nullptr);
61 al::setSklAnimFrameRate(this, al::calcSpeed(actor: this) * 0.23f, 0);
62
63 if (al::isPadTriggerA(port: mPort)) {
64 al::setNerve(user: this, nerve: &NrvPlayer.Jump);
65 return;
66 }
67
68 if (al::isCollidedGround(this)) {
69 mAirTime = 0;
70 } else {
71 mAirTime += 1;
72 if (mAirTime > 5) {
73 al::setNerve(user: this, nerve: &NrvPlayer.Fall);
74 return;
75 }
76 }
77 if (al::isVelocitySlow(actor: this, threshold: 1.0f)) {
78 al::setNerve(user: this, nerve: &NrvPlayer.Wait);
79 return;
80 }
81
82 al::reboundVelocityFromCollision(actor: this, reboundStrength: 0.0f, reboundMin: 0.0f, friction: 1.0f);
83}
84
85void Player::exeJump() {
86 if (al::isFirstStep(user: this)) {
87 al::startAction(actor: this, actionName: "Jump");
88 al::addVelocityJump(actor: this, force: 28.0f);
89 }
90 al::addVelocityToGravity(actor: this, force: 1.0f);
91 al::scaleVelocity(actor: this, factor: 0.99f);
92 al::addPlayerAccelStickGravity(this, nullptr, 0.2f, sead::Vector3f{0.0f, 1.0f, 0.0f}, mPort,
93 nullptr);
94
95 bool onGround = al::isOnGround(this, 0); // required for match
96 al::reboundVelocityFromCollision(actor: this, reboundStrength: 0.0f, reboundMin: 0.0f, friction: 1.0f);
97 if (onGround)
98 al::setNerve(user: this, nerve: &NrvPlayer.Wait);
99}
100
101void Player::exeFall() {
102 if (al::isFirstStep(user: this))
103 al::startAction(actor: this, actionName: "Fall");
104 al::addVelocityToGravity(actor: this, force: 0.7f);
105 al::scaleVelocity(actor: this, factor: 0.99f);
106 if (al::isLessEqualStep(user: this, step: 10) && al::isPadTriggerA(port: mPort)) {
107 al::setNerve(user: this, nerve: &NrvPlayer.Jump);
108 return;
109 }
110
111 if (al::isOnGround(this, 0)) {
112 al::reboundVelocityFromCollision(actor: this, reboundStrength: 0.0f, reboundMin: 0.0f, friction: 1.0f);
113 al::setNerve(user: this, nerve: &NrvPlayer.Wait);
114 }
115}
116
117void Player::exeDamage() {
118 if ((al::isFirstStep(user: this)))
119 al::startAction(actor: this, actionName: "Damage");
120 al::addVelocityToGravity(actor: this, force: 0.7f);
121 al::scaleVelocity(actor: this, factor: 0.99f);
122 al::reboundVelocityFromCollision(actor: this, reboundStrength: 0.0f, reboundMin: 0.0f, friction: 1.0f);
123 if (al::isStep(user: this, step: 60)) {
124 al::setVelocityZero(this);
125 al::setNerve(user: this, nerve: &NrvPlayer.Fall);
126 }
127}
128
129void Player::control() {
130 if (al::isPadTriggerL(port: mPort)) {
131 al::setVelocityZero(this);
132 al::setTrans(actor: this, trans: {0.0f, 100.0f, 800.0f});
133 al::resetPosition(actor: this);
134 al::setNerve(user: this, nerve: &NrvPlayer.Fall);
135 }
136}
137
138// NON_MATCHING: issue with getting actorTrans
139void Player::attackSensor(al::HitSensor* self, al::HitSensor* other) {
140 const sead::Vector3f& actorTransRef = al::getActorTrans(other);
141 const sead::Vector3f& transRef = al::getTrans(actor: this);
142 sead::Vector3f actorTrans = actorTransRef;
143 sead::Vector3f trans = transRef;
144
145 if ((al::isNerve(user: this, nerve: &NrvPlayer.Jump) || al::isNerve(user: this, nerve: &NrvPlayer.Fall)) &&
146 (al::isSensorEnemy(other) || al::isSensorPlayer(other)) &&
147 (al::getVelocity(actor: this).dot(t: al::getGravity(actor: this)) > 0.0f) &&
148 ((actorTrans - trans).dot(t: al::getGravity(actor: this)) > 0.0f) &&
149 al::sendMsgPlayerAttackTrample(receiver: other, sender: self, comboCounter: nullptr))
150 al::setVelocityJump(actor: this, speed: 23.0f);
151}
152
153bool Player::receiveMsg(const al::SensorMsg* message, al::HitSensor* other, al::HitSensor* self) {
154 if (al::isMsgPlayerTrample(msg: message) || al::isMsgEnemyAttack(msg: message)) {
155 if (!al::isNerve(user: this, nerve: &Damage)) {
156 sead::Vector3f offset = al::getTrans(actor: this) - al::getSensorPos(other);
157 al::verticalizeVec(out: &offset, vertical: al::getGravity(actor: this), vec: offset);
158 al::tryNormalizeOrZero(out: &offset);
159
160 if (!al::isNearZero(vec: offset)) {
161 sead::Vector3f* front = al::getFrontPtr(actor: this);
162 front->set(offset);
163 }
164
165 sead::Vector3f velocity = offset * 10.0f;
166 al::setVelocity(actor: this, vel: velocity);
167
168 al::addVelocityJump(actor: this, force: 20.0f);
169 al::setNerve(user: this, nerve: &Damage);
170 return true;
171 }
172 }
173 return false;
174}
175