Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Player: Implement PlayerActionSlopeSlideControl #335

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 4 additions & 4 deletions data/odyssey_functions.csv
Original file line number Diff line number Diff line change
Expand Up @@ -26083,10 +26083,10 @@ Address,Quality,Size,Name
0x0000007100418c60,U,000060,_ZN28PlayerActionPivotTurnControl5resetEv
0x0000007100418c9c,U,001064,_ZN28PlayerActionPivotTurnControl6updateEv
0x00000071004190c4,U,000032,_ZN28PlayerActionPivotTurnControl17calcMoveDirectionEPN4sead7Vector3IfEERKS2_
0x00000071004190e4,U,000068,_ZN29PlayerActionSlopeSlideControlC2EPN2al9LiveActorEPK11PlayerConstPK11PlayerInputPK19IUsePlayerCollision
0x0000007100419128,U,000184,_ZN29PlayerActionSlopeSlideControl5setupEv
0x00000071004191e0,U,000284,_ZN29PlayerActionSlopeSlideControl24setupCutSlideOppositeDirEv
0x00000071004192fc,U,002068,_ZN29PlayerActionSlopeSlideControl6updateEffffffffffb
0x00000071004190e4,O,000068,_ZN29PlayerActionSlopeSlideControlC2EPN2al9LiveActorEPK11PlayerConstPK11PlayerInputPK19IUsePlayerCollision
0x0000007100419128,O,000184,_ZN29PlayerActionSlopeSlideControl5setupEv
0x00000071004191e0,O,000284,_ZN29PlayerActionSlopeSlideControl24setupCutSlideOppositeDirEv
0x00000071004192fc,O,002068,_ZN29PlayerActionSlopeSlideControl6updateEffffffffffb
0x0000007100419b10,U,000124,_ZN23PlayerActionTurnControlC2EPN2al9LiveActorE
0x0000007100419b8c,U,000028,_ZN23PlayerActionTurnControl5setupEffffiii
0x0000007100419ba8,U,000024,_ZN23PlayerActionTurnControl5resetEv
Expand Down
164 changes: 164 additions & 0 deletions src/Player/PlayerActionSlopeSlideControl.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
#include "Player/PlayerActionSlopeSlideControl.h"

#include "Library/LiveActor/ActorMovementFunction.h"
#include "Library/LiveActor/ActorPoseKeeper.h"
#include "Library/LiveActor/ActorPoseUtil.h"
#include "Library/Math/MathUtil.h"

#include "Player/PlayerConst.h"
#include "Player/PlayerInput.h"
#include "Util/ObjUtil.h"
#include "Util/PlayerCollisionUtil.h"

PlayerActionSlopeSlideControl::PlayerActionSlopeSlideControl(al::LiveActor* player,
const PlayerConst* pConst,
const PlayerInput* input,
const IUsePlayerCollision* collider)
: mPlayer(player), mConst(pConst), mInput(input), mCollision(collider) {}

void PlayerActionSlopeSlideControl::setup() {
mGroundNormal = -al::getGravity(mPlayer);
mDirSlide = {0.0f, 0.0f, 0.0f};

if (rs::isCollidedGround(mCollision)) {
al::calcDirSlide(&mDirSlide, al::getGravity(mPlayer),
rs::getCollidedGroundNormal(mCollision));
if (!rs::isJustLand(mCollision))
mGroundNormal = rs::getCollidedGroundNormal(mCollision);
}

mHorizontalVelocity = {0.0f, 0.0f, 0.0f};
}

void PlayerActionSlopeSlideControl::setupCutSlideOppositeDir() {
setup();

sead::Vector3f groundNormal = {0.0f, 0.0f, 0.0f};
rs::calcGroundNormalOrGravityDir(&groundNormal, mPlayer, mCollision);

sead::Vector3f slideDir = {0.0f, 0.0f, 0.0f};
sead::Vector3f* velocityPtr = al::getVelocityPtr(mPlayer);
al::alongVectorNormalH(velocityPtr, *velocityPtr, mGroundNormal, groundNormal);
if (rs::calcSlideDir(&slideDir, al::getGravity(mPlayer), groundNormal))
al::limitVectorOppositeDir(velocityPtr, slideDir, *velocityPtr, velocityPtr->length());

*velocityPtr -= mConst->getGravityMove() * groundNormal;
mGroundNormal = groundNormal;
}

f32 PlayerActionSlopeSlideControl::update(f32 accel, f32 brake, f32 against, f32 anglePowerMax,
f32 maxSpeed, f32 sideAccel, f32 sideBrake,
f32 sideMaxSpeed, f32 turnDegree, f32 gravity,
bool isRolling) {
sead::Vector3f prevGroundNormal = mGroundNormal;
sead::Vector3f up = -al::getGravity(mPlayer);
sead::Vector3f velocity = al::getVelocity(mPlayer);
bool isOnGroundSlopeSlideEnd = rs::isOnGroundSlopeSlideEnd(mPlayer, mCollision, mConst);
if (rs::isOnGround(mPlayer, mCollision)) {
mGroundNormal = rs::getCollidedGroundNormal(mCollision);
up = mGroundNormal;
al::calcDirSlide(&mDirSlide, al::getGravity(mPlayer), up);
al::alongVectorNormalH(&velocity, velocity, prevGroundNormal, up);

sead::Vector3f velDirSlide = {0.0f, 0.0f, 0.0f};
sead::Vector3f velSide = {0.0f, 0.0f, 0.0f};
if (isOnGroundSlopeSlideEnd) {
al::separateVectorParallelVertical(&velSide, &velDirSlide, up, velocity);
velDirSlide *= brake;
velSide *= sideBrake;
if (isRolling) {
sead::Vector3f moveInput = {0.0f, 0.0f, 0.0f};
mInput->calcMoveInput(&moveInput, up);

sead::Vector3f normDirSlide = {0.0f, 0.0f, 0.0f};
al::tryNormalizeOrZero(&normDirSlide, velDirSlide);

sead::Vector3f side;
side.setCross(up, normDirSlide);
al::tryNormalizeOrZero(&side);

f32 sideInput = side.dot(moveInput);
sead::Vector3f moveSideVec = side * sideInput * sideAccel;
al::addVectorLimit(&velDirSlide, moveSideVec, maxSpeed);
}
} else {
al::separateVectorParallelVertical(&velDirSlide, &velSide, mDirSlide, velocity);
sead::Vector3f moveInput = {0.0f, 0.0f, 0.0f};
mInput->calcMoveInput(&moveInput, up);
f32 speedDirSlide = velDirSlide.dot(mDirSlide);
if (speedDirSlide < 0.0)
velDirSlide *= brake;

f32 moveInputAgainst = sead::Mathf::clamp(-mDirSlide.dot(moveInput), 0.0f, 1.0f);
f32 minSpeedNorm = sead::Mathf::clamp(1.0f - (moveInputAgainst * against), 0.0, 1.0);
f32 speedNorm = sead::Mathf::clamp(speedDirSlide + 1.0f, minSpeedNorm, 1.0f);

f32 anglePower = sead::Mathf::clamp(
90.0f - al::calcAngleDegree(mDirSlide, al::getGravity(mPlayer)), 0.0f, 90.0f);

f32 anglePowerNorm = 1.0f;
if (anglePowerMax > 0.0)
anglePowerNorm = sead::Mathf::clampMax(anglePower / anglePowerMax, 1.0f);

al::addVectorLimit(&velDirSlide, mDirSlide * accel * anglePowerNorm * speedNorm,
maxSpeed);
velSide *= sideBrake;
sead::Vector3f inputDir = {0.0f, 0.0f, 0.0f};
if (al::tryNormalizeOrZero(&inputDir, moveInput)) {
sead::Vector3f sideDir;
sideDir.setCross(up, mDirSlide);
al::addVectorLimit(&velSide,
sideDir * sideDir.dot(inputDir) * moveInput.length() * sideAccel,
sideMaxSpeed);
}
}

sead::Vector3f vel;
vel.x = velDirSlide.x + velSide.x;
vel.y = velDirSlide.y + velSide.y;
vel.z = velDirSlide.z + velSide.z;
al::limitLength(&vel, vel, maxSpeed);
al::setVelocity(mPlayer, vel - (mConst->getGravityMove() * up));
} else {
mGroundNormal = up;
f32 prevUpVel = prevGroundNormal.dot(al::getVelocity(mPlayer));
al::alongVectorNormalH(al::getVelocityPtr(mPlayer), al::getVelocity(mPlayer),
prevGroundNormal, mGroundNormal);
sead::Vector3f* velPtr = al::getVelocityPtr(mPlayer);
velPtr->x = (prevUpVel * mGroundNormal.x) + velPtr->x;
velPtr->y = (prevUpVel * mGroundNormal.y) + velPtr->y;
velPtr->z = (prevUpVel * mGroundNormal.z) + velPtr->z;
al::addVectorLimit(al::getVelocityPtr(mPlayer), up * -gravity, mConst->getFallSpeedMax());
}

sead::Vector3f hVel = {0.0f, 0.0f, 0.0f};
al::verticalizeVec(&hVel, up, al::getVelocity(mPlayer));
sead::Vector3f hVelDir = {0.0f, 0.0f, 0.0f};

f32 rumbleStrength;
if (al::tryNormalizeOrZero(&hVelDir, hVel)) {
sead::Vector3f front = {0.0f, 0.0f, 0.0f};
al::calcFrontDir(&front, mPlayer);
al::verticalizeVec(&front, up, front);
al::tryNormalizeOrZero(&front);
if (turnDegree > 0.0) {
f32 angleFrontVel = 2 * al::calcAngleDegree(front, hVelDir);
f32 turn = sead::Mathf::clamp(angleFrontVel / turnDegree, 0.0f, 1.0f);
sead::Vector3f upFrontVel;
upFrontVel.setCross(front, hVelDir);
rumbleStrength = -al::sign(up.dot(upFrontVel)) * turn;
} else {
rumbleStrength = 0.0;
}

al::turnVecToVecCosOnPlane(&front, hVelDir, up,
sead::Mathf::cos(sead::Mathf::deg2rad(turnDegree)));
rs::slerpUpFront(mPlayer, up, front, mConst->getSlerpQuatRate(),
mConst->getHillPoseDegreeMax());
} else {
rumbleStrength = 0.0;
}

mHorizontalVelocity = hVel;
return rumbleStrength;
}
14 changes: 7 additions & 7 deletions src/Player/PlayerActionSlopeSlideControl.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
#pragma once

#include <basis/seadTypes.h>
#include <math/seadVector.h>

namespace al {
Expand All @@ -12,11 +11,12 @@ class IUsePlayerCollision;

class PlayerActionSlopeSlideControl {
public:
PlayerActionSlopeSlideControl(al::LiveActor*, const PlayerConst*, const PlayerInput*,
const IUsePlayerCollision*);
PlayerActionSlopeSlideControl(al::LiveActor* player, const PlayerConst* pConst,
const PlayerInput* input, const IUsePlayerCollision* collider);
void setup();
void setupCutSlideOppositeDir();
f32 update(f32, f32, f32, f32, f32, f32, f32, f32, f32, f32, bool);
f32 update(f32 accel, f32 brake, f32 against, f32 anglePowerMax, f32 maxSpeed, f32 sideAccel,
f32 sideBrake, f32 sideMaxSpeed, f32 turnDegree, f32 gravity, bool isRolling);

const sead::Vector3f& getDirSlide() const { return mDirSlide; }

Expand All @@ -29,9 +29,9 @@ class PlayerActionSlopeSlideControl {
const PlayerConst* mConst;
const PlayerInput* mInput;
const IUsePlayerCollision* mCollision;
sead::Vector3f mDirSlide = {0.0f, 0.0f, 0.0f};
sead::Vector3f mGroundNormal = {0.0f, 0.0f, 0.0f};
sead::Vector3f mHorizontalVelocity = {0.0f, 0.0f, 0.0f};
sead::Vector3f mDirSlide = sead::Vector3f::zero;
sead::Vector3f mGroundNormal = sead::Vector3f::zero;
sead::Vector3f mHorizontalVelocity = sead::Vector3f::zero;
};

static_assert(sizeof(PlayerActionSlopeSlideControl) == 0x48);
3 changes: 3 additions & 0 deletions src/Util/ObjUtil.h
Original file line number Diff line number Diff line change
Expand Up @@ -38,4 +38,7 @@ void startHitReactionHipDropLand(al::LiveActor*, bool);

void waitGround(al::LiveActor*, const IUsePlayerCollision*, f32, f32, f32, f32);

void slerpUpFront(al::LiveActor*, const sead::Vector3f&, const sead::Vector3f&, f32, f32);

bool calcSlideDir(sead::Vector3f*, const sead::Vector3f&, const sead::Vector3f&);
} // namespace rs