Skip to content

Commit be17f43

Browse files
committed
Add new show/hide and load/unload tooling
1 parent 8a20d70 commit be17f43

File tree

13 files changed

+194
-13
lines changed

13 files changed

+194
-13
lines changed

CMakeLists.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -129,6 +129,8 @@ set(SOURCE_FILES
129129
src/UI/SettingsMenu.hpp
130130
src/UI/BombJumping.hpp
131131
src/UI/BombJumping.cpp
132+
src/UI/RoomMenu.cpp
133+
src/UI/RoomMenu.hpp
132134

133135
src/world/WorldRenderer.cpp
134136
src/world/WorldRenderer.hpp

README.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -67,6 +67,10 @@ Youtube video on macOS (Linux is similar): [https://www.youtube.com/watch?v=fyz6
6767

6868
## Changelog
6969

70+
### 2.4.1
71+
- Add option to occlude/show rooms (e.g. "where's the room")
72+
- Add load/unload room option (not perfect)
73+
7074
### 2.4.0
7175
- New option to show current loads in bottom left
7276

src/NewPauseScreen.cpp

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@
2525
#include "ImGuiEngine.hpp"
2626
#include "version.h"
2727
#include "UI/PlayerMenu.hpp"
28+
#include "UI/RoomMenu.hpp"
2829

2930
#define PAD_MAX_CONTROLLERS 4
3031

@@ -179,6 +180,7 @@ void NewPauseScreen::RenderMenu() {
179180
GUI::drawInventoryMenu();
180181
GUI::drawSettingsMenu();
181182
GUI::drawWarpMenu();
183+
GUI::drawRoomMenu();
182184
ImGui::Text("v%s", PRAC_MOD_VERSION);
183185
}
184186
ImGui::End();

src/UI/RoomMenu.cpp

Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
#include "RoomMenu.hpp"
2+
3+
#include <imgui.h>
4+
#include "ImHelpers.hpp"
5+
#include "os.h"
6+
#include "prime/CStateManager.hpp"
7+
#include "prime/CWorld.hpp"
8+
#include "WarpMenu.h"
9+
10+
11+
namespace GUI {
12+
void hideAllRooms();
13+
void showVisibilityControls();
14+
15+
void showLoadControls();
16+
17+
void drawRoomMenu() {
18+
if (ImGui::TreeNode("Rooms")) {
19+
20+
if (ImGui::TreeNode("Visibility")) {
21+
ImGui::Text("Warning: If you show too many rooms, the game may crash!");
22+
if (ImGui::Button("Hide all")) {
23+
hideAllRooms();
24+
}
25+
showVisibilityControls();
26+
ImGui::TreePop();
27+
}
28+
if (ImGui::TreeNode("Load")) {
29+
ImGui::Text("Warning: If you load too many rooms, the game may crash!");
30+
showLoadControls();
31+
ImGui::TreePop();
32+
}
33+
ImGui::TreePop();
34+
}
35+
}
36+
37+
void hideAllRooms() {
38+
CStateManager *stateManager = ((CStateManager *) 0x8045A1A8);
39+
CWorld *world = stateManager->GetWorld();
40+
if (world == nullptr) {
41+
return;
42+
}
43+
TAreaId areaId = world->GetCurrentAreaId();
44+
auto areas = world->areas();
45+
for (int i = 0; i < areas->length(); i++) {
46+
auto area = areas->get(i).ptr;
47+
if (area->areaIDx() == areaId) continue;
48+
area->SetOcclusionState(EOcclusionState::Occluded);
49+
}
50+
}
51+
52+
void showVisibilityControls() {
53+
CStateManager *stateManager = ((CStateManager *) 0x8045A1A8);
54+
CWorld *world = stateManager->GetWorld();
55+
if (world == nullptr) {
56+
return;
57+
}
58+
TAreaId areaId = world->GetCurrentAreaId();
59+
auto areas = world->areas();
60+
for (int i = 0; i < areas->length(); i++) {
61+
auto area = areas->get(i).ptr;
62+
auto post = area->postConstructed();
63+
if (post != nullptr && area->curChain() == EChain::Alive) {
64+
if (area->areaIDx() == areaId) continue;
65+
const char *name = getNameForAreaAsset(world->GetWorldId(), area->mrea());
66+
ImGui::Text("%s", name);
67+
ImGui::SameLine();
68+
if (post->occlusionState() == EOcclusionState::Occluded) {
69+
char label[32];
70+
memset(label, 0, 32);
71+
snprintf(label, 32, "Show###%d", area->mrea());
72+
if (ImGui::Button(label)) {
73+
area->SetOcclusionState(EOcclusionState::Visible);
74+
}
75+
} else {
76+
char label[32];
77+
memset(label, 0, 32);
78+
snprintf(label, 32, "Show###%d", area->mrea());
79+
if (ImGui::Button(label)) {
80+
area->SetOcclusionState(EOcclusionState::Occluded);
81+
}
82+
}
83+
}
84+
}
85+
}
86+
87+
void showLoadControls() {
88+
CStateManager *stateManager = ((CStateManager *) 0x8045A1A8);
89+
CWorld *world = stateManager->GetWorld();
90+
if (world == nullptr) {
91+
return;
92+
}
93+
TAreaId areaId = world->GetCurrentAreaId();
94+
auto currentArea = world->areas()->get(areaId).ptr;
95+
auto docks = currentArea->docks();
96+
for (int i = 0; i < docks->length(); i++) {
97+
auto dock = &docks->get(i);
98+
auto refs = dock->refs();
99+
for (int j = 0; j < refs->length(); j++) {
100+
auto ref = &refs->get(j);
101+
auto connectedAreaId = ref->x0_area;
102+
auto connectedArea = world->areas()->get(connectedAreaId).ptr;
103+
const char *name = getNameForAreaAsset(world->GetWorldId(), connectedArea->mrea());
104+
ImGui::Text("%s %x", name, ref->x6_loadOther);
105+
ImGui::SameLine();
106+
bool loadOther = (ref->x6_loadOther & 0x80) > 0;
107+
if (loadOther) {
108+
char label[32];
109+
memset(label, 0, 32);
110+
snprintf(label, 32, "Unload###%d", connectedAreaId);
111+
if (ImGui::Button(label)) {
112+
ref->x6_loadOther &= 0x7F;
113+
}
114+
} else {
115+
char label[32];
116+
memset(label, 0, 32);
117+
snprintf(label, 32, "Load###%d", connectedAreaId);
118+
if (ImGui::Button(label)) {
119+
ref->x6_loadOther |= 0x80;
120+
}
121+
}
122+
}
123+
}
124+
}
125+
}
126+

src/UI/RoomMenu.hpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
#pragma once
2+
3+
namespace GUI {
4+
void drawRoomMenu();
5+
}

src/include/prime/CGameArea.hpp

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,21 +5,55 @@
55

66
class CStateManager;
77

8+
enum class EOcclusionState { Occluded, Visible };
9+
enum class EChain {
10+
Invalid = -1,
11+
ToDeallocate,
12+
Deallocated,
13+
Loading,
14+
Alive,
15+
AliveJudgement,
16+
};
17+
818
class CPostConstructed {
919
public:
1020
float *GetWorldLightingLevel() { return (GetField<float>(this, 0x1128)); };
21+
EOcclusionState occlusionState() { return *(GetField<EOcclusionState>(this, 0x10dc)); };
22+
1123
};
1224

1325

1426
class CGameArea {
1527
public:
28+
struct PACKED Dock {
29+
struct PACKED SDockReference {
30+
TAreaId x0_area;
31+
s16 x4_dock;
32+
u8 x6_loadOther;
33+
};
34+
35+
// These are weird, so just going direct
36+
// s32 GetReferenceCount();
37+
// TAreaId GetConnectedAreaId(s32 other);
38+
// bool GetShouldLoadOther(s32 other);
39+
// void SetShouldLoadOther(s32 other, bool should);
40+
inline u32 refCount() { return *GetField<u32>(this, 0x8); };
41+
inline rstl::vector<SDockReference>* refs() { return GetField<rstl::vector<SDockReference>>(this, 0x8); };
42+
char padding[0x4c];
43+
};
44+
1645
void StartStreamIn(CStateManager&);
1746
void Validate(CStateManager&);
1847
void LoadScriptObjects(CStateManager&);
1948

2049
inline CAssetId mrea() { return *GetField<u32>(this, 0x84); };
2150
inline u32 areaID() { return *GetField<u32>(this, 0x88); };
51+
inline u32 areaIDx() { return *GetField<u32>(this, 0x4); }; // this is like, the index in the array
52+
inline rstl::vector<u16>* attachedAreaIndices() { return GetField<rstl::vector<u16>>(this, 0x90); };
53+
inline rstl::vector<Dock>* docks() { return GetField<rstl::vector<Dock>>(this, 0xD0); };
2254
inline CPostConstructed *postConstructed() { return *GetField<CPostConstructed*>(this, 0x12C); };
55+
inline EChain curChain() { return *GetField<EChain>(this, 0x138); };
56+
void SetOcclusionState(EOcclusionState state);
2357
};
2458

2559
#endif // CGAMEAREA_HPP

src/include/prime/CWorld.hpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,11 @@ class CWorld {
1818
static void AuxGetAreaId(TAreaId* out, CWorld* obj, CAssetId areaAssetId);
1919

2020
CGameArea* IGetAreaAlways(TAreaId id);
21+
CAssetId GetWorldId() const { return *(GetField<CAssetId>(this, 0x8)); };
2122
TAreaId GetCurrentAreaId() const { return *(GetField<TAreaId>(this, 0x68)); };
2223
void SetPauseState(bool paused);
24+
void ScheduleAreaToLoad(CGameArea* area, CStateManager *mgr);
25+
void MoveToChain(CGameArea* area, EChain chain);
2326
inline rstl::vector<rstl::auto_ptr<CGameArea>> *areas() { return GetField<rstl::vector<rstl::auto_ptr<CGameArea>>>(this, 0x18); };
2427
};
2528

src/include/rstl/vector.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,8 @@ class PACKED vector {
2929

3030
inline uint32 length() const { return end; }
3131
inline uint32 capacity() const { return size; }
32-
inline T& operator[](int i) const { return ptr[i]; }
32+
inline T& operator[](int i) { return ptr[i]; }
33+
inline T& get(int i) { return ptr[i]; }
3334
inline T* data() const { return ptr; }
3435
};
3536

src/include/settings.hpp

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,12 @@
33

44
#include <gctypes.h>
55

6+
#ifdef DEBUG
7+
#define DEBUG_TRUE true
8+
#else
9+
#define DEBUG_TRUE false
10+
#endif
11+
612
struct Settings {
713
bool OSD_show: 1{true};
814
bool OSD_showFrameTime: 1{false};
@@ -15,7 +21,7 @@ struct Settings {
1521
bool OSD_showIGT: 1{true};
1622
bool OSD_showCurrentRoomTime: 1{true};
1723
bool OSD_showPreviousRoomTime: 1{true};
18-
bool OSD_showLoads: 1{false};
24+
bool OSD_showLoads: 1{DEBUG_TRUE};
1925

2026
bool BOMBJUMP_enable: 1{false};
2127

src/include/types.h

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -13,13 +13,8 @@ typedef s16 TUniqueId;
1313
typedef uint ResId;
1414
typedef uint CAssetId;
1515

16-
struct TAreaId {
17-
s32 id;
18-
19-
inline TAreaId(s32 v) : id(v) {}
20-
inline operator s32() const { return id; }
21-
};
16+
using TAreaId = s32;
2217

2318
#define kInvalidAreaId (TAreaId(-1))
2419

25-
#endif
20+
#endif

0 commit comments

Comments
 (0)