mirror of https://github.com/AxioDL/metaforce.git
More CMorphBall implementations
This commit is contained in:
parent
2c4967ca4d
commit
41032d0a7c
|
@ -45,6 +45,7 @@ set(WORLD_SOURCES
|
||||||
CScriptActorKeyframe.hpp CScriptActorKeyframe.cpp
|
CScriptActorKeyframe.hpp CScriptActorKeyframe.cpp
|
||||||
CScriptWater.hpp CScriptWater.cpp
|
CScriptWater.hpp CScriptWater.cpp
|
||||||
CScriptGrapplePoint.hpp CScriptGrapplePoint.cpp
|
CScriptGrapplePoint.hpp CScriptGrapplePoint.cpp
|
||||||
|
CScriptSpiderBallAttractionSurface.hpp CScriptSpiderBallAttractionSurface.cpp
|
||||||
CScriptPickupGenerator.hpp CScriptPickupGenerator.cpp
|
CScriptPickupGenerator.hpp CScriptPickupGenerator.cpp
|
||||||
CScriptPointOfInterest.hpp CScriptPointOfInterest.cpp
|
CScriptPointOfInterest.hpp CScriptPointOfInterest.cpp
|
||||||
CScriptAreaAttributes.hpp CScriptAreaAttributes.cpp
|
CScriptAreaAttributes.hpp CScriptAreaAttributes.cpp
|
||||||
|
|
|
@ -10,6 +10,8 @@
|
||||||
#include "TCastTo.hpp"
|
#include "TCastTo.hpp"
|
||||||
#include "Camera/CGameCamera.hpp"
|
#include "Camera/CGameCamera.hpp"
|
||||||
#include "Collision/CGameCollision.hpp"
|
#include "Collision/CGameCollision.hpp"
|
||||||
|
#include "CScriptSpiderBallAttractionSurface.hpp"
|
||||||
|
#include "CScriptSpiderBallWaypoint.hpp"
|
||||||
|
|
||||||
namespace urde
|
namespace urde
|
||||||
{
|
{
|
||||||
|
@ -386,68 +388,384 @@ bool CMorphBall::IsMovementAllowed() const
|
||||||
return x1e00_ <= 0.f;
|
return x1e00_ <= 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::UpdateSpiderBall(const CFinalInput&, CStateManager&, float)
|
void CMorphBall::UpdateSpiderBall(const CFinalInput& input, CStateManager& mgr, float dt)
|
||||||
{
|
{
|
||||||
|
SetSpiderBallSwingingState(CheckForSwitchToSpiderBallSwinging(mgr));
|
||||||
|
if (x18be_spiderBallSwinging)
|
||||||
|
ApplySpiderBallSwingingForces(input, mgr, dt);
|
||||||
|
else
|
||||||
|
ApplySpiderBallRollForces(input, mgr, dt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::ApplySpiderBallSwingingForces(const CFinalInput&, CStateManager&, float)
|
void CMorphBall::ApplySpiderBallSwingingForces(const CFinalInput& input, CStateManager& mgr, float dt)
|
||||||
{
|
{
|
||||||
|
x18b4_ = 0.04f;
|
||||||
|
x18b8_ = 0.99f;
|
||||||
|
x1880_playerToSpiderNormal = x1890_spiderTrackPoint - x0_player.GetTranslation();
|
||||||
|
float playerToSpiderDist = x1880_playerToSpiderNormal.magnitude();
|
||||||
|
x1880_playerToSpiderNormal = x1880_playerToSpiderNormal * (-1.f / playerToSpiderDist);
|
||||||
|
float movement = GetSpiderBallControllerMovement(input);
|
||||||
|
UpdateSpiderBallSwingControllerMovementTimer(movement, dt);
|
||||||
|
float swingMovement = movement * GetSpiderBallSwingControllerMovementScalar();
|
||||||
|
float f29 = playerToSpiderDist * 110000.f / 3.7f;
|
||||||
|
x0_player.ApplyForceWR(
|
||||||
|
x1880_playerToSpiderNormal.cross(x18a8_spiderDistBetweenPoints).cross(x1880_playerToSpiderNormal).normalized() *
|
||||||
|
f29 * swingMovement * 0.06f, zeus::CAxisAngle::sIdentity);
|
||||||
|
x0_player.SetMomentumWR({0.f, 0.f, x0_player.GetMass() * g_tweakBall->GetBallGravity()});
|
||||||
|
x18fc_refPullVel = (1.f - x188c_spiderPullMovement) * 3.7f + 1.4f;
|
||||||
|
x1900_playerToSpiderTrackDist = playerToSpiderDist;
|
||||||
|
zeus::CVector3f playerVel = x0_player.GetVelocity();
|
||||||
|
float playerSpeed = playerVel.magnitude();
|
||||||
|
playerVel -= x1880_playerToSpiderNormal * playerSpeed * x1880_playerToSpiderNormal.dot(playerVel.normalized());
|
||||||
|
float maxPullVel = 0.04f;
|
||||||
|
if (x188c_spiderPullMovement == 1.f && std::fabs(x1880_playerToSpiderNormal.z) > 0.8f)
|
||||||
|
maxPullVel = 0.3f;
|
||||||
|
playerVel += x1880_playerToSpiderNormal *
|
||||||
|
zeus::clamp(-maxPullVel, x18fc_refPullVel - playerToSpiderDist, maxPullVel) / dt;
|
||||||
|
x0_player.SetVelocityWR(playerVel);
|
||||||
}
|
}
|
||||||
|
|
||||||
zeus::CVector3f CMorphBall::TransformSpiderBallForcesToView(const zeus::CVector2f& forces, CStateManager& mgr)
|
zeus::CVector3f CMorphBall::TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr)
|
||||||
{
|
{
|
||||||
return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis *
|
return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis *
|
||||||
zeus::CVector3f(forces.x, forces.y, 0.f);
|
zeus::CVector3f(forces.x, forces.y, 0.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::ApplySpiderBallRollForces(const CFinalInput&, CStateManager&, float)
|
zeus::CVector3f CMorphBall::TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr)
|
||||||
{
|
{
|
||||||
|
return mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis *
|
||||||
|
zeus::CVector3f(forces.x, 0.f, forces.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::CalculateSpiderBallAttractionSurfaceForces(const CFinalInput&, CStateManager&,
|
void CMorphBall::ApplySpiderBallRollForces(const CFinalInput& input, CStateManager& mgr, float dt)
|
||||||
const zeus::CTransform&)
|
|
||||||
{
|
{
|
||||||
|
zeus::CVector2f surfaceForces = CalculateSpiderBallAttractionSurfaceForces(input);
|
||||||
|
zeus::CVector3f viewSurfaceForces = TransformSpiderBallForcesXZ(surfaceForces, mgr);
|
||||||
|
zeus::CTransform camXf = mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform();
|
||||||
|
zeus::CVector3f spiderDirNorm = x189c_spiderInterpDistBetweenPoints.normalized();
|
||||||
|
float upDot = std::fabs(spiderDirNorm.dot(camXf.basis[2]));
|
||||||
|
float foreDot = std::fabs(spiderDirNorm.dot(camXf.basis[1]));
|
||||||
|
if (x0_player.x9c4_29_ && upDot < 0.25f && foreDot > 0.25f)
|
||||||
|
viewSurfaceForces = TransformSpiderBallForcesXY(surfaceForces, mgr);
|
||||||
|
float forceMag = surfaceForces.magnitude();
|
||||||
|
zeus::CVector2f x1d0;
|
||||||
|
float f26 = x18c0_isSpiderSurface ? forceMag : viewSurfaceForces.dot(spiderDirNorm);
|
||||||
|
bool r27 = true;
|
||||||
|
bool r30 = false;
|
||||||
|
if (std::fabs(forceMag) > 0.05f)
|
||||||
|
{
|
||||||
|
x1d0 = surfaceForces.normalized();
|
||||||
|
if (!x18c0_isSpiderSurface && x1d0.dot(x190c_) > 0.9f)
|
||||||
|
{
|
||||||
|
f26 = x1914_ >= 0.f ? forceMag : -forceMag;
|
||||||
|
r30 = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (std::fabs(f26) > 0.05f)
|
||||||
|
f26 = f26 >= 0.f ? forceMag : -forceMag;
|
||||||
|
else
|
||||||
|
r27 = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
r27 = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::CheckForSwitchToSpiderBallSwinging(CStateManager&)
|
if (!r30)
|
||||||
{
|
{
|
||||||
|
x190c_ = x1d0;
|
||||||
|
x1914_ = f26;
|
||||||
|
x1920_ = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::FindClosestSpiderBallWaypoint(CStateManager&, const zeus::CVector3f&, zeus::CVector3f&,
|
if (!r27)
|
||||||
zeus::CVector3f&, zeus::CVector3f&, float&, zeus::CVector3f&, bool&,
|
|
||||||
zeus::CTransform&) const
|
|
||||||
{
|
{
|
||||||
|
f26 = 0.f;
|
||||||
|
ResetSpiderBallForces();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::SetSpiderBallSwingingState(bool)
|
bool r31 = true;
|
||||||
{
|
if (!r27 && x0_player.GetVelocity().magnitude() <= 6.5f)
|
||||||
|
r31 = false;
|
||||||
|
|
||||||
|
zeus::CVector3f f27;
|
||||||
|
if (x18bd_ && r27)
|
||||||
|
{
|
||||||
|
if (x18c0_isSpiderSurface)
|
||||||
|
f27 = viewSurfaceForces * 0.1f;
|
||||||
|
else
|
||||||
|
f27 = x18a8_spiderDistBetweenPoints.normalized() * 0.1f * (f26 >= 0.f ? 1.f : -1.f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::GetSpiderBallControllerMovement(const CFinalInput&, bool, bool)
|
zeus::CVector3f ballPos = GetBallToWorld().origin + f27;
|
||||||
|
float distance = 0.f;
|
||||||
|
if (!(!r31 && x18bd_ && x188c_spiderPullMovement == 1.f && !x18bf_))
|
||||||
{
|
{
|
||||||
|
if (FindClosestSpiderBallWaypoint(mgr, ballPos, x1890_spiderTrackPoint, x189c_spiderInterpDistBetweenPoints,
|
||||||
|
x18a8_spiderDistBetweenPoints, distance, x1880_playerToSpiderNormal,
|
||||||
|
x18c0_isSpiderSurface, x18c4_spiderSurfaceTransform))
|
||||||
|
{
|
||||||
|
x18bc_ = true;
|
||||||
|
x18bf_ = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x1880_playerToSpiderNormal = x1890_spiderTrackPoint - ballPos;
|
||||||
|
distance = x1880_playerToSpiderNormal.magnitude();
|
||||||
|
x1880_playerToSpiderNormal = x1880_playerToSpiderNormal * (-1.f / distance);
|
||||||
|
x18bc_ = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x18bc_)
|
||||||
|
{
|
||||||
|
if (distance < kSpiderBallCollisionRadius)
|
||||||
|
x18bd_ = true;
|
||||||
|
if (x18bd_)
|
||||||
|
{
|
||||||
|
if (r31)
|
||||||
|
{
|
||||||
|
if (!x18c0_isSpiderSurface)
|
||||||
|
{
|
||||||
|
x18b4_ = 0.4f;
|
||||||
|
x18b8_ = 0.2f;
|
||||||
|
float f2 = viewSurfaceForces.dot(x189c_spiderInterpDistBetweenPoints.normalized());
|
||||||
|
if (r30 && x1920_)
|
||||||
|
{
|
||||||
|
f2 = x1918_;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x1918_ = f2;
|
||||||
|
x1920_ = false;
|
||||||
|
}
|
||||||
|
float f25;
|
||||||
|
if (std::fabs(f2) > 0.1f)
|
||||||
|
{
|
||||||
|
f25 = std::copysign(zeus::clamp(-1.f, forceMag, 1.f), f2);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
f25 = 0.f;
|
||||||
|
ResetSpiderBallForces();
|
||||||
|
}
|
||||||
|
if (distance > 1.05f)
|
||||||
|
f25 *= (1.05f - (distance - 1.05f)) / 1.05f;
|
||||||
|
x0_player.ApplyForceWR(x18a8_spiderDistBetweenPoints.normalized() * 90000.f * f25,
|
||||||
|
zeus::CAxisAngle::sIdentity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x18b4_ = 0.3f;
|
||||||
|
x18b8_ = 0.2f;
|
||||||
|
float f31 = x18c4_spiderSurfaceTransform.basis[0].dot(viewSurfaceForces);
|
||||||
|
float f30 = x18c4_spiderSurfaceTransform.basis[2].dot(viewSurfaceForces);
|
||||||
|
zeus::CVector3f forceVec = (f31 * x18c4_spiderSurfaceTransform.basis[0] +
|
||||||
|
f30 * x18c4_spiderSurfaceTransform.basis[2]) * 45000.f;
|
||||||
|
x0_player.ApplyForceWR(forceVec, zeus::CAxisAngle::sIdentity);
|
||||||
|
if (forceVec.magSquared() > 0.f)
|
||||||
|
{
|
||||||
|
float angle = std::atan2(45000.f * f31, 45000.f * f30);
|
||||||
|
if (angle - x18f4_ > M_PIF / 2.f)
|
||||||
|
angle = angle - M_PIF;
|
||||||
|
else if (x18f4_ - angle > M_PIF / 2.f)
|
||||||
|
angle = angle + M_PIF;
|
||||||
|
x18f8_ = angle;
|
||||||
|
}
|
||||||
|
x18f4_ += std::copysign(std::min(std::fabs(x18f8_ - x18f4_), 0.2f), x18f8_ - x18f4_);
|
||||||
|
x189c_spiderInterpDistBetweenPoints =
|
||||||
|
x18c4_spiderSurfaceTransform.rotate(zeus::CTransform::RotateY(x18f4_).basis[2]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
x0_player.ApplyForceWR({0.f, 0.f,
|
||||||
|
g_tweakBall->GetBallGravity() * x0_player.GetMass() * 8.f * (1.f - x188c_spiderPullMovement)},
|
||||||
|
zeus::CAxisAngle::sIdentity);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x18b4_ = 0.2f;
|
||||||
|
x18b8_ = 0.2f;
|
||||||
|
}
|
||||||
|
x0_player.SetMomentumWR(4.f * x0_player.GetMass() * g_tweakBall->GetBallGravity() * x1880_playerToSpiderNormal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
zeus::CVector2f CMorphBall::CalculateSpiderBallAttractionSurfaceForces(const CFinalInput& input) const
|
||||||
|
{
|
||||||
|
if (!IsMovementAllowed())
|
||||||
|
return zeus::CVector2f();
|
||||||
|
|
||||||
|
return {ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) -
|
||||||
|
ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input),
|
||||||
|
ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) -
|
||||||
|
ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input)};
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMorphBall::CheckForSwitchToSpiderBallSwinging(CStateManager& mgr) const
|
||||||
|
{
|
||||||
|
if (!x18bd_)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
if (x188c_spiderPullMovement == 1.f)
|
||||||
|
{
|
||||||
|
if (x18be_spiderBallSwinging)
|
||||||
|
{
|
||||||
|
zeus::CTransform ballToWorld = GetBallToWorld();
|
||||||
|
zeus::CVector3f closestPoint, interpDeltaBetweenPoints, deltaBetweenPoints, normal;
|
||||||
|
float distance = 0.f;
|
||||||
|
bool isSurface;
|
||||||
|
zeus::CTransform surfaceTransform;
|
||||||
|
return !(FindClosestSpiderBallWaypoint(mgr, ballToWorld.origin, closestPoint, interpDeltaBetweenPoints,
|
||||||
|
deltaBetweenPoints, distance, normal, isSurface, surfaceTransform)
|
||||||
|
&& distance < 2.1f);
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (x18be_spiderBallSwinging)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return std::fabs(x1880_playerToSpiderNormal.z) > 0.9f;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CMorphBall::FindClosestSpiderBallWaypoint(CStateManager& mgr, const zeus::CVector3f& ballCenter,
|
||||||
|
zeus::CVector3f& closestPoint,
|
||||||
|
zeus::CVector3f& interpDeltaBetweenPoints,
|
||||||
|
zeus::CVector3f& deltaBetweenPoints, float& distance,
|
||||||
|
zeus::CVector3f& normal, bool& isSurface,
|
||||||
|
zeus::CTransform& surfaceTransform) const
|
||||||
|
{
|
||||||
|
bool ret = false;
|
||||||
|
zeus::CAABox aabb(ballCenter - 2.1f, ballCenter + 2.1f);
|
||||||
|
rstl::reserved_vector<TUniqueId, 1024> nearList;
|
||||||
|
mgr.BuildNearList(nearList, aabb, CMaterialFilter::skPassEverything, nullptr);
|
||||||
|
float minDist = 2.1f;
|
||||||
|
|
||||||
|
for (TUniqueId id : nearList)
|
||||||
|
{
|
||||||
|
if (TCastToConstPtr<CScriptSpiderBallAttractionSurface> surface = mgr.GetObjectById(id))
|
||||||
|
{
|
||||||
|
zeus::CUnitVector3f surfaceNorm(surface->GetTransform().basis[1]);
|
||||||
|
zeus::CPlane plane(surfaceNorm, surface->GetTranslation().dot(surfaceNorm));
|
||||||
|
zeus::CVector3f intersectPoint;
|
||||||
|
if (plane.rayPlaneIntersection(ballCenter + surfaceNorm * 2.1f,
|
||||||
|
ballCenter - surfaceNorm * 2.1f, intersectPoint))
|
||||||
|
{
|
||||||
|
zeus::CVector3f halfScale = surface->GetScale() * 0.5f;
|
||||||
|
zeus::CVector3f localPoint = zeus::CTransform::Scale(1.f / halfScale) *
|
||||||
|
surface->GetTransform().inverse() * intersectPoint;
|
||||||
|
localPoint.x = zeus::clamp(-1.f, localPoint.x, 1.f);
|
||||||
|
localPoint.z = zeus::clamp(-1.f, localPoint.z, 1.f);
|
||||||
|
zeus::CVector3f worldPoint = surface->GetTransform() * zeus::CTransform::Scale(halfScale) * localPoint;
|
||||||
|
zeus::CVector3f finalDelta = worldPoint - ballCenter;
|
||||||
|
float finalMag = finalDelta.magnitude();
|
||||||
|
if (finalMag < minDist)
|
||||||
|
{
|
||||||
|
minDist = finalMag;
|
||||||
|
closestPoint = worldPoint;
|
||||||
|
distance = finalMag;
|
||||||
|
normal = finalDelta * (-1.f / finalMag);
|
||||||
|
isSurface = true;
|
||||||
|
surfaceTransform = surface->GetTransform();
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (TUniqueId id : nearList)
|
||||||
|
{
|
||||||
|
if (TCastToConstPtr<CScriptSpiderBallWaypoint> wp = mgr.GetObjectById(id))
|
||||||
|
{
|
||||||
|
const CScriptSpiderBallWaypoint* closestWp = nullptr;
|
||||||
|
zeus::CVector3f worldPoint;
|
||||||
|
zeus::CVector3f useDeltaBetweenPoints = deltaBetweenPoints;
|
||||||
|
zeus::CVector3f useInterpDeltaBetweenPoints = interpDeltaBetweenPoints;
|
||||||
|
wp->GetClosestPointAlongWaypoints(mgr, ballCenter, 2.1f, closestWp, worldPoint, useDeltaBetweenPoints,
|
||||||
|
0.8f, useInterpDeltaBetweenPoints);
|
||||||
|
if (closestWp)
|
||||||
|
{
|
||||||
|
zeus::CVector3f ballToPoint = worldPoint - ballCenter;
|
||||||
|
float ballToPointMag = ballToPoint.magnitude();
|
||||||
|
if (ballToPointMag < minDist)
|
||||||
|
{
|
||||||
|
minDist = ballToPointMag;
|
||||||
|
closestPoint = worldPoint;
|
||||||
|
interpDeltaBetweenPoints = useInterpDeltaBetweenPoints;
|
||||||
|
deltaBetweenPoints = useDeltaBetweenPoints;
|
||||||
|
distance = ballToPointMag;
|
||||||
|
normal = ballToPoint * (-1.f / ballToPointMag);
|
||||||
|
isSurface = false;
|
||||||
|
ret = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CMorphBall::SetSpiderBallSwingingState(bool active)
|
||||||
|
{
|
||||||
|
if (x18be_spiderBallSwinging != active)
|
||||||
|
{
|
||||||
|
ResetSpiderBallSwingControllerMovementTimer();
|
||||||
|
x18bf_ = true;
|
||||||
|
}
|
||||||
|
x18be_spiderBallSwinging = active;
|
||||||
|
}
|
||||||
|
|
||||||
|
float CMorphBall::GetSpiderBallControllerMovement(const CFinalInput& input) const
|
||||||
|
{
|
||||||
|
if (!IsMovementAllowed())
|
||||||
|
return 0.f;
|
||||||
|
|
||||||
|
float forward = ControlMapper::GetAnalogInput(ControlMapper::ECommands::Forward, input) -
|
||||||
|
ControlMapper::GetAnalogInput(ControlMapper::ECommands::Backward, input);
|
||||||
|
float turn = ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnRight, input) -
|
||||||
|
ControlMapper::GetAnalogInput(ControlMapper::ECommands::TurnLeft, input);
|
||||||
|
float angle = zeus::radToDeg(std::atan2(forward, turn));
|
||||||
|
float hyp = std::sqrt(forward * forward + turn * turn);
|
||||||
|
if (angle > -35.f && angle < 125.f)
|
||||||
|
return hyp;
|
||||||
|
if (angle < -55.f || angle > 145.f)
|
||||||
|
return -hyp;
|
||||||
|
return 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::ResetSpiderBallSwingControllerMovementTimer()
|
void CMorphBall::ResetSpiderBallSwingControllerMovementTimer()
|
||||||
{
|
{
|
||||||
|
x1904_swingControlDir = 0.f;
|
||||||
|
x1908_swingControlTime = 0.f;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::UpdateSpiderBallSwingControllerMovementTimer(float, float)
|
void CMorphBall::UpdateSpiderBallSwingControllerMovementTimer(float movement, float dt)
|
||||||
{
|
{
|
||||||
|
if (std::fabs(movement) < 0.05f)
|
||||||
|
{
|
||||||
|
ResetSpiderBallSwingControllerMovementTimer();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if ((movement >= 0.f ? 1.f : -1.f) != x1904_swingControlDir)
|
||||||
|
{
|
||||||
|
ResetSpiderBallSwingControllerMovementTimer();
|
||||||
|
x1904_swingControlDir = (movement >= 0.f ? 1.f : -1.f);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
x1908_swingControlTime += dt;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
float CMorphBall::GetSpiderBallSwingControllerMovementScalar() const
|
float CMorphBall::GetSpiderBallSwingControllerMovementScalar() const
|
||||||
{
|
{
|
||||||
return 0.f;
|
if (x1908_swingControlTime < 1.2f)
|
||||||
|
return 1.f;
|
||||||
|
return std::max(0.f, (2.4f - x1908_swingControlTime) / 1.2f);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMorphBall::CreateSpiderBallParticles(const zeus::CVector3f&, const zeus::CVector3f&)
|
void CMorphBall::CreateSpiderBallParticles(const zeus::CVector3f&, const zeus::CVector3f&)
|
||||||
|
@ -470,15 +788,16 @@ void CMorphBall::ComputeMarioMovement(const CFinalInput& input, CStateManager& m
|
||||||
if (!IsMovementAllowed())
|
if (!IsMovementAllowed())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
x188c_ = (ControlMapper::GetAnalogInput(ControlMapper::ECommands::SpiderBall, input) >= 0.5f / 100.f) ? 1.f : 0.f;
|
x188c_spiderPullMovement =
|
||||||
|
(ControlMapper::GetAnalogInput(ControlMapper::ECommands::SpiderBall, input) >= 0.5f / 100.f) ? 1.f : 0.f;
|
||||||
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) &&
|
if (mgr.GetPlayerState()->HasPowerUp(CPlayerState::EItemType::SpiderBall) &&
|
||||||
x188c_ != 0.f && x191c_damageTimer == 0.f)
|
x188c_spiderPullMovement != 0.f && x191c_damageTimer == 0.f)
|
||||||
{
|
{
|
||||||
if (x187c_spiderBallState != ESpiderBallState::Active)
|
if (x187c_spiderBallState != ESpiderBallState::Active)
|
||||||
{
|
{
|
||||||
x18bd_ = false;
|
x18bd_ = false;
|
||||||
x187c_spiderBallState = ESpiderBallState::Active;
|
x187c_spiderBallState = ESpiderBallState::Active;
|
||||||
x18a8_initialSpiderBallUp = x189c_spiderBallDir = x0_player.GetTransform().basis[2];
|
x18a8_spiderDistBetweenPoints = x189c_spiderInterpDistBetweenPoints = x0_player.GetTransform().basis[2];
|
||||||
}
|
}
|
||||||
UpdateSpiderBall(input, mgr, dt);
|
UpdateSpiderBall(input, mgr, dt);
|
||||||
|
|
||||||
|
@ -540,7 +859,8 @@ void CMorphBall::ComputeMarioMovement(const CFinalInput& input, CStateManager& m
|
||||||
zeus::CVector3f controlForce = controlXf.rotate({0.f, f28f, 0.f}) + controlXf.rotate({f27f, 0.f, 0.f});
|
zeus::CVector3f controlForce = controlXf.rotate({0.f, f28f, 0.f}) + controlXf.rotate({f27f, 0.f, 0.f});
|
||||||
x1c_ = controlForce;
|
x1c_ = controlForce;
|
||||||
if (x1de4_24 && !GetIsInHalfPipeMode())
|
if (x1de4_24 && !GetIsInHalfPipeMode())
|
||||||
controlForce = x1924_surfaceToWorld.rotate({x1924_surfaceToWorld.transposeRotate(controlForce).x, 0.f, 0.f});
|
controlForce =
|
||||||
|
x1924_surfaceToWorld.rotate({x1924_surfaceToWorld.transposeRotate(controlForce).x, 0.f, 0.f});
|
||||||
|
|
||||||
if (GetIsInHalfPipeMode() && controlForce.magnitude() > FLT_EPSILON)
|
if (GetIsInHalfPipeMode() && controlForce.magnitude() > FLT_EPSILON)
|
||||||
{
|
{
|
||||||
|
@ -642,8 +962,8 @@ void CMorphBall::UpdateBallDynamics(CStateManager& mgr, float dt)
|
||||||
x191c_damageTimer = std::max(0.f, x191c_damageTimer);
|
x191c_damageTimer = std::max(0.f, x191c_damageTimer);
|
||||||
if (x187c_spiderBallState == ESpiderBallState::Active)
|
if (x187c_spiderBallState == ESpiderBallState::Active)
|
||||||
{
|
{
|
||||||
x1924_surfaceToWorld = CalculateSurfaceToWorld(x1880_spiderTrackNormal,
|
x1924_surfaceToWorld = CalculateSurfaceToWorld(x1880_playerToSpiderNormal,
|
||||||
x1890_spiderTrackPoint, x189c_spiderBallDir);
|
x1890_spiderTrackPoint, x189c_spiderInterpDistBetweenPoints);
|
||||||
x2c_tireLeanAngle = 0.f;
|
x2c_tireLeanAngle = 0.f;
|
||||||
if (!x28_tireMode)
|
if (!x28_tireMode)
|
||||||
SwitchToTire();
|
SwitchToTire();
|
||||||
|
|
|
@ -64,25 +64,25 @@ private:
|
||||||
CCollisionInfoList x74_collisionInfos;
|
CCollisionInfoList x74_collisionInfos;
|
||||||
u32 xc78_ = 0;
|
u32 xc78_ = 0;
|
||||||
ESpiderBallState x187c_spiderBallState = ESpiderBallState::Inactive;
|
ESpiderBallState x187c_spiderBallState = ESpiderBallState::Inactive;
|
||||||
zeus::CVector3f x1880_spiderTrackNormal;
|
zeus::CVector3f x1880_playerToSpiderNormal;
|
||||||
float x188c_ = 1.f;
|
float x188c_spiderPullMovement = 1.f;
|
||||||
zeus::CVector3f x1890_spiderTrackPoint;
|
zeus::CVector3f x1890_spiderTrackPoint;
|
||||||
zeus::CVector3f x189c_spiderBallDir;
|
zeus::CVector3f x189c_spiderInterpDistBetweenPoints;
|
||||||
zeus::CVector3f x18a8_initialSpiderBallUp;
|
zeus::CVector3f x18a8_spiderDistBetweenPoints;
|
||||||
float x18b4_ = 0.f;
|
float x18b4_ = 0.f;
|
||||||
float x18b8_ = 0.f;
|
float x18b8_ = 0.f;
|
||||||
bool x18bc_ = false;
|
bool x18bc_ = false;
|
||||||
bool x18bd_ = false;
|
bool x18bd_ = false;
|
||||||
bool x18be_ = false;
|
bool x18be_spiderBallSwinging = false;
|
||||||
bool x18bf_ = true;
|
bool x18bf_ = true;
|
||||||
bool x18c0_ = false;
|
bool x18c0_isSpiderSurface = false;
|
||||||
zeus::CTransform x18c4_;
|
zeus::CTransform x18c4_spiderSurfaceTransform;
|
||||||
float x18f4_ = 0.f;
|
float x18f4_ = 0.f;
|
||||||
float x18f8_ = 0.f;
|
float x18f8_ = 0.f;
|
||||||
float x18fc_ = 0.f;
|
float x18fc_refPullVel = 0.f;
|
||||||
float x1900_ = 0.f;
|
float x1900_playerToSpiderTrackDist = 0.f;
|
||||||
float x1904_ = 0.f;
|
float x1904_swingControlDir = 0.f;
|
||||||
float x1908_ = 0.f;
|
float x1908_swingControlTime = 0.f;
|
||||||
zeus::CVector2f x190c_;
|
zeus::CVector2f x190c_;
|
||||||
float x1914_ = 0.f;
|
float x1914_ = 0.f;
|
||||||
float x1918_ = 0.f;
|
float x1918_ = 0.f;
|
||||||
|
@ -171,7 +171,8 @@ private:
|
||||||
static std::unique_ptr<CModelData> GetMorphBallModel(const char* name, float radius);
|
static std::unique_ptr<CModelData> GetMorphBallModel(const char* name, float radius);
|
||||||
void SelectMorphBallSounds(const CMaterialList& mat);
|
void SelectMorphBallSounds(const CMaterialList& mat);
|
||||||
void UpdateMorphBallSounds(float dt);
|
void UpdateMorphBallSounds(float dt);
|
||||||
static zeus::CVector3f TransformSpiderBallForcesToView(const zeus::CVector2f& forces, CStateManager& mgr);
|
static zeus::CVector3f TransformSpiderBallForcesXY(const zeus::CVector2f& forces, CStateManager& mgr);
|
||||||
|
static zeus::CVector3f TransformSpiderBallForcesXZ(const zeus::CVector2f& forces, CStateManager& mgr);
|
||||||
void ResetSpiderBallForces();
|
void ResetSpiderBallForces();
|
||||||
public:
|
public:
|
||||||
CMorphBall(CPlayer& player, float radius);
|
CMorphBall(CPlayer& player, float radius);
|
||||||
|
@ -188,19 +189,21 @@ public:
|
||||||
float BallTurnInput(const CFinalInput& input) const;
|
float BallTurnInput(const CFinalInput& input) const;
|
||||||
void ComputeBallMovement(const CFinalInput& input, CStateManager& mgr, float dt);
|
void ComputeBallMovement(const CFinalInput& input, CStateManager& mgr, float dt);
|
||||||
bool IsMovementAllowed() const;
|
bool IsMovementAllowed() const;
|
||||||
void UpdateSpiderBall(const CFinalInput&, CStateManager&, float);
|
void UpdateSpiderBall(const CFinalInput& input, CStateManager& mgr, float dt);
|
||||||
void ApplySpiderBallSwingingForces(const CFinalInput&, CStateManager&, float);
|
void ApplySpiderBallSwingingForces(const CFinalInput& input, CStateManager& mgr, float dt);
|
||||||
void ApplySpiderBallRollForces(const CFinalInput&, CStateManager&, float);
|
void ApplySpiderBallRollForces(const CFinalInput& input, CStateManager& mgr, float dt);
|
||||||
void CalculateSpiderBallAttractionSurfaceForces(const CFinalInput&, CStateManager&,
|
zeus::CVector2f CalculateSpiderBallAttractionSurfaceForces(const CFinalInput& input) const;
|
||||||
const zeus::CTransform&);
|
bool CheckForSwitchToSpiderBallSwinging(CStateManager& mgr) const;
|
||||||
void CheckForSwitchToSpiderBallSwinging(CStateManager&);
|
bool FindClosestSpiderBallWaypoint(CStateManager& mgr, const zeus::CVector3f& ballCenter,
|
||||||
void FindClosestSpiderBallWaypoint(CStateManager&, const zeus::CVector3f&, zeus::CVector3f&,
|
zeus::CVector3f& closestPoint,
|
||||||
zeus::CVector3f&, zeus::CVector3f&, float&, zeus::CVector3f&, bool&,
|
zeus::CVector3f& interpDeltaBetweenPoints,
|
||||||
zeus::CTransform&) const;
|
zeus::CVector3f& deltaBetweenPoints, float& distance,
|
||||||
void SetSpiderBallSwingingState(bool);
|
zeus::CVector3f& normal, bool& isSurface,
|
||||||
void GetSpiderBallControllerMovement(const CFinalInput&, bool, bool);
|
zeus::CTransform& surfaceTransform) const;
|
||||||
|
void SetSpiderBallSwingingState(bool active);
|
||||||
|
float GetSpiderBallControllerMovement(const CFinalInput& input) const;
|
||||||
void ResetSpiderBallSwingControllerMovementTimer();
|
void ResetSpiderBallSwingControllerMovementTimer();
|
||||||
void UpdateSpiderBallSwingControllerMovementTimer(float, float);
|
void UpdateSpiderBallSwingControllerMovementTimer(float movement, float dt);
|
||||||
float GetSpiderBallSwingControllerMovementScalar() const;
|
float GetSpiderBallSwingControllerMovementScalar() const;
|
||||||
void CreateSpiderBallParticles(const zeus::CVector3f&, const zeus::CVector3f&);
|
void CreateSpiderBallParticles(const zeus::CVector3f&, const zeus::CVector3f&);
|
||||||
void ComputeMarioMovement(const CFinalInput& input, CStateManager& mgr, float dt);
|
void ComputeMarioMovement(const CFinalInput& input, CStateManager& mgr, float dt);
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
#include "CScriptSpiderBallAttractionSurface.hpp"
|
||||||
|
#include "CActorParameters.hpp"
|
||||||
|
#include "TCastTo.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
CScriptSpiderBallAttractionSurface::CScriptSpiderBallAttractionSurface(
|
||||||
|
TUniqueId uid, const std::string& name, const CEntityInfo& info,
|
||||||
|
const zeus::CTransform& xf, const zeus::CVector3f& scale, bool active)
|
||||||
|
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), {EMaterialTypes::Unknown},
|
||||||
|
CActorParameters::None(), kInvalidUniqueId), xe8_scale(scale),
|
||||||
|
xf4_aabb(zeus::CAABox(scale * -0.5f, scale * 0.5f).getTransformedAABox(xf.getRotation()))
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptSpiderBallAttractionSurface::Accept(IVisitor& visitor)
|
||||||
|
{
|
||||||
|
visitor.Visit(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptSpiderBallAttractionSurface::Think(float dt, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
// Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptSpiderBallAttractionSurface::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
CActor::AcceptScriptMsg(msg, sender, mgr);
|
||||||
|
}
|
||||||
|
|
||||||
|
rstl::optional_object<zeus::CAABox> CScriptSpiderBallAttractionSurface::GetTouchBounds() const
|
||||||
|
{
|
||||||
|
if (GetActive())
|
||||||
|
return {zeus::CAABox(xf4_aabb.min + GetTranslation(), xf4_aabb.max + GetTranslation())};
|
||||||
|
return {};
|
||||||
|
}
|
||||||
|
|
||||||
|
void CScriptSpiderBallAttractionSurface::Touch(CActor& actor, CStateManager& mgr)
|
||||||
|
{
|
||||||
|
// Empty
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
#ifndef __URDE_CSCRIPTSPIDERBALLATTRACTIONSURFACE_HPP__
|
||||||
|
#define __URDE_CSCRIPTSPIDERBALLATTRACTIONSURFACE_HPP__
|
||||||
|
|
||||||
|
#include "CActor.hpp"
|
||||||
|
|
||||||
|
namespace urde
|
||||||
|
{
|
||||||
|
|
||||||
|
class CScriptSpiderBallAttractionSurface : public CActor
|
||||||
|
{
|
||||||
|
zeus::CVector3f xe8_scale;
|
||||||
|
zeus::CAABox xf4_aabb;
|
||||||
|
public:
|
||||||
|
CScriptSpiderBallAttractionSurface(TUniqueId uid, const std::string& name, const CEntityInfo& info,
|
||||||
|
const zeus::CTransform& xf, const zeus::CVector3f& scale, bool active);
|
||||||
|
void Accept(IVisitor& visitor);
|
||||||
|
void Think(float dt, CStateManager& mgr);
|
||||||
|
void AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId sender, CStateManager& mgr);
|
||||||
|
rstl::optional_object<zeus::CAABox> GetTouchBounds() const;
|
||||||
|
void Touch(CActor& actor, CStateManager& mgr);
|
||||||
|
const zeus::CVector3f& GetScale() const { return xe8_scale; }
|
||||||
|
};
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif // __URDE_CSCRIPTSPIDERBALLATTRACTIONSURFACE_HPP__
|
|
@ -57,11 +57,11 @@ void CScriptSpiderBallWaypoint::BuildWaypointListAndBounds(CStateManager& mgr)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
CScriptSpiderBallWaypoint* curWaypoint = this;
|
CScriptSpiderBallWaypoint* curWaypoint = this;
|
||||||
TUniqueId uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::Yes);
|
TUniqueId uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck);
|
||||||
while (uid != kInvalidUniqueId)
|
while (uid != kInvalidUniqueId)
|
||||||
{
|
{
|
||||||
curWaypoint = static_cast<CScriptSpiderBallWaypoint*>(mgr.ObjectById(uid));
|
curWaypoint = static_cast<CScriptSpiderBallWaypoint*>(mgr.ObjectById(uid));
|
||||||
uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::Yes);
|
uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck);
|
||||||
}
|
}
|
||||||
|
|
||||||
curWaypoint->AccumulateBounds(x34_transform.origin);
|
curWaypoint->AccumulateBounds(x34_transform.origin);
|
||||||
|
@ -73,7 +73,23 @@ void CScriptSpiderBallWaypoint::AddPreviousWaypoint(TUniqueId uid)
|
||||||
xec_waypoints.push_back(uid);
|
xec_waypoints.push_back(uid);
|
||||||
}
|
}
|
||||||
|
|
||||||
TUniqueId CScriptSpiderBallWaypoint::NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive)
|
TUniqueId CScriptSpiderBallWaypoint::PreviousWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const
|
||||||
|
{
|
||||||
|
for (TUniqueId id : xec_waypoints)
|
||||||
|
{
|
||||||
|
if (const CEntity* ent = mgr.GetObjectById(id))
|
||||||
|
{
|
||||||
|
if (checkActive == ECheckActiveWaypoint::SkipCheck)
|
||||||
|
return id;
|
||||||
|
else if (ent->GetActive())
|
||||||
|
return id;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return kInvalidUniqueId;
|
||||||
|
}
|
||||||
|
|
||||||
|
TUniqueId CScriptSpiderBallWaypoint::NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const
|
||||||
{
|
{
|
||||||
for (const SConnection& conn : x20_conns)
|
for (const SConnection& conn : x20_conns)
|
||||||
{
|
{
|
||||||
|
@ -82,13 +98,131 @@ TUniqueId CScriptSpiderBallWaypoint::NextWaypoint(const CStateManager& mgr, EChe
|
||||||
TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
|
TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
|
||||||
if (uid != kInvalidUniqueId)
|
if (uid != kInvalidUniqueId)
|
||||||
{
|
{
|
||||||
const CEntity* ent = mgr.GetObjectById(uid);
|
if (const CEntity* ent = mgr.GetObjectById(uid))
|
||||||
if (ent && checkActive == ECheckActiveWaypoint::Yes && ent->GetActive())
|
{
|
||||||
|
if (checkActive == ECheckActiveWaypoint::SkipCheck)
|
||||||
return ent->GetUniqueId();
|
return ent->GetUniqueId();
|
||||||
|
else if (ent->GetActive())
|
||||||
|
return ent->GetUniqueId();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return kInvalidUniqueId;
|
return kInvalidUniqueId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CScriptSpiderBallWaypoint::GetClosestPointAlongWaypoints(CStateManager& mgr, const zeus::CVector3f& ballPos,
|
||||||
|
float maxPointToBallDist, const CScriptSpiderBallWaypoint*& closestWaypoint, zeus::CVector3f& closestPoint,
|
||||||
|
zeus::CVector3f& deltaBetweenPoints, float deltaBetweenInterpDist, zeus::CVector3f& interpDeltaBetweenPoints) const
|
||||||
|
{
|
||||||
|
const CScriptSpiderBallWaypoint* wp = this;
|
||||||
|
while (wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck) != kInvalidUniqueId)
|
||||||
|
wp = static_cast<const CScriptSpiderBallWaypoint*>(
|
||||||
|
mgr.GetObjectById(wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck)));
|
||||||
|
float minPointToBallDistSq = maxPointToBallDist * maxPointToBallDist;
|
||||||
|
float deltaBetweenInterpDistSq = deltaBetweenInterpDist * deltaBetweenInterpDist;
|
||||||
|
zeus::CVector3f lastPoint = wp->GetTranslation();
|
||||||
|
zeus::CVector3f lastDelta;
|
||||||
|
bool computeDelta = wp->GetActive();
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId)
|
||||||
|
{
|
||||||
|
if (computeDelta)
|
||||||
|
{
|
||||||
|
const CScriptSpiderBallWaypoint* prevWp = wp;
|
||||||
|
wp = static_cast<const CScriptSpiderBallWaypoint*>(
|
||||||
|
mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check)));
|
||||||
|
zeus::CVector3f thisDelta = wp->GetTranslation() - lastPoint;
|
||||||
|
zeus::CVector3f lastPointToBall = ballPos - lastPoint;
|
||||||
|
if (prevWp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check) == kInvalidUniqueId)
|
||||||
|
lastDelta = thisDelta;
|
||||||
|
float pointToBallDistSq = lastPointToBall.magSquared();
|
||||||
|
if (pointToBallDistSq < minPointToBallDistSq)
|
||||||
|
{
|
||||||
|
minPointToBallDistSq = pointToBallDistSq;
|
||||||
|
closestPoint = lastPoint;
|
||||||
|
deltaBetweenPoints = thisDelta;
|
||||||
|
interpDeltaBetweenPoints = (thisDelta.normalized() + lastDelta.normalized()) * 0.5f;
|
||||||
|
closestWaypoint = wp;
|
||||||
|
}
|
||||||
|
float projectedT = lastPointToBall.dot(thisDelta);
|
||||||
|
if (projectedT >= 0.f)
|
||||||
|
{
|
||||||
|
float normT = projectedT / thisDelta.magSquared();
|
||||||
|
if (normT < 1.f)
|
||||||
|
{
|
||||||
|
zeus::CVector3f projectedPoint = zeus::CVector3f::lerp(lastPoint, wp->GetTranslation(), normT);
|
||||||
|
float projToBallDistSq = (ballPos - projectedPoint).magSquared();
|
||||||
|
if (projToBallDistSq < minPointToBallDistSq)
|
||||||
|
{
|
||||||
|
minPointToBallDistSq = projToBallDistSq;
|
||||||
|
closestPoint = projectedPoint;
|
||||||
|
deltaBetweenPoints = thisDelta;
|
||||||
|
interpDeltaBetweenPoints = deltaBetweenPoints;
|
||||||
|
closestWaypoint = wp;
|
||||||
|
float lastToProjDist = (lastPoint - projectedPoint).magnitude();
|
||||||
|
if (lastToProjDist < deltaBetweenInterpDistSq)
|
||||||
|
{
|
||||||
|
interpDeltaBetweenPoints =
|
||||||
|
zeus::CVector3f::lerp(0.5f * (thisDelta.normalized() + lastDelta.normalized()),
|
||||||
|
thisDelta.normalized(), lastToProjDist / deltaBetweenInterpDist);
|
||||||
|
}
|
||||||
|
else if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId)
|
||||||
|
{
|
||||||
|
lastToProjDist = (projectedPoint - wp->GetTranslation()).magnitude();
|
||||||
|
if (lastToProjDist < deltaBetweenInterpDist)
|
||||||
|
{
|
||||||
|
float t = lastToProjDist / deltaBetweenInterpDist;
|
||||||
|
interpDeltaBetweenPoints =
|
||||||
|
zeus::CVector3f::lerp(((static_cast<const CScriptSpiderBallWaypoint*>(
|
||||||
|
mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check)))->
|
||||||
|
GetTranslation() - wp->GetTranslation()).normalized() +
|
||||||
|
thisDelta.normalized()) * 0.5f, thisDelta.normalized(), t);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
lastDelta = thisDelta;
|
||||||
|
lastPoint = wp->GetTranslation();
|
||||||
|
computeDelta = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
wp = static_cast<const CScriptSpiderBallWaypoint*>(
|
||||||
|
mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check)));
|
||||||
|
lastPoint = wp->GetTranslation();
|
||||||
|
computeDelta = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck) != kInvalidUniqueId)
|
||||||
|
{
|
||||||
|
wp = static_cast<const CScriptSpiderBallWaypoint*>(
|
||||||
|
mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck)));
|
||||||
|
computeDelta = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((ballPos - lastPoint).magSquared() < minPointToBallDistSq)
|
||||||
|
{
|
||||||
|
closestPoint = lastPoint;
|
||||||
|
if (wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId)
|
||||||
|
{
|
||||||
|
wp = static_cast<const CScriptSpiderBallWaypoint*>(
|
||||||
|
mgr.GetObjectById(wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck)));
|
||||||
|
deltaBetweenPoints = lastPoint - wp->GetTranslation();
|
||||||
|
interpDeltaBetweenPoints = deltaBetweenPoints;
|
||||||
|
}
|
||||||
|
closestWaypoint = wp;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -9,8 +9,8 @@ class CScriptSpiderBallWaypoint : public CActor
|
||||||
{
|
{
|
||||||
enum class ECheckActiveWaypoint
|
enum class ECheckActiveWaypoint
|
||||||
{
|
{
|
||||||
No,
|
Check,
|
||||||
Yes
|
SkipCheck
|
||||||
};
|
};
|
||||||
u32 xe8_;
|
u32 xe8_;
|
||||||
std::vector<TUniqueId> xec_waypoints;
|
std::vector<TUniqueId> xec_waypoints;
|
||||||
|
@ -22,10 +22,15 @@ public:
|
||||||
void Render(const CStateManager& mgr) const { CActor::Render(mgr); }
|
void Render(const CStateManager& mgr) const { CActor::Render(mgr); }
|
||||||
void AddToRenderer(const zeus::CFrustum&, const CStateManager&) {}
|
void AddToRenderer(const zeus::CFrustum&, const CStateManager&) {}
|
||||||
std::experimental::optional<zeus::CAABox> GetTouchBounds() const { return xfc_aabox; }
|
std::experimental::optional<zeus::CAABox> GetTouchBounds() const { return xfc_aabox; }
|
||||||
void AccumulateBounds(const zeus::CVector3f&);
|
void AccumulateBounds(const zeus::CVector3f& v);
|
||||||
void BuildWaypointListAndBounds(CStateManager&);
|
void BuildWaypointListAndBounds(CStateManager& mgr);
|
||||||
void AddPreviousWaypoint(TUniqueId);
|
void AddPreviousWaypoint(TUniqueId uid);
|
||||||
TUniqueId NextWaypoint(const CStateManager&, ECheckActiveWaypoint);
|
TUniqueId PreviousWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const;
|
||||||
|
TUniqueId NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const;
|
||||||
|
void GetClosestPointAlongWaypoints(CStateManager& mgr, const zeus::CVector3f& ballPos,
|
||||||
|
float maxPointToBallDist, const CScriptSpiderBallWaypoint*& closestWaypoint,
|
||||||
|
zeus::CVector3f& closestPoint, zeus::CVector3f& deltaBetweenPoints,
|
||||||
|
float deltaBetweenInterpDist, zeus::CVector3f& interpDeltaBetweenPoints) const;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -61,6 +61,7 @@
|
||||||
#include "CScriptWater.hpp"
|
#include "CScriptWater.hpp"
|
||||||
#include "CScriptWaypoint.hpp"
|
#include "CScriptWaypoint.hpp"
|
||||||
#include "CScriptWorldTeleporter.hpp"
|
#include "CScriptWorldTeleporter.hpp"
|
||||||
|
#include "CScriptSpiderBallAttractionSurface.hpp"
|
||||||
#include "CSimplePool.hpp"
|
#include "CSimplePool.hpp"
|
||||||
#include "CStateManager.hpp"
|
#include "CStateManager.hpp"
|
||||||
#include "CVisorParameters.hpp"
|
#include "CVisorParameters.hpp"
|
||||||
|
@ -1450,7 +1451,12 @@ CEntity* ScriptLoader::LoadDebugCameraWaypoint(CStateManager& mgr, CInputStream&
|
||||||
CEntity* ScriptLoader::LoadSpiderBallAttractionSurface(CStateManager& mgr, CInputStream& in, int propCount,
|
CEntity* ScriptLoader::LoadSpiderBallAttractionSurface(CStateManager& mgr, CInputStream& in, int propCount,
|
||||||
const CEntityInfo& info)
|
const CEntityInfo& info)
|
||||||
{
|
{
|
||||||
|
if (!EnsurePropertyCount(propCount, 5, "SpiderBallAttractionSurface"))
|
||||||
return nullptr;
|
return nullptr;
|
||||||
|
SScaledActorHead aHead = LoadScaledActorHead(in, mgr);
|
||||||
|
bool active = in.readBool();
|
||||||
|
return new CScriptSpiderBallAttractionSurface(mgr.AllocateUniqueId(), aHead.x0_name, info, aHead.x10_transform,
|
||||||
|
aHead.x40_scale, active);
|
||||||
}
|
}
|
||||||
|
|
||||||
CEntity* ScriptLoader::LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
CEntity* ScriptLoader::LoadPuddleToadGamma(CStateManager& mgr, CInputStream& in, int propCount, const CEntityInfo& info)
|
||||||
|
|
|
@ -183,7 +183,7 @@ public:
|
||||||
~reserved_vector()
|
~reserved_vector()
|
||||||
{
|
{
|
||||||
for (size_t i=0 ; i<base::x0_size ; ++i)
|
for (size_t i=0 ; i<base::x0_size ; ++i)
|
||||||
std::default_delete<T>()(std::addressof(base::_value(i)));
|
base::_value(i).~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
void push_back(const T& d)
|
void push_back(const T& d)
|
||||||
|
@ -224,7 +224,7 @@ public:
|
||||||
Log.report(logvisor::Fatal, "pop_back() called on empty rstl::reserved_vector.");
|
Log.report(logvisor::Fatal, "pop_back() called on empty rstl::reserved_vector.");
|
||||||
#endif
|
#endif
|
||||||
--base::x0_size;
|
--base::x0_size;
|
||||||
std::default_delete<T>()(std::addressof(base::_value(base::x0_size)));
|
base::_value(base::x0_size).~T();
|
||||||
}
|
}
|
||||||
|
|
||||||
iterator insert(const_iterator pos, const T& value)
|
iterator insert(const_iterator pos, const T& value)
|
||||||
|
@ -288,7 +288,7 @@ public:
|
||||||
else if (size < base::x0_size)
|
else if (size < base::x0_size)
|
||||||
{
|
{
|
||||||
for (size_t i = size; i < base::x0_size; ++i)
|
for (size_t i = size; i < base::x0_size; ++i)
|
||||||
std::default_delete<T>()(std::addressof(base::_value(i)));
|
base::_value(i).~T();
|
||||||
base::x0_size = size;
|
base::x0_size = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -308,7 +308,7 @@ public:
|
||||||
else if (size < base::x0_size)
|
else if (size < base::x0_size)
|
||||||
{
|
{
|
||||||
for (size_t i = size; i < base::x0_size; ++i)
|
for (size_t i = size; i < base::x0_size; ++i)
|
||||||
std::default_delete<T>()(std::addressof(base::_value(i)));
|
base::_value(i).~T();
|
||||||
base::x0_size = size;
|
base::x0_size = size;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -322,14 +322,14 @@ public:
|
||||||
for (auto it = base::_const_cast_iterator(pos) + 1; it != base::end(); ++it)
|
for (auto it = base::_const_cast_iterator(pos) + 1; it != base::end(); ++it)
|
||||||
*(it - 1) = std::forward<T>(*it);
|
*(it - 1) = std::forward<T>(*it);
|
||||||
--base::x0_size;
|
--base::x0_size;
|
||||||
std::default_delete<T>()(std::addressof(base::_value(base::x0_size)));
|
base::_value(base::x0_size).~T();
|
||||||
return base::_const_cast_iterator(pos);
|
return base::_const_cast_iterator(pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
void clear()
|
void clear()
|
||||||
{
|
{
|
||||||
for (auto it = base::begin(); it != base::end(); ++it)
|
for (auto it = base::begin(); it != base::end(); ++it)
|
||||||
std::default_delete<T>()(std::addressof(*it));
|
it->~T();
|
||||||
base::x0_size = 0;
|
base::x0_size = 0;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -348,7 +348,7 @@ class prereserved_vector : public _reserved_vector_base<T, N>
|
||||||
void _deinit()
|
void _deinit()
|
||||||
{
|
{
|
||||||
for (auto& i : base::x4_data)
|
for (auto& i : base::x4_data)
|
||||||
std::default_delete<T>()(reinterpret_cast<T*>(std::addressof(i)));
|
reinterpret_cast<T*>(std::addressof(i))->~T();
|
||||||
}
|
}
|
||||||
public:
|
public:
|
||||||
using base = _reserved_vector_base<T, N>;
|
using base = _reserved_vector_base<T, N>;
|
||||||
|
|
2
hecl
2
hecl
|
@ -1 +1 @@
|
||||||
Subproject commit 4dbfba0cd9d2e13b61da4e99404c9f48a3599afe
|
Subproject commit 53a34e2bba8ff2dcf2aafdbd0e64e18b5fa50ffd
|
2
specter
2
specter
|
@ -1 +1 @@
|
||||||
Subproject commit 81afe9b52644b13ecac849082d51098a2cfdea20
|
Subproject commit 6a89d8c22b9dfc83b93baee1344096fca7008af9
|
Loading…
Reference in New Issue