summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCaladius <Caladius@users.noreply.github.com>2025-10-30 11:49:39 -0400
committerGitHub <noreply@github.com>2025-10-30 11:49:39 -0400
commitc91588d8af126f68f032b65e552f6d8a029ded22 (patch)
tree2f86291b5a742841967a710cd4dd130117f3a5bb
parent84f3aedf609b2795f3ba39612312a948be97fb8b (diff)
[Rando] Implement Traps (#1287)
* Initial Trap Implementation with 1 Trap Example. * New TrapTypes and Per Trap Custom Messages * Spruce up Menu and add placeholders for toggling traps * Reordering and clean up * Seeded Trap Models * Trap Type Opt-in * Add Jinx Trap * Add Enemy (Like Like) Trap * Fix Shop Item draws and convert for Progressive * Placeholder for Custom Model * Implemented time trap[Please Squash this] (#13) * Implemented time trap * Finished comment because im braindead today * Forgot to fix indentation(whoops) * Changed things not mess with the games code, added some more Time Trap messages * Removed a include I forgot to yoink from the base code. * Removed header define for VerifyTimeSkip * Clangit * Missed some leftovers from a merge conflict. * Clang format throwing a fit over a empty line * Added Timeskip CVar placeholder * Fixed issue where game crashes past midnight * Added Moonfall skipping prevention messures. * Added fallback loop to handle the remaining cycles in the event of a overflow. * Cleaner implementation * Keep it simple stupid * changed function name to be more accurate * Removed outdated comment, used TimeSkipInc for moonfall skip prevention * Reverted max trap(accidentally pushed it while testing) * Removed old unused value * Reduced the iteration by 1 to be closer to where it was at before. * Will this fix Windows? * Added TRAP_TIME to trapToCvarMap * Corrected typo on comment * Clangit...again * Added calls to load environment values and adjust the weather. * Update Time Trap and clean up code * Add Flash effect to Time Trap * Added a few more timeTrapMessages * I hate you clang format * Fix Trading Post Kick Out Time * Added map for all locations I can think of that close. * Clangit yet again * Removed Inn handling because the edge case related to it closing cannot happen * Corrected a whoopie I made when I was dealing with a conflict * Removed pointless condition check that is always true * Removed duped variable * Removed unnecessary data from SCENE_8ITEMSHO kickout entry * Removed now used TRADING_POS_ACTOR_PARAM --------- Co-authored-by: Caladius <clatini88@gmail.com> * Comment out Kick Out code for later TODO * Clean out commented code * Adds Wallet Trap and updates some tooltips * More Trap Messages * Even more trap messages * moooooore messages * update for clang * Feedback changes for Time Trap * Update Trap functions * Fix Matrix call * Trap Model Import (Thanks Zrc) * rename * Adjust size * update name for uniformity * Update mm/2s2h/Rando/MiscBehavior/Traps.cpp Co-authored-by: Eblo <7004497+Eblo@users.noreply.github.com> * Update mm/2s2h/Rando/MiscBehavior/Traps.cpp Co-authored-by: Eblo <7004497+Eblo@users.noreply.github.com> * feedback updates * Update notifications to remove color codes from trap messages when item skip is on * VBify Object Dependency * Fix comma * fix headers * Refactor ObjectDependency hook * Check if item get cutscenes are being skipped * Use brackets for LUS include * Header update --------- Co-authored-by: sitton76 <58642183+sitton76@users.noreply.github.com> Co-authored-by: Eblo <7004497+Eblo@users.noreply.github.com>
-rw-r--r--mm/2s2h/CustomMessage/CustomMessage.cpp14
-rw-r--r--mm/2s2h/CustomMessage/CustomMessage.h1
-rw-r--r--mm/2s2h/DeveloperTools/ObjectDependency.cpp16
-rw-r--r--mm/2s2h/GameInteractor/GameInteractor.cpp11
-rw-r--r--mm/2s2h/GameInteractor/GameInteractor.h13
-rw-r--r--mm/2s2h/Rando/ActorBehavior/ActorBehavior.cpp1
-rw-r--r--mm/2s2h/Rando/ActorBehavior/ActorBehavior.h1
-rw-r--r--mm/2s2h/Rando/ActorBehavior/EnGirlA.cpp4
-rw-r--r--mm/2s2h/Rando/DrawItem.cpp66
-rw-r--r--mm/2s2h/Rando/GiveItem.cpp4
-rw-r--r--mm/2s2h/Rando/Menu.cpp66
-rw-r--r--mm/2s2h/Rando/MiscBehavior/CheckQueue.cpp21
-rw-r--r--mm/2s2h/Rando/MiscBehavior/MiscBehavior.h1
-rw-r--r--mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp12
-rw-r--r--mm/2s2h/Rando/MiscBehavior/Traps.cpp282
-rw-r--r--mm/2s2h/Rando/MiscBehavior/Traps.h10
-rw-r--r--mm/2s2h/Rando/StaticData/Items.cpp1
-rw-r--r--mm/2s2h/Rando/StaticData/Options.cpp2
-rw-r--r--mm/2s2h/Rando/StaticData/StaticData.h1
-rw-r--r--mm/2s2h/Rando/Types.h4
-rw-r--r--mm/assets/2s2h_assets.h3
-rw-r--r--mm/assets/custom/objects/object_trap/gTrapDL11
-rw-r--r--mm/assets/custom/objects/object_trap/ice_2bin0 -> 4188 bytes
-rw-r--r--mm/assets/custom/objects/object_trap/mat_object_trap_model_ice21
-rw-r--r--mm/assets/custom/objects/object_trap/object_trap_model_tri_0158
-rw-r--r--mm/assets/custom/objects/object_trap/object_trap_model_vtx_0156
-rw-r--r--mm/src/code/z_scene.c3
27 files changed, 866 insertions, 17 deletions
diff --git a/mm/2s2h/CustomMessage/CustomMessage.cpp b/mm/2s2h/CustomMessage/CustomMessage.cpp
index b2b1cd311..ff3a16152 100644
--- a/mm/2s2h/CustomMessage/CustomMessage.cpp
+++ b/mm/2s2h/CustomMessage/CustomMessage.cpp
@@ -9,6 +9,20 @@ extern f32 sNESFontWidths[160];
CustomMessage::Entry activeCustomMessage;
+std::string CustomMessage::RemoveColorCodes(const std::string& input) {
+ std::string output = input;
+ const std::vector<std::string> codes = { "%r", "%w", "%y", "%g", "%b", "%p" };
+
+ for (const auto& code : codes) {
+ size_t pos = 0;
+ while ((pos = output.find(code, pos)) != std::string::npos) {
+ output.erase(pos, code.length());
+ }
+ }
+
+ return output;
+}
+
void CustomMessage::StartTextbox(std::string msg, CustomMessage::Entry options) {
options.msg = msg;
activeCustomMessage = options;
diff --git a/mm/2s2h/CustomMessage/CustomMessage.h b/mm/2s2h/CustomMessage/CustomMessage.h
index a1668ca3f..6a9a0761a 100644
--- a/mm/2s2h/CustomMessage/CustomMessage.h
+++ b/mm/2s2h/CustomMessage/CustomMessage.h
@@ -32,6 +32,7 @@ void StartTextbox(std::string msg, Entry options = {});
void SetActiveCustomMessage(std::string msg, Entry options = {});
// Helpers
+std::string RemoveColorCodes(const std::string& input);
void Replace(std::string* msg, const std::string& placeholder, const std::string& value);
void AddLineBreaks(std::string* msg);
void ReplaceColorChars(std::string* msg);
diff --git a/mm/2s2h/DeveloperTools/ObjectDependency.cpp b/mm/2s2h/DeveloperTools/ObjectDependency.cpp
new file mode 100644
index 000000000..6811df9df
--- /dev/null
+++ b/mm/2s2h/DeveloperTools/ObjectDependency.cpp
@@ -0,0 +1,16 @@
+#include <libultraship/bridge/consolevariablebridge.h>
+#include "2s2h/GameInteractor/GameInteractor.h"
+#include "2s2h/ShipInit.hpp"
+
+extern "C" {
+#include "variables.h"
+}
+
+#define CVAR_NAME "gDeveloperTools.DisableObjectDependency"
+#define CVAR CVarGetInteger(CVAR_NAME, 0)
+
+void RegisterObjectDependency() {
+ COND_VB_SHOULD(VB_ENABLE_OBJECT_DEPENDENCY, CVAR, { *should = false; });
+}
+
+static RegisterShipInitFunc initFunc(RegisterObjectDependency, { CVAR_NAME });
diff --git a/mm/2s2h/GameInteractor/GameInteractor.cpp b/mm/2s2h/GameInteractor/GameInteractor.cpp
index 7c3dd4d26..487af4f19 100644
--- a/mm/2s2h/GameInteractor/GameInteractor.cpp
+++ b/mm/2s2h/GameInteractor/GameInteractor.cpp
@@ -510,10 +510,15 @@ void ProcessEvents(Actor* actor) {
f32 x2 = e->posX * c - e->posZ * s;
f32 z2 = e->posX * s + e->posZ * c;
Actor_Spawn(&gPlayState->actorCtx, gPlayState, e->actorId, x + x2, y + e->posY, z + z2, 0,
- e->rot + player->actor.world.rot.y, 0, e->params);
+ e->rotY + player->actor.world.rot.y, 0, e->params);
} else {
- Actor_Spawn(&gPlayState->actorCtx, gPlayState, e->actorId, e->posX, e->posY, e->posZ, 0, e->rot, 0,
- e->params);
+ Actor_Spawn(&gPlayState->actorCtx, gPlayState, e->actorId, e->posX, e->posY, e->posZ, e->rotX, e->rotY,
+ e->rotZ, e->params);
+ }
+ GameInteractor::Instance->currentEvent = GIEventNone{};
+ } else if (auto e = std::get_if<GIEventTrap>(&nextEvent)) {
+ if (e->action) {
+ e->action();
}
GameInteractor::Instance->currentEvent = GIEventNone{};
}
diff --git a/mm/2s2h/GameInteractor/GameInteractor.h b/mm/2s2h/GameInteractor/GameInteractor.h
index 8c44f5b5a..c0e74180a 100644
--- a/mm/2s2h/GameInteractor/GameInteractor.h
+++ b/mm/2s2h/GameInteractor/GameInteractor.h
@@ -255,7 +255,8 @@ typedef enum {
VB_SET_CAMERA_FOV,
VB_USE_ITEM_CONSIDER_ITEM_ACTION,
VB_ENEMY_DROP_COLLECTIBLE,
- VB_DRAW_SLIME_RANDO_ITEM
+ VB_DRAW_SLIME_RANDO_ITEM,
+ VB_ENABLE_OBJECT_DEPENDENCY,
} GIVanillaBehavior;
typedef enum {
@@ -369,7 +370,9 @@ struct GIEventSpawnActor {
f32 posX;
f32 posY;
f32 posZ;
- s16 rot;
+ s16 rotX;
+ s16 rotY;
+ s16 rotZ;
s32 params;
// if true, the coordinates are made relative to the player's position and rotation, 0 rotation is facing the same
// direction as the player, x+ is to the players right, y+ is up, z+ is in front of the player
@@ -383,7 +386,11 @@ struct GIEventTransition {
u8 transitionType;
};
-typedef std::variant<GIEventNone, GIEventGiveItem, GIEventSpawnActor, GIEventTransition> GIEvent;
+struct GIEventTrap {
+ std::function<void()> action;
+};
+
+typedef std::variant<GIEventNone, GIEventGiveItem, GIEventSpawnActor, GIEventTransition, GIEventTrap> GIEvent;
class GameInteractor {
public:
diff --git a/mm/2s2h/Rando/ActorBehavior/ActorBehavior.cpp b/mm/2s2h/Rando/ActorBehavior/ActorBehavior.cpp
index 04600c8bd..af100a565 100644
--- a/mm/2s2h/Rando/ActorBehavior/ActorBehavior.cpp
+++ b/mm/2s2h/Rando/ActorBehavior/ActorBehavior.cpp
@@ -142,6 +142,7 @@ void Rando::ActorBehavior::OnFileLoad() {
Rando::ActorBehavior::InitObjWarpstoneBehavior();
Rando::ActorBehavior::InitPlayerBehavior();
Rando::ActorBehavior::InitSoulsBehavior();
+ Rando::ActorBehavior::InitTrapsBehavior();
COND_HOOK(ShouldVanillaBehavior, IS_RANDO, MiscVanillaBehaviorHandler);
}
diff --git a/mm/2s2h/Rando/ActorBehavior/ActorBehavior.h b/mm/2s2h/Rando/ActorBehavior/ActorBehavior.h
index 30b82dfda..1a9a3dd64 100644
--- a/mm/2s2h/Rando/ActorBehavior/ActorBehavior.h
+++ b/mm/2s2h/Rando/ActorBehavior/ActorBehavior.h
@@ -98,6 +98,7 @@ void InitObjTsuboBehavior();
void InitObjWarpstoneBehavior();
void InitPlayerBehavior();
void InitSoulsBehavior();
+void InitTrapsBehavior();
} // namespace ActorBehavior
diff --git a/mm/2s2h/Rando/ActorBehavior/EnGirlA.cpp b/mm/2s2h/Rando/ActorBehavior/EnGirlA.cpp
index 5f20dba6b..6ee339972 100644
--- a/mm/2s2h/Rando/ActorBehavior/EnGirlA.cpp
+++ b/mm/2s2h/Rando/ActorBehavior/EnGirlA.cpp
@@ -1,6 +1,7 @@
#include "ActorBehavior.h"
#include <libultraship/bridge/consolevariablebridge.h>
#include "2s2h/CustomMessage/CustomMessage.h"
+#include "2s2h/Rando/MiscBehavior/Traps.h"
extern "C" {
#include "variables.h"
@@ -67,6 +68,9 @@ void EnGirlA_RandoBuyFunc(PlayState* play, EnGirlA* enGirlA) {
RandoItemId randoItemId = Rando::ConvertItem(randoSaveCheck.randoItemId, (RandoCheckId)enGirlA->actor.world.rot.z);
randoSaveCheck.obtained = true;
Rupees_ChangeBy(-play->msgCtx.unk1206C);
+ if (randoItemId == RI_TRAP) {
+ RollTrapType();
+ }
Rando::GiveItem(randoItemId);
}
diff --git a/mm/2s2h/Rando/DrawItem.cpp b/mm/2s2h/Rando/DrawItem.cpp
index 54ccd568b..73e752e4f 100644
--- a/mm/2s2h/Rando/DrawItem.cpp
+++ b/mm/2s2h/Rando/DrawItem.cpp
@@ -16,6 +16,8 @@ extern "C" {
#include "objects/object_sek/object_sek.h"
#include "objects/object_st/object_st.h"
+#include "assets/overlays/ovl_Arrow_Ice/ovl_Arrow_Ice.h"
+
Gfx* ResourceMgr_LoadGfxByName(const char* path);
}
@@ -297,6 +299,64 @@ void DrawSkulltulaToken(RandoItemId randoItemId, Actor* actor) {
CLOSE_DISPS(gPlayState->state.gfxCtx);
}
+void DrawTrapModel() {
+ OPEN_DISPS(gPlayState->state.gfxCtx);
+
+ Gfx_SetupDL25_Xlu(gPlayState->state.gfxCtx);
+ Matrix_Scale(0.03f, 0.03f, 0.03f, MTXMODE_APPLY);
+
+ MATRIX_FINALIZE_AND_LOAD(POLY_XLU_DISP++, gPlayState->state.gfxCtx);
+ gSPDisplayList(POLY_XLU_DISP++, (Gfx*)gTrapDL);
+
+ CLOSE_DISPS(gPlayState->state.gfxCtx);
+}
+
+void DrawRandomTrapModel(RandoItemId randoItemId, Actor* actor) {
+ uint32_t seed = gSaveContext.save.shipSaveInfo.rando.finalSeed / 100000;
+ int actorData = (int)gPlayState->sceneId + seed;
+
+ if (actor != NULL) {
+ actorData += abs(actor->home.pos.x + actor->home.pos.y + actor->params);
+ }
+
+ int drawRandoItemId = actorData % ((int)RI_MAX - 3);
+
+ if (drawRandoItemId == RI_UNKNOWN || drawRandoItemId >= RI_TRAP) {
+ drawRandoItemId++;
+ }
+
+ // Handle Progressive Items
+ switch (drawRandoItemId) {
+ case RI_BOMB_BAG_20:
+ case RI_BOMB_BAG_30:
+ case RI_BOMB_BAG_40:
+ drawRandoItemId = RI_PROGRESSIVE_BOMB_BAG;
+ break;
+ case RI_BOW:
+ case RI_QUIVER_40:
+ case RI_QUIVER_50:
+ drawRandoItemId = RI_PROGRESSIVE_BOW;
+ break;
+ case RI_SINGLE_MAGIC:
+ case RI_DOUBLE_MAGIC:
+ drawRandoItemId = RI_PROGRESSIVE_MAGIC;
+ break;
+ case RI_SWORD_GILDED:
+ case RI_SWORD_KOKIRI:
+ case RI_SWORD_RAZOR:
+ drawRandoItemId = RI_PROGRESSIVE_SWORD;
+ break;
+ case RI_WALLET_ADULT:
+ case RI_WALLET_GIANT:
+ drawRandoItemId = RI_PROGRESSIVE_WALLET;
+ break;
+ default:
+ break;
+ }
+
+ Rando::DrawItem((RandoItemId)drawRandoItemId, actor);
+}
+
void DrawTriforcePiece(RandoItemId randoItemId) {
Gfx* triforcePieceModels[3] = {
(Gfx*)gTriforcePiece0DL,
@@ -473,6 +533,12 @@ void Rando::DrawItem(RandoItemId randoItemId, Actor* actor) {
case RI_TRIFORCE_PIECE:
DrawTriforcePiece(randoItemId);
break;
+ case RI_TRAP:
+ DrawRandomTrapModel(randoItemId, actor);
+ break;
+ case RI_MAX_TRAP:
+ DrawTrapModel();
+ break;
case RI_NONE:
case RI_UNKNOWN:
break;
diff --git a/mm/2s2h/Rando/GiveItem.cpp b/mm/2s2h/Rando/GiveItem.cpp
index 28a9b1819..f76cfbed8 100644
--- a/mm/2s2h/Rando/GiveItem.cpp
+++ b/mm/2s2h/Rando/GiveItem.cpp
@@ -1,4 +1,5 @@
#include "Rando/Rando.h"
+#include "Rando/MiscBehavior/MiscBehavior.h"
extern "C" {
#include "variables.h"
@@ -288,6 +289,9 @@ void Rando::GiveItem(RandoItemId randoItemId) {
case RI_ABILITY_SWIM:
Flags_SetRandoInf(RANDO_INF_OBTAINED_SWIM);
break;
+ case RI_TRAP:
+ Rando::MiscBehavior::OfferTrapItem();
+ break;
case RI_JUNK:
case RI_NONE:
break;
diff --git a/mm/2s2h/Rando/Menu.cpp b/mm/2s2h/Rando/Menu.cpp
index b5fc784c2..4f489d03a 100644
--- a/mm/2s2h/Rando/Menu.cpp
+++ b/mm/2s2h/Rando/Menu.cpp
@@ -290,6 +290,14 @@ static void DrawItemsTab() {
CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
CVarCheckbox("Infinite Upgrades", "gPlaceholderBool",
CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
+ CVarCheckbox("Song of Double Time", "gPlaceholderBool",
+ CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
+ CVarCheckbox("Inverted Song of Time", "gPlaceholderBool",
+ CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
+ CVarCheckbox("Saria's Song", "gPlaceholderBool",
+ CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
+ CVarCheckbox("Sun's Song", "gPlaceholderBool",
+ CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
ImGui::EndChild();
ImGui::SameLine();
ImGui::BeginChild("randoItemsColumn2", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y));
@@ -313,14 +321,56 @@ static void DrawItemsTab() {
ImGui::EndChild();
ImGui::SameLine();
ImGui::BeginChild("randoItemsColumn3", ImVec2(columnWidth, ImGui::GetContentRegionAvail().y));
- CVarCheckbox("Song of Double Time", "gPlaceholderBool",
- CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
- CVarCheckbox("Inverted Song of Time", "gPlaceholderBool",
- CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
- CVarCheckbox("Saria's Song", "gPlaceholderBool",
- CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
- CVarCheckbox("Sun's Song", "gPlaceholderBool",
- CheckboxOptions({ { .disabled = true, .disabledTooltip = "Coming Soon" } }));
+ CVarCheckbox("Shuffle Traps", Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar,
+ CheckboxOptions({ { .tooltip = "Ice Trap time!" } }));
+ CVarSliderInt(
+ "##trapcount", Rando::StaticData::Options[RO_TRAP_AMOUNT].cvar,
+ IntSliderOptions({ { .tooltip = "How many Traps are shuffled into the Item Pool.",
+ .disabled = (bool)!CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar, 0),
+ .disabledTooltip = "Shuffle Traps is disabled." } })
+ .LabelPosition(LabelPosition::None)
+ .Color(UIWidgets::Colors(CVarGetInteger("gSettings.Menu.Theme", 5)))
+ .Format("Traps: %i")
+ .Min(1)
+ .Max(10)
+ .DefaultValue(5));
+ ImGui::SeparatorText("Toggle Trap Types");
+ CVarCheckbox(
+ "Freeze Traps", "gRando.Traps.Freeze",
+ CheckboxOptions({ { .tooltip = "Freezes Link in place.",
+ .disabled = (bool)!CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar, 0),
+ .disabledTooltip = "Shuffle Traps is disabled." } }));
+ CVarCheckbox(
+ "Blast Traps", "gRando.Traps.Blast",
+ CheckboxOptions({ { .tooltip = "Link explodes with Powder Keg force.",
+ .disabled = (bool)!CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar, 0),
+ .disabledTooltip = "Shuffle Traps is disabled." } }));
+ CVarCheckbox(
+ "Shock Traps", "gRando.Traps.Shock",
+ CheckboxOptions({ { .tooltip = "Shocks Link for a few seconds.",
+ .disabled = (bool)!CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar, 0),
+ .disabledTooltip = "Shuffle Traps is disabled." } }));
+ CVarCheckbox(
+ "Jinx Traps", "gRando.Traps.Jinx",
+ CheckboxOptions({ { .tooltip = "Afflicts Link with Jinx.",
+ .disabled = (bool)!CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar, 0),
+ .disabledTooltip = "Shuffle Traps is disabled." } }));
+ CVarCheckbox(
+ "Wallet Traps", "gRando.Traps.Wallet",
+ CheckboxOptions({ { .tooltip = "Links rupees scatter around him.",
+ .disabled = (bool)!CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar, 0),
+ .disabledTooltip = "Shuffle Traps is disabled." } }));
+ CVarCheckbox( // This only spawns a Like Like, more enemies may be added in the future but each would need fine
+ // tuning
+ "Like Like Traps", "gRando.Traps.Enemy",
+ CheckboxOptions({ { .tooltip = "Spawns a Like Like on top of Link.",
+ .disabled = (bool)!CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar, 0),
+ .disabledTooltip = "Shuffle Traps is disabled." } }));
+ CVarCheckbox(
+ "Time Traps", "gRando.Traps.Time",
+ CheckboxOptions({ { .tooltip = "Advances Time 90 Minutes (Game Time).",
+ .disabled = (bool)!CVarGetInteger(Rando::StaticData::Options[RO_SHUFFLE_TRAPS].cvar, 0),
+ .disabledTooltip = "Shuffle Traps is disabled." } }));
ImGui::EndChild();
}
diff --git a/mm/2s2h/Rando/MiscBehavior/CheckQueue.cpp b/mm/2s2h/Rando/MiscBehavior/CheckQueue.cpp
index bef7eb663..9f372fe4f 100644
--- a/mm/2s2h/Rando/MiscBehavior/CheckQueue.cpp
+++ b/mm/2s2h/Rando/MiscBehavior/CheckQueue.cpp
@@ -1,13 +1,16 @@
#include "MiscBehavior.h"
+#include <libultraship/bridge/consolevariablebridge.h>
#include "2s2h/GameInteractor/GameInteractor.h"
#include "2s2h/CustomItem/CustomItem.h"
#include "2s2h/CustomMessage/CustomMessage.h"
#include "2s2h/BenGui/Notification.h"
#include "2s2h/Rando/StaticData/StaticData.h"
#include "2s2h/ShipUtils.h"
+#include "Traps.h"
extern "C" {
#include "variables.h"
+#include <functions.h>
extern TexturePtr gItemIcons[131];
extern s16 D_801CFF94[250];
}
@@ -58,10 +61,20 @@ void Rando::MiscBehavior::CheckQueue() {
randoItemId = RI_TRIFORCE_PIECE_PREVIOUS;
}
+ if (randoItemId == RI_TRAP) {
+ prefix = "";
+ message = GetTrapMessage();
+ // We need to remove the Color Codes if the player is skipping Item Get Cutscenes as the
+ // Notification Emit doesnt support it.
+ if (CVarGetInteger("gEnhancements.Cutscenes.SkipGetItemCutscenes", 0) >= 2) {
+ message = CustomMessage::RemoveColorCodes(message);
+ }
+ }
+
CustomMessage::Entry entry = {
.textboxType = 2,
.icon = Rando::StaticData::GetIconForZMessage(randoItemId),
- .msg = prefix + " " + message + "!",
+ .msg = (prefix == "" ? "" : prefix + " ") + message + (randoItemId == RI_TRAP ? "" : "!"),
};
if (CUSTOM_ITEM_FLAGS & CustomItem::GIVE_ITEM_CUTSCENE) {
@@ -88,7 +101,11 @@ void Rando::MiscBehavior::CheckQueue() {
// If the item has been given, the CUSTOM_ITEM_PARAM is set to the RI, prior to that it's the RC
if (CUSTOM_ITEM_FLAGS & CustomItem::CALLED_ACTION) {
- randoItemId = (RandoItemId)CUSTOM_ITEM_PARAM;
+ if ((RandoItemId)CUSTOM_ITEM_PARAM == RI_TRAP) {
+ randoItemId = RI_MAX_TRAP;
+ } else {
+ randoItemId = (RandoItemId)CUSTOM_ITEM_PARAM;
+ }
} else {
auto& randoSaveCheck = RANDO_SAVE_CHECKS[CUSTOM_ITEM_PARAM];
randoItemId =
diff --git a/mm/2s2h/Rando/MiscBehavior/MiscBehavior.h b/mm/2s2h/Rando/MiscBehavior/MiscBehavior.h
index 18432c372..d0f93f436 100644
--- a/mm/2s2h/Rando/MiscBehavior/MiscBehavior.h
+++ b/mm/2s2h/Rando/MiscBehavior/MiscBehavior.h
@@ -21,6 +21,7 @@ void OnFileCreate(s16 fileNum);
void OnFlagSet(FlagType flagType, u32 flag);
void OnSceneFlagSet(s16 sceneId, FlagType flagType, u32 flag);
void OnSceneInit(s16 sceneId, s8 spawnNum);
+void OfferTrapItem();
} // namespace MiscBehavior
diff --git a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp
index f41e47afc..6edec7fb1 100644
--- a/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp
+++ b/mm/2s2h/Rando/MiscBehavior/OnFileCreate.cpp
@@ -323,6 +323,18 @@ void Rando::MiscBehavior::OnFileCreate(s16 fileNum) {
throw std::runtime_error("No items in logic");
}
+ // Handle Shuffling Traps
+ if (RANDO_SAVE_OPTIONS[RO_SHUFFLE_TRAPS] == RO_GENERIC_YES) {
+ for (int i = 0; i < RANDO_SAVE_OPTIONS[RO_TRAP_AMOUNT]; i++) {
+ for (int j = 0; j < itemPool.size(); j++) {
+ if (itemPool[j] == RI_JUNK) {
+ itemPool[j] = RI_TRAP;
+ break;
+ }
+ }
+ }
+ }
+
int heartPiecesRemoved = 0;
// Add/Remove junk items to/from the pool to make the item pool size match the check pool size
while (checkPool.size() != itemPool.size()) {
diff --git a/mm/2s2h/Rando/MiscBehavior/Traps.cpp b/mm/2s2h/Rando/MiscBehavior/Traps.cpp
new file mode 100644
index 000000000..6a7528dc2
--- /dev/null
+++ b/mm/2s2h/Rando/MiscBehavior/Traps.cpp
@@ -0,0 +1,282 @@
+#include "Traps.h"
+#include <libultraship/bridge/consolevariablebridge.h>
+#include "MiscBehavior.h"
+#include "Rando/ActorBehavior/ActorBehavior.h"
+#include "2s2h/DeveloperTools/SaveEditor.h"
+
+extern "C" {
+#include "variables.h"
+#include "functions.h"
+#include "overlays/actors/ovl_En_Time_Tag/z_en_time_tag.h"
+void func_80833B18(PlayState* play, Player* thisx, s32 arg2, f32 speed, f32 velocityY, s16 arg5,
+ s32 invincibilityTimer);
+void EnTimeTag_KickOut_Transition(EnTimeTag* enTimeTag, PlayState* play);
+}
+
+#define MORNING_TIME 0x4000
+#define DAY_LENGTH 0x10000
+// Adjust so that 6 A.M. is 0 and 5:59 A.M. is 0xFFFF
+#define ZERO_DAY_START(time) (((u16)(time - MORNING_TIME) % DAY_LENGTH))
+
+extern void UpdateGameTime(u16 gameTime);
+
+int roll = TRAP_FREEZE;
+const u16 timeSkipInterval = 4000;
+
+std::map<TrapTypes, const char*> trapToCvarMap = {
+ { TRAP_FREEZE, "gRando.Traps.Freeze" }, { TRAP_BLAST, "gRando.Traps.Blast" },
+ { TRAP_SHOCK, "gRando.Traps.Shock" }, { TRAP_JINX, "gRando.Traps.Jinx" },
+ { TRAP_WALLET, "gRando.Traps.Wallet" }, { TRAP_ENEMY, "gRando.Traps.Enemy" },
+ { TRAP_TIME, "gRando.Traps.Time" },
+};
+
+std::vector<TrapTypes> getEnabledTrapTypes() {
+ std::vector<TrapTypes> enabledTrapTypes;
+ for (auto& trap : trapToCvarMap) {
+ if (CVarGetInteger(trap.second, 0)) {
+ enabledTrapTypes.push_back(trap.first);
+ }
+ }
+ if (enabledTrapTypes.size() == 0) {
+ enabledTrapTypes.push_back(TRAP_FREEZE);
+ }
+ return enabledTrapTypes;
+};
+
+int RollTrapType() {
+ auto enabledTraps = getEnabledTrapTypes();
+ roll = enabledTraps[rand() % enabledTraps.size()];
+ return roll;
+}
+
+// clang-format off
+std::vector<std::string> defaultTrapMessages = {
+ "This item is available in the %bRando DLC%w.",
+ "This is what happens when %gCaladius%w is left unsupervised.",
+ "Oh no!",
+ "Uh oh!",
+ "KEKW",
+ "We've been trying to reach you about your Horse's %gextended warranty%w.",
+ "Admit it, you wish this was %gGreg%w.",
+ "Error 404: Item Not Found",
+ "Get dunked on!",
+ "This %rTrap%w is brought to you by today's sponsor...\n%gRaid Shadow Legends%w!",
+};
+
+std::vector<std::string> freezeTrapMessages = {
+ "%rOcarina of Time%w called, they want their %bIce Trap%w back.",
+ "Greetings from %bSnowhead%w! Wish you were here.",
+ "This item was too %bcool%w for you anyway.",
+ "Let me see your best %bKing Zora%w impersonation.",
+ "There's no business like %bSnow%w business!",
+ "How much does a polar bear weigh? Enough to break the %bice%w.",
+ "You found the %yTrifo%w... Wait, nevermind...",
+ "Quick Time Event! Don't die.",
+};
+
+std::vector<std::string> blastTrapMessages = {
+ "Coming to you live from the %yThunderdome%w!",
+ "There was supposed to be an Earth shattering %yKaboom%w!",
+ "Pardon me while I %yburst%w.",
+ "This is not the greatest %yblast%w in the world, this is just a tribute.",
+ "Hey look, this %yitem%w is ticking!",
+ "This is sure to make %gPamela%w leave the house.",
+ "You found a %yDodongo Snack%w!",
+};
+
+std::vector<std::string> shockTrapMessages = {
+ "We're losing him!\n%gCLEAR%w",
+ "It's got what %gplants%w need.",
+ "On todays episode of Grey's Anatomy...",
+ "I'm giving it all I've got, captain!",
+ "Now simulating a CD in a Microwave.",
+ "Hang in there, for %gMeryl%w."
+};
+
+std::vector<std::string> jinxTrapMessages = {
+ "Looks like someone's got a case of the %bMondays%w. :( ",
+ "Your wrist hurts! The doctor says no more swords.",
+};
+
+std::vector<std::string> walletTrapMessages = {
+ "Spare some %rchange%w?",
+ "%rBreaking News%w: the Moon hasn't crashed, but Termina's economy sure has."
+};
+
+std::vector<std::string> enemyTrapMessages = {
+ "You made a new friend!",
+ // Like Like Specific, will need to adjust if new enemies are added.
+ "Someone likes you! They %rLike Like%w you!",
+ "You don't need a shield anyway.",
+ "This item sucks.",
+};
+
+std::vector<std::string> timeTrapMessages = {
+ "%yTime%w flashes before your eyes!",
+ "You have played the %ySun's Song%w!",
+ "The %rGoddess of Time%w smites you!",
+ "Spent an hour and a half admiring this %bfake item%w.",
+ "You found a great place to take a nap!",
+ "Break time! Not like the world is ending right?",
+ "I just need you to tell me how to get to the %ytime machine%w.",
+ "Mweep",
+};
+
+std::map<TrapTypes, std::vector<std::string>> trapMessageList = {
+ { TRAP_FREEZE, freezeTrapMessages },
+ { TRAP_BLAST, blastTrapMessages },
+ { TRAP_SHOCK, shockTrapMessages },
+ { TRAP_JINX, jinxTrapMessages },
+ { TRAP_WALLET, walletTrapMessages },
+ { TRAP_ENEMY, enemyTrapMessages },
+ { TRAP_TIME, timeTrapMessages },
+};
+// clang-format on
+
+std::string GetTrapMessage() {
+ RollTrapType();
+ auto findIt = trapMessageList.find((TrapTypes)roll);
+ if (findIt == trapMessageList.end()) {
+ return defaultTrapMessages[rand() % defaultTrapMessages.size()];
+ } else {
+ return findIt->second[rand() % findIt->second.size()];
+ }
+}
+
+void Rando::MiscBehavior::OfferTrapItem() {
+ if (!gPlayState) {
+ return;
+ }
+
+ switch (roll) {
+ case TRAP_FREEZE:
+ GameInteractor::Instance->events.emplace_back(
+ GIEventTrap{ .action = []() { func_80833B18(gPlayState, GET_PLAYER(gPlayState), 3, 0, 0, 0, 0); } });
+ break;
+ case TRAP_BLAST:
+ GameInteractor::Instance->events.emplace_back(GIEventTrap{ .action = []() {
+ Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_BOM, GET_PLAYER(gPlayState)->actor.world.pos.x,
+ GET_PLAYER(gPlayState)->actor.world.pos.y, GET_PLAYER(gPlayState)->actor.world.pos.z, 1, 0,
+ 0, 0);
+ } });
+ break;
+ case TRAP_SHOCK:
+ GameInteractor::Instance->events.emplace_back(
+ GIEventTrap{ .action = []() { func_80833B18(gPlayState, GET_PLAYER(gPlayState), 4, 0, 0, 0, 0); } });
+ break;
+ case TRAP_JINX:
+ GameInteractor::Instance->events.emplace_back(GIEventTrap{ .action = []() {
+ Actor_PlaySfx(&GET_PLAYER(gPlayState)->actor, NA_SE_EN_BUBLE_BITE);
+ gSaveContext.jinxTimer = 1200;
+ } });
+ break;
+ case TRAP_WALLET:
+ GameInteractor::Instance->events.emplace_back(GIEventTrap{ .action = []() {
+ int16_t currentRupees = gSaveContext.save.saveInfo.playerData.rupees;
+ if (currentRupees != 0) {
+ Vec3f positional = GET_PLAYER(gPlayState)->actor.world.pos;
+ positional.y = GET_PLAYER(gPlayState)->actor.world.pos.y + 100.0f;
+ Item00Type rupee = ITEM00_RUPEE_GREEN;
+ int16_t spawnedRupees = 0;
+ int16_t remainingRupees = currentRupees;
+ for (int i = spawnedRupees; spawnedRupees < remainingRupees;) {
+ if (currentRupees >= 20) {
+ rupee = ITEM00_RUPEE_RED;
+ spawnedRupees += 20;
+ Rupees_ChangeBy(-20);
+ currentRupees -= 20;
+ } else if (currentRupees >= 5) {
+ rupee = ITEM00_RUPEE_BLUE;
+ spawnedRupees += 5;
+ Rupees_ChangeBy(-5);
+ currentRupees -= 5;
+ } else if (currentRupees >= 1) {
+ rupee = ITEM00_RUPEE_GREEN;
+ spawnedRupees += 1;
+ Rupees_ChangeBy(-1);
+ currentRupees -= 1;
+ }
+ EnItem00* rupeeActor = (EnItem00*)Item_DropCollectible(gPlayState, &positional, rupee);
+ rupeeActor->actor.speed = Rand_CenteredFloat(5.0f);
+ rupeeActor->unk152 = 600; // Extending Time before Despawning
+ }
+ }
+ } });
+ break;
+ case TRAP_ENEMY:
+ GameInteractor::Instance->events.emplace_back(GIEventTrap{ .action = []() {
+ Actor_Spawn(&gPlayState->actorCtx, gPlayState, ACTOR_EN_RR, GET_PLAYER(gPlayState)->actor.world.pos.x,
+ GET_PLAYER(gPlayState)->actor.world.pos.y, GET_PLAYER(gPlayState)->actor.world.pos.z, 0, 0,
+ 0, 1);
+ } });
+ break;
+ case TRAP_TIME:
+ GameInteractor::Instance->events.emplace_back(GIEventTrap{ .action = []() {
+ u16 previous_time = gSaveContext.save.time;
+ u16 new_time = gSaveContext.save.time + timeSkipInterval;
+ if (previous_time < MORNING_TIME && new_time >= MORNING_TIME) {
+ // Handles case where Night -> Day
+ if (gSaveContext.save.day != 3) {
+ gSaveContext.save.day++;
+ gSaveContext.save.eventDayCount++;
+ UpdateGameTime(new_time);
+ Interface_NewDay(gPlayState, CURRENT_DAY);
+ // Load environment values for new day
+ Environment_NewDay(&gPlayState->envCtx);
+ // Clear weather from day 2
+ gWeatherMode = WEATHER_MODE_CLEAR;
+ gPlayState->envCtx.lightningState = LIGHTNING_OFF;
+ } else {
+ // Handles Moonfall case, prevents skipping past it by setting time right before Moonfall.
+ UpdateGameTime(MORNING_TIME - (timeSkipInterval / 10));
+ }
+ } else {
+ // Every other case
+ UpdateGameTime(new_time);
+ }
+ TransitionFade_SetColor(&gPlayState->unk_18E48, 0x000000);
+ R_TRANS_FADE_FLASH_ALPHA_STEP = -1;
+ Player_PlaySfx(GET_PLAYER(gPlayState), NA_SE_SY_TRANSFORM_MASK_FLASH);
+
+ // Handle kickouts, if needed
+ EnTimeTag* enTimeTag = (EnTimeTag*)Actor_FindNearby(gPlayState, &GET_PLAYER(gPlayState)->actor,
+ ACTOR_EN_TIME_TAG, ACTORCAT_ITEMACTION, 99999.9f);
+ if (enTimeTag != nullptr) {
+ TimeTagType timeTagType = (TimeTagType)TIMETAG_GET_TYPE(&enTimeTag->actor);
+ if (timeTagType == TIMETAG_KICKOUT_DOOR || timeTagType >= TIMETAG_KICKOUT_FINAL_HOURS) {
+ s16 kickoutHour = TIMETAG_KICKOUT_HOUR(&enTimeTag->actor);
+ s16 kickoutMinute = TIMETAG_KICKOUT_MINUTE(&enTimeTag->actor);
+ s32 kickoutTime = CLOCK_TIME(kickoutHour, kickoutMinute);
+ kickoutTime = ZERO_DAY_START(kickoutTime);
+ previous_time = ZERO_DAY_START(previous_time);
+ new_time = ZERO_DAY_START(new_time);
+ // If we were here before the kickout time, and now it's after, then get out of my house
+ if (previous_time <= kickoutTime && new_time >= kickoutTime) {
+ // Unless this is the Stock Pot Inn, and the room key is obtained
+ if (!(gPlayState->sceneId == SCENE_YADOYA &&
+ Flags_GetRandoInf(RANDO_INF_OBTAINED_ROOM_KEY))) {
+ // This comes from EnTimeTag_KickOut_WaitForTime
+ Player_SetCsActionWithHaltedActors(gPlayState, &enTimeTag->actor, PLAYER_CSACTION_WAIT);
+ Message_StartTextbox(gPlayState, 0x1883 + TIMETAG_KICKOUT_GET_TEXT(&enTimeTag->actor),
+ NULL);
+ enTimeTag->actionFunc = EnTimeTag_KickOut_Transition;
+ }
+ }
+ }
+ }
+ } });
+ break;
+ default:
+ break;
+ }
+}
+
+void Rando::ActorBehavior::InitTrapsBehavior() {
+ // Selectively disable object dependency for actors spawned by traps
+ COND_VB_SHOULD(VB_ENABLE_OBJECT_DEPENDENCY, IS_RANDO && RANDO_SAVE_OPTIONS[RO_SHUFFLE_TRAPS], {
+ ObjectId objectId = (ObjectId)va_arg(args, int);
+ if (objectId == OBJECT_RR) { // Like-Like
+ *should = false;
+ }
+ });
+} \ No newline at end of file
diff --git a/mm/2s2h/Rando/MiscBehavior/Traps.h b/mm/2s2h/Rando/MiscBehavior/Traps.h
new file mode 100644
index 000000000..a842c2462
--- /dev/null
+++ b/mm/2s2h/Rando/MiscBehavior/Traps.h
@@ -0,0 +1,10 @@
+#ifndef RANDO_TRAP_H
+#define RANDO_TRAP_H
+
+#include "Rando/Rando.h"
+typedef enum { TRAP_FREEZE, TRAP_BLAST, TRAP_SHOCK, TRAP_JINX, TRAP_WALLET, TRAP_ENEMY, TRAP_TIME, TRAP_MAX } TrapTypes;
+
+extern int RollTrapType();
+extern std::string GetTrapMessage();
+
+#endif \ No newline at end of file
diff --git a/mm/2s2h/Rando/StaticData/Items.cpp b/mm/2s2h/Rando/StaticData/Items.cpp
index 2173d519c..0b6644884 100644
--- a/mm/2s2h/Rando/StaticData/Items.cpp
+++ b/mm/2s2h/Rando/StaticData/Items.cpp
@@ -187,6 +187,7 @@ std::map<RandoItemId, RandoStaticItem> Items = {
RI(RI_TINGLE_MAP_SNOWHEAD, "", "Tingle's Snowhead Map", RITYPE_LESSER, ITEM_TINGLE_MAP, GI_TINGLE_MAP_SNOWHEAD, GID_TINGLE_MAP),
RI(RI_TINGLE_MAP_STONE_TOWER, "", "Tingle's Stone Tower Map", RITYPE_LESSER, ITEM_TINGLE_MAP, GI_TINGLE_MAP_STONE_TOWER, GID_TINGLE_MAP),
RI(RI_TINGLE_MAP_WOODFALL, "", "Tingle's Woodfall Map", RITYPE_LESSER, ITEM_TINGLE_MAP, GI_TINGLE_MAP_WOODFALL, GID_TINGLE_MAP),
+ RI(RI_TRAP, "a", "Knockoff Item", RITYPE_LESSER, ITEM_NONE, GI_NONE, GID_NONE),
RI(RI_TRIFORCE_PIECE, "a", "Piece of the Triforce", RITYPE_MAJOR, ITEM_NONE, GI_NONE, GID_NONE),
RI(RI_TRIFORCE_PIECE_PREVIOUS, "a", "Piece of the Triforce", RITYPE_MAJOR, ITEM_NONE, GI_NONE, GID_NONE), // This only exists to aid in the drawing of unique models, it has no use outside of that.
RI(RI_WALLET_ADULT, "the", "Adult's Wallet", RITYPE_MAJOR, ITEM_WALLET_ADULT, GI_WALLET_ADULT, GID_WALLET_ADULT),
diff --git a/mm/2s2h/Rando/StaticData/Options.cpp b/mm/2s2h/Rando/StaticData/Options.cpp
index b7d40747f..16410bc14 100644
--- a/mm/2s2h/Rando/StaticData/Options.cpp
+++ b/mm/2s2h/Rando/StaticData/Options.cpp
@@ -23,6 +23,7 @@ std::map<RandoOptionId, RandoStaticOption> Options = {
RO(RO_HINTS_OATH_TO_ORDER, RO_GENERIC_OFF),
RO(RO_HINTS_PURCHASEABLE, RO_GENERIC_OFF),
RO(RO_HINTS_SPIDER_HOUSES, RO_GENERIC_OFF),
+ RO(RO_TRAP_AMOUNT, 5),
RO(RO_LOGIC, RO_LOGIC_GLITCHLESS),
RO(RO_MINIMUM_STRAY_FAIRIES, STRAY_FAIRY_SCATTERED_TOTAL),
RO(RO_PLENTIFUL_ITEMS, RO_GENERIC_OFF),
@@ -36,6 +37,7 @@ std::map<RandoOptionId, RandoStaticOption> Options = {
RO(RO_SHUFFLE_FROGS, RO_GENERIC_OFF),
RO(RO_SHUFFLE_GOLD_SKULLTULAS, RO_GENERIC_OFF),
RO(RO_SHUFFLE_GRASS_DROPS, RO_GENERIC_OFF),
+ RO(RO_SHUFFLE_TRAPS, RO_GENERIC_OFF),
RO(RO_SHUFFLE_OWL_STATUES, RO_GENERIC_OFF),
RO(RO_SHUFFLE_POT_DROPS, RO_GENERIC_OFF),
RO(RO_SHUFFLE_SHOPS, RO_GENERIC_OFF),
diff --git a/mm/2s2h/Rando/StaticData/StaticData.h b/mm/2s2h/Rando/StaticData/StaticData.h
index b072f31f3..858c43716 100644
--- a/mm/2s2h/Rando/StaticData/StaticData.h
+++ b/mm/2s2h/Rando/StaticData/StaticData.h
@@ -53,6 +53,7 @@ u8 GetIconForZMessage(RandoItemId itemId);
const char* GetIconTexturePath(RandoItemId itemId);
bool ShouldShowGetItemCutscene(RandoItemId itemId);
std::string GetItemName(RandoItemId randoItemId, bool includeArticle = true);
+std::string GetTrapMessage();
struct RandoStaticOption {
RandoOptionId randoOptionId;
diff --git a/mm/2s2h/Rando/Types.h b/mm/2s2h/Rando/Types.h
index 55f72831d..297749727 100644
--- a/mm/2s2h/Rando/Types.h
+++ b/mm/2s2h/Rando/Types.h
@@ -2455,6 +2455,7 @@ typedef enum {
RI_TINGLE_MAP_SNOWHEAD,
RI_TINGLE_MAP_STONE_TOWER,
RI_TINGLE_MAP_WOODFALL,
+ RI_TRAP,
RI_TRIFORCE_PIECE,
RI_TRIFORCE_PIECE_PREVIOUS,
RI_WALLET_ADULT,
@@ -2464,6 +2465,7 @@ typedef enum {
RI_WOODFALL_MAP,
RI_WOODFALL_SMALL_KEY,
RI_WOODFALL_STRAY_FAIRY,
+ RI_MAX_TRAP,
RI_MAX,
} RandoItemId;
@@ -2785,6 +2787,7 @@ typedef enum {
RO_HINTS_OATH_TO_ORDER,
RO_HINTS_PURCHASEABLE,
RO_HINTS_SPIDER_HOUSES,
+ RO_TRAP_AMOUNT,
RO_LOGIC,
RO_MINIMUM_STRAY_FAIRIES,
RO_PLENTIFUL_ITEMS,
@@ -2798,6 +2801,7 @@ typedef enum {
RO_SHUFFLE_FROGS,
RO_SHUFFLE_GRASS_DROPS,
RO_SHUFFLE_GOLD_SKULLTULAS,
+ RO_SHUFFLE_TRAPS,
RO_SHUFFLE_OWL_STATUES,
RO_SHUFFLE_POT_DROPS,
RO_SHUFFLE_SHOPS,
diff --git a/mm/assets/2s2h_assets.h b/mm/assets/2s2h_assets.h
index 0ddb4497e..f19690152 100644
--- a/mm/assets/2s2h_assets.h
+++ b/mm/assets/2s2h_assets.h
@@ -385,3 +385,6 @@ static const ALIGN_ASSET(2) char gTriforcePiece2DL[] = dgTriforcePiece2DL;
#define dgTriforcePieceCompletedDL "__OTR__objects/object_triforce_completed/gTriforcePieceCompletedDL"
static const ALIGN_ASSET(2) char gTriforcePieceCompletedDL[] = dgTriforcePieceCompletedDL;
+
+#define dgTrapDL "__OTR__objects/object_trap/gTrapDL"
+static const ALIGN_ASSET(2) char gTrapDL[] = dgTrapDL;
diff --git a/mm/assets/custom/objects/object_trap/gTrapDL b/mm/assets/custom/objects/object_trap/gTrapDL
new file mode 100644
index 000000000..5ba726a43
--- /dev/null
+++ b/mm/assets/custom/objects/object_trap/gTrapDL
@@ -0,0 +1,11 @@
+<DisplayList Version="0">
+ <CallDisplayList Path="objects/object_trap/mat_object_trap_model_ice"/>
+ <CallDisplayList Path="objects/object_trap/object_trap_model_tri_0"/>
+ <PipeSync/>
+ <SetGeometryMode G_LIGHTING="1" />
+ <ClearGeometryMode G_TEXTURE_GEN="1" />
+ <SetCombineLERP A0="G_CCMUX_0" B0="G_CCMUX_0" C0="G_CCMUX_0" D0="G_CCMUX_SHADE" Aa0="G_ACMUX_0" Ab0="G_ACMUX_0" Ac0="G_ACMUX_0" Ad0="G_ACMUX_ENVIRONMENT" A1="G_CCMUX_0" B1="G_CCMUX_0" C1="G_CCMUX_0" D1="G_CCMUX_SHADE" Aa1="G_ACMUX_0" Ab1="G_ACMUX_0" Ac1="G_ACMUX_0" Ad1="G_ACMUX_ENVIRONMENT"/>
+ <Texture S="65535" T="65535" Level="0" Tile="0" On="0"/>
+ <EndDisplayList/>
+</DisplayList>
+
diff --git a/mm/assets/custom/objects/object_trap/ice_2 b/mm/assets/custom/objects/object_trap/ice_2
new file mode 100644
index 000000000..671d0a95f
--- /dev/null
+++ b/mm/assets/custom/objects/object_trap/ice_2
Binary files differ
diff --git a/mm/assets/custom/objects/object_trap/mat_object_trap_model_ice b/mm/assets/custom/objects/object_trap/mat_object_trap_model_ice
new file mode 100644
index 000000000..26fb276cc
--- /dev/null
+++ b/mm/assets/custom/objects/object_trap/mat_object_trap_model_ice
@@ -0,0 +1,21 @@
+<DisplayList Version="0">
+ <PipeSync/>
+ <SetCombineLERP A0="G_CCMUX_0" B0="G_CCMUX_0" C0="G_CCMUX_0" D0="G_CCMUX_TEXEL0" Aa0="G_ACMUX_0" Ab0="G_ACMUX_0" Ac0="G_ACMUX_0" Ad0="G_ACMUX_1" A1="G_CCMUX_COMBINED" B1="G_CCMUX_0" C1="G_CCMUX_PRIMITIVE" D1="G_CCMUX_0" Aa1="G_ACMUX_0" Ab1="G_ACMUX_0" Ac1="G_ACMUX_0" Ad1="G_ACMUX_COMBINED"/>
+ <SetGeometryMode G_ZBUFFER="1" G_SHADE="1" G_CULL_BACK="1" G_FOG="1" G_LIGHTING="1" G_SHADING_SMOOTH="1" />
+ <ClearGeometryMode G_CULL_FRONT="1" G_TEXTURE_GEN="1" G_TEXTURE_GEN_LINEAR="1" />
+ <SetOtherMode Cmd="G_SETOTHERMODE_H" Sft="4" Length="20" G_AD_NOISE="1" G_CD_MAGICSQ="1" G_CK_NONE="1" G_TC_FILT="1" G_TF_BILERP="1" G_TL_TILE="1" G_TD_CLAMP="1" G_TP_PERSP="1" G_CYC_2CYCLE="1" G_PM_NPRIMITIVE="1" />
+ <SetOtherMode Cmd="G_SETOTHERMODE_L" Sft="0" Length="32" G_AC_NONE="1" G_ZS_PIXEL="1" G_RM_FOG_SHADE_A="1" G_RM_AA_ZB_OPA_SURF2="1" />
+ <Texture S="65535" T="65535" Level="0" Tile="0" On="1"/>
+ <SetTextureLUT Mode="G_TT_NONE"/>
+ <TileSync/>
+ <SetTextureImage Path="objects/object_trap/ice_2" Format="G_IM_FMT_IA" Size="G_IM_SIZ_8b_LOAD_BLOCK" Width="1"/>
+ <SetTile Format="G_IM_FMT_IA" Size="G_IM_SIZ_8b_LOAD_BLOCK" Line="0" TMem="0" Tile="7" Palette="0" Cms0="G_TX_WRAP" Cms1="G_TX_NOMIRROR" Cmt0="G_TX_WRAP" Cmt1="G_TX_NOMIRROR" MaskS="6" ShiftS="0" MaskT="6" ShiftT="0"/>
+ <LoadSync/>
+ <LoadBlock Tile="7" Uls="0" Ult="0" Lrs="2047" Dxt="256"/>
+ <PipeSync/>
+ <SetTile Format="G_IM_FMT_IA" Size="G_IM_SIZ_8b" Line="8" TMem="0" Tile="0" Palette="0" Cms0="G_TX_WRAP" Cms1="G_TX_NOMIRROR" Cmt0="G_TX_WRAP" Cmt1="G_TX_NOMIRROR" MaskS="6" ShiftS="0" MaskT="6" ShiftT="0"/>
+ <SetTileSize T="0" Uls="0" Ult="0" Lrs="252" Lrt="252"/>
+ <SetPrimColor M="0" L="0" R="99" G="178" B="185" A="255"/>
+ <EndDisplayList/>
+</DisplayList>
+
diff --git a/mm/assets/custom/objects/object_trap/object_trap_model_tri_0 b/mm/assets/custom/objects/object_trap/object_trap_model_tri_0
new file mode 100644
index 000000000..fb46fa598
--- /dev/null
+++ b/mm/assets/custom/objects/object_trap/object_trap_model_tri_0
@@ -0,0 +1,158 @@
+<DisplayList Version="0">
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="0" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="1" V01="3" V02="2"/>
+ <Triangle1 V00="1" V01="4" V02="3"/>
+ <Triangle1 V00="5" V01="3" V02="4"/>
+ <Triangle1 V00="5" V01="6" V02="3"/>
+ <Triangle1 V00="7" V01="6" V02="5"/>
+ <Triangle1 V00="7" V01="8" V02="6"/>
+ <Triangle1 V00="7" V01="9" V02="8"/>
+ <Triangle1 V00="7" V01="10" V02="9"/>
+ <Triangle1 V00="10" V01="11" V02="9"/>
+ <Triangle1 V00="10" V01="12" V02="11"/>
+ <Triangle1 V00="13" V01="11" V02="12"/>
+ <Triangle1 V00="13" V01="14" V02="11"/>
+ <Triangle1 V00="0" V01="14" V02="13"/>
+ <Triangle1 V00="0" V01="15" V02="14"/>
+ <Triangle1 V00="0" V01="2" V02="15"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="16" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="2" V01="1" V02="3"/>
+ <Triangle1 V00="4" V01="2" V02="3"/>
+ <Triangle1 V00="5" V01="2" V02="4"/>
+ <Triangle1 V00="5" V01="6" V02="2"/>
+ <Triangle1 V00="2" V01="6" V02="7"/>
+ <Triangle1 V00="8" V01="2" V02="7"/>
+ <Triangle1 V00="0" V01="2" V02="8"/>
+ <Triangle1 V00="9" V01="10" V02="11"/>
+ <Triangle1 V00="9" V01="12" V02="10"/>
+ <Triangle1 V00="9" V01="13" V02="12"/>
+ <Triangle1 V00="9" V01="14" V02="13"/>
+ <Triangle1 V00="14" V01="15" V02="13"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="32" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="3" V01="2" V02="1"/>
+ <Triangle1 V00="3" V01="4" V02="2"/>
+ <Triangle1 V00="5" V01="4" V02="3"/>
+ <Triangle1 V00="5" V01="6" V02="4"/>
+ <Triangle1 V00="5" V01="7" V02="6"/>
+ <Triangle1 V00="5" V01="8" V02="7"/>
+ <Triangle1 V00="8" V01="9" V02="7"/>
+ <Triangle1 V00="8" V01="10" V02="9"/>
+ <Triangle1 V00="11" V01="9" V02="10"/>
+ <Triangle1 V00="11" V01="12" V02="9"/>
+ <Triangle1 V00="12" V01="13" V02="9"/>
+ <Triangle1 V00="14" V01="13" V02="12"/>
+ <Triangle1 V00="14" V01="15" V02="13"/>
+ <Triangle1 V00="13" V01="15" V02="2"/>
+ <Triangle1 V00="4" V01="13" V02="2"/>
+ <Triangle1 V00="6" V01="13" V02="4"/>
+ <Triangle1 V00="6" V01="7" V02="13"/>
+ <Triangle1 V00="13" V01="7" V02="9"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="48" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="0" V01="3" V02="1"/>
+ <Triangle1 V00="0" V01="4" V02="3"/>
+ <Triangle1 V00="0" V01="5" V02="4"/>
+ <Triangle1 V00="5" V01="6" V02="4"/>
+ <Triangle1 V00="5" V01="7" V02="6"/>
+ <Triangle1 V00="8" V01="6" V02="7"/>
+ <Triangle1 V00="8" V01="9" V02="6"/>
+ <Triangle1 V00="10" V01="9" V02="8"/>
+ <Triangle1 V00="10" V01="8" V02="11"/>
+ <Triangle1 V00="8" V01="12" V02="11"/>
+ <Triangle1 V00="8" V01="13" V02="12"/>
+ <Triangle1 V00="14" V01="12" V02="13"/>
+ <Triangle1 V00="14" V01="15" V02="12"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="64" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="0" V01="3" V02="1"/>
+ <Triangle1 V00="0" V01="4" V02="3"/>
+ <Triangle1 V00="0" V01="5" V02="4"/>
+ <Triangle1 V00="5" V01="6" V02="4"/>
+ <Triangle1 V00="5" V01="7" V02="6"/>
+ <Triangle1 V00="8" V01="6" V02="7"/>
+ <Triangle1 V00="8" V01="9" V02="6"/>
+ <Triangle1 V00="10" V01="9" V02="8"/>
+ <Triangle1 V00="10" V01="8" V02="11"/>
+ <Triangle1 V00="8" V01="12" V02="11"/>
+ <Triangle1 V00="8" V01="13" V02="12"/>
+ <Triangle1 V00="14" V01="12" V02="13"/>
+ <Triangle1 V00="14" V01="15" V02="12"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="80" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="0" V01="3" V02="1"/>
+ <Triangle1 V00="0" V01="4" V02="3"/>
+ <Triangle1 V00="0" V01="5" V02="4"/>
+ <Triangle1 V00="6" V01="3" V02="4"/>
+ <Triangle1 V00="6" V01="1" V02="3"/>
+ <Triangle1 V00="6" V01="7" V02="1"/>
+ <Triangle1 V00="8" V01="7" V02="6"/>
+ <Triangle1 V00="8" V01="6" V02="9"/>
+ <Triangle1 V00="6" V01="4" V02="9"/>
+ <Triangle1 V00="10" V01="11" V02="12"/>
+ <Triangle1 V00="10" V01="12" V02="13"/>
+ <Triangle1 V00="14" V01="13" V02="12"/>
+ <Triangle1 V00="14" V01="12" V02="15"/>
+ <Triangle1 V00="8" V01="14" V02="15"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="96" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="2" V01="1" V02="3"/>
+ <Triangle1 V00="2" V01="3" V02="4"/>
+ <Triangle1 V00="5" V01="4" V02="3"/>
+ <Triangle1 V00="5" V01="3" V02="6"/>
+ <Triangle1 V00="7" V01="8" V02="9"/>
+ <Triangle1 V00="10" V01="9" V02="8"/>
+ <Triangle1 V00="10" V01="11" V02="9"/>
+ <Triangle1 V00="12" V01="11" V02="10"/>
+ <Triangle1 V00="12" V01="13" V02="11"/>
+ <Triangle1 V00="12" V01="14" V02="13"/>
+ <Triangle1 V00="12" V01="15" V02="14"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="112" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="0" V01="3" V02="1"/>
+ <Triangle1 V00="4" V01="1" V02="3"/>
+ <Triangle1 V00="4" V01="5" V02="1"/>
+ <Triangle1 V00="6" V01="5" V02="4"/>
+ <Triangle1 V00="6" V01="4" V02="7"/>
+ <Triangle1 V00="4" V01="8" V02="7"/>
+ <Triangle1 V00="4" V01="9" V02="8"/>
+ <Triangle1 V00="10" V01="8" V02="9"/>
+ <Triangle1 V00="10" V01="11" V02="8"/>
+ <Triangle1 V00="12" V01="11" V02="10"/>
+ <Triangle1 V00="12" V01="13" V02="11"/>
+ <Triangle1 V00="12" V01="14" V02="13"/>
+ <Triangle1 V00="12" V01="15" V02="14"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="128" Count="16"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="0" V01="3" V02="1"/>
+ <Triangle1 V00="4" V01="1" V02="3"/>
+ <Triangle1 V00="4" V01="5" V02="1"/>
+ <Triangle1 V00="6" V01="5" V02="4"/>
+ <Triangle1 V00="6" V01="4" V02="7"/>
+ <Triangle1 V00="4" V01="8" V02="7"/>
+ <Triangle1 V00="9" V01="7" V02="8"/>
+ <Triangle1 V00="9" V01="8" V02="10"/>
+ <Triangle1 V00="11" V01="10" V02="8"/>
+ <Triangle1 V00="11" V01="8" V02="12"/>
+ <Triangle1 V00="11" V01="13" V02="10"/>
+ <Triangle1 V00="11" V01="14" V02="13"/>
+ <Triangle1 V00="9" V01="10" V02="13"/>
+ <Triangle1 V00="9" V01="13" V02="15"/>
+ <Triangle1 V00="6" V01="9" V02="15"/>
+ <Triangle1 V00="6" V01="7" V02="9"/>
+ <LoadVertices Path="objects/object_trap/object_trap_model_vtx_0" VertexBufferIndex="0" VertexOffset="144" Count="10"/>
+ <Triangle1 V00="0" V01="1" V02="2"/>
+ <Triangle1 V00="0" V01="2" V02="3"/>
+ <Triangle1 V00="4" V01="3" V02="2"/>
+ <Triangle1 V00="4" V01="2" V02="5"/>
+ <Triangle1 V00="6" V01="4" V02="5"/>
+ <Triangle1 V00="6" V01="7" V02="4"/>
+ <Triangle1 V00="4" V01="7" V02="8"/>
+ <Triangle1 V00="4" V01="8" V02="3"/>
+ <Triangle1 V00="0" V01="3" V02="8"/>
+ <Triangle1 V00="0" V01="8" V02="9"/>
+ <EndDisplayList/>
+</DisplayList>
+
diff --git a/mm/assets/custom/objects/object_trap/object_trap_model_vtx_0 b/mm/assets/custom/objects/object_trap/object_trap_model_vtx_0
new file mode 100644
index 000000000..6ffc4dfe3
--- /dev/null
+++ b/mm/assets/custom/objects/object_trap/object_trap_model_vtx_0
@@ -0,0 +1,156 @@
+<Vertex Version="0">
+ <Vtx X="0" Y="240" Z="-540" S="1008" T="92" R="0" G="115" B="202" A="255"/>
+ <Vtx X="-545" Y="240" Z="-546" S="83" T="82" R="185" G="79" B="185" A="255"/>
+ <Vtx X="-468" Y="275" Z="-468" S="214" T="214" R="235" G="124" B="236" A="255"/>
+ <Vtx X="-468" Y="275" Z="0" S="214" T="1008" R="229" G="124" B="0" A="255"/>
+ <Vtx X="-540" Y="240" Z="0" S="92" T="1008" R="202" G="115" B="0" A="255"/>
+ <Vtx X="-545" Y="240" Z="546" S="83" T="1934" R="185" G="79" B="71" A="255"/>
+ <Vtx X="-468" Y="275" Z="468" S="214" T="1802" R="235" G="124" B="20" A="255"/>
+ <Vtx X="0" Y="240" Z="540" S="1008" T="1924" R="0" G="115" B="54" A="255"/>
+ <Vtx X="0" Y="275" Z="468" S="1008" T="1802" R="0" G="124" B="27" A="255"/>
+ <Vtx X="468" Y="275" Z="468" S="1802" T="1802" R="21" G="124" B="20" A="255"/>
+ <Vtx X="545" Y="240" Z="546" S="1933" T="1934" R="71" G="79" B="71" A="255"/>
+ <Vtx X="468" Y="275" Z="0" S="1802" T="1008" R="27" G="124" B="0" A="255"/>
+ <Vtx X="540" Y="240" Z="0" S="1924" T="1008" R="54" G="115" B="0" A="255"/>
+ <Vtx X="545" Y="240" Z="-546" S="1933" T="82" R="71" G="79" B="185" A="255"/>
+ <Vtx X="468" Y="275" Z="-468" S="1802" T="214" R="21" G="124" B="236" A="255"/>
+ <Vtx X="0" Y="275" Z="-468" S="1008" T="214" R="0" G="124" B="229" A="255"/>
+ <Vtx X="0" Y="275" Z="-468" S="1008" T="214" R="0" G="124" B="229" A="255"/>
+ <Vtx X="-468" Y="275" Z="-468" S="214" T="214" R="235" G="124" B="236" A="255"/>
+ <Vtx X="0" Y="275" Z="0" S="1008" T="1008" R="0" G="127" B="0" A="255"/>
+ <Vtx X="-468" Y="275" Z="0" S="214" T="1008" R="229" G="124" B="0" A="255"/>
+ <Vtx X="-468" Y="275" Z="468" S="214" T="1802" R="235" G="124" B="20" A="255"/>
+ <Vtx X="0" Y="275" Z="468" S="1008" T="1802" R="0" G="124" B="27" A="255"/>
+ <Vtx X="468" Y="275" Z="468" S="1802" T="1802" R="21" G="124" B="20" A="255"/>
+ <Vtx X="468" Y="275" Z="0" S="1802" T="1008" R="27" G="124" B="0" A="255"/>
+ <Vtx X="468" Y="275" Z="-468" S="1802" T="214" R="21" G="124" B="236" A="255"/>
+ <Vtx X="0" Y="-840" Z="-540" S="1008" T="92" R="0" G="141" B="202" A="255"/>
+ <Vtx X="-468" Y="-875" Z="-468" S="214" T="214" R="235" G="132" B="236" A="255"/>
+ <Vtx X="-545" Y="-840" Z="-546" S="83" T="82" R="185" G="177" B="185" A="255"/>
+ <Vtx X="0" Y="-875" Z="-468" S="1008" T="214" R="0" G="132" B="229" A="255"/>
+ <Vtx X="468" Y="-875" Z="-468" S="1802" T="214" R="21" G="132" B="236" A="255"/>
+ <Vtx X="545" Y="-840" Z="-546" S="1933" T="82" R="71" G="177" B="185" A="255"/>
+ <Vtx X="468" Y="-875" Z="0" S="1802" T="1008" R="27" G="132" B="0" A="255"/>
+ <Vtx X="545" Y="-840" Z="-546" S="1933" T="82" R="71" G="177" B="185" A="255"/>
+ <Vtx X="540" Y="-840" Z="0" S="1924" T="1008" R="54" G="141" B="0" A="255"/>
+ <Vtx X="468" Y="-875" Z="0" S="1802" T="1008" R="27" G="132" B="0" A="255"/>
+ <Vtx X="545" Y="-840" Z="546" S="1933" T="1934" R="71" G="177" B="71" A="255"/>
+ <Vtx X="468" Y="-875" Z="468" S="1802" T="1802" R="21" G="132" B="20" A="255"/>
+ <Vtx X="0" Y="-840" Z="540" S="1008" T="1924" R="0" G="141" B="54" A="255"/>
+ <Vtx X="0" Y="-875" Z="468" S="1008" T="1802" R="0" G="132" B="27" A="255"/>
+ <Vtx X="-468" Y="-875" Z="468" S="214" T="1802" R="235" G="132" B="20" A="255"/>
+ <Vtx X="-545" Y="-840" Z="546" S="83" T="1934" R="185" G="177" B="71" A="255"/>
+ <Vtx X="-468" Y="-875" Z="0" S="214" T="1008" R="229" G="132" B="0" A="255"/>
+ <Vtx X="-540" Y="-840" Z="0" S="92" T="1008" R="202" G="141" B="0" A="255"/>
+ <Vtx X="-545" Y="-840" Z="-546" S="83" T="82" R="185" G="177" B="185" A="255"/>
+ <Vtx X="-468" Y="-875" Z="-468" S="214" T="214" R="235" G="132" B="236" A="255"/>
+ <Vtx X="0" Y="-875" Z="0" S="1008" T="1008" R="0" G="129" B="0" A="255"/>
+ <Vtx X="0" Y="-875" Z="-468" S="1008" T="214" R="0" G="132" B="229" A="255"/>
+ <Vtx X="468" Y="-875" Z="-468" S="1802" T="214" R="21" G="132" B="236" A="255"/>
+ <Vtx X="546" Y="-300" Z="546" S="1933" T="1008" R="90" G="0" B="90" A="255"/>
+ <Vtx X="486" Y="-786" Z="586" S="1832" T="1832" R="28" G="223" B="119" A="255"/>
+ <Vtx X="545" Y="-840" Z="546" S="1933" T="1924" R="71" G="177" B="71" A="255"/>
+ <Vtx X="486" Y="-300" Z="586" S="1832" T="1008" R="37" G="0" B="122" A="255"/>
+ <Vtx X="486" Y="186" Z="586" S="1832" T="184" R="28" G="33" B="119" A="255"/>
+ <Vtx X="545" Y="240" Z="546" S="1933" T="92" R="71" G="79" B="71" A="255"/>
+ <Vtx X="0" Y="186" Z="586" S="1008" T="184" R="0" G="42" B="120" A="255"/>
+ <Vtx X="0" Y="240" Z="540" S="1008" T="92" R="0" G="80" B="99" A="255"/>
+ <Vtx X="-545" Y="240" Z="546" S="83" T="92" R="185" G="79" B="71" A="255"/>
+ <Vtx X="-486" Y="186" Z="586" S="184" T="184" R="228" G="33" B="119" A="255"/>
+ <Vtx X="-546" Y="-300" Z="546" S="83" T="1008" R="166" G="0" B="90" A="255"/>
+ <Vtx X="-586" Y="186" Z="486" S="184" T="184" R="137" G="33" B="28" A="255"/>
+ <Vtx X="-586" Y="186" Z="0" S="1008" T="184" R="136" G="42" B="0" A="255"/>
+ <Vtx X="-540" Y="240" Z="0" S="1008" T="92" R="157" G="80" B="0" A="255"/>
+ <Vtx X="-545" Y="240" Z="-546" S="1933" T="92" R="185" G="79" B="185" A="255"/>
+ <Vtx X="-586" Y="186" Z="-486" S="1832" T="184" R="137" G="33" B="228" A="255"/>
+ <Vtx X="-546" Y="-300" Z="-546" S="1933" T="1008" R="166" G="0" B="166" A="255"/>
+ <Vtx X="-586" Y="186" Z="-486" S="1832" T="184" R="137" G="33" B="228" A="255"/>
+ <Vtx X="-545" Y="240" Z="-546" S="1933" T="92" R="185" G="79" B="185" A="255"/>
+ <Vtx X="-586" Y="-300" Z="-486" S="1832" T="1008" R="134" G="0" B="219" A="255"/>
+ <Vtx X="-586" Y="-786" Z="-486" S="1832" T="1832" R="137" G="223" B="228" A="255"/>
+ <Vtx X="-545" Y="-840" Z="-546" S="1933" T="1924" R="185" G="177" B="185" A="255"/>
+ <Vtx X="-586" Y="-786" Z="0" S="1008" T="1832" R="136" G="214" B="0" A="255"/>
+ <Vtx X="-540" Y="-840" Z="0" S="1008" T="1924" R="157" G="176" B="0" A="255"/>
+ <Vtx X="-545" Y="-840" Z="546" S="83" T="1924" R="185" G="177" B="71" A="255"/>
+ <Vtx X="-586" Y="-786" Z="486" S="184" T="1832" R="137" G="223" B="28" A="255"/>
+ <Vtx X="-546" Y="-300" Z="546" S="83" T="1008" R="166" G="0" B="90" A="255"/>
+ <Vtx X="-486" Y="-786" Z="586" S="184" T="1832" R="228" G="223" B="119" A="255"/>
+ <Vtx X="0" Y="-786" Z="586" S="1008" T="1832" R="0" G="214" B="120" A="255"/>
+ <Vtx X="0" Y="-840" Z="540" S="1008" T="1924" R="0" G="176" B="99" A="255"/>
+ <Vtx X="545" Y="-840" Z="546" S="1933" T="1924" R="71" G="177" B="71" A="255"/>
+ <Vtx X="486" Y="-786" Z="586" S="1832" T="1832" R="28" G="223" B="119" A="255"/>
+ <Vtx X="486" Y="-300" Z="586" S="1832" T="1008" R="37" G="0" B="122" A="255"/>
+ <Vtx X="0" Y="-786" Z="586" S="1008" T="1832" R="0" G="214" B="120" A="255"/>
+ <Vtx X="486" Y="-786" Z="586" S="1832" T="1832" R="28" G="223" B="119" A="255"/>
+ <Vtx X="0" Y="-300" Z="586" S="1008" T="1008" R="0" G="0" B="127" A="255"/>
+ <Vtx X="0" Y="186" Z="586" S="1008" T="184" R="0" G="42" B="120" A="255"/>
+ <Vtx X="486" Y="186" Z="586" S="1832" T="184" R="28" G="33" B="119" A="255"/>
+ <Vtx X="-486" Y="-300" Z="586" S="184" T="1008" R="219" G="0" B="122" A="255"/>
+ <Vtx X="-486" Y="-786" Z="586" S="184" T="1832" R="228" G="223" B="119" A="255"/>
+ <Vtx X="-546" Y="-300" Z="546" S="83" T="1008" R="166" G="0" B="90" A="255"/>
+ <Vtx X="-486" Y="186" Z="586" S="184" T="184" R="228" G="33" B="119" A="255"/>
+ <Vtx X="-586" Y="-300" Z="-486" S="1832" T="1008" R="134" G="0" B="219" A="255"/>
+ <Vtx X="-586" Y="-786" Z="-486" S="1832" T="1832" R="137" G="223" B="228" A="255"/>
+ <Vtx X="-586" Y="-786" Z="0" S="1008" T="1832" R="136" G="214" B="0" A="255"/>
+ <Vtx X="-586" Y="-300" Z="0" S="1008" T="1008" R="129" G="0" B="0" A="255"/>
+ <Vtx X="-586" Y="-300" Z="486" S="184" T="1008" R="134" G="0" B="37" A="255"/>
+ <Vtx X="-586" Y="-786" Z="486" S="184" T="1832" R="137" G="223" B="28" A="255"/>
+ <Vtx X="-546" Y="-300" Z="546" S="83" T="1008" R="166" G="0" B="90" A="255"/>
+ <Vtx X="-586" Y="186" Z="486" S="184" T="184" R="137" G="33" B="28" A="255"/>
+ <Vtx X="-586" Y="-300" Z="486" S="184" T="1008" R="134" G="0" B="37" A="255"/>
+ <Vtx X="-586" Y="186" Z="0" S="1008" T="184" R="136" G="42" B="0" A="255"/>
+ <Vtx X="-586" Y="-300" Z="0" S="1008" T="1008" R="129" G="0" B="0" A="255"/>
+ <Vtx X="-586" Y="-300" Z="-486" S="1832" T="1008" R="134" G="0" B="219" A="255"/>
+ <Vtx X="-586" Y="186" Z="-486" S="1832" T="184" R="137" G="33" B="228" A="255"/>
+ <Vtx X="545" Y="-840" Z="-546" S="1933" T="1924" R="71" G="177" B="185" A="255"/>
+ <Vtx X="0" Y="-840" Z="-540" S="1008" T="1924" R="0" G="176" B="157" A="255"/>
+ <Vtx X="0" Y="-786" Z="-586" S="1008" T="1832" R="0" G="214" B="136" A="255"/>
+ <Vtx X="-545" Y="-840" Z="-546" S="83" T="1924" R="185" G="177" B="185" A="255"/>
+ <Vtx X="-486" Y="-786" Z="-586" S="184" T="1832" R="228" G="223" B="137" A="255"/>
+ <Vtx X="-546" Y="-300" Z="-546" S="83" T="1008" R="166" G="0" B="166" A="255"/>
+ <Vtx X="-486" Y="-300" Z="-586" S="184" T="1008" R="219" G="0" B="134" A="255"/>
+ <Vtx X="-486" Y="186" Z="-586" S="184" T="184" R="228" G="33" B="137" A="255"/>
+ <Vtx X="-545" Y="240" Z="-546" S="83" T="92" R="185" G="79" B="185" A="255"/>
+ <Vtx X="-545" Y="240" Z="-546" S="83" T="92" R="185" G="79" B="185" A="255"/>
+ <Vtx X="0" Y="186" Z="-586" S="1008" T="184" R="0" G="42" B="136" A="255"/>
+ <Vtx X="-486" Y="186" Z="-586" S="184" T="184" R="228" G="33" B="137" A="255"/>
+ <Vtx X="0" Y="240" Z="-540" S="1008" T="92" R="0" G="80" B="157" A="255"/>
+ <Vtx X="545" Y="240" Z="-546" S="1933" T="92" R="71" G="79" B="185" A="255"/>
+ <Vtx X="486" Y="186" Z="-586" S="1832" T="184" R="28" G="33" B="137" A="255"/>
+ <Vtx X="546" Y="-300" Z="-546" S="1933" T="1008" R="90" G="0" B="166" A="255"/>
+ <Vtx X="586" Y="186" Z="-486" S="1832" T="184" R="119" G="33" B="228" A="255"/>
+ <Vtx X="586" Y="186" Z="0" S="1008" T="184" R="120" G="42" B="0" A="255"/>
+ <Vtx X="540" Y="240" Z="0" S="1008" T="92" R="99" G="80" B="0" A="255"/>
+ <Vtx X="545" Y="240" Z="546" S="83" T="92" R="71" G="79" B="71" A="255"/>
+ <Vtx X="586" Y="186" Z="486" S="184" T="184" R="119" G="33" B="28" A="255"/>
+ <Vtx X="546" Y="-300" Z="546" S="83" T="1008" R="90" G="0" B="90" A="255"/>
+ <Vtx X="586" Y="-300" Z="486" S="184" T="1008" R="122" G="0" B="37" A="255"/>
+ <Vtx X="586" Y="-786" Z="486" S="184" T="1832" R="119" G="223" B="28" A="255"/>
+ <Vtx X="545" Y="-840" Z="546" S="83" T="1924" R="71" G="177" B="71" A="255"/>
+ <Vtx X="545" Y="-840" Z="546" S="83" T="1924" R="71" G="177" B="71" A="255"/>
+ <Vtx X="586" Y="-786" Z="0" S="1008" T="1832" R="120" G="214" B="0" A="255"/>
+ <Vtx X="586" Y="-786" Z="486" S="184" T="1832" R="119" G="223" B="28" A="255"/>
+ <Vtx X="540" Y="-840" Z="0" S="1008" T="1924" R="99" G="176" B="0" A="255"/>
+ <Vtx X="545" Y="-840" Z="-546" S="1933" T="1924" R="71" G="177" B="185" A="255"/>
+ <Vtx X="586" Y="-786" Z="-486" S="1832" T="1832" R="119" G="223" B="228" A="255"/>
+ <Vtx X="546" Y="-300" Z="-546" S="1933" T="1008" R="90" G="0" B="166" A="255"/>
+ <Vtx X="486" Y="-786" Z="-586" S="1832" T="1832" R="28" G="223" B="137" A="255"/>
+ <Vtx X="0" Y="-786" Z="-586" S="1008" T="1832" R="0" G="214" B="136" A="255"/>
+ <Vtx X="486" Y="-300" Z="-586" S="1832" T="1008" R="37" G="0" B="134" A="255"/>
+ <Vtx X="0" Y="-300" Z="-586" S="1008" T="1008" R="0" G="0" B="129" A="255"/>
+ <Vtx X="-486" Y="-300" Z="-586" S="184" T="1008" R="219" G="0" B="134" A="255"/>
+ <Vtx X="-486" Y="-786" Z="-586" S="184" T="1832" R="228" G="223" B="137" A="255"/>
+ <Vtx X="0" Y="186" Z="-586" S="1008" T="184" R="0" G="42" B="136" A="255"/>
+ <Vtx X="-486" Y="186" Z="-586" S="184" T="184" R="228" G="33" B="137" A="255"/>
+ <Vtx X="486" Y="186" Z="-586" S="1832" T="184" R="28" G="33" B="137" A="255"/>
+ <Vtx X="586" Y="-300" Z="486" S="184" T="1008" R="122" G="0" B="37" A="255"/>
+ <Vtx X="586" Y="-786" Z="486" S="184" T="1832" R="119" G="223" B="28" A="255"/>
+ <Vtx X="586" Y="-786" Z="0" S="1008" T="1832" R="120" G="214" B="0" A="255"/>
+ <Vtx X="586" Y="-300" Z="0" S="1008" T="1008" R="127" G="0" B="0" A="255"/>
+ <Vtx X="586" Y="-300" Z="-486" S="1832" T="1008" R="122" G="0" B="219" A="255"/>
+ <Vtx X="586" Y="-786" Z="-486" S="1832" T="1832" R="119" G="223" B="228" A="255"/>
+ <Vtx X="546" Y="-300" Z="-546" S="1933" T="1008" R="90" G="0" B="166" A="255"/>
+ <Vtx X="586" Y="186" Z="-486" S="1832" T="184" R="119" G="33" B="228" A="255"/>
+ <Vtx X="586" Y="186" Z="0" S="1008" T="184" R="120" G="42" B="0" A="255"/>
+ <Vtx X="586" Y="186" Z="486" S="184" T="184" R="119" G="33" B="28" A="255"/>
+</Vertex>
diff --git a/mm/src/code/z_scene.c b/mm/src/code/z_scene.c
index e76d74ed7..52def8ff0 100644
--- a/mm/src/code/z_scene.c
+++ b/mm/src/code/z_scene.c
@@ -1,5 +1,6 @@
#include "global.h"
#include <libultraship/bridge/consolevariablebridge.h>
+#include "GameInteractor/GameInteractor.h"
/**
* Spawn an object file of a specified ID that will persist through room changes.
@@ -112,7 +113,7 @@ s32 Object_GetSlot(ObjectContext* objectCtx, s16 objectId) {
}
}
- return CVarGetInteger("gDeveloperTools.DisableObjectDependency", 0) ? 0 : OBJECT_SLOT_NONE;
+ return GameInteractor_Should(VB_ENABLE_OBJECT_DEPENDENCY, true, objectId) ? OBJECT_SLOT_NONE : 0;
}
s32 Object_IsLoaded(ObjectContext* objectCtx, s32 slot) {