mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2025-02-16 07:10:34 -05:00
More mirror mode fixes and additions (#3009)
* mirror fishing rod * mirror ivan fairy controls * add mirror dungeons only option * mirror sold out GI texture * update dungeons mirror mode for more options * maybe don't include that
This commit is contained in:
parent
5daf5a14ac
commit
6fdfcd2a61
@ -5,6 +5,7 @@ extern "C" {
|
|||||||
#include <libultraship/libultra.h>
|
#include <libultraship/libultra.h>
|
||||||
#include "objects/gameplay_keep/gameplay_keep.h"
|
#include "objects/gameplay_keep/gameplay_keep.h"
|
||||||
#include "objects/object_fz/object_fz.h"
|
#include "objects/object_fz/object_fz.h"
|
||||||
|
#include "objects/object_gi_soldout/object_gi_soldout.h"
|
||||||
#include "objects/object_ik/object_ik.h"
|
#include "objects/object_ik/object_ik.h"
|
||||||
#include "objects/object_link_child/object_link_child.h"
|
#include "objects/object_link_child/object_link_child.h"
|
||||||
|
|
||||||
@ -192,6 +193,50 @@ void ApplyAuthenticGfxPatches() {
|
|||||||
PatchIronKnuckleTextureOverflow();
|
PatchIronKnuckleTextureOverflow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Patches the Sold Out GI DL to render the texture in the mirror boundary
|
||||||
|
void PatchMirroredSoldOutGI() {
|
||||||
|
static const char gSoldOutGIVtx[] = "__OTR__objects/object_gi_soldout/object_gi_soldoutVtx_000400";
|
||||||
|
|
||||||
|
static Vtx* mirroredSoldOutVtx;
|
||||||
|
|
||||||
|
// Using a dummy texture here, but will be ignoring the texture command itself
|
||||||
|
// Only need to patch over the two SetTile commands to get the MIRROR effect
|
||||||
|
Gfx mirroredSoldOutTex[] = {
|
||||||
|
gsDPLoadTextureBlock("", G_IM_FMT_IA, G_IM_SIZ_8b, 32, 32, 0, G_TX_MIRROR | G_TX_WRAP,
|
||||||
|
G_TX_NOMIRROR | G_TX_CLAMP, 5, 5, G_TX_NOLOD, G_TX_NOLOD),
|
||||||
|
};
|
||||||
|
|
||||||
|
if (CVarGetInteger("gMirroredWorld", 0)) {
|
||||||
|
if (mirroredSoldOutVtx == nullptr) {
|
||||||
|
// Copy the original vertices that we want to modify (4 at the beginning of the resource)
|
||||||
|
mirroredSoldOutVtx = (Vtx*)malloc(sizeof(Vtx) * 4);
|
||||||
|
Vtx* origVtx = (Vtx*)ResourceGetDataByName(gSoldOutGIVtx);
|
||||||
|
memcpy(mirroredSoldOutVtx, origVtx, sizeof(Vtx) * 4);
|
||||||
|
|
||||||
|
// Offset the vertex U coordinate values by the width of the texture
|
||||||
|
for (size_t i = 0; i < 4; i++) {
|
||||||
|
mirroredSoldOutVtx[i].v.tc[0] += 32 << 5;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceMgr_PatchGfxByName(gGiSoldOutDL, "SoldOutGITexture_1", 9, mirroredSoldOutTex[1]);
|
||||||
|
ResourceMgr_PatchGfxByName(gGiSoldOutDL, "SoldOutGITexture_2", 13, mirroredSoldOutTex[5]);
|
||||||
|
ResourceMgr_PatchGfxByName(gGiSoldOutDL, "SoldOutGITextureCords_1", 17, gsSPVertex(mirroredSoldOutVtx, 4, 0));
|
||||||
|
// noop as the original vertex command is 128 bit wide
|
||||||
|
ResourceMgr_PatchGfxByName(gGiSoldOutDL, "SoldOutGITextureCords_2", 18, gsSPNoOp());
|
||||||
|
} else {
|
||||||
|
if (mirroredSoldOutVtx != nullptr) {
|
||||||
|
free(mirroredSoldOutVtx);
|
||||||
|
mirroredSoldOutVtx = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
ResourceMgr_UnpatchGfxByName(gGiSoldOutDL, "SoldOutGITexture_1");
|
||||||
|
ResourceMgr_UnpatchGfxByName(gGiSoldOutDL, "SoldOutGITexture_2");
|
||||||
|
ResourceMgr_UnpatchGfxByName(gGiSoldOutDL, "SoldOutGITextureCords_1");
|
||||||
|
ResourceMgr_UnpatchGfxByName(gGiSoldOutDL, "SoldOutGITextureCords_2");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Patches the Sun Song Etching in the Royal Grave to be mirrored in mirror mode
|
// Patches the Sun Song Etching in the Royal Grave to be mirrored in mirror mode
|
||||||
// This is achieved by mirroring the texture at the boundary and overriding the vertex texture coordinates
|
// This is achieved by mirroring the texture at the boundary and overriding the vertex texture coordinates
|
||||||
void PatchMirroredSunSongEtching() {
|
void PatchMirroredSunSongEtching() {
|
||||||
@ -200,7 +245,7 @@ void PatchMirroredSunSongEtching() {
|
|||||||
static const char gMqRoyalGraveBackRoomSongVtx[] = "__OTR__scenes/mq/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80";
|
static const char gMqRoyalGraveBackRoomSongVtx[] = "__OTR__scenes/mq/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80";
|
||||||
static const char gNonMqRoyalGraveBackRoomSongVtx[] = "__OTR__scenes/nonmq/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80";
|
static const char gNonMqRoyalGraveBackRoomSongVtx[] = "__OTR__scenes/nonmq/hakaana_ouke_scene/hakaana_ouke_room_2Vtx_004F80";
|
||||||
|
|
||||||
static Vtx* mirroredVtx;
|
static Vtx* mirroredSunSongVtx;
|
||||||
|
|
||||||
// Using a dummy texture here, but will be ignoring the texture command itself
|
// Using a dummy texture here, but will be ignoring the texture command itself
|
||||||
// Only need to patch over the two SetTile commands to get the MIRROR effect
|
// Only need to patch over the two SetTile commands to get the MIRROR effect
|
||||||
@ -222,27 +267,27 @@ void PatchMirroredSunSongEtching() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (CVarGetInteger("gMirroredWorld", 0)) {
|
if (CVarGetInteger("gMirroredWorld", 0)) {
|
||||||
if (mirroredVtx == nullptr) {
|
if (mirroredSunSongVtx == nullptr) {
|
||||||
// Copy the original vertices that we want to modify (4 at the beginning of the resource)
|
// Copy the original vertices that we want to modify (4 at the beginning of the resource)
|
||||||
mirroredVtx = (Vtx*)malloc(sizeof(Vtx) * 4);
|
mirroredSunSongVtx = (Vtx*)malloc(sizeof(Vtx) * 4);
|
||||||
Vtx* origVtx = (Vtx*)ResourceGetDataByName(royalGraveBackRoomSongVtx);
|
Vtx* origVtx = (Vtx*)ResourceGetDataByName(royalGraveBackRoomSongVtx);
|
||||||
memcpy(mirroredVtx, origVtx, sizeof(Vtx) * 4);
|
memcpy(mirroredSunSongVtx, origVtx, sizeof(Vtx) * 4);
|
||||||
|
|
||||||
// Offset the vertex U coordinate values by the width of the texture
|
// Offset the vertex U coordinate values by the width of the texture
|
||||||
for (size_t i = 0; i < 4; i++) {
|
for (size_t i = 0; i < 4; i++) {
|
||||||
mirroredVtx[i].v.tc[0] += 128 << 5;
|
mirroredSunSongVtx[i].v.tc[0] += 128 << 5;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceMgr_PatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTexture_1", 13, mirroredSunSongTex[1]);
|
ResourceMgr_PatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTexture_1", 13, mirroredSunSongTex[1]);
|
||||||
ResourceMgr_PatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTexture_2", 17, mirroredSunSongTex[5]);
|
ResourceMgr_PatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTexture_2", 17, mirroredSunSongTex[5]);
|
||||||
ResourceMgr_PatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_1", 24, gsSPVertex(mirroredVtx, 4, 0));
|
ResourceMgr_PatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_1", 24, gsSPVertex(mirroredSunSongVtx, 4, 0));
|
||||||
// noop as the original vertex command is 128 bit wide
|
// noop as the original vertex command is 128 bit wide
|
||||||
ResourceMgr_PatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_2", 25, gsSPNoOp());
|
ResourceMgr_PatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTextureCords_2", 25, gsSPNoOp());
|
||||||
} else {
|
} else {
|
||||||
if (mirroredVtx != nullptr) {
|
if (mirroredSunSongVtx != nullptr) {
|
||||||
free(mirroredVtx);
|
free(mirroredSunSongVtx);
|
||||||
mirroredVtx = nullptr;
|
mirroredSunSongVtx = nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResourceMgr_UnpatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTexture_1");
|
ResourceMgr_UnpatchGfxByName(royalGraveBackRoomDL, "RoyalGraveSunSongTexture_1");
|
||||||
@ -253,5 +298,6 @@ void PatchMirroredSunSongEtching() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void ApplyMirrorWorldGfxPatches() {
|
void ApplyMirrorWorldGfxPatches() {
|
||||||
|
PatchMirroredSoldOutGI();
|
||||||
PatchMirroredSunSongEtching();
|
PatchMirroredSunSongEtching();
|
||||||
}
|
}
|
||||||
|
@ -16,6 +16,11 @@ typedef enum {
|
|||||||
MIRRORED_WORLD_ALWAYS,
|
MIRRORED_WORLD_ALWAYS,
|
||||||
MIRRORED_WORLD_RANDOM,
|
MIRRORED_WORLD_RANDOM,
|
||||||
MIRRORED_WORLD_RANDOM_SEEDED,
|
MIRRORED_WORLD_RANDOM_SEEDED,
|
||||||
|
MIRRORED_WORLD_DUNGEONS_All,
|
||||||
|
MIRRORED_WORLD_DUNGEONS_VANILLA,
|
||||||
|
MIRRORED_WORLD_DUNGEONS_MQ,
|
||||||
|
MIRRORED_WORLD_DUNGEONS_RANDOM,
|
||||||
|
MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED,
|
||||||
} MirroredWorldMode;
|
} MirroredWorldMode;
|
||||||
|
|
||||||
typedef enum {
|
typedef enum {
|
||||||
|
@ -15,6 +15,8 @@ extern "C" {
|
|||||||
#include "functions.h"
|
#include "functions.h"
|
||||||
extern SaveContext gSaveContext;
|
extern SaveContext gSaveContext;
|
||||||
extern PlayState* gPlayState;
|
extern PlayState* gPlayState;
|
||||||
|
|
||||||
|
uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
|
||||||
}
|
}
|
||||||
bool performDelayedSave = false;
|
bool performDelayedSave = false;
|
||||||
bool performSave = false;
|
bool performSave = false;
|
||||||
@ -557,16 +559,26 @@ void UpdateMirrorModeState(int32_t sceneNum) {
|
|||||||
bool nextMirroredWorld = false;
|
bool nextMirroredWorld = false;
|
||||||
|
|
||||||
int16_t mirroredMode = CVarGetInteger("gMirroredWorldMode", MIRRORED_WORLD_OFF);
|
int16_t mirroredMode = CVarGetInteger("gMirroredWorldMode", MIRRORED_WORLD_OFF);
|
||||||
|
int16_t inDungeon = (sceneNum >= SCENE_YDAN && sceneNum <= SCENE_GANONTIKA_SONOGO && sceneNum != SCENE_GERUDOWAY) ||
|
||||||
|
(sceneNum >= SCENE_YDAN_BOSS && sceneNum <= SCENE_GANON_FINAL) ||
|
||||||
|
(sceneNum == SCENE_GANON_DEMO);
|
||||||
|
|
||||||
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) {
|
if (mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) {
|
||||||
uint32_t seed = sceneNum + (gSaveContext.n64ddFlag ? (gSaveContext.seedIcons[0] + gSaveContext.seedIcons[1] + gSaveContext.seedIcons[2] + gSaveContext.seedIcons[3] + gSaveContext.seedIcons[4]) : gSaveContext.sohStats.fileCreatedAt);
|
uint32_t seed = sceneNum + (gSaveContext.n64ddFlag ? (gSaveContext.seedIcons[0] + gSaveContext.seedIcons[1] +
|
||||||
|
gSaveContext.seedIcons[2] + gSaveContext.seedIcons[3] + gSaveContext.seedIcons[4]) : gSaveContext.sohStats.fileCreatedAt);
|
||||||
Random_Init(seed);
|
Random_Init(seed);
|
||||||
}
|
}
|
||||||
|
|
||||||
uint8_t randomNumber = Random(0, 2);
|
bool randomMirror = Random(0, 2) == 1;
|
||||||
|
|
||||||
if (
|
if (
|
||||||
mirroredMode == MIRRORED_WORLD_ALWAYS ||
|
mirroredMode == MIRRORED_WORLD_ALWAYS ||
|
||||||
(mirroredMode > MIRRORED_WORLD_ALWAYS && randomNumber == 1)
|
((mirroredMode == MIRRORED_WORLD_RANDOM || mirroredMode == MIRRORED_WORLD_RANDOM_SEEDED) && randomMirror) ||
|
||||||
|
// Dungeon modes
|
||||||
|
(inDungeon && (mirroredMode == MIRRORED_WORLD_DUNGEONS_All ||
|
||||||
|
(mirroredMode == MIRRORED_WORLD_DUNGEONS_VANILLA && !ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
|
||||||
|
(mirroredMode == MIRRORED_WORLD_DUNGEONS_MQ && ResourceMgr_IsSceneMasterQuest(sceneNum)) ||
|
||||||
|
((mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM || mirroredMode == MIRRORED_WORLD_DUNGEONS_RANDOM_SEEDED) && randomMirror)))
|
||||||
) {
|
) {
|
||||||
nextMirroredWorld = true;
|
nextMirroredWorld = true;
|
||||||
CVarSetInteger("gMirroredWorld", 1);
|
CVarSetInteger("gMirroredWorld", 1);
|
||||||
|
@ -62,7 +62,10 @@ std::string GetWindowButtonText(const char* text, bool menuOpen) {
|
|||||||
|
|
||||||
static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" };
|
static const char* chestStyleMatchesContentsOptions[4] = { "Disabled", "Both", "Texture Only", "Size Only" };
|
||||||
static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" };
|
static const char* bunnyHoodOptions[3] = { "Disabled", "Faster Run & Longer Jump", "Faster Run" };
|
||||||
static const char* mirroredWorldModes[4] = { "Disabled", "Always", "Random", "Random (Seeded)" };
|
static const char* mirroredWorldModes[9] = {
|
||||||
|
"Disabled", "Always", "Random", "Random (Seeded)", "Dungeons",
|
||||||
|
"Dungeons (Vanilla)", "Dungeons (MQ)", "Dungeons Random", "Dungeons Random (Seeded)",
|
||||||
|
};
|
||||||
static const char* enemyRandomizerModes[3] = { "Disabled", "Random", "Random (Seeded)" };
|
static const char* enemyRandomizerModes[3] = { "Disabled", "Random", "Random (Seeded)" };
|
||||||
static const char* allPowers[9] = {
|
static const char* allPowers[9] = {
|
||||||
"Vanilla (1x)",
|
"Vanilla (1x)",
|
||||||
@ -1054,6 +1057,11 @@ void DrawEnhancementsMenu() {
|
|||||||
"- Always: Always mirror the world\n"
|
"- Always: Always mirror the world\n"
|
||||||
"- Random: Randomly decide to mirror the world on each scene change\n"
|
"- Random: Randomly decide to mirror the world on each scene change\n"
|
||||||
"- Random (Seeded): Scenes are mirrored based on the current randomizer seed/file\n"
|
"- Random (Seeded): Scenes are mirrored based on the current randomizer seed/file\n"
|
||||||
|
"- Dungeons: Mirror the world in Dungeons\n"
|
||||||
|
"- Dungeons (Vanilla): Mirror the world in vanilla Dungeons\n"
|
||||||
|
"- Dungeons (MQ): Mirror the world in MQ Dungeons\n"
|
||||||
|
"- Dungeons Random: Randomly decide to mirror the world in Dungeons\n"
|
||||||
|
"- Dungeons Random (Seeded): Dungeons are mirrored based on the current randomizer seed/file\n"
|
||||||
);
|
);
|
||||||
|
|
||||||
UIWidgets::PaddedText("Enemy Randomizer", true, false);
|
UIWidgets::PaddedText("Enemy Randomizer", true, false);
|
||||||
|
@ -574,7 +574,7 @@ void EnPartner_Update(Actor* thisx, PlayState* play) {
|
|||||||
|
|
||||||
Input sControlInput = play->state.input[this->actor.params];
|
Input sControlInput = play->state.input[this->actor.params];
|
||||||
|
|
||||||
f32 relX = sControlInput.cur.stick_x / 10.0f;
|
f32 relX = sControlInput.cur.stick_x / 10.0f * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1);
|
||||||
f32 relY = sControlInput.cur.stick_y / 10.0f;
|
f32 relY = sControlInput.cur.stick_y / 10.0f;
|
||||||
|
|
||||||
Vec3f camForward = { GET_ACTIVE_CAM(play)->at.x - GET_ACTIVE_CAM(play)->eye.x, 0.0f,
|
Vec3f camForward = { GET_ACTIVE_CAM(play)->at.x - GET_ACTIVE_CAM(play)->eye.x, 0.0f,
|
||||||
|
@ -2025,7 +2025,7 @@ void Fishing_DrawRod(PlayState* play) {
|
|||||||
spC8 = player->unk_85C - spC8;
|
spC8 = player->unk_85C - spC8;
|
||||||
|
|
||||||
spC4 = player->unk_858;
|
spC4 = player->unk_858;
|
||||||
Math_SmoothStepToF(&player->unk_858, input->rel.stick_x * 0.02f, 0.3f, 5.0f, 0.0f);
|
Math_SmoothStepToF(&player->unk_858, input->rel.stick_x * 0.02f * (CVarGetInteger("gMirroredWorld", 0) ? -1 : 1), 0.3f, 5.0f, 0.0f);
|
||||||
spC4 = player->unk_858 - spC4;
|
spC4 = player->unk_858 - spC4;
|
||||||
|
|
||||||
if (player->unk_858 > 1.0f) {
|
if (player->unk_858 > 1.0f) {
|
||||||
|
Loading…
Reference in New Issue
Block a user