| 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 | |
| 19 | namespace { |
| 20 | NERVE_IMPL(Player, Wait); |
| 21 | NERVE_IMPL(Player, Run); |
| 22 | NERVE_IMPL(Player, Jump); |
| 23 | NERVE_IMPL(Player, Fall); |
| 24 | NERVE_IMPL(Player, Damage); |
| 25 | |
| 26 | NERVES_MAKE_NOSTRUCT(Player, Damage); |
| 27 | NERVES_MAKE_STRUCT(Player, Fall, Jump, Run, Wait); |
| 28 | } // namespace |
| 29 | |
| 30 | Player::Player(const char* actorName, const char* archiveName, s32 port) |
| 31 | : al::LiveActor(actorName), mArchiveName(archiveName), mPort(port) {} |
| 32 | |
| 33 | void 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 | |
| 40 | void 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 | |
| 52 | void 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 | |
| 85 | void 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 | |
| 101 | void 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 | |
| 117 | void 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 | |
| 129 | void 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 |
| 139 | void 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 | |
| 153 | bool 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 | |