metaforce/Runtime/World/CScriptSpiderBallWaypoint.cpp

207 lines
8.8 KiB
C++
Raw Normal View History

#include "Runtime/World/CScriptSpiderBallWaypoint.hpp"
#include "Runtime/CStateManager.hpp"
#include "Runtime/World/CActorParameters.hpp"
#include "TCastTo.hpp" // Generated file, do not modify include path
2021-04-10 08:42:06 +00:00
namespace metaforce {
2017-11-13 06:19:18 +00:00
CScriptSpiderBallWaypoint::CScriptSpiderBallWaypoint(TUniqueId uid, std::string_view name, const CEntityInfo& info,
const zeus::CTransform& xf, bool active, u32 w1)
2017-12-19 03:05:50 +00:00
: CActor(uid, active, name, info, xf, CModelData::CModelDataNull(), CMaterialList(EMaterialTypes::NoStepLogic),
CActorParameters::None(), kInvalidUniqueId)
2018-12-08 05:30:43 +00:00
, xe8_(w1) {}
2018-12-08 05:30:43 +00:00
void CScriptSpiderBallWaypoint::Accept(IVisitor& visitor) { visitor.Visit(this); }
2018-12-08 05:30:43 +00:00
void CScriptSpiderBallWaypoint::AcceptScriptMsg(EScriptObjectMessage msg, TUniqueId uid, CStateManager& mgr) {
CActor::AcceptScriptMsg(msg, uid, mgr);
if (msg == EScriptObjectMessage::InitializedInArea) {
2018-12-08 05:30:43 +00:00
BuildWaypointListAndBounds(mgr);
} else if (msg == EScriptObjectMessage::Arrived) {
2018-12-08 05:30:43 +00:00
SendScriptMsgs(EScriptObjectState::Arrived, mgr, EScriptObjectMessage::None);
}
}
2018-12-08 05:30:43 +00:00
void CScriptSpiderBallWaypoint::AccumulateBounds(const zeus::CVector3f& v) {
if (!xfc_aabox) {
2018-12-08 05:30:43 +00:00
xfc_aabox.emplace(v, v);
}
2018-12-08 05:30:43 +00:00
xfc_aabox->accumulateBounds(v);
}
2018-12-08 05:30:43 +00:00
void CScriptSpiderBallWaypoint::BuildWaypointListAndBounds(CStateManager& mgr) {
u32 validConnections = 0;
for (const SConnection& conn : x20_conns) {
if (conn.x0_state == EScriptObjectState::Arrived && conn.x4_msg == EScriptObjectMessage::Next) {
const TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
2018-12-08 05:30:43 +00:00
if (uid != kInvalidUniqueId) {
static_cast<CScriptSpiderBallWaypoint*>(mgr.ObjectById(uid))->AddPreviousWaypoint(GetUniqueId());
++validConnections;
}
}
2018-12-08 05:30:43 +00:00
}
if (validConnections == 0) {
2018-12-08 05:30:43 +00:00
AccumulateBounds(x34_transform.origin);
} else {
2018-12-08 05:30:43 +00:00
CScriptSpiderBallWaypoint* curWaypoint = this;
TUniqueId uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck);
while (uid != kInvalidUniqueId) {
curWaypoint = static_cast<CScriptSpiderBallWaypoint*>(mgr.ObjectById(uid));
uid = curWaypoint->NextWaypoint(mgr, ECheckActiveWaypoint::SkipCheck);
}
2018-12-08 05:30:43 +00:00
curWaypoint->AccumulateBounds(x34_transform.origin);
}
}
2018-12-08 05:30:43 +00:00
void CScriptSpiderBallWaypoint::AddPreviousWaypoint(TUniqueId uid) { xec_waypoints.push_back(uid); }
TUniqueId CScriptSpiderBallWaypoint::PreviousWaypoint(const CStateManager& mgr,
ECheckActiveWaypoint checkActive) const {
for (const auto& id : xec_waypoints) {
2018-12-08 05:30:43 +00:00
if (const CEntity* ent = mgr.GetObjectById(id)) {
if (checkActive == ECheckActiveWaypoint::SkipCheck) {
2018-12-08 05:30:43 +00:00
return id;
}
if (ent->GetActive()) {
2018-12-08 05:30:43 +00:00
return id;
}
2017-09-18 03:02:48 +00:00
}
2018-12-08 05:30:43 +00:00
}
2017-09-18 03:02:48 +00:00
2018-12-08 05:30:43 +00:00
return kInvalidUniqueId;
2017-09-18 03:02:48 +00:00
}
2018-12-08 05:30:43 +00:00
TUniqueId CScriptSpiderBallWaypoint::NextWaypoint(const CStateManager& mgr, ECheckActiveWaypoint checkActive) const {
for (const SConnection& conn : x20_conns) {
2021-06-02 21:54:58 +00:00
if (conn.x0_state != EScriptObjectState::Arrived || conn.x4_msg != EScriptObjectMessage::Next) {
continue;
}
const TUniqueId uid = mgr.GetIdForScript(conn.x8_objId);
if (const CEntity* ent = mgr.GetObjectById(uid)) {
if (checkActive == ECheckActiveWaypoint::SkipCheck) {
return ent->GetUniqueId();
}
if (ent->GetActive()) {
return ent->GetUniqueId();
2018-12-08 05:30:43 +00:00
}
}
2018-12-08 05:30:43 +00:00
}
2018-12-08 05:30:43 +00:00
return kInvalidUniqueId;
}
2017-09-18 03:02:48 +00:00
void CScriptSpiderBallWaypoint::GetClosestPointAlongWaypoints(CStateManager& mgr, const zeus::CVector3f& ballPos,
2018-12-08 05:30:43 +00:00
float maxPointToBallDist,
const CScriptSpiderBallWaypoint*& closestWaypoint,
zeus::CVector3f& closestPoint,
zeus::CVector3f& deltaBetweenPoints,
float deltaBetweenInterpDist,
zeus::CVector3f& interpDeltaBetweenPoints) const {
const auto* wp = this;
while (wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck) != kInvalidUniqueId) {
2018-12-08 05:30:43 +00:00
wp = static_cast<const CScriptSpiderBallWaypoint*>(
mgr.GetObjectById(wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::SkipCheck)));
}
2018-12-08 05:30:43 +00:00
float minPointToBallDistSq = maxPointToBallDist * maxPointToBallDist;
const float deltaBetweenInterpDistSq = deltaBetweenInterpDist * deltaBetweenInterpDist;
2018-12-08 05:30:43 +00:00
zeus::CVector3f lastPoint = wp->GetTranslation();
zeus::CVector3f lastDelta;
bool computeDelta = wp->GetActive();
2018-12-08 05:30:43 +00:00
while (true) {
if (wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId) {
if (computeDelta) {
const auto* prevWp = wp;
2017-09-18 03:02:48 +00:00
wp = static_cast<const CScriptSpiderBallWaypoint*>(
2018-12-08 05:30:43 +00:00
mgr.GetObjectById(wp->NextWaypoint(mgr, ECheckActiveWaypoint::Check)));
const zeus::CVector3f thisDelta = wp->GetTranslation() - lastPoint;
const zeus::CVector3f lastPointToBall = ballPos - lastPoint;
if (prevWp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check) == kInvalidUniqueId) {
2018-12-08 05:30:43 +00:00
lastDelta = thisDelta;
}
const float pointToBallDistSq = lastPointToBall.magSquared();
2018-12-08 05:30:43 +00:00
if (pointToBallDistSq < minPointToBallDistSq) {
minPointToBallDistSq = pointToBallDistSq;
closestPoint = lastPoint;
deltaBetweenPoints = thisDelta;
interpDeltaBetweenPoints = (thisDelta.normalized() + lastDelta.normalized()) * 0.5f;
closestWaypoint = wp;
2017-09-18 03:02:48 +00:00
}
const float projectedT = lastPointToBall.dot(thisDelta);
2018-12-08 05:30:43 +00:00
if (projectedT >= 0.f) {
const float normT = projectedT / thisDelta.magSquared();
2018-12-08 05:30:43 +00:00
if (normT < 1.f) {
const zeus::CVector3f projectedPoint = zeus::CVector3f::lerp(lastPoint, wp->GetTranslation(), normT);
const float projToBallDistSq = (ballPos - projectedPoint).magSquared();
2018-12-08 05:30:43 +00:00
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) {
const float t = lastToProjDist / deltaBetweenInterpDist;
2018-12-08 05:30:43 +00:00
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);
}
}
2017-09-18 03:02:48 +00:00
}
2018-12-08 05:30:43 +00:00
}
2017-09-18 03:02:48 +00:00
}
2018-12-08 05:30:43 +00:00
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;
}
2017-09-18 03:02:48 +00:00
}
2018-12-08 05:30:43 +00:00
}
if ((ballPos - lastPoint).magSquared() >= minPointToBallDistSq) {
return;
}
closestPoint = lastPoint;
if (wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check) != kInvalidUniqueId) {
wp = static_cast<const CScriptSpiderBallWaypoint*>(
mgr.GetObjectById(wp->PreviousWaypoint(mgr, ECheckActiveWaypoint::Check)));
deltaBetweenPoints = lastPoint - wp->GetTranslation();
interpDeltaBetweenPoints = deltaBetweenPoints;
2018-12-08 05:30:43 +00:00
}
closestWaypoint = wp;
2017-09-18 03:02:48 +00:00
}
2021-04-10 08:42:06 +00:00
} // namespace metaforce