1#include "Player/PlayerCeilingCheck.h"
2
3#include "Library/Base/StringUtil.h"
4#include "Library/Collision/Collider.h"
5
6#include "Player/PlayerCollisionCheckSphereMove.h"
7
8PlayerCeilingCheck::PlayerCeilingCheck(al::CollisionDirector* director) {
9 mCollisionCheckSphereMove = new PlayerCollisionCheckSphereMove(director, 16);
10 setupCeilingCheckNormal();
11}
12
13void PlayerCeilingCheck::setupCeilingCheckNormal() {
14 mIsCeilingCheckNormal = true;
15 mIsCeilingCheckGrab = false;
16}
17
18void PlayerCeilingCheck::update(const sead::Vector3f& trans, const sead::Vector3f& up, f32 tall,
19 f32 collisionRadiusSquat, f32 headClearance, f32 holdHeight) {
20 sead::Vector3f checkStart;
21 checkStart.set(trans);
22
23 f32 playerHeight;
24 sead::Vector3f newCheckStart;
25 if (mIsCeilingCheckGrab) {
26 newCheckStart = trans - (collisionRadiusSquat + headClearance) * up;
27 playerHeight = 2 * tall;
28 } else {
29 newCheckStart = trans + (collisionRadiusSquat - headClearance) * up;
30 playerHeight = (2 * tall) - (2 * collisionRadiusSquat);
31 tall -= 2 * collisionRadiusSquat;
32 }
33 checkStart = newCheckStart;
34
35 f32 checkHeight = playerHeight + headClearance + holdHeight;
36 f32 minTStandUp = (tall + headClearance) / checkHeight;
37 mCollisionCheckSphereMove->checkSphereMove(checkStart, checkHeight * up, collisionRadiusSquat);
38
39 sead::Vector3f down = -up;
40 f32 minTValue2 = 1.0f;
41 f32 minTValue = 1.0f;
42 s32 minIndex = -1;
43 for (u32 i = 0; i < mCollisionCheckSphereMove->getNum(); i++) {
44 if (!al::isCeilingPolygon(mCollisionCheckSphereMove->getNormal(i), down))
45 continue;
46
47 f32 tValue = mCollisionCheckSphereMove->getTValue(i);
48 if (minTValue > tValue)
49 minTValue = tValue;
50
51 if (mIsCeilingCheckNormal &&
52 al::isEqualString(str1: mCollisionCheckSphereMove->getMapCodeName(i), str2: "Press"))
53 continue;
54
55 if (al::isEqualString(str1: mCollisionCheckSphereMove->getWallCodeName(i), str2: "NoCeilSquat"))
56 continue;
57
58 minIndex = minTValue2 > tValue ? i : minIndex;
59 minTValue2 = sead::Mathf::clampMax(val: minTValue2, max_: tValue);
60 }
61
62 f32 minTHoldUp = (0.99f * (checkHeight - holdHeight));
63 f32 maxTPressedCeil = (0.01f * (checkHeight - holdHeight));
64
65 mIsEnableStandUp = minTValue2 >= minTStandUp;
66 mIsEnableHoldUp = minTValue >= minTHoldUp / checkHeight;
67 mIsPressedCeil = minTValue2 < maxTPressedCeil / checkHeight;
68 mCeilCheckHeight = checkHeight + (checkStart - trans).dot(t: up);
69 mSafetyCeilSpace = mCeilCheckHeight;
70 if (minIndex >= 0)
71 mSafetyCeilSpace = (mCollisionCheckSphereMove->getPos(minIndex) - trans).dot(t: up);
72}
73
74void PlayerCeilingCheck::setupCeilingCheckGrab() {
75 mIsCeilingCheckNormal = false;
76 mIsCeilingCheckGrab = true;
77}
78
79void PlayerCeilingCheck::setCollisionPartsFilter(const al::CollisionPartsFilterBase* filter) {
80 mCollisionCheckSphereMove->setCollisionPartsFilter(filter);
81}
82