From e5dd64ab552e0715449359d9b9d6c31a4dc9000d Mon Sep 17 00:00:00 2001 From: Luke Street Date: Thu, 15 Sep 2022 00:08:47 -0400 Subject: [PATCH] CScriptMazeNode progress Former-commit-id: ff0275b48fec1f094604fa7f1e366e68aa8fe0eb --- include/Kyoto/Graphics/CColor.hpp | 8 +- include/MetroidPrime/CActor.hpp | 1 + include/MetroidPrime/CEntity.hpp | 1 + include/MetroidPrime/CStateManager.hpp | 15 ++ .../ScriptObjects/CScriptMazeNode.hpp | 4 + .../ScriptObjects/CScriptMazeNode.cpp | 140 +++++++++++------- 6 files changed, 115 insertions(+), 54 deletions(-) diff --git a/include/Kyoto/Graphics/CColor.hpp b/include/Kyoto/Graphics/CColor.hpp index eb6682e7..dca452bd 100644 --- a/include/Kyoto/Graphics/CColor.hpp +++ b/include/Kyoto/Graphics/CColor.hpp @@ -32,10 +32,10 @@ public: static uint Lerp(uint a, uint b, float t); static CColor Modulate(const CColor& a, const CColor& b); static CColor Add(const CColor& a, const CColor& b); - f32 GetRed() const { return CCast::ToReal32(mR) * (1/255.f); } - f32 GetGreen() const { return CCast::ToReal32(mG) * (1/255.f); } - f32 GetBlue() const { return CCast::ToReal32(mB) * (1/255.f); } - f32 GetAlpha() const { return CCast::ToReal32(mA) * (1/255.f); } + f32 GetRed() const { return CCast::ToReal32(mR) * (1 / 255.f); } + f32 GetGreen() const { return CCast::ToReal32(mG) * (1 / 255.f); } + f32 GetBlue() const { return CCast::ToReal32(mB) * (1 / 255.f); } + f32 GetAlpha() const { return CCast::ToReal32(mA) * (1 / 255.f); } u8 GetRedu8() const { return mR; } u8 GetGreenu8() const { return mG; } u8 GetBlueu8() const { return mB; } diff --git a/include/MetroidPrime/CActor.hpp b/include/MetroidPrime/CActor.hpp index 959b7602..20748af8 100644 --- a/include/MetroidPrime/CActor.hpp +++ b/include/MetroidPrime/CActor.hpp @@ -252,6 +252,7 @@ public: const CTransform4f& GetTransform() const { return x34_transform; } CVector3f GetTranslation() const { return x34_transform.GetTranslation(); } + void SetTranslation(const CVector3f& vec); /// ???? bool NullModel() const { return !GetAnimationData() && !GetModelData()->HasNormalModel(); } diff --git a/include/MetroidPrime/CEntity.hpp b/include/MetroidPrime/CEntity.hpp index ba48e776..620c4933 100644 --- a/include/MetroidPrime/CEntity.hpp +++ b/include/MetroidPrime/CEntity.hpp @@ -26,6 +26,7 @@ public: TUniqueId GetUniqueId() const { return x8_uid; } TAreaId GetAreaId() const; bool GetActive() const { return x30_24_active; } + const rstl::vector& GetConnectionList() const { return x20_conns; } static rstl::vector NullConnectionList; diff --git a/include/MetroidPrime/CStateManager.hpp b/include/MetroidPrime/CStateManager.hpp index 35479227..9729033f 100644 --- a/include/MetroidPrime/CStateManager.hpp +++ b/include/MetroidPrime/CStateManager.hpp @@ -8,6 +8,7 @@ #include "rstl/auto_ptr.hpp" #include "rstl/list.hpp" +#include "rstl/pair.hpp" #include "rstl/rc_ptr.hpp" #include "rstl/reserved_vector.hpp" #include "rstl/single_ptr.hpp" @@ -42,8 +43,11 @@ public: bool AddDrawableActor(const CActor& actor, const CVector3f& pos, const CAABox& bounds) const; void SetupParticleHook(const CActor& actor) const; void FreeScriptObject(TUniqueId uid); + rstl::pair< TEditorId, TUniqueId > GenerateObject(const TEditorId& eid); CEntity* ObjectById(TUniqueId uid); + const CEntity* GetObjectById(TUniqueId uid) const; + TUniqueId GetIdForScript(TEditorId eid) const; CCameraManager* CameraManager() { return x870_cameraManager; } const CCameraManager* GetCameraManager() const { return x870_cameraManager; } @@ -57,6 +61,9 @@ public: f32 GetThermalColdScale1() const { return xf24_thermColdScale1; } f32 GetThermalColdScale2() const { return xf28_thermColdScale2; } + bool IsGeneratingObject() const { return xf94_26_generatingObject; } + void SetIsGeneratingObject(bool gen) { xf94_26_generatingObject = gen; } + private: u16 x0_nextFreeIndex; rstl::reserved_vector< u16, 1024 > x8_objectIndexArray; @@ -83,6 +90,14 @@ private: u8 pad2[0x658]; f32 xf24_thermColdScale1; f32 xf28_thermColdScale2; + u8 pad3[0x6c]; + bool xf94_24_readyToRender : 1; + bool xf94_25_quitGame : 1; + bool xf94_26_generatingObject : 1; + bool xf94_27_inMapScreen : 1; + bool xf94_28_inSaveUI : 1; + bool xf94_29_cinematicPause : 1; + bool xf94_30_fullThreat : 1; }; #endif diff --git a/include/MetroidPrime/ScriptObjects/CScriptMazeNode.hpp b/include/MetroidPrime/ScriptObjects/CScriptMazeNode.hpp index 87ec8f9b..2e70597c 100644 --- a/include/MetroidPrime/ScriptObjects/CScriptMazeNode.hpp +++ b/include/MetroidPrime/ScriptObjects/CScriptMazeNode.hpp @@ -81,6 +81,10 @@ public: static void LoadMazeSeeds(); + inline void SendScriptMsg(CStateManager& mgr, CEntity* to, EScriptObjectMessage msg) { + mgr.SendScriptMsg(to, GetUniqueId(), msg); + } + private: enum ESide { Invalid = -1, diff --git a/src/MetroidPrime/ScriptObjects/CScriptMazeNode.cpp b/src/MetroidPrime/ScriptObjects/CScriptMazeNode.cpp index 7d06c874..f39cc6f9 100644 --- a/src/MetroidPrime/ScriptObjects/CScriptMazeNode.cpp +++ b/src/MetroidPrime/ScriptObjects/CScriptMazeNode.cpp @@ -87,7 +87,6 @@ static inline int GetRandom(CRandom16& rand, int offset) { return tmp - ((tmp / 5) * 5) + offset; } -// TODO non-matching void CMazeState::GenerateObstacles() { if (!x94_24_initialized) { Initialize(); @@ -99,13 +98,12 @@ void CMazeState::GenerateObstacles() { int puddle1Idx = GetRandom(x0_rand, 13); int puddle2Idx = GetRandom(x0_rand, 29); - int row = x88_enterRow; - int col = x84_enterCol; - int prevRow = x88_enterRow; int prevCol = x84_enterCol; - + int prevRow = x88_enterRow; ESide side = kS_Invalid; int idx = 0; + int col = prevCol; + int row = prevRow; while (col != x8c_targetCol || row != x90_targetRow) { if (idx == gate1Idx || idx == gate2Idx || idx == gate3Idx) { @@ -129,102 +127,102 @@ void CMazeState::GenerateObstacles() { } } - int nextCol = col; - int nextRow = row; - if (row > 1 && side != kS_Bottom && GetCellInline(col, row).x0_24_openTop && GetCellInline(col, row - 1).x1_25_onPath) { + int curCol = col; + int curRow = row; + if (row > 0 && side != kS_Bottom && GetCellInline(col, row).x0_24_openTop && GetCellInline(col, row - 1).x1_25_onPath) { side = kS_Top; - nextRow--; + row--; } else if (row < skMazeRows - 1 && side != kS_Top && GetCellInline(col, row).x0_26_openBottom && GetCellInline(col, row + 1).x1_25_onPath) { side = kS_Bottom; - nextRow++; - } else if (col > 1 && side != kS_Right && GetCellInline(col, row).x0_27_openLeft && GetCellInline(col - 1, row).x1_25_onPath) { + row++; + } else if (col > 0 && side != kS_Right && GetCellInline(col, row).x0_27_openLeft && GetCellInline(col - 1, row).x1_25_onPath) { side = kS_Left; - nextCol--; - } else if (col < skMazeRows && side != kS_Left && GetCellInline(col, row).x0_25_openRight && GetCellInline(col + 1, row).x1_25_onPath) { + col--; + } else if (col < skMazeCols - 1 && side != kS_Left && GetCellInline(col, row).x0_25_openRight && + GetCellInline(col + 1, row).x1_25_onPath) { side = kS_Right; - nextCol++; + col++; } else { return; } +#define GetCellInline(c, r) x4_cells[c + r * skMazeCols] if (idx == puddle1Idx || idx == puddle2Idx) { - if (col == 0 || row == 0 || col == skMazeCols - 1 || row == skMazeRows - 1) { + if (curCol == 0 || curRow == 0 || curCol == skMazeCols - 1 || curRow == skMazeRows - 1) { if (idx == puddle1Idx) { puddle1Idx++; } else { puddle2Idx++; } } else { - SMazeCell& cell = GetCellInline(col, row); - cell.x1_24_puddle = true; + // SMazeCell& cell = GetCellInline(curCol, curRow); + GetCellInline(curCol, curRow).x1_24_puddle = true; switch (side) { case kS_Top: - GetCellInline(nextCol, nextRow).x0_26_openBottom = false; - cell.x0_24_openTop = false; + GetCellInline(col, row).x0_26_openBottom = false; + GetCellInline(curCol, curRow).x0_24_openTop = false; break; case kS_Right: - GetCellInline(nextCol, nextRow).x0_27_openLeft = false; - cell.x0_25_openRight = false; + GetCellInline(col, row).x0_27_openLeft = false; + GetCellInline(curCol, curRow).x0_25_openRight = false; break; case kS_Bottom: - GetCellInline(nextCol, nextRow).x0_24_openTop = false; - cell.x0_26_openBottom = false; + GetCellInline(col, row).x0_24_openTop = false; + GetCellInline(curCol, curRow).x0_26_openBottom = false; break; case kS_Left: - GetCellInline(nextCol, nextRow).x0_25_openRight = false; - cell.x0_27_openLeft = false; + GetCellInline(col, row).x0_25_openRight = false; + GetCellInline(curCol, curRow).x0_27_openLeft = false; break; } } } idx++; - prevCol = col; - prevRow = row; - col = nextCol; - row = nextRow; - }; + prevCol = curCol; + prevRow = curRow; + } } -// TODO non-matching void CMazeState::Initialize() { int path[NUM_MAZE_CELLS]; + int pathIdx = 0; int targetRow = x90_targetRow; int targetCol = x8c_targetCol; int cellIdx = x84_enterCol + x88_enterRow * skMazeCols; - path[0] = cellIdx; + int max = targetCol + targetRow * skMazeCols; + + path[pathIdx++] = cellIdx; x4_cells[cellIdx].x1_26_checked = true; - int pathLength = 1; - while (cellIdx != targetCol + targetRow * skMazeCols) { + + while (cellIdx != max) { if (x4_cells[cellIdx].x0_24_openTop && !x4_cells[cellIdx - skMazeCols].x1_26_checked) { - path[pathLength] = cellIdx - skMazeCols; - pathLength++; + path[pathIdx++] = cellIdx - skMazeCols; } if (x4_cells[cellIdx].x0_25_openRight && !x4_cells[cellIdx + 1].x1_26_checked) { - path[pathLength] = cellIdx + 1; - pathLength++; + path[pathIdx++] = cellIdx + 1; } if (x4_cells[cellIdx].x0_26_openBottom && !x4_cells[cellIdx + skMazeCols].x1_26_checked) { - path[pathLength] = cellIdx + skMazeCols; - pathLength++; + path[pathIdx++] = cellIdx + skMazeCols; } if (x4_cells[cellIdx].x0_27_openLeft && !x4_cells[cellIdx - 1].x1_26_checked) { - path[pathLength] = cellIdx - 1; - pathLength++; + path[pathIdx++] = cellIdx - 1; } - if (cellIdx == path[pathLength - 1]) { - pathLength--; + if (cellIdx == path[pathIdx - 1]) { + pathIdx--; } - cellIdx = path[pathLength - 1]; + cellIdx = path[pathIdx - 1]; x4_cells[cellIdx].x1_26_checked = true; } - for (; pathLength != 0; pathLength--) { - int idx = path[pathLength]; - if (x4_cells[idx].x1_26_checked) { - x4_cells[idx].x1_25_onPath = true; + + while (pathIdx--) { + cellIdx = path[pathIdx]; + if (x4_cells[cellIdx].x1_26_checked) { + x4_cells[cellIdx].x1_25_onPath = true; } } + x94_24_initialized = true; } @@ -249,8 +247,49 @@ CScriptMazeNode::CScriptMazeNode(TUniqueId uid, const rstl::string& name, const void CScriptMazeNode::Accept(IVisitor& visitor) { visitor.Visit(*this); } +static inline TUniqueId GenerateObject(CStateManager& mgr, const SConnection& conn) { + bool wasGeneratingObject = mgr.IsGeneratingObject(); + mgr.SetIsGeneratingObject(true); + TUniqueId objUid = mgr.GenerateObject(conn.x8_objId).second; + mgr.SetIsGeneratingObject(wasGeneratingObject); + return objUid; +} + +// TODO non-matching +// https://decomp.me/scratch/IvHBz void CScriptMazeNode::GenerateObjects(CStateManager& mgr) { - // TODO + rstl::vector< SConnection >::const_iterator conn = GetConnectionList().begin(); + for (; conn != GetConnectionList().end(); ++conn) { + if (conn->x0_state != kSS_MaxReached || conn->x4_msg != kSM_Activate) { + continue; + } + CEntity* ent = mgr.ObjectById(mgr.GetIdForScript(conn->x8_objId)); + CScriptEffect* scriptEffect = TCastToPtr< CScriptEffect >(ent); + CScriptActor* scriptActor = TCastToPtr< CScriptActor >(ent); + CScriptTrigger* scriptTrigger = TCastToPtr< CScriptTrigger >(ent); + if ((scriptEffect || scriptActor || scriptTrigger) && (!scriptEffect || !x13c_25_hasGate)) { + // TUniqueId objUid = GenerateObject(mgr, *conn); + bool wasGeneratingObject = mgr.IsGeneratingObject(); + mgr.SetIsGeneratingObject(true); + TUniqueId objUid = mgr.GenerateObject(conn->x8_objId).second; + mgr.SetIsGeneratingObject(wasGeneratingObject); + if (CActor* actor = static_cast< CActor* >(mgr.ObjectById(objUid))) { + mgr.SendScriptMsg(actor, GetUniqueId(), kSM_Activate); + if (scriptEffect) { + actor->SetTranslation(GetTranslation() + x120_effectPos); + x11c_effectId = objUid; + } + if (scriptActor) { + actor->SetTranslation(GetTranslation() + x100_actorPos); + xfc_actorId = objUid; + } + if (scriptTrigger) { + actor->SetTranslation(GetTranslation() + x110_triggerPos); + x10c_triggerId = objUid; + } + } + } + } } void CScriptMazeNode::Reset(CStateManager& mgr) { @@ -262,6 +301,7 @@ void CScriptMazeNode::Reset(CStateManager& mgr) { } // TODO non-matching +// https://decomp.me/scratch/3F51I void CScriptMazeNode::SendScriptMsgs(CStateManager& mgr, EScriptObjectMessage msg) { mgr.SendScriptMsg(mgr.ObjectById(x11c_effectId), GetUniqueId(), msg); mgr.SendScriptMsg(mgr.ObjectById(xfc_actorId), GetUniqueId(), msg);