2
0
mirror of https://github.com/AxioDL/metaforce.git synced 2025-12-10 04:27:42 +00:00

Work on CParasite

This commit is contained in:
Jack Andersen
2018-11-12 23:20:11 -10:00
parent bf3636a16e
commit 660e7cd239
17 changed files with 755 additions and 358 deletions

View File

@@ -3,6 +3,8 @@
#include "CStateManager.hpp"
#include "TCastTo.hpp"
#include "CScriptWaypoint.hpp"
#include "Collision/CMetroidAreaCollider.hpp"
#include "Collision/CGameCollision.hpp"
namespace urde
{
@@ -10,19 +12,20 @@ CWallWalker::CWallWalker(ECharacter chr, TUniqueId uid, std::string_view name, E
const CEntityInfo& eInfo, const zeus::CTransform& xf,
CModelData&& mData, const CPatternedInfo& pInfo, EMovementType mType,
EColliderType colType, EBodyType bType, const CActorParameters& aParms,
float f1, float f2, EKnockBackVariant kbVariant, float f3, EWalkerType wType, float f4, bool b1)
float collisionCloseMargin, float alignAngVel, EKnockBackVariant kbVariant,
float advanceWpRadius, EWalkerType wType, float playerObstructionMinDist, bool disableMove)
: CPatterned(chr, uid, name, flavType, eInfo, xf, std::move(mData), pInfo, mType, colType, bType, aParms, kbVariant)
, x590_colSphere(zeus::CSphere(zeus::CVector3f::skZero, pInfo.GetHalfExtent()), x68_material)
, x5b0_collisionCloseMargin(f1)
, x5b4_(f2)
, x5c0_advanceWpRadius(f3)
, x5c4_(f4)
, x5b0_collisionCloseMargin(collisionCloseMargin)
, x5b4_alignAngVel(alignAngVel)
, x5c0_advanceWpRadius(advanceWpRadius)
, x5c4_playerObstructionMinDist(playerObstructionMinDist)
, x5cc_bendingHackAnim(GetModelData()->GetAnimationData()->GetCharacterInfo().GetAnimationIndex("BendingAnimationHack"sv))
, x5d0_walkerType(wType)
, x5d6_24_(false)
, x5d6_25_(false)
, x5d6_26_(false)
, x5d6_27_(b1)
, x5d6_24_alignToFloor(false)
, x5d6_25_hasAlignSurface(false)
, x5d6_26_playerObstructed(false)
, x5d6_27_disableMove(disableMove)
, x5d6_28_addBendingWeight(true)
, x5d6_29_applyBendingHack(false)
{
@@ -39,6 +42,74 @@ void CWallWalker::OrientToSurfaceNormal(const zeus::CVector3f& normal, float cla
SetTransform((zeus::CQuaternion(x34_transform.basis) * q).normalized().toTransform(GetTranslation()));
}
bool CWallWalker::PointOnSurface(const CCollisionSurface& surf, const zeus::CVector3f& point)
{
zeus::CVector3f normal = surf.GetNormal();
zeus::CVector3f projPt = ProjectPointToPlane(point, surf.GetVert(0), normal);
for (int i = 0; i < 3; ++i)
{
zeus::CVector3f projDelta = projPt - surf.GetVert(i);
zeus::CVector3f edge = surf.GetVert((i + 2) % 3) - surf.GetVert(i);
if (projDelta.cross(edge).dot(normal) < 0.f)
return false;
}
return true;
}
void CWallWalker::AlignToFloor(CStateManager& mgr, float radius, const zeus::CVector3f& newPos, float dt)
{
bool hasSurface = false;
float margin = radius + x5b0_collisionCloseMargin;
zeus::CAABox aabb(newPos - margin, newPos + margin);
CAreaCollisionCache ccache(aabb);
CGameCollision::BuildAreaCollisionCache(mgr, ccache);
if (x5d6_25_hasAlignSurface)
x5d6_25_hasAlignSurface = PointOnSurface(x568_alignNormal, newPos);
if (!x5d6_25_hasAlignSurface || !(x5d4_thinkCounter & 0x3))
{
for (auto& leaf : ccache)
{
for (auto& node : leaf)
{
CAreaOctTree::TriListReference triArr = node.GetTriangleArray();
for (u16 i = 0; i < triArr.GetSize(); ++i)
{
u16 triIdx = triArr.GetAt(i);
CCollisionSurface surf = leaf.GetOctTree().GetMasterListTriangle(triIdx);
if (std::fabs(surf.GetPlane().pointToPlaneDist(newPos)) < margin &&
PointOnSurface(surf, newPos))
{
x568_alignNormal = surf;
hasSurface = true;
}
}
}
}
x5d6_25_hasAlignSurface = hasSurface;
}
if (x5d6_25_hasAlignSurface)
{
OrientToSurfaceNormal(x568_alignNormal.GetNormal(), x5b4_alignAngVel * dt);
x5b8_tumbleAngle = 0.f;
x5d6_28_addBendingWeight = false;
}
else
{
float angDelta = zeus::radToDeg(x138_velocity.magnitude()) / x590_colSphere.GetSphere().radius * dt;
OrientToSurfaceNormal(x34_transform.basis[1], angDelta);
if (x450_bodyController->HasBodyState(pas::EAnimationState::Step))
{
x450_bodyController->GetCommandMgr().DeliverCmd(
CBCStepCmd(pas::EStepDirection::Down, pas::EStepType::Normal));
}
else
{
x5d6_28_addBendingWeight = true;
}
x5b8_tumbleAngle += angDelta;
}
}
void CWallWalker::GotoNextWaypoint(CStateManager& mgr)
{
if (TCastToPtr<CScriptWaypoint> wp = mgr.ObjectById(x2dc_destObj))
@@ -49,7 +120,7 @@ void CWallWalker::GotoNextWaypoint(CStateManager& mgr)
x2dc_destObj = wp->NextWaypoint(mgr);
if (!zeus::close_enough(wp->GetPause(), 0.f))
{
x5bc_ = wp->GetPause();
x5bc_patrolPauseRemTime = wp->GetPause();
if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
}
@@ -62,16 +133,17 @@ void CWallWalker::GotoNextWaypoint(CStateManager& mgr)
void CWallWalker::PreThink(float dt, CStateManager& mgr)
{
CPatterned::PreThink(dt, mgr);
if (!GetActive() || x5d6_26_ || x5bc_ > 0.f || x5d6_27_ || x450_bodyController->IsFrozen() || !x5d6_24_)
if (!GetActive() || x5d6_26_playerObstructed || x5bc_patrolPauseRemTime > 0.f || x5d6_27_disableMove ||
x450_bodyController->IsFrozen() || !x5d6_24_alignToFloor)
return;
zeus::CQuaternion quat(GetTransform().buildMatrix3f());
AddMotionState(PredictMotion(dt));
zeus::CQuaternion quat2(GetTransform().buildMatrix3f());
ClearForcesAndTorques();
if (x5d6_25_)
if (x5d6_25_hasAlignSurface)
{
zeus::CPlane plane = x568_.GetPlane();
zeus::CPlane plane = x568_alignNormal.GetPlane();
const float futureDt = (10.f * dt);
SetTranslation(GetTranslation() * (1.f - futureDt) +
(((GetTranslation() - ((plane.vec.dot(GetTranslation())) - plane.d) -
@@ -136,7 +208,7 @@ void CWallWalker::UpdateWPDestination(CStateManager& mgr)
x2dc_destObj = wp->NextWaypoint(mgr);
if (std::fabs(wp->GetPause()) > 0.00001f)
{
x5bc_ = wp->GetPause();
x5bc_patrolPauseRemTime = wp->GetPause();
if (x5d0_walkerType == EWalkerType::Parasite)
x450_bodyController->SetLocomotionType(pas::ELocomotionType::Relaxed);
mgr.SendScriptMsg(wp, GetUniqueId(), EScriptObjectMessage::Arrived);
@@ -146,4 +218,5 @@ void CWallWalker::UpdateWPDestination(CStateManager& mgr)
SetDestPos(wpPos);
}
}
}