1#include "Player/PlayerJudgeGrabCeil.h"
2
3#include "Library/Collision/CollisionParts.h"
4#include "Library/LiveActor/ActorMovementFunction.h"
5#include "Library/LiveActor/ActorPoseUtil.h"
6#include "Library/Math/MathUtil.h"
7
8#include "Player/IPlayerModelChanger.h"
9#include "Player/PlayerCarryKeeper.h"
10#include "Player/PlayerConst.h"
11#include "Player/PlayerExternalVelocity.h"
12#include "Util/ObjUtil.h"
13#include "Util/PlayerCollisionUtil.h"
14
15PlayerJudgeGrabCeil::PlayerJudgeGrabCeil(const al::LiveActor* player, const PlayerConst* pConst,
16 const IUsePlayerCollision* collider,
17 const IPlayerModelChanger* modelChanger,
18 const PlayerCarryKeeper* carryKeeper,
19 const PlayerExternalVelocity* externalVelocity)
20 : mPlayer(player), mConst(pConst), mCollision(collider), mModelChanger(modelChanger),
21 mCarryKeeper(carryKeeper), mExternalVelocity(externalVelocity) {}
22
23void PlayerJudgeGrabCeil::reset() {
24 mIsJudge = false;
25 _48 = {0.0f, 0.0f, 0.0f};
26 _54 = {0.0f, 0.0f, 0.0f};
27 _60 = {0.0f, 0.0f, 0.0f};
28}
29
30void PlayerJudgeGrabCeil::update() {
31 mIsJudge = false;
32
33 if (mCarryKeeper->isCarry() || mModelChanger->is2DModel() ||
34 mExternalVelocity->isExistForce() || !rs::isCollisionCodeGrabCeilAny(mCollision))
35 return;
36
37 if (rs::isCollisionCodeGrabCeilWall(mCollision)) {
38 sead::Vector3f pos = rs::getCollidedWallPos(mCollision);
39 sead::Vector3f normal = rs::getCollidedWallNormal(mCollision);
40
41 if (!mExternalVelocity->isExistSnapForce()) {
42 sead::Vector3f verticalVelocity = al::getVelocity(actor: mPlayer);
43 al::verticalizeVec(out: &verticalVelocity, vertical: al::getGravity(actor: mPlayer), vec: verticalVelocity);
44 if (al::tryNormalizeOrZero(out: &verticalVelocity) && normal.dot(t: verticalVelocity) > 0.0f)
45 return;
46 }
47
48 sead::Vector3f forceMovePower = {0.0f, 0.0f, 0.0f};
49 rs::getCollidedWallCollisionParts(mCollision)->calcForceMovePower(&forceMovePower, pos);
50
51 mIsJudge = rs::findGrabCeilPosWallHit(
52 &mCollidedParts, &_48, &_54, &_60, mPlayer, -normal, pos + forceMovePower,
53 mConst->getTall(), mConst->getGrabCeilRange(), mConst->getGrabCeilBodyRadius());
54
55 return;
56 }
57
58 sead::Vector3f collidedNormal = {0.0f, 0.0f, 0.0f};
59 sead::Vector3f collidedPos = {0.0f, 0.0f, 0.0f};
60 const al::CollisionParts* collidedParts = nullptr;
61
62 if (rs::isCollisionCodeGrabCeilCeiling(mCollision)) {
63 collidedNormal = rs::getCollidedCeilingNormal(mCollision);
64 collidedPos = rs::getCollidedCeilingPos(mCollision);
65 collidedParts = rs::getCollidedCeilingCollisionParts(mCollision);
66 } else if (rs::isCollisionCodeGrabCeilGrround(mCollision)) {
67 collidedNormal = rs::getCollidedGroundNormal(mCollision);
68 collidedPos = rs::getCollidedGroundPos(mCollision);
69 collidedParts = rs::getCollidedGroundCollisionParts(mCollision);
70 if (!mExternalVelocity->isExistSnapForce()) {
71 sead::Vector3f velocity = al::getVelocity(actor: mPlayer);
72 if (al::tryNormalizeOrZero(out: &velocity) && velocity.dot(t: collidedNormal) > 0.0f)
73 return;
74 }
75 }
76
77 sead::Vector3f forceMovePower = {0.0f, 0.0f, 0.0f};
78 collidedParts->calcForceMovePower(&forceMovePower, collidedPos);
79
80 mIsJudge = rs::findGrabCeilPosNoWallHit(
81 &mCollidedParts, &_48, &_54, &_60, mPlayer, collidedNormal, collidedPos + forceMovePower,
82 mConst->getTall(), mConst->getGrabCeilRange(), mConst->getGrabCeilBodyRadius());
83
84 if (!mIsJudge)
85 return;
86
87 f32 dot = _54.dot(t: al::getVelocity(actor: mPlayer));
88 if (sead::Mathf::abs(x: dot) > mConst->getNormalMinSpeed()) {
89 if (dot < 0.0f) {
90 _54 *= -1;
91 al::normalize(vec: &_54);
92 }
93 } else {
94 sead::Vector3f front = {0.0f, 0.0f, 0.0f};
95 al::calcFrontDir(front: &front, actor: mPlayer);
96 if (front.dot(t: _54) < 0.0f) {
97 _54 *= -1;
98 al::normalize(vec: &_54);
99 }
100 }
101}
102
103bool PlayerJudgeGrabCeil::judge() const {
104 return mIsJudge;
105}
106