diff --git a/Runtime/Camera/CBallCamera.cpp b/Runtime/Camera/CBallCamera.cpp index 3fcedcebf..066f99918 100644 --- a/Runtime/Camera/CBallCamera.cpp +++ b/Runtime/Camera/CBallCamera.cpp @@ -536,7 +536,7 @@ void CBallCamera::UpdateTransform(const zeus::CVector3f& lookDir, const zeus::CV SetTranslation(pos); } -zeus::CVector3f CBallCamera::ConstrainYawAngle(const CPlayer& player, float angleVel, float maxAngle, float dt, +zeus::CVector3f CBallCamera::ConstrainYawAngle(const CPlayer& player, float distance, float yawSpeed, float dt, CStateManager& mgr) const { zeus::CVector3f playerToCamFlat = GetTranslation() - player.GetTranslation(); @@ -563,8 +563,8 @@ zeus::CVector3f CBallCamera::ConstrainYawAngle(const CPlayer& player, float angl float angleProj = zeus::clamp(-1.f, playerToCamFlat.dot(-lookDir), 1.f); if (angleProj >= 1.f) return -lookDir; - return zeus::CQuaternion::lookAt(playerToCamFlat, -lookDir, angleVel * dt * - zeus::clamp(0.f, std::acos(angleProj) / maxAngle, 1.f)).transform(playerToCamFlat); + return zeus::CQuaternion::lookAt(playerToCamFlat, -lookDir, distance * dt * + zeus::clamp(0.f, std::acos(angleProj) / yawSpeed, 1.f)).transform(playerToCamFlat); } void CBallCamera::CheckFailsafe(float dt, CStateManager& mgr) @@ -933,44 +933,230 @@ void CBallCamera::UpdateUsingFreeLook(float dt, CStateManager& mgr) x36c_ = 0; } -zeus::CVector3f CBallCamera::InterpolateCameraElevation(const zeus::CVector3f& camPos) const +zeus::CVector3f CBallCamera::InterpolateCameraElevation(const zeus::CVector3f& camPos) { - return {}; + if (x1a0_elevation < 2.f) + return camPos; + + zeus::CVector3f ret = camPos; + if (!x18c_31_ && x350_.HasMaterial(EMaterialTypes::Floor)) + { + x3d4_ = 1.f; + ret.z = x3d8_ = GetTranslation().z; + } + else if (x3d4_ > 0.f) + { + ret.z = (camPos.z - x3d8_) * (1.f - zeus::clamp(0.f, x3d4_, 1.f)) + x3d8_; + } + + return ret; } zeus::CVector3f CBallCamera::CalculateCollidersCentroid(const std::vector& colliderList, int w1) const { - return {}; + if (colliderList.size() < 3) + return zeus::CVector3f::skForward; + + int r10 = 0; + const CCameraCollider* prevCol = &colliderList.back(); + float f6 = 0.f; + float f7 = 0.f; + float f8 = 0.f; + for (const CCameraCollider& col : colliderList) + { + if (prevCol->x4c_occlusionCount < 2 && col.x4c_occlusionCount < 2) + { + float f3 = prevCol->x50_scale * prevCol->x8_.z; + float f1 = prevCol->x50_scale * col.x8_.x; + float f4 = prevCol->x50_scale * prevCol->x8_.x; + float f5 = prevCol->x50_scale * col.x8_.z; + + float f2 = f4 * f5 - f1 * f3; + f6 += f2; + f7 += f2 * (f1 + f4); + f8 += f2 * (f5 + f3); + } + else + { + r10 += 1; + } + prevCol = &col; + } + + if (r10 / float(colliderList.size()) <= x330_) + { + return zeus::CVector3f::skForward; + } + else if (0.f != f6) + { + float f2 = 3.f * f6; + return {f7 / f2, 0.f, f8 / f2}; + } + + return {0.f, 2.f, 0.f}; } zeus::CVector3f CBallCamera::ApplyColliders() { - return {}; + zeus::CVector3f smallCentroid = CalculateCollidersCentroid(x264_smallColliders, x2c4_); + zeus::CVector3f mediumCentroid = CalculateCollidersCentroid(x274_mediumColliders, x2c8_); + zeus::CVector3f largeCentroid = CalculateCollidersCentroid(x284_largeColliders, x2cc_); + + if (smallCentroid.y == 0.f) + x2a0_ = smallCentroid; + else + x2a0_ = zeus::CVector3f::skZero; + + float centroidX = x2a0_.x; + float centroidZ = x2a0_.z; + + if (mediumCentroid.y == 0.f) + x2ac_ = mediumCentroid; + else + x2ac_ = zeus::CVector3f::skZero; + + centroidX += x2ac_.x; + centroidZ += x2ac_.z; + + if (largeCentroid.y == 0.f) + x2b8_ = largeCentroid; + else + x2b8_ = zeus::CVector3f::skZero; + + centroidX += x2b8_.x; + centroidZ += x2b8_.z; + + if (x18c_31_) + centroidX /= 1.5f; + centroidZ /= 3.f; + + if (!x18c_31_ && x368_ == kInvalidUniqueId) + { + float f26 = 1.5f; + float f27 = 1.f; + if (x350_.HasMaterial(EMaterialTypes::Floor)) + f27 += 2.f * x358_; + if (x350_.HasMaterial(EMaterialTypes::Wall)) + f26 += 3.f * zeus::clamp(0.f, x358_ - 0.25f, 1.f); + centroidX *= f26; + centroidZ *= f27; + } + + if (!x18c_28_) + return zeus::CVector3f::skZero; + + if (std::fabs(centroidX) < 0.05f) + centroidX = 0.f; + if (std::fabs(centroidZ) < 0.05f) + centroidZ = 0.f; + + if (x18c_31_) + centroidZ *= 0.5f; + + return {centroidX, 0.f, centroidZ}; } void CBallCamera::UpdateColliders(const zeus::CTransform& xf, std::vector& colliderList, int& r6, - int r7, float f1, const rstl::reserved_vector& nearList, float f2, + int r7, float f1, const rstl::reserved_vector& nearList, float dt, CStateManager& mgr) { - + if (r6 < colliderList.size()) + { + x310_ = {0.f, g_tweakBall->GetBallCameraOffset().y, g_tweakPlayer->GetPlayerBallHalfExtent()}; + x310_.y *= x308_; + x31c_ = mgr.GetPlayer().GetMoveDir() * x310_.y; + x31c_.z = x310_.z; + x31c_ += mgr.GetPlayer().GetTranslation(); + zeus::CTransform xd0 = zeus::lookAt(xf.origin, x31c_); + float f26 = 1.f / f1; + for (int i=0 ; i& nearList, - float dt, CStateManager& mgr) +zeus::CVector3f CBallCamera::AvoidGeometry(const zeus::CTransform& xf, + const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr) { + switch (x328_) + { + case 0: + UpdateColliders(xf, x264_smallColliders, x2d0_, 1, 4.f, nearList, dt, mgr); + break; + case 1: + UpdateColliders(xf, x274_mediumColliders, x2d4_, 3, 4.f, nearList, dt, mgr); + break; + case 2: + UpdateColliders(xf, x284_largeColliders, x2d8_, 4, 4.f, nearList, dt, mgr); + break; + case 3: + UpdateColliders(xf, x284_largeColliders, x2d8_, 4, 4.f, nearList, dt, mgr); + break; + default: + break; + } + x328_ += 1; + if (x328_ >= 4) + x328_ = 0; + + return ApplyColliders(); } -void CBallCamera::AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr) +zeus::CVector3f CBallCamera::AvoidGeometryFull(const zeus::CTransform& xf, + const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr) { - + UpdateColliders(xf, x264_smallColliders, x2d0_, x264_smallColliders.size(), 4.f, nearList, dt, mgr); + UpdateColliders(xf, x274_mediumColliders, x2d4_, x274_mediumColliders.size(), 4.f, nearList, dt, mgr); + UpdateColliders(xf, x284_largeColliders, x2d8_, x284_largeColliders.size(), 4.f, nearList, dt, mgr); + return ApplyColliders(); } zeus::CAABox CBallCamera::CalculateCollidersBoundingBox(const std::vector& colliderList, CStateManager& mgr) const { - return {}; + zeus::CAABox aabb; + for (const CCameraCollider& col : colliderList) + aabb.accumulateBounds(col.x2c_); + aabb.accumulateBounds(mgr.GetPlayer().GetTranslation()); + return aabb; } int CBallCamera::CountObscuredColliders(const std::vector& colliderList) const @@ -984,12 +1170,285 @@ int CBallCamera::CountObscuredColliders(const std::vector& coll void CBallCamera::UpdateCollidersDistances(std::vector& colliderList, float f1, float f2, float f3) { - + float f31 = f3; + for (CCameraCollider& col : colliderList) + { + float f23 = std::cos(f31) * f2; + if (f31 > M_PIF / 2.f) + f23 *= 0.25f; + col.x14_ = {std::sin(f31) * f1, 0.f, f23}; + f31 += 2.f * M_PIF / float(colliderList.size()); + } } void CBallCamera::UpdateUsingColliders(float dt, CStateManager& mgr) { + if (mgr.GetPlayer().GetBombJumpCount() == 1) + return; + zeus::CVector3f ballPos = mgr.GetPlayer().GetBallPosition(); + + if (mgr.GetPlayer().GetBombJumpCount() == 2) + { + zeus::CVector3f xa60 = x1d8_ - GetTranslation(); + if (x18d_26_) + xa60 = ballPos - GetTranslation(); + + if (xa60.canBeNormalized()) + { + xa60.normalize(); + UpdateTransform(xa60, GetTranslation(), dt, mgr); + } + } + else if (mgr.GetPlayer().GetMorphballTransitionState() != CPlayer::EPlayerMorphBallState::Unmorphed || + x18d_25_) + { + zeus::CTransform x8e0 = x34_transform; + zeus::CVector3f f28 = GetTranslation(); + x2c4_ = CountObscuredColliders(x264_smallColliders); + x2c8_ = CountObscuredColliders(x274_mediumColliders); + x2cc_ = CountObscuredColliders(x284_largeColliders); + zeus::CVector3f xa78 = {0.f, 0.f, GetTranslation().z - ballPos.z}; + zeus::CVector3f xa6c = GetTranslation() - ballPos; + xa6c.z = 0.f; + float f25 = 0.f; + if (xa6c.canBeNormalized()) + f25 = xa6c.magnitude(); + else + xa6c = -mgr.GetPlayer().GetMoveDir(); + xa78 = GetTranslation() - xa78; + zeus::CTransform x910; + if ((xa78 - ballPos).canBeNormalized()) + x910 = zeus::lookAt(ballPos, xa78); + float distance = x214_ballCameraSpring.ApplyDistanceSpring(x190_curMinDistance, f25, (3.f + x308_) * dt); + zeus::CVector3f xa84 = ballPos - GetTranslation(); + xa84.z = 0.f; + if (xa84.canBeNormalized()) + { + xa84.normalize(); + if (std::fabs(std::acos(zeus::clamp(-1.f, xa84.dot(mgr.GetPlayer().GetMoveDir()), 1.f))) > + zeus::degToRad(150.f) && mgr.GetPlayer().GetVelocity().canBeNormalized()) + { + distance = x214_ballCameraSpring. + ApplyDistanceSpring(x308_ * (x19c_backwardsDistance -x190_curMinDistance) + + x190_curMinDistance, f25, 3.f * dt); + } + } + x334_ = CalculateCollidersBoundingBox(x284_largeColliders, mgr); + rstl::reserved_vector nearList; + mgr.BuildNearList(nearList, x334_, BallCameraFilter, + TCastToConstPtr(mgr.GetObjectById(x46c_collisionActorId)).GetPtr()); + if (!x18c_31_ && x368_ == kInvalidUniqueId) + { + if (x34c_ > 0.f || x350_.HasMaterial(EMaterialTypes::Floor) || x350_.HasMaterial(EMaterialTypes::Wall)) + { + x32c_ += 2.f * dt; + if (x32c_ < 2.f) + x32c_ = 2.f; + if (x32c_ > 2.f) + x32c_ = 2.f; + UpdateCollidersDistances(x264_smallColliders, 2.31f * x32c_, 2.31f * x32c_ * 0.5f, -M_PIF / 2.f); + UpdateCollidersDistances(x274_mediumColliders, 4.62f * x32c_, 4.62f * x32c_ * 0.5f, -M_PIF / 2.f); + UpdateCollidersDistances(x284_largeColliders, 7.f * x32c_, 7.f * x32c_ * 0.5f, -M_PIF / 2.f); + } + } + else + { + float f1 = 1.f; + if (x18d_24_ && mgr.GetPlayer().GetMoveSpeed() < 1.f) + f1 = 0.25f; + x32c_ += (f1 - x32c_) * dt * 2.f; + UpdateCollidersDistances(x264_smallColliders, x32c_ * 2.31f, x32c_ * 2.31f, -M_PIF / 2.f); + UpdateCollidersDistances(x274_mediumColliders, x32c_ * 4.62f, x32c_ * 4.62f, -M_PIF / 2.f); + UpdateCollidersDistances(x284_largeColliders, x32c_ * 7.f, x32c_ * 7.f, -M_PIF / 2.f); + } + + float elevation = x1a0_elevation; + bool r27 = !ConstrainElevationAndDistance(elevation, distance, dt, mgr); + zeus::CVector3f xa9c = x910.rotate({0.f, distance, elevation}); + + if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) + { + if (!door->x2a8_26_) + { + if (x400_state == EBallCameraState::Three) + { + zeus::CVector3f xaa8 = GetTranslation() - ballPos; + if (xaa8.canBeNormalized()) + xaa8.normalize(); + else + xaa8 = GetTransform().basis[1]; + if (std::fabs(f25 - x430_boostElevation) < 1.f) + { + xaa8 = ConstrainYawAngle(mgr.GetPlayer(), g_tweakBall->GetBallCameraBoostDistance(), + g_tweakBall->GetBallCameraBoostYawSpeed(), dt, mgr); + } + xaa8.normalize(); + xaa8.z = 0.f; + xaa8 = xaa8 * distance; + xaa8.z = 1.f; + xa9c = xaa8; + r27 = false; + } + if (x18c_25_ && (x400_state == EBallCameraState::Two || x188_behaviour == EBallCameraBehaviour::One)) + { + zeus::CVector3f xab4 = GetTranslation() - ballPos; + if (xab4.canBeNormalized()) + xab4.normalize(); + else + xab4 = GetTransform().basis[1]; + if (std::fabs(f25 - x404_chaseElevation) < 3.f) + { + xab4 = ConstrainYawAngle(mgr.GetPlayer(), g_tweakBall->GetBallCameraChaseDistance(), + g_tweakBall->GetBallCameraChaseYawSpeed(), dt, mgr); + } + xab4.z = 0.f; + xab4.normalize(); + xab4 = xab4 * distance; + xab4.z = 2.736f; + xa9c = xab4; + r27 = false; + } + } + } + + if (x188_behaviour == EBallCameraBehaviour::Two) + { + xa9c = x45c_; + if (x18c_27_) + { + zeus::CVector3f xac0 = x45c_; + if (xac0.canBeNormalized()) + xac0.normalize(); + else + xac0 = -mgr.GetPlayer().GetMoveDir(); + TUniqueId intersectId = kInvalidUniqueId; + CRayCastResult result = + mgr.RayWorldIntersection(intersectId, ballPos, xac0, distance, BallCameraFilter, nearList); + if (result.IsValid()) + xa9c = xac0 * result.GetT() * 0.9f; + } + r27 = false; + } + + distance = xa9c.magnitude(); + zeus::CVector3f xacc = ballPos + xa9c; + float d = 0.f; + if (DetectCollision(ballPos, xacc, 0.3f, d, mgr)) + { + if (d >= 1.f) + { + xa9c = xa9c.normalized() * d; + xacc = ballPos + xa9c; + } + else + { + xa9c = ballPos + GetTranslation(); + xacc = GetTranslation(); + } + } + + zeus::CTransform x940 = zeus::lookAt(xacc, x1d8_); + zeus::CTransform x970 = zeus::lookAt(GetTranslation(), x1d8_); + x1e4_ = x940; + x940 = x970; + zeus::CVector3f xad8; + if (x18d_25_ || !x18c_31_) + xad8 = AvoidGeometryFull(x940, nearList, dt, mgr); + else + xad8 = AvoidGeometry(x940, nearList, dt, mgr); + + zeus::CVector3f xae4 = GetTranslation() - ballPos; + xae4.z = 0.f; + if (xae4.magnitude() < 2.f) + { + if (x18c_31_ && x478_ > 2) + xad8 = xad8 / float(x478_); + if (d < 3.f) + { + xad8 = xad8 * 0.25f; + if (x18c_31_ && x478_ > 0) + xad8 = xad8 * x308_; + } + if (d < 1.f) + xad8 = zeus::CVector3f::skZero; + } + + zeus::CVector3f xaf0 = x940.rotate(xad8) + xacc - ballPos; + if (xaf0.canBeNormalized()) + xaf0.normalize(); + zeus::CVector3f f27 = xaf0 * distance + ballPos; + + if (x188_behaviour == EBallCameraBehaviour::Six) + if (TCastToConstPtr cam = mgr.GetObjectById(mgr.GetCameraManager()->GetPathCameraId())) + f27 = cam->GetTranslation(); + + xaf0 = x294_ - f27; + float f24 = xaf0.magnitude(); + if (xaf0.canBeNormalized()) + xaf0.normalize(); + + x294_ = xaf0 * x228_ballCameraCentroidSpring.ApplyDistanceSpring(0.f, f24, dt) + f27; + zeus::CVector3f xafc = f28 - x294_; + f24 = xafc.magnitude(); + if (xafc.canBeNormalized()) + xafc.normalize(); + + float f1 = x250_ballCameraCentroidDistanceSpring.ApplyDistanceSpring(0.f, f24, (x18d_28_ ? 3.f : 1.f) * dt); + if (x400_state == EBallCameraState::Three) + f1 = x448_ballCameraBoostSpring.ApplyDistanceSpring(0.f, f24, dt); + else if (x18c_25_ && (x400_state == EBallCameraState::Two || x188_behaviour == EBallCameraBehaviour::One)) + f1 = x41c_ballCameraChaseSpring.ApplyDistanceSpring(0.f, f24, dt); + + zeus::CVector3f xb08 = xafc * f1 + x294_; + if (mgr.GetPlayer().GetMorphBall()->GetSpiderBallState() != CMorphBall::ESpiderBallState::Active && + !x18e_24_ && mgr.GetPlayer().GetVelocity().z > 8.f) + { + zeus::CVector3f delta = xb08 - f28; + delta.z = zeus::clamp(-0.1f * dt, delta.z, 0.1f * dt); + xb08 = f28 + delta; + } + + if (r27 && x400_state != EBallCameraState::Four) + xb08 = InterpolateCameraElevation(xb08); + + if (x18d_29_) + xb08.z = elevation + ballPos.z; + + if (xae4.magnitude() < 2.f) + { + if (xb08.z < 2.f + ballPos.z) + xb08.z = 2.f + ballPos.z; + x214_ballCameraSpring.Reset(); + } + + xb08 = ClampElevationToWater(xb08, mgr); + if (xae4.magnitude() < 2.f && x3dc_tooCloseActorId != kInvalidUniqueId && x3e0_tooCloseActorDist < 5.f) + if (TCastToConstPtr door = mgr.GetObjectById(x3dc_tooCloseActorId)) + if (!door->x2a8_26_) + xb08 = GetTranslation(); + + float backupZ = xb08.z; + xb08 = MoveCollisionActor(xb08, dt, mgr); + + if (x18c_31_ && x478_ > 0) + { + xb08.z = backupZ; + xb08 = MoveCollisionActor(xb08, dt, mgr); + } + + zeus::CVector3f xb14 = x1d8_ - xb08; + if (x18d_26_) + xb14 = ballPos - xb08; + if (xb14.canBeNormalized()) + { + xb14.normalize(); + UpdateTransform(xb14, xb08, dt, mgr); + } + + if (x470_ > 0.f) + x470_ -= dt; + } } void CBallCamera::UpdateUsingSpindleCameras(float dt, CStateManager& mgr) @@ -1046,9 +1505,9 @@ void CBallCamera::ActivateFailsafe(float dt, CStateManager& mgr) } -void CBallCamera::ConstrainElevationAndDistance(float& elevation, float& distance, float f1, CStateManager& mgr) +bool CBallCamera::ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr) { - + return false; } zeus::CVector3f CBallCamera::FindDesiredPosition(float distance, float elevation, diff --git a/Runtime/Camera/CBallCamera.hpp b/Runtime/Camera/CBallCamera.hpp index ca86cd320..a42c14e3c 100644 --- a/Runtime/Camera/CBallCamera.hpp +++ b/Runtime/Camera/CBallCamera.hpp @@ -124,12 +124,12 @@ private: zeus::CVector3f x2a0_ = zeus::CVector3f::skUp; zeus::CVector3f x2ac_ = zeus::CVector3f::skUp; zeus::CVector3f x2b8_ = zeus::CVector3f::skUp; - u32 x2c4_ = 0; - u32 x2c8_ = 0; - u32 x2cc_ = 0; - u32 x2d0_ = 0; - u32 x2d4_ = 0; - u32 x2d8_ = 0; + int x2c4_ = 0; + int x2c8_ = 0; + int x2cc_ = 0; + int x2d0_ = 0; + int x2d4_ = 0; + int x2d8_ = 0; zeus::CVector3f x2dc_; float x2e8_ = 0.f; float x2ec_ = 0.f; @@ -193,7 +193,7 @@ private: bool ShouldResetSpline(CStateManager& mgr) const; void UpdatePlayerMovement(float dt, CStateManager& mgr); void UpdateTransform(const zeus::CVector3f& lookDir, const zeus::CVector3f& pos, float dt, CStateManager& mgr); - zeus::CVector3f ConstrainYawAngle(const CPlayer& player, float angleVel, float maxAngle, float dt, + zeus::CVector3f ConstrainYawAngle(const CPlayer& player, float distance, float yawSpeed, float dt, CStateManager& mgr) const; void CheckFailsafe(float dt, CStateManager& mgr); void UpdateObjectTooCloseId(CStateManager& mgr); @@ -205,16 +205,16 @@ private: zeus::CVector3f TweenVelocity(const zeus::CVector3f& curVel, const zeus::CVector3f& newVel, float rate, float dt); zeus::CVector3f MoveCollisionActor(const zeus::CVector3f& pos, float dt, CStateManager& mgr); void UpdateUsingFreeLook(float dt, CStateManager& mgr); - zeus::CVector3f InterpolateCameraElevation(const zeus::CVector3f& camPos) const; + zeus::CVector3f InterpolateCameraElevation(const zeus::CVector3f& camPos); zeus::CVector3f CalculateCollidersCentroid(const std::vector& colliderList, int w1) const; zeus::CVector3f ApplyColliders(); void UpdateColliders(const zeus::CTransform& xf, std::vector& colliderList, int& r6, int r7, - float f1, const rstl::reserved_vector& nearList, float f2, + float f1, const rstl::reserved_vector& nearList, float dt, CStateManager& mgr); - void AvoidGeometry(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr); - void AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, - float dt, CStateManager& mgr); + zeus::CVector3f AvoidGeometry(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr); + zeus::CVector3f AvoidGeometryFull(const zeus::CTransform& xf, const rstl::reserved_vector& nearList, + float dt, CStateManager& mgr); zeus::CAABox CalculateCollidersBoundingBox(const std::vector& colliderList, CStateManager& mgr) const; int CountObscuredColliders(const std::vector& colliderList) const; @@ -228,7 +228,7 @@ private: bool SplineIntersectTest(CMaterialList& intersectMat, CStateManager& mgr) const; static bool IsBallNearDoor(const zeus::CVector3f& pos, CStateManager& mgr); void ActivateFailsafe(float dt, CStateManager& mgr); - void ConstrainElevationAndDistance(float& elevation, float& distance, float f1, CStateManager& mgr); + bool ConstrainElevationAndDistance(float& elevation, float& distance, float dt, CStateManager& mgr); zeus::CVector3f FindDesiredPosition(float distance, float elevation, const zeus::CVector3f& dir, CStateManager& mgr); static bool DetectCollision(const zeus::CVector3f& from, const zeus::CVector3f& to, float margin, float& d, CStateManager& mgr); diff --git a/Runtime/Camera/CCameraSpline.cpp b/Runtime/Camera/CCameraSpline.cpp index 8d5d91886..010f2a13e 100644 --- a/Runtime/Camera/CCameraSpline.cpp +++ b/Runtime/Camera/CCameraSpline.cpp @@ -20,7 +20,33 @@ void CCameraSpline::CalculateKnots(TUniqueId cameraId, const std::vector waypoint = mgr.ObjectById(mgr.GetIdForScript(lastConn->x8_objId)); - //if (waypoint) + x14_wpTracker.clear(); + x14_wpTracker.reserve(4); + while (waypoint) + { + auto search = std::find_if(x14_wpTracker.begin(), x14_wpTracker.end(), + [&waypoint](const auto& a) { return a == waypoint->GetUniqueId(); }); + if (search == x14_wpTracker.end()) + { + x14_wpTracker.push_back(waypoint->GetUniqueId()); + waypoint = mgr.ObjectById(waypoint->GetRandomNextWaypointId(mgr)); + } + } + Reset(x14_wpTracker.size()); + x14_wpTracker.clear(); + + waypoint = mgr.ObjectById(mgr.GetIdForScript(lastConn->x8_objId)); + while (waypoint) + { + auto search = std::find_if(x14_wpTracker.begin(), x14_wpTracker.end(), + [&waypoint](const auto& a) { return a == waypoint->GetUniqueId(); }); + if (search == x14_wpTracker.end()) + { + x14_wpTracker.push_back(waypoint->GetUniqueId()); + AddKnot(waypoint->GetTranslation(), waypoint->GetTransform().basis[1]); + waypoint = mgr.ObjectById(waypoint->GetRandomNextWaypointId(mgr)); + } + } } } diff --git a/Runtime/Camera/CCameraSpline.hpp b/Runtime/Camera/CCameraSpline.hpp index dc1afa575..3c59974ec 100644 --- a/Runtime/Camera/CCameraSpline.hpp +++ b/Runtime/Camera/CCameraSpline.hpp @@ -10,7 +10,7 @@ class CCameraSpline { friend class CBallCamera; std::vector x4_positions; - std::vector x14_; + std::vector x14_wpTracker; std::vector x24_t; std::vector x34_directions; float x44_length = 0.f; diff --git a/Runtime/MkCastTo.py b/Runtime/MkCastTo.py index 3f187e983..099538311 100644 --- a/Runtime/MkCastTo.py +++ b/Runtime/MkCastTo.py @@ -117,6 +117,8 @@ public: TCastToPtr() = default; TCastToPtr(CEntity* p); TCastToPtr(CEntity& p); + TCastToPtr& operator=(CEntity& p); + TCastToPtr& operator=(CEntity* p); ''') @@ -139,6 +141,8 @@ public: TCastToConstPtr() = default; TCastToConstPtr(const CEntity* p) : TCastToPtr(const_cast(p)) {} TCastToConstPtr(const CEntity& p) : TCastToPtr(const_cast(p)) {} + TCastToConstPtr& operator=(const CEntity& p) { TCastToPtr::operator=(const_cast(p)); return *this; } + TCastToConstPtr& operator=(const CEntity* p) { TCastToPtr::operator=(const_cast(p)); return *this; } const T* GetPtr() const { return TCastToPtr::ptr; } operator const T*() const { return GetPtr(); } const T& operator*() const { return *GetPtr(); } @@ -169,6 +173,12 @@ TCastToPtr::TCastToPtr(CEntity* p) { p->Accept(*this); } template TCastToPtr::TCastToPtr(CEntity& p) { p.Accept(*this); } +template +TCastToPtr& TCastToPtr::operator=(CEntity* p) { p->Accept(*this); return *this; } + +template +TCastToPtr& TCastToPtr::operator=(CEntity& p) { p.Accept(*this); return *this; } + ''') for tp in CENTITY_TYPES: diff --git a/Runtime/World/CPlayer.hpp b/Runtime/World/CPlayer.hpp index 5af53dbb0..736e76858 100644 --- a/Runtime/World/CPlayer.hpp +++ b/Runtime/World/CPlayer.hpp @@ -678,6 +678,7 @@ public: const zeus::CVector3f& GetMoveDir() const { return x50c_moveDir; } const zeus::CVector3f& GetLeaveMorphDir() const { return x518_leaveMorphDir; } u32 GetBombJumpCount() const { return x9d0_bombJumpCount; } + float GetMoveSpeed() const { return x4f8_moveSpeed; } }; } diff --git a/Runtime/World/CScriptCameraWaypoint.cpp b/Runtime/World/CScriptCameraWaypoint.cpp index 4934ce334..512839ce7 100644 --- a/Runtime/World/CScriptCameraWaypoint.cpp +++ b/Runtime/World/CScriptCameraWaypoint.cpp @@ -1,6 +1,7 @@ #include "CScriptCameraWaypoint.hpp" #include "CActorParameters.hpp" #include "TCastTo.hpp" +#include "CStateManager.hpp" namespace urde { @@ -27,4 +28,24 @@ void CScriptCameraWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None); } +TUniqueId CScriptCameraWaypoint::GetRandomNextWaypointId(CStateManager& mgr) const +{ + std::vector candidateIds; + for (const SConnection& conn : x20_conns) + { + if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) + { + TUniqueId uid = mgr.GetIdForScript(conn.x8_objId); + if (uid == kInvalidUniqueId) + continue; + candidateIds.push_back(uid); + } + } + + if (candidateIds.empty()) + return kInvalidUniqueId; + + return candidateIds[mgr.GetActiveRandom()->Range(0, s32(candidateIds.size() - 1))]; +} + } diff --git a/Runtime/World/CScriptCameraWaypoint.hpp b/Runtime/World/CScriptCameraWaypoint.hpp index c196adc6e..6e69fbcd7 100644 --- a/Runtime/World/CScriptCameraWaypoint.hpp +++ b/Runtime/World/CScriptCameraWaypoint.hpp @@ -18,6 +18,7 @@ public: void AcceptScriptMsg(EScriptObjectMessage, TUniqueId, CStateManager&); void AddToRenderer(const zeus::CFrustum&, const CStateManager&) const {} void Render(const CStateManager&) const {} + TUniqueId GetRandomNextWaypointId(CStateManager& mgr) const; }; }