Work on CSamusDoll

This commit is contained in:
Jack Andersen 2017-05-04 08:56:20 -10:00
parent 394cbf36e0
commit 4ff1475f0e
14 changed files with 715 additions and 46 deletions

View File

@ -584,36 +584,22 @@ void CAutoMapper::ProcessMapRotateInput(const CFinalInput& input, const CStateMa
float deltaFrames = input.DeltaTime() * 60.f;
SetShouldRotatingSoundBePlaying(true);
zeus::CEulerAngles eulers(xa8_renderStates[0].x8_camOrientation);
float angX = eulers.x - std::floor(eulers.x / (2.f * M_PIF)) * 2.f * M_PIF;
if (angX < 0.f)
angX += 2.f * M_PIF;
float angZ = eulers.z - std::floor(eulers.z / (2.f * M_PIF)) * 2.f * M_PIF;
if (angZ < 0.f)
angZ += 2.f * M_PIF;
zeus::CRelAngle angX(eulers.x);
zeus::CRelAngle angZ(eulers.z);
float dt = deltaFrames * g_tweakAutoMapper->GetCamRotateDegreesPerFrame();
angZ -= zeus::degToRad(dt * dirs[2]);
if (angZ - std::floor(angZ / (2.f * M_PIF)) * 2.f * M_PIF < 0.f)
angZ += 2.f * M_PIF;
angZ += zeus::degToRad(dt * dirs[3]);
if (angZ - std::floor(angZ / (2.f * M_PIF)) * 2.f * M_PIF < 0.f)
angZ += 2.f * M_PIF;
angX -= zeus::degToRad(dt * dirs[0]);
if (angX - std::floor(angX / (2.f * M_PIF)) * 2.f * M_PIF < 0.f)
angX += 2.f * M_PIF;
angX += zeus::degToRad(dt * dirs[1]);
if (angX - std::floor(angX / (2.f * M_PIF)) * 2.f * M_PIF < 0.f)
angX += 2.f * M_PIF;
angX = zeus::radToDeg(angX);
if (angX > 180.f)
angX -= 360.f;
angX = zeus::degToRad(zeus::clamp(g_tweakAutoMapper->GetMinCamRotateX(), angX,
float angXDeg = angX.asDegrees();
if (angXDeg > 180.f)
angXDeg -= 360.f;
angX = zeus::degToRad(zeus::clamp(g_tweakAutoMapper->GetMinCamRotateX(), angXDeg,
g_tweakAutoMapper->GetMaxCamRotateX()));
if (angX - std::floor(angX / (2.f * M_PIF)) * 2.f * M_PIF < 0.f)
angX += 2.f * M_PIF;
zeus::CQuaternion quat;
quat.rotateZ(angZ);
@ -1573,9 +1559,7 @@ void CAutoMapper::Draw(const CStateManager& mgr, const zeus::CTransform& xf, flo
float func = zeus::clamp(0.f, 0.5f * (1.f + std::sin(5.f * CGraphics::GetSecondsMod900() - (M_PIF / 2.f))), 1.f);
float scale = std::min(0.6f * g_tweakAutoMapper->GetMaxCamDist() / g_tweakAutoMapper->GetMinCamDist(), objectScale);
zeus::CEulerAngles eulers(mgr.GetCameraManager()->GetCurrentCameraTransform(mgr));
float angle = eulers.z - std::floor(eulers.z / (2.f * M_PIF)) * 2.f * M_PIF;
if (angle < 0.f)
angle += 2.f * M_PIF;
zeus::CRelAngle angle(eulers.z);
zeus::CTransform playerXf(zeus::CMatrix3f::RotateZ(angle),
CMapArea::GetAreaPostTranslate(*x24_world, mgr.GetNextAreaId()) + mgr.GetPlayer().GetTranslation());
CGraphics::SetModelMatrix(mapXf * playerXf * zeus::CTransform::Scale(scale * (0.25f * func + 0.75f)));

View File

@ -206,6 +206,7 @@ public:
void AdvanceAnim(CCharAnimTime& time, zeus::CVector3f&, zeus::CQuaternion&);
void SetXRayModel(const TLockedToken<CModel>& model, const TLockedToken<CSkinRules>& skinRules);
void SetInfraModel(const TLockedToken<CModel>& model, const TLockedToken<CSkinRules>& skinRules);
const TCachedToken<CSkinnedModel>& GetModelData() const { return xd8_modelData; }
static void PoseSkinnedModel(CSkinnedModel& model, const CPoseAsTransforms& pose,
const CModelFlags& drawFlags,

View File

@ -21,5 +21,26 @@ u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f &,
return 0;
}
bool RaySphereIntersection(const zeus::CSphere& sphere, const zeus::CVector3f& pos, const zeus::CVector3f& dir,
float mag, float& T, zeus::CVector3f& point)
{
zeus::CVector3f rayToSphere = sphere.position - pos;
float magSq = rayToSphere.magSquared();
float dirDot = rayToSphere.dot(dir);
float radSq = sphere.radius * sphere.radius;
if (dirDot < 0.f && magSq > radSq)
return false;
float intersectSq = radSq - (magSq - dirDot * dirDot);
if (intersectSq < 0.f)
return false;
T = magSq > radSq ? dirDot - std::sqrt(intersectSq) : dirDot + std::sqrt(intersectSq);
if (T < mag || mag == 0.f)
{
point = pos + T * dir;
return true;
}
return false;
}
}
}

View File

@ -11,6 +11,7 @@ namespace CollisionUtil
bool LineIntersectsOBBox(const zeus::COBBox&, const zeus::CMRay&, float&);
u32 RayAABoxIntersection(const zeus::CMRay&, const zeus::CAABox&, const zeus::CVector3f&, float&);
u32 RaySphereIntersection_Double(const zeus::CSphere&, const zeus::CVector3f&, const zeus::CVector3f&, double&);
bool RaySphereIntersection(const zeus::CSphere&, const zeus::CVector3f&, const zeus::CVector3f&, float, float&, zeus::CVector3f&);
}
}
#endif // __URDE_COLLISIONUTIL_HPP__

View File

@ -118,9 +118,7 @@ void CHudRadarInterface::Draw(const CStateManager& mgr, float alpha) const
float camZ = zeus::CEulerAngles(zeus::CQuaternion(
mgr.GetCameraManager()->GetCurrentCamera(mgr)->GetTransform().basis)).z;
float angleZ = camZ - std::floor(camZ / (2.f * M_PIF)) * 2.f * M_PIF;
if (angleZ < 0.f)
angleZ += 2.f * M_PIF;
zeus::CRelAngle angleZ(camZ);
drawParms.xc_preTranslate = zeus::CTransform::RotateY(angleZ);
drawParms.x3c_postTranslate = x40_BaseWidget_RadarStuff->GetWorldTransform();
float enemyRadius = g_tweakGui->GetRadarEnemyPaintRadius();

View File

@ -9,12 +9,53 @@ CInventoryScreen::CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, c
const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp)
: CPauseScreenBase(mgr, frame, pauseStrg)
{
CPlayerState& playerState = *mgr.GetPlayerState();
x19c_samusDoll = std::make_unique<CSamusDoll>(suitDgrp, ballDgrp,
CPlayerState::EPlayerSuit(int(playerState.GetCurrentSuit()) +
playerState.IsFusionEnabled() * 4),
playerState.GetCurrentBeam(),
playerState.HasPowerUp(CPlayerState::EItemType::SpiderBall),
playerState.HasPowerUp(CPlayerState::EItemType::GrappleBeam));
}
bool CInventoryScreen::InputDisabled() const
{
return false;
}
void CInventoryScreen::TransitioningAway()
{
}
void CInventoryScreen::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue)
{
}
void CInventoryScreen::Touch()
{
}
void CInventoryScreen::ProcessControllerInput(const CFinalInput& input)
{
}
void CInventoryScreen::Draw(float transInterp, float totalAlpha, float yOff)
{
}
float CInventoryScreen::GetCameraYBias() const
{
return 0.f;
}
bool CInventoryScreen::VReady() const
{
return true;
return false;
}
void CInventoryScreen::VActivate() const
@ -22,10 +63,38 @@ void CInventoryScreen::VActivate() const
}
void CInventoryScreen::ChangedMode()
{
}
void CInventoryScreen::UpdateRightTable()
{
}
u32 CInventoryScreen::GetRightTableCount() const
{
return 0;
}
bool CInventoryScreen::IsRightLogDynamic() const
{
return false;
}
void CInventoryScreen::UpdateRightLogColors(bool active, const zeus::CColor& activeColor,
const zeus::CColor& inactiveColor)
{
}
void CInventoryScreen::UpdateRightLogHighlight(bool active, int idx,
const zeus::CColor& activeColor,
const zeus::CColor& inactiveColor)
{
}
}
}

View File

@ -15,13 +15,29 @@ namespace MP1
class CInventoryScreen : public CPauseScreenBase
{
std::unique_ptr<CSamusDoll> x19c_samusDoll;
float x1a0_ = 0.f;
float x1a4_ = 0.f;
u32 x1a8_ = 0;
bool x1ac_ = false;
public:
CInventoryScreen(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg,
const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp);
bool InputDisabled() const;
void TransitioningAway();
void Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue);
void Touch();
void ProcessControllerInput(const CFinalInput& input);
void Draw(float transInterp, float totalAlpha, float yOff);
float GetCameraYBias() const;
bool VReady() const;
void VActivate() const;
void ChangedMode();
void UpdateRightTable();
u32 GetRightTableCount() const;
bool IsRightLogDynamic() const;
void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor);
void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, const zeus::CColor& inactiveColor);
};
}

View File

@ -177,7 +177,7 @@ void CPauseScreen::ProcessControllerInput(const CStateManager& mgr, const CFinal
bool bExits = false;
if (std::unique_ptr<CPauseScreenBase>& curScreen = x7c_screens[x78_activeIdx])
{
if (curScreen->GetMode() == CPauseScreenBase::EMode::Zero)
if (curScreen->GetMode() == CPauseScreenBase::EMode::LeftTable)
bExits = true;
curScreen->ProcessControllerInput(input);
}
@ -233,12 +233,12 @@ void CPauseScreen::Update(float dt, const CStateManager& mgr, CRandom16& rand, C
if (x8_curSubscreen != xc_nextSubscreen)
{
x10_interp = std::max(0.f, x10_interp - dt);
x10_alphaInterp = std::max(0.f, x10_alphaInterp - dt);
if (!curScreen || !curScreen->InputDisabled())
{
if (!otherScreen || otherScreen->IsReady())
{
if (x10_interp == 0.f)
if (x10_alphaInterp == 0.f)
TransitionComplete();
}
}
@ -248,7 +248,7 @@ void CPauseScreen::Update(float dt, const CStateManager& mgr, CRandom16& rand, C
{
curScreen->Update(dt, rand, archQueue);
zeus::CColor color = zeus::CColor::skWhite;
color.a = std::min(curScreen->GetAlpha(), x8_curSubscreen != xc_nextSubscreen ? x10_interp / 0.5f : 1.f);
color.a = std::min(curScreen->GetAlpha(), x8_curSubscreen != xc_nextSubscreen ? x10_alphaInterp / 0.5f : 1.f);
x40_textpane_a->SetColor(color);
x44_textpane_b->SetColor(color);
}
@ -273,7 +273,7 @@ void CPauseScreen::Draw()
std::unique_ptr<CPauseScreenBase>& curScreen = x7c_screens[x78_activeIdx];
if (curScreen && curScreen->CanDraw())
{
float useInterp = x10_interp == 0.f ? 1.f : x10_interp / 0.5f;
float useInterp = x10_alphaInterp == 0.f ? 1.f : x10_alphaInterp / 0.5f;
float initInterp = std::min(curScreen->GetAlpha(), useInterp);
if (xc_nextSubscreen == ESubScreen::Invalid)
totalAlpha = useInterp;

View File

@ -28,7 +28,7 @@ private:
u32 x4_ = 2;
ESubScreen x8_curSubscreen = ESubScreen::Invalid;
ESubScreen xc_nextSubscreen = ESubScreen::Invalid;
float x10_interp = 0.f;
float x10_alphaInterp = 0.f;
TLockedToken<CStringTable> x14_strgPauseScreen;
const CDependencyGroup& x20_suitDgrp;
const CDependencyGroup& x24_ballDgrp;

View File

@ -7,6 +7,7 @@
#include "GuiSys/CAuiImagePane.hpp"
#include "GuiSys/CGuiWidgetDrawParms.hpp"
#include "GameGlobalObjects.hpp"
#include "Audio/CSfxManager.hpp"
namespace urde
{
@ -78,7 +79,7 @@ bool CPauseScreenBase::IsReady()
if (x198_24_ready)
{
VActivate();
Activate(EMode::Zero);
ChangeMode(EMode::LeftTable);
UpdateSideTable(x70_tablegroup_leftlog);
UpdateRightTable();
return true;
@ -86,14 +87,113 @@ bool CPauseScreenBase::IsReady()
return false;
}
void CPauseScreenBase::Activate(EMode mode)
void CPauseScreenBase::ChangeMode(EMode mode)
{
if (x10_mode == mode)
return;
EMode oldMode = x10_mode;
zeus::CColor color = g_tweakGuiColors->GetPauseItemAmberColor();
zeus::CColor colorDim = color;
colorDim.a = 0.5f;
switch (x10_mode)
{
case EMode::LeftTable:
x6c_basewidget_leftlog->SetColor(colorDim);
x70_tablegroup_leftlog->SetIsActive(false);
break;
case EMode::Invalid:
case EMode::RightTable:
if (IsRightLogDynamic())
UpdateRightLogColors(false, color, colorDim);
else
x80_basewidget_rightlog->SetColor(colorDim);
x84_tablegroup_rightlog->SetIsActive(false);
break;
case EMode::TextScroll:
CSfxManager::SfxStart(1431, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
break;
default: break;
}
x10_mode = mode;
switch (x10_mode)
{
case EMode::LeftTable:
if (oldMode == EMode::RightTable)
CSfxManager::SfxStart(1431, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
x6c_basewidget_leftlog->SetColor(color);
x70_tablegroup_leftlog->SetIsActive(true);
UpdateSideTable(x70_tablegroup_leftlog);
x18_ = 0;
x1c_ = 0;
x84_tablegroup_rightlog->SetUserSelection(1);
UpdateSideTable(x84_tablegroup_rightlog);
break;
case EMode::RightTable:
if (IsRightLogDynamic())
UpdateRightLogColors(true, color, colorDim);
else
x80_basewidget_rightlog->SetColor(colorDim);
x84_tablegroup_rightlog->SetIsActive(true);
UpdateSideTable(x84_tablegroup_rightlog);
break;
case EMode::TextScroll:
x6c_basewidget_leftlog->SetColor(colorDim);
if (IsRightLogDynamic())
UpdateRightLogColors(true, color, colorDim);
else
x80_basewidget_rightlog->SetColor(colorDim);
x70_tablegroup_leftlog->SetIsActive(false);
x84_tablegroup_rightlog->SetIsActive(false);
break;
default: break;
}
ChangedMode();
}
void CPauseScreenBase::UpdateSideTable(CGuiTableGroup* table)
{
if (!table)
return;
zeus::CColor selColor = zeus::CColor::skWhite;
zeus::CColor deselColor = {1.f, 1.f, 1.f, 0.5f};
bool tableActive = true;
if (table == x84_tablegroup_rightlog && x10_mode != EMode::RightTable)
tableActive = false;
table->SetColors(selColor, deselColor);
if (table == x84_tablegroup_rightlog)
{
int sel = x1c_ - x18_;
x8c_model_righthighlight->SetLocalTransform(
x8c_model_righthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_ * sel));
x8c_model_righthighlight->SetVisibility(x10_mode == EMode::RightTable, ETraversalMode::Children);
int selInView = x1c_ % 5;
if (IsRightLogDynamic())
{
UpdateRightLogHighlight(tableActive, selInView, selColor, deselColor);
}
else
{
for (int i=0 ; i<x144_model_titles.size() ; ++i)
x144_model_titles[i]->SetColor((i == selInView && tableActive) ? selColor : deselColor);
}
}
else
{
int sel = x70_tablegroup_leftlog->GetUserSelection();
x78_model_lefthighlight->SetLocalTransform(
x78_model_lefthighlight->GetTransform() * zeus::CTransform::Translate(0.f, 0.f, x38_ * sel));
for (int i=0 ; i<xc0_model_categories.size() ; ++i)
xc0_model_categories[i]->SetColor(i == sel ? selColor : deselColor);
}
}
void CPauseScreenBase::Update(float dt, CRandom16& rand, CArchitectureQueue& archQueue)
@ -103,8 +203,8 @@ void CPauseScreenBase::Update(float dt, CRandom16& rand, CArchitectureQueue& arc
x14_alpha = std::min(2.f * dt + x14_alpha, 1.f);
u32 rightCount = GetRightTableCount();
bool pulseRightUp = x10_mode == EMode::One && x18_ > 0;
bool pulseRightDown = x10_mode == EMode::One && x18_ + 5 < rightCount;
bool pulseRightUp = x10_mode == EMode::RightTable && x18_ > 0;
bool pulseRightDown = x10_mode == EMode::RightTable && x18_ + 5 < rightCount;
float rightUpT = pulseRightUp ? CGraphics::GetSecondsMod900() : 0.f;
float rightDownT = pulseRightDown ? CGraphics::GetSecondsMod900() : 0.f;
@ -148,7 +248,10 @@ void CPauseScreenBase::Draw(float mainAlpha, float frameAlpha, float yOff)
void CPauseScreenBase::UpdateRightTable()
{
x18_ = 0;
x1c_ = 0;
x84_tablegroup_rightlog->SetUserSelection(1);
UpdateSideTable(x84_tablegroup_rightlog);
}
static const char* PaneSuffixes[] =

View File

@ -27,11 +27,11 @@ public:
enum class EMode
{
Invalid = -1,
Zero = 0,
One = 1,
Two = 2
LeftTable = 0,
RightTable = 1,
TextScroll = 2
};
private:
protected:
const CStateManager& x4_mgr;
CGuiFrame& x8_frame;
const CStringTable& xc_pauseStrg;
@ -93,8 +93,7 @@ private:
};
void InitializeFrameGlue();
static std::string GetImagePaneName(u32 i);
protected:
void Activate(EMode mode);
void ChangeMode(EMode mode);
void UpdateSideTable(CGuiTableGroup* table);
public:
CPauseScreenBase(const CStateManager& mgr, CGuiFrame& frame, const CStringTable& pauseStrg);
@ -115,8 +114,12 @@ public:
virtual float GetCameraYBias() const { return 0.f; }
virtual bool VReady() const=0;
virtual void VActivate() const=0;
virtual void ChangedMode() {}
virtual void UpdateRightTable();
virtual u32 GetRightTableCount() const=0;
virtual bool IsRightLogDynamic() const { return false; }
virtual void UpdateRightLogColors(bool active, const zeus::CColor& activeColor, zeus::CColor& inactiveColor) {}
virtual void UpdateRightLogHighlight(bool active, int idx, const zeus::CColor& activeColor, zeus::CColor& inactiveColor) {}
};
}

View File

@ -1,16 +1,414 @@
#include "CSamusDoll.hpp"
#include "GameGlobalObjects.hpp"
#include "CSimplePool.hpp"
#include "CDependencyGroup.hpp"
#include "zeus/CEulerAngles.hpp"
#include "Collision/CollisionUtil.hpp"
namespace urde
{
namespace MP1
{
const zeus::CVector3f CSamusDoll::skInitialOffset = {0.f, 0.f, 0.8f};
static const std::pair<const char*, u32> SpiderBallGlassModels[] =
{
{"SamusSpiderBallGlassCMDL", 0},
{"SamusSpiderBallGlassCMDL", 0},
{"SamusSpiderBallGlassCMDL", 1},
{"SamusPhazonBallGlassCMDL", 0},
{"SamusSpiderBallGlassCMDL", 0},
{"SamusSpiderBallGlassCMDL", 0},
{"SamusSpiderBallGlassCMDL", 1},
{"SamusPhazonBallGlassCMDL", 0},
};
static const std::pair<const char*, u32> SpiderBallCharacters[] =
{
{"SamusSpiderBallANCS", 0},
{"SamusSpiderBallANCS", 0},
{"SamusSpiderBallANCS", 1},
{"SamusPhazonBallANCS", 0},
{"SamusFusionBallANCS", 0},
{"SamusFusionBallANCS", 2},
{"SamusFusionBallANCS", 1},
{"SamusFusionBallANCS", 3},
};
static const std::pair<const char*, u32> BallCharacters[] =
{
{"SamusBallANCS", 0},
{"SamusBallANCS", 0},
{"SamusBallANCS", 1},
{"SamusBallANCS", 0},
{"SamusFusionBallANCS", 0},
{"SamusFusionBallANCS", 2},
{"SamusFusionBallANCS", 1},
{"SamusFusionBallANCS", 3},
};
static const u32 SpiderBallGlowColorIdxs[] =
{
3, 3, 2, 4, 5, 7, 6, 8
};
static const u32 BallGlowColorIdxs[] =
{
0, 0, 1, 0, 5, 7, 6, 8
};
static const char* BeamModels[] =
{
"CMDL_InvPowerBeam",
"CMDL_InvIceBeam",
"CMDL_InvWaveBeam",
"CMDL_InvPlasmaBeam",
"CMDL_InvPowerBeam"
};
static const char* VisorModels[] =
{
"CMDL_InvVisor",
"CMDL_InvGravityVisor",
"CMDL_InvVisor",
"CMDL_InvPhazonVisor",
"CMDL_InvFusionVisor",
"CMDL_InvFusionVisor",
"CMDL_InvFusionVisor",
"CMDL_InvFusionVisor"
};
static const char* FinModels[] =
{
"CMDL_InvPowerFins",
"CMDL_InvPowerFins",
"CMDL_InvPowerFins",
"CMDL_InvPowerFins",
"CMDL_InvPowerFins",
"CMDL_InvVariaFins",
"CMDL_InvGravityFins",
"CMDL_InvPhazonFins"
};
static const u32 Character1Idxs[8] =
{
0, 6, 2, 10, 16, 24, 20, 28
};
static const u32 CharacterBootsIdxs[8] =
{
1, 7, 3, 11, 17, 25, 21, 29
};
static const u32 Character2and3Idxs[8][2] =
{
{14, 15},
{8, 9},
{4, 5},
{12, 13},
{18, 19},
{26, 27},
{22, 23},
{30, 31}
};
CSamusDoll::CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp,
CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam,
bool hasSpiderBall, bool hasGrappleBeam)
: x44_suit(suit), x48_beam(beam)
{
x1d4_spiderBallGlass = g_SimplePool->GetObj(SpiderBallGlassModels[int(suit)].first);
x1e0_ballMatIdx = hasSpiderBall ? SpiderBallCharacters[int(suit)].second : BallCharacters[int(suit)].second;
x1e4_glassMatIdx = SpiderBallGlassModels[int(suit)].second;
x1e8_ballGlowColorIdx = hasSpiderBall ? SpiderBallGlowColorIdxs[int(suit)] : BallGlowColorIdxs[int(suit)];
x1ec_itemScreenSamus = g_SimplePool->GetObj("ANCS_ItemScreenSamus");
x1f4_invBeam = g_SimplePool->GetObj(BeamModels[int(beam)]);
x200_invVisor = g_SimplePool->GetObj(VisorModels[int(suit)]);
x20c_invGrappleBeam = g_SimplePool->GetObj("CMDL_InvGrappleBeam");
x218_invFins = g_SimplePool->GetObj(FinModels[int(suit)]);
x224_ballInnerGlow = g_SimplePool->GetObj("BallInnerGlow");
x22c_ballInnerGlowGen = std::make_unique<CElementGen>(x224_ballInnerGlow,
CElementGen::EModelOrientationType::Normal,
CElementGen::EOptionalSystemFlags::One);
x230_ballTransitionFlash = g_SimplePool->GetObj("MorphBallTransitionFlash");
x23c_lights.push_back(CLight::BuildDirectional(zeus::CVector3f::skForward, zeus::CColor::skWhite));
x24c_actorLights = std::make_unique<CActorLights>(8, zeus::CVector3f::skZero, 4, 4, false, false, false, 0.1f);
x270_24_hasSpiderBall = hasSpiderBall;
x270_25_hasGrappleBeam = hasGrappleBeam;
x22c_ballInnerGlowGen->SetGlobalScale(zeus::CVector3f(0.625f));
x0_depToks.reserve(suitDgrp.GetObjectTagVector().size() + ballDgrp.GetObjectTagVector().size());
for (const SObjectTag& tag : suitDgrp.GetObjectTagVector())
{
x0_depToks.push_back(g_SimplePool->GetObj(tag));
x0_depToks.back().Lock();
}
for (const SObjectTag& tag : ballDgrp.GetObjectTagVector())
{
x0_depToks.push_back(g_SimplePool->GetObj(tag));
x0_depToks.back().Lock();
}
}
bool CSamusDoll::IsLoaded() const
{
if (x270_31_loaded)
return true;
if (!x1ec_itemScreenSamus.IsLoaded())
return false;
if (!x1f4_invBeam.IsLoaded())
return false;
if (!x200_invVisor.IsLoaded())
return false;
if (!x20c_invGrappleBeam.IsLoaded())
return false;
if (!x1d4_spiderBallGlass.IsLoaded())
return false;
if (x218_invFins && !x218_invFins.IsLoaded())
return false;
return xc8_suitModel1.operator bool();
}
CModelData CSamusDoll::BuildSuitModelData1(CPlayerState::EPlayerSuit suit)
{
CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id,
Character1Idxs[int(suit)], zeus::CVector3f::skOne, 2, true));
CAnimPlaybackParms parms(2, -1, 1.f, true);
ret.AnimationData()->SetAnimation(parms, false);
return ret;
}
CModelData CSamusDoll::BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit)
{
CModelData ret(CAnimRes(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id,
CharacterBootsIdxs[int(suit)], zeus::CVector3f::skOne, 2, true));
CAnimPlaybackParms parms(2, -1, 1.f, true);
ret.AnimationData()->SetAnimation(parms, false);
return ret;
}
bool CSamusDoll::CheckLoadComplete()
{
if (IsLoaded())
return true;
for (const CToken& tok : x0_depToks)
if (!tok.IsLoaded())
return false;
xc8_suitModel1.emplace(BuildSuitModelData1(x44_suit));
for (int i=0 ; i<2 ; ++i)
{
CAnimRes res(g_ResFactory->GetResourceIdByName("ANCS_ItemScreenSamus")->id,
Character2and3Idxs[int(x44_suit)][i],
zeus::CVector3f::skOne, 2, true);
CModelData mData(res);
x118_suitModel1and2.push_back(mData.GetAnimationData()->GetModelData());
x118_suitModel1and2.back().Lock();
}
x134_suitModelBoots.emplace(BuildSuitModelDataBoots(x44_suit));
CAnimRes res(g_ResFactory->GetResourceIdByName(x270_24_hasSpiderBall ?
SpiderBallCharacters[int(x44_suit)].first :
BallCharacters[int(x44_suit)].first)->id,
0, zeus::CVector3f::skOne, 0, true);
x184_ballModelData.emplace(res);
x1e0_ballMatIdx = x270_24_hasSpiderBall ?
SpiderBallCharacters[int(x44_suit)].second :
BallCharacters[int(x44_suit)].second;
x270_31_loaded = true;
return true;
}
void CSamusDoll::Update(float dt, CRandom16& rand)
{
}
void CSamusDoll::Draw(const CStateManager& mgr, float alpha)
{
}
void CSamusDoll::Touch()
{
if (!CheckLoadComplete())
return;
xc8_suitModel1->AnimationData()->PreRender();
x134_suitModelBoots->AnimationData()->PreRender();
x184_ballModelData->AnimationData()->PreRender();
xc8_suitModel1->Touch(CModelData::EWhichModel::Normal, 0);
x134_suitModelBoots->Touch(CModelData::EWhichModel::Normal, 0);
x184_ballModelData->Touch(CModelData::EWhichModel::Normal, 0);
}
void CSamusDoll::SetupLights()
{
x23c_lights[0] = CLight::BuildDirectional(xb0_rot.toTransform().basis[1], zeus::CColor(0.75f, 1.f));
x24c_actorLights->BuildFakeLightList(x23c_lights, zeus::CColor::skBlack);
}
void CSamusDoll::CheckTransition(bool morphballComplete)
{
if (x54_ > 0.f)
return;
if (x4d_morphballComplete == morphballComplete)
return;
x4d_morphballComplete = morphballComplete;
SetTransitionAnimation();
}
void CSamusDoll::SetTransitionAnimation()
{
if (!x4c_intoBallComplete)
{
xc8_suitModel1->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false);
x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{0, -1, 1.f, true}, false);
x50_ = x54_ = xc8_suitModel1->GetAnimationData()->GetAnimationDuration(0);
}
else if (!x4d_morphballComplete)
{
xc8_suitModel1->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false);
x134_suitModelBoots->AnimationData()->SetAnimation(CAnimPlaybackParms{1, -1, 1.f, true}, false);
x50_ = x54_ = xc8_suitModel1->GetAnimationData()->GetAnimationDuration(1);
}
}
void CSamusDoll::SetRotationSfxPlaying(bool playing)
{
if (playing)
{
if (x268_rotateSfx)
return;
x268_rotateSfx = CSfxManager::SfxStart(1375, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId);
}
else
{
CSfxManager::SfxStop(x268_rotateSfx);
x268_rotateSfx.reset();
}
}
void CSamusDoll::SetOffsetSfxPlaying(bool playing)
{
if (playing)
{
if (x264_offsetSfx)
return;
x264_offsetSfx = CSfxManager::SfxStart(1406, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId);
}
else
{
CSfxManager::SfxStop(x264_offsetSfx);
x264_offsetSfx.reset();
}
}
void CSamusDoll::SetZoomSfxPlaying(bool playing)
{
if (playing)
{
if (x26c_zoomSfx)
return;
x26c_zoomSfx = CSfxManager::SfxStart(1376, 1.f, 0.f, false, 0x7f, true, kInvalidAreaId);
}
else
{
CSfxManager::SfxStop(x26c_zoomSfx);
x26c_zoomSfx.reset();
}
}
void CSamusDoll::SetRotation(float xDelta, float zDelta, float f3)
{
if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f)
return;
SetRotationSfxPlaying(xDelta != 0.f || zDelta != 0.f);
zeus::CEulerAngles angles(xb0_rot);
zeus::CRelAngle angX(angles.x);
zeus::CRelAngle angZ(angles.z);
angX += xDelta;
angZ += zDelta;
float angXCenter = angX;
if (angXCenter > M_PIF)
angXCenter -= 2.f * M_PIF;
angX = zeus::clamp(-M_PIF / 2.f, angXCenter, M_PIF / 2.f);
float angZCenter = angZ;
if (angZCenter > M_PIF)
angZCenter -= 2.f * M_PIF;
angZ = zeus::clamp(-M_PIF / 2.f, angZCenter, M_PIF / 2.f);
zeus::CQuaternion quat;
quat.rotateZ(angZ);
quat.rotateX(angX);
xb0_rot = quat;
}
void CSamusDoll::SetOffset(const zeus::CVector3f& offset, float sfxThreshold)
{
if (xc4_viewInterp != 0.f && xc4_viewInterp != 1.f)
return;
zeus::CVector3f oldOffset = xa4_offset;
zeus::CMatrix3f rotMtx = xb0_rot.toTransform().basis;
xa4_offset += rotMtx * zeus::CVector3f(offset.x, 0.f, offset.z);
SetOffsetSfxPlaying((oldOffset - xa4_offset).magnitude() > sfxThreshold);
float oldZoom = xc0_zoom;
xc0_zoom = zeus::clamp(-4.f, xc0_zoom + offset.y, -2.2f);
bool zoomSfx = std::fabs(xc0_zoom - oldZoom) > sfxThreshold;
float zoomDelta = offset.y - (xc0_zoom - oldZoom);
zeus::CVector3f newOffset = rotMtx[1] * zoomDelta + xa4_offset;
zeus::CVector3f delta = newOffset - xa4_offset;
oldOffset = xa4_offset;
if (!delta.isZero())
{
zeus::CSphere sphere(skInitialOffset, 1.f);
float T;
zeus::CVector3f point;
if (CollisionUtil::RaySphereIntersection(sphere, xa4_offset, delta.normalized(), 0.f, T, point))
{
if ((point - xa4_offset).magnitude() < std::fabs(zoomDelta))
xa4_offset = point;
else
xa4_offset = newOffset;
}
else
{
xa4_offset = newOffset;
}
}
if ((oldOffset - xa4_offset).magnitude() > sfxThreshold)
zoomSfx = true;
SetZoomSfxPlaying(zoomSfx);
delta = xa4_offset - skInitialOffset;
if (delta.magnitude() > 1.f)
xa4_offset = delta.normalized() + skInitialOffset;
}
void CSamusDoll::BeginViewInterpolate(bool zoomOut)
{
if (xc4_viewInterp == 0.f)
{
CSfxManager::SfxStart(1440, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
}
else
{
SetOffsetSfxPlaying(false);
SetZoomSfxPlaying(false);
SetRotationSfxPlaying(false);
CSfxManager::SfxStart(1441, 1.f, 0.f, false, 0x7f, false, kInvalidAreaId);
}
xc4_viewInterp = zoomOut ? FLT_EPSILON : (-1.f + FLT_EPSILON);
x84_interpStartOffset = xa4_offset;
x90_interpStartRot = xb0_rot;
xa0_interpStartZoom = xc0_zoom;
x80_ = zoomOut ? -2.2f : -3.6f;
}
}
}

View File

@ -4,6 +4,10 @@
#include "CPlayerState.hpp"
#include "CToken.hpp"
#include "Character/CModelData.hpp"
#include "Character/CAnimCharacterSet.hpp"
#include "Particle/CElementGen.hpp"
#include "Character/CActorLights.hpp"
#include "Audio/CSfxManager.hpp"
namespace urde
{
@ -19,14 +23,85 @@ class CSamusDoll
CPlayerState::EPlayerSuit x44_suit;
CPlayerState::EBeamId x48_beam;
bool x4c_intoBallComplete = false;
bool x4d_morphball = false;
bool x4d_morphballComplete = false;
float x50_ = 1.f;
float x54_ = 0.f;
float x58_ = 0.f;
float x5c_ = 0.f;
float x60_ = 0.f;
float x64_ = 0.f;
float x68_ = 0.f;
float x6c_ = 0.f;
zeus::CQuaternion x70_;
float x80_ = -3.6f;
zeus::CVector3f x84_interpStartOffset = skInitialOffset;
zeus::CQuaternion x90_interpStartRot;
float xa0_interpStartZoom = -3.6f;
zeus::CVector3f xa4_offset = skInitialOffset;
zeus::CQuaternion xb0_rot;
float xc0_zoom = -3.6f;
float xc4_viewInterp = 0.f;
std::experimental::optional<CModelData> xc8_suitModel1;
rstl::reserved_vector<TCachedToken<CSkinnedModel>, 2> x118_suitModel1and2;
std::experimental::optional<CModelData> x134_suitModelBoots;
std::experimental::optional<CModelData> x184_ballModelData;
bool x1d0_ = false;
TLockedToken<CModel> x1d4_spiderBallGlass;
u32 x1e0_ballMatIdx;
u32 x1e4_glassMatIdx;
u32 x1e8_ballGlowColorIdx;
TLockedToken<CAnimCharacterSet> x1ec_itemScreenSamus;
TLockedToken<CModel> x1f4_invBeam;
TLockedToken<CModel> x200_invVisor;
TLockedToken<CModel> x20c_invGrappleBeam;
TLockedToken<CModel> x218_invFins;
TLockedToken<CGenDescription> x224_ballInnerGlow;
std::unique_ptr<CElementGen> x22c_ballInnerGlowGen;
TLockedToken<CGenDescription> x230_ballTransitionFlash;
std::vector<CLight> x23c_lights;
std::unique_ptr<CActorLights> x24c_actorLights;
bool x25c_ = false;
float x260_ = 0.f;
CSfxHandle x264_offsetSfx;
CSfxHandle x268_rotateSfx;
CSfxHandle x26c_zoomSfx;
union
{
struct
{
bool x270_24_hasSpiderBall : 1;
bool x270_25_hasGrappleBeam : 1;
bool x270_26_ : 1;
bool x270_27_ : 1;
bool x270_28_ : 1;
bool x270_29_ : 1;
bool x270_30_ : 1;
bool x270_31_loaded : 1;
};
u32 _dummy = 0;
};
static const zeus::CVector3f skInitialOffset;
static CModelData BuildSuitModelData1(CPlayerState::EPlayerSuit suit);
static CModelData BuildSuitModelDataBoots(CPlayerState::EPlayerSuit suit);
void SetupLights();
void SetTransitionAnimation();
void SetRotationSfxPlaying(bool playing);
void SetOffsetSfxPlaying(bool playing);
void SetZoomSfxPlaying(bool playing);
public:
CSamusDoll(const CDependencyGroup& suitDgrp, const CDependencyGroup& ballDgrp,
CPlayerState::EPlayerSuit suit, CPlayerState::EBeamId beam,
bool hasSpiderBall, bool hasGrappleBeam);
bool IsLoaded() const;
bool CheckLoadComplete();
void Update(float dt, CRandom16& rand);
void Draw(const CStateManager& mgr, float alpha);
void Touch();
void CheckTransition(bool morphballComplete);
void SetRotation(float xDelta, float zDelta, float);
void SetOffset(const zeus::CVector3f& offset, float sfxThreshold);
void BeginViewInterpolate(bool zoomOut);
};
}

@ -1 +1 @@
Subproject commit 07daf408244c41188e90bbf3e7a78be37a1d0dce
Subproject commit f5f78fdeefd8a0d1a708ca31df8dc2cb2adc8482