This commit is contained in:
Philip Dubé
2026-07-24 15:19:36 +00:00
committed by GitHub
parent da4e6dc332
commit 581af47419
20 changed files with 24 additions and 24 deletions
+1 -1
View File
@@ -72,7 +72,7 @@ Congratulations, you are now sailing with the Ship of Harkinian! Have fun!
| Ctrl+R | Reset |
# Project Overview
Ship of Harkinian (SOH) is built atop a custom library dubbed libultraship (LUS). Back in the N64 days, there was an SDK distributed to developers named libultra; LUS is designed to mimic the functionality of libultra on modern hardware. In addition, we are dependant on the source code provided by the OOT decompilation project.
Ship of Harkinian (SOH) is built atop a custom library dubbed libultraship (LUS). Back in the N64 days, there was an SDK distributed to developers named libultra; LUS is designed to mimic the functionality of libultra on modern hardware. In addition, we are dependent on the source code provided by the OOT decompilation project.
In order for the game to function, you will require a **legally acquired** ROM for Ocarina of Time. Click [here](https://ship.equipment/) to check the compatibility of your specific rom. Any copyrighted assets are extracted from the ROM and reformatted as a .o2r archive file which the code uses.
+1 -1
View File
@@ -72,7 +72,7 @@ if (IS_DAY || gTimeIncrement >= 0x190) {
}
```
We can make a quick change to this code to verify this is indeed what we are looking for, lets multiply the gTimeIncrement by 10:
We can make a quick change to this code to verify this is indeed what we are looking for, let's multiply the gTimeIncrement by 10:
```diff
if (IS_DAY || gTimeIncrement >= 0x190) {
@@ -19,7 +19,7 @@ static constexpr int32_t CVAR_TOT_MEDALLION_COLORS_DEFAULT = 0;
#define dgEndGrayscaleAndEndDlistDL "__OTR__helpers/cosmetics/gEndGrayscaleAndEndDlistDL"
static const ALIGN_ASSET(2) char gEndGrayscaleAndEndDlistDL[] = dgEndGrayscaleAndEndDlistDL;
// This is used for the Temple of Time Medalions' color
// This is used for the Temple of Time Medallions' color
#define dtokinoma_room_0DL_007A70 "__OTR__scenes/shared/tokinoma_scene/tokinoma_room_0DL_007A70"
static const ALIGN_ASSET(2) char tokinoma_room_0DL_007A70[] = dtokinoma_room_0DL_007A70;
#define dtokinoma_room_0DL_007FD0 "__OTR__scenes/shared/tokinoma_scene/tokinoma_room_0DL_007FD0"
+1 -1
View File
@@ -48,7 +48,7 @@ void SaveConfig() {
void Warp(WarpPoint& warpPoint) {
if (gPlayState == NULL) {
// If gPlayState is NULL, it means the the user opted into BootToWarpPoint and the game is starting up.
// If gPlayState is NULL, it means the user opted into BootToWarpPoint and the game is starting up.
gSaveContext.gameMode = GAMEMODE_NORMAL;
gSaveContext.fileNum = 0xFE; // temporary file so that this will respect debug save file option
Sram_InitDebugSave();
@@ -1276,7 +1276,7 @@ void InitHeader(bool has_header = true) {
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding(); // This is to adjust Vertical pos of item in a cell to be normlized.
ImGui::AlignTextToFramePadding(); // This is to adjust Vertical pos of item in a cell to be normalized.
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x);
}
@@ -468,13 +468,13 @@ void SetMarginAll(const char* ButtonName, bool SetActivated, const char* tooltip
CVarSetInteger(cvarNameMargins.c_str(), false); // force set off
} else if ((strcmp(cvarName, MarginCvarNonAnchor[i]) == 0) &&
(CVarGetInteger(cvarPosType.c_str(), 0) !=
ORIGINAL_LOCATION)) { // Our element is not in original position regarless it has no
// anchor by default since player made it anchored we can toggle
ORIGINAL_LOCATION)) { // Element not in original position, regardless. It has no
// anchor by default; since player made it anchored we can toggle
// margins
CVarSetInteger(cvarNameMargins.c_str(), SetActivated);
} else if (strcmp(cvarName, MarginCvarNonAnchor[i]) !=
0) { // Our elements has an anchor by default so regarless of it's position right now
// that okay to toggle margins.
0) { // Our element has an anchor by default, so regardless of its position right now
// it's okay to toggle margins.
CVarSetInteger(cvarNameMargins.c_str(), SetActivated);
}
}
@@ -1500,7 +1500,7 @@ void Table_InitHeader(bool has_header = true) {
}
ImGui::TableNextRow();
ImGui::TableNextColumn();
ImGui::AlignTextToFramePadding(); // This is to adjust Vertical pos of item in a cell to be normlized.
ImGui::AlignTextToFramePadding(); // This is to adjust Vertical pos of item in a cell to be normalized.
ImGui::SetCursorPosX(ImGui::GetCursorPosX() - 2);
ImGui::PushItemWidth(ImGui::GetContentRegionAvail().x - 60);
}
+1 -1
View File
@@ -68,7 +68,7 @@ void ColViewerWindow::DrawElement() {
CVarCheckbox("Apply as decal", CVAR_DEVELOPER_TOOLS("ColViewer.Decal"),
checkOpt.DefaultValue(true).Tooltip(
"Applies the collision as a decal display. This can be useful if there is z-fighting occuring "
"Applies the collision as a decal display. This can be useful if there is z-fighting occurring "
"with the scene geometry, but can cause other artifacts."));
CVarCheckbox("Shaded", CVAR_DEVELOPER_TOOLS("ColViewer.Shaded"),
checkOpt.DefaultValue(false).Tooltip("Applies the scene's shading to the collision display."));
@@ -3,7 +3,7 @@ GameInteractor is meant to be used for interacting with the game (yup...).
It exposes functions that directly modify, add or remove game related elements.
GameInteractionEffects.cpp is used when code that needs these
functions also need a check wether a command can be run or not.
functions also need a check whether a command can be run or not.
If these checks need to happen wherever GameInteractor functions are needed, the
GameInteractor functions can be called directly.
+1 -1
View File
@@ -897,7 +897,7 @@ void SetupDisplayNames() {
strcpy(itemTimestampDisplayName[TIMESTAMP_FOUND_SPEAK_DEKU], "Speak Deku: ");
strcpy(itemTimestampDisplayName[TIMESTAMP_FOUND_SPEAK_GERUDO], "Speak Gerudo: ");
strcpy(itemTimestampDisplayName[TIMESTAMP_FOUND_SPEAK_GORON], "Speak Goron: ");
strcpy(itemTimestampDisplayName[TIMESTAMP_FOUND_SPEAK_HYLIAN], "SpeakHylian: ");
strcpy(itemTimestampDisplayName[TIMESTAMP_FOUND_SPEAK_HYLIAN], "Speak Hylian: ");
strcpy(itemTimestampDisplayName[TIMESTAMP_FOUND_SPEAK_KOKIRI], "Speak Kokiri: ");
strcpy(itemTimestampDisplayName[TIMESTAMP_FOUND_SPEAK_ZORA], "Speak Zora: ");
strcpy(itemTimestampDisplayName[TIMESTAMP_FOUND_DMC_BEAN_SOUL], "DMC Bean Soul: ");
@@ -1557,7 +1557,7 @@ void StaticData::HintTable_Init_Exclude_Overworld() {
/*french*/ "Selon moi, une #jarre dans le Village de Cocorico# contient #[[1]]#.", {QM_RED, QM_GREEN}));
hintTextTable[RHT_POT_DAMPE] = HintText(CustomMessage("They say that a #pot in gravekeeper's tomb# contains #[[1]]#.",
//TODO_TRANSLATE check these to make sure they refernce dampe's tomb not the graveyard area
//TODO_TRANSLATE check these to make sure they reference dampe's tomb not the graveyard area
/*german*/ "Man erzählt sich, daß ein #Krug auf dem Friedhof# #[[1]]# enthielte.",
/*french*/ "Selon moi, une #jarre dans le Cimetière# contient #[[1]]#.", {QM_RED, QM_GREEN}));
@@ -768,7 +768,7 @@ bool SpiritCertainAccess(RandomizerRegion region) {
Spirit Shared can take up to 3 regions, this is because checks can exist in many regions at the same time
and the logic needs to be able to check the access logic from those regions to check the other universes properly.
anyAge is equivalent to a self referencing Here, used for events and any check where that is relevent.
anyAge is equivalent to a self referencing Here, used for events and any check where that is relevant.
*/
bool SpiritShared(RandomizerRegion region, ConditionFn condition, bool anyAge, RandomizerRegion otherRegion,
@@ -928,7 +928,7 @@ void RegionTable_Init_FireTemple() {
ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_MAIN, true),
ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_MIDDLE, logic->CanUse(RG_SONG_OF_TIME) || logic->CanUse(RG_HOVER_BOOTS)),
ENTRANCE(RR_FIRE_TEMPLE_MQ_2_FIRE_WALLS_UPPER_DOOR, true),
//This one might be a bit too hard for base logic, but is only relevent in doorsanity or with RT_FIRE_MQ_MAZE_HOVERS
//This one might be a bit too hard for base logic, but is only relevant in doorsanity or with RT_FIRE_MQ_MAZE_HOVERS
ENTRANCE(RR_FIRE_TEMPLE_MQ_FIRE_MAZE_SWITCH, logic->CanUse(RG_SONG_OF_TIME) && logic->CanUse(RG_HOVER_BOOTS) && (logic->TakeDamage() || logic->CanJumpslash())),
});
@@ -843,7 +843,7 @@ void RegionTable_Init_SpiritTemple() {
LOCATION(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, SpiritShared(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND, []{return logic->CanOpenLargeChest();})),
}, {
//Exits
//If it is ever relevent for 1 age to spawn the mirror shield chest for the other can longshot across, it needs an eventAccess
//If it is ever relevant for 1 age to spawn the mirror shield chest for the other can longshot across, it needs an eventAccess
ENTRANCE(RR_SPIRIT_TEMPLE_MQ_RIGHT_HAND_EXIT, true),
ENTRANCE(RR_DESERT_COLOSSUS, SpiritCertainAccess(RR_SPIRIT_TEMPLE_MQ_OUTER_RIGHT_HAND)),
});
@@ -110,7 +110,7 @@ void RegionTable_Init_ZorasFountain() {
LOCATION(RC_ZF_GS_HIDDEN_CAVE, logic->IsAdult && logic->CanGetEnemyDrop(RE_GOLD_SKULLTULA, ED_BOMB_THROW) && logic->CanGetNightTimeGS()),
}, {
//Exits
//It is possible to avoid fall damage by jumping towards the right and landing in deeper water, but this is basically never relevent
//It is possible to avoid fall damage by jumping towards the right and landing in deeper water, but this is basically never relevant
ENTRANCE(RR_ZORAS_FOUNTAIN, logic->HasItem(RG_BRONZE_SCALE) || logic->TakeDamage()),
ENTRANCE(RR_ZF_HIDDEN_CAVE, true),
});
@@ -319,7 +319,7 @@ void Settings::CreateOptionDescriptions() {
mOptionDescriptions[RSK_SHUFFLE_TREES] =
"Trees will contain randomized items which are dropped the first time the player rolls into one.\n"
"Trees will have a special appearance when carrying randomized items.\n"
"\nSome trees are dependant on Link's age, such as some trees in Hyrule Field.\nTwo trees at Hyrule Castle are "
"\nSome trees are dependent on Link's age, such as some trees in Hyrule Field.\nTwo trees at Hyrule Castle are "
"only shuffle with No Logic.";
mOptionDescriptions[RSK_SHUFFLE_BUSHES] =
"Bushes in Hyrule Field & Zora's Fountain will contain randomized items when first walked through.";
+1 -1
View File
@@ -1759,7 +1759,7 @@ void Settings::CreateOptions() {
OPT_TRICK(RT_WATER_BK_REGION, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::INTERMEDIATE }, "WTBKHB");
OPT_TRICK(RT_WATER_NORTH_BASEMENT_LEDGE_JUMP, RCQUEST_BOTH, RA_WATER_TEMPLE, { Tricks::Tag::INTERMEDIATE },
"WTBolLdg");
// Also used in MQ logic, but won't be relevent unless a way to enter tower without irons exists (likely a clip +
// Also used in MQ logic, but won't be relevant unless a way to enter tower without irons exists (likely a clip +
// swim)
OPT_TRICK(RT_WATER_FW_CENTRAL_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTGSFW");
OPT_TRICK(RT_WATER_IRONS_CENTRAL_GS, RCQUEST_VANILLA, RA_WATER_TEMPLE, { Tricks::Tag::NOVICE }, "WTGSIB");
+1 -1
View File
@@ -832,7 +832,7 @@ void Menu::DrawElement() {
float columnHeight = sectionHeight - style.ItemSpacing.y * 4;
ImGui::SetNextWindowPos(pos + style.ItemSpacing * 2);
// Increase sidebar width on larger screens to accomodate people scaling their menus.
// Increase sidebar width on larger screens to accommodate people scaling their menus.
float sidebarWidth = 200 - style.ItemSpacing.x;
if (menuSize.x > 1600) {
sidebarWidth = menuSize.x * 0.15f;
+1 -1
View File
@@ -405,7 +405,7 @@ void RegisterResolutionWidgets() {
.RaceDisable(false);
// Error/Warning display
mSohMenu
->AddWidget(path, ICON_FA_EXCLAMATION_TRIANGLE " Significant frame rate (FPS) drops may be occuring.",
->AddWidget(path, ICON_FA_EXCLAMATION_TRIANGLE " Significant frame rate (FPS) drops may be occurring.",
WIDGET_TEXT)
.RaceDisable(false)
.PreFunc(
+1 -1
View File
@@ -1391,7 +1391,7 @@ void SohMenu::AddMenuEnhancements() {
.CVar(CVAR_ENHANCEMENT("DeleteFileOnDeath"))
.Options(CheckboxOptions().Tooltip("Dying will delete your file.\n\n" ICON_FA_EXCLAMATION_TRIANGLE
" WARNING " ICON_FA_EXCLAMATION_TRIANGLE
"\nTHIS IS NOT REVERSIBLE!\nUSE AT YOUR OWN RISK!"));
"\nTHIS IS IRREVERSIBLE!\nUSE AT YOUR OWN RISK!"));
AddWidget(path, "Switch Timer Multiplier", WIDGET_CVAR_SLIDER_INT)
.CVar(CVAR_ENHANCEMENT("SwitchTimerMultiplier"))
.Options(IntSliderOptions().Min(-5).Max(5).DefaultValue(0).Format("%+d").Tooltip(
@@ -79,7 +79,7 @@ void BgSpot00Hanebasi_Init(Actor* thisx, PlayState* play) {
}
if (gSaveContext.sceneLayer != 6) {
// Don't close the bridge in rando to accomodate hyrule castle exit
// Don't close the bridge in rando to accommodate hyrule castle exit
if (CHECK_QUEST_ITEM(QUEST_KOKIRI_EMERALD) && CHECK_QUEST_ITEM(QUEST_GORON_RUBY) &&
CHECK_QUEST_ITEM(QUEST_ZORA_SAPPHIRE) && !Flags_GetEventChkInf(EVENTCHKINF_ZELDA_FLED_HYRULE_CASTLE) &&
!(IS_RANDO)) {