mirror of
https://github.com/HarbourMasters/Shipwright
synced 2026-05-24 23:31:34 -04:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 32ad0ab4b8 | |||
| a5f7478b99 | |||
| 750ae907c2 | |||
| f665326a67 | |||
| 418d0f8e6c | |||
| 13b8f26435 | |||
| ba5d5c25d1 | |||
| 1fe862515d | |||
| 6eef813e5d | |||
| 76c9895432 | |||
| 048207eb7d | |||
| 170b9c1224 | |||
| 1e7cf8858f | |||
| 4b10a887a6 | |||
| ff3548a1b6 | |||
| fda198db76 | |||
| 7f06087cef | |||
| 6ae28273d1 | |||
| 5b2a50cac2 | |||
| 1e258318a1 | |||
| 156de816fb | |||
| ecb10e6ac2 | |||
| f42f86e3ef | |||
| 85bccab1bb |
@@ -101,9 +101,9 @@ jobs:
|
||||
- name: Install latest SDL
|
||||
run: |
|
||||
export PATH="/usr/lib/ccache:/usr/local/opt/ccache/libexec:$PATH"
|
||||
wget https://www.libsdl.org/release/SDL2-2.24.1.tar.gz
|
||||
tar -xzf SDL2-2.24.1.tar.gz
|
||||
cd SDL2-2.24.1
|
||||
wget https://www.libsdl.org/release/SDL2-2.26.1.tar.gz
|
||||
tar -xzf SDL2-2.26.1.tar.gz
|
||||
cd SDL2-2.26.1
|
||||
./configure
|
||||
make -j 10
|
||||
sudo make install
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ set(CMAKE_CXX_STANDARD 20 CACHE STRING "The C++ standard to use")
|
||||
set(CMAKE_OSX_DEPLOYMENT_TARGET "10.15" CACHE STRING "Minimum OS X deployment version" FORCE)
|
||||
|
||||
project(Ship LANGUAGES C CXX
|
||||
VERSION 5.1.3)
|
||||
set(PROJECT_BUILD_NAME "BRADLEY DELTA" CACHE STRING "")
|
||||
VERSION 5.1.4)
|
||||
set(PROJECT_BUILD_NAME "BRADLEY ECHO" CACHE STRING "")
|
||||
set(PROJECT_TEAM "github.com/harbourmasters" CACHE STRING "")
|
||||
|
||||
set_property(DIRECTORY ${CMAKE_SOURCE_DIR} PROPERTY VS_STARTUP_PROJECT soh)
|
||||
|
||||
@@ -32,17 +32,16 @@ def main():
|
||||
parser.add_argument("-z", "--zapd", help="Path to ZAPD executable", dest="zapd_exe", type=str)
|
||||
parser.add_argument("rom", help="Path to the rom", type=str, nargs="?")
|
||||
parser.add_argument("--non-interactive", help="Runs the script non-interactively for use in build scripts.", dest="non_interactive", action="store_true")
|
||||
parser.add_argument("-v", "--verbose", help="Display rom's header checksums and their corresponding xml folder", dest="verbose", action="store_true")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
rom_paths = [ args.rom ] if args.rom else rom_chooser.chooseROM(args.non_interactive)
|
||||
for rom_path in rom_paths:
|
||||
rom = Z64Rom(rom_path)
|
||||
|
||||
roms = [ Z64Rom(args.rom) ] if args.rom else rom_chooser.chooseROM(args.verbose, args.non_interactive)
|
||||
for rom in roms:
|
||||
if (os.path.exists("Extract")):
|
||||
shutil.rmtree("Extract")
|
||||
|
||||
BuildOTR("../soh/assets/xml/" + rom.version.xml_ver + "/", rom_path, zapd_exe=args.zapd_exe)
|
||||
BuildOTR("../soh/assets/xml/" + rom.version.xml_ver + "/", rom.file_path, zapd_exe=args.zapd_exe)
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
|
||||
@@ -2,12 +2,13 @@ import os, sys, glob
|
||||
|
||||
from rom_info import Z64Rom
|
||||
|
||||
def chooseROM(non_interactive=False):
|
||||
def chooseROM(verbose=False, non_interactive=False):
|
||||
roms = []
|
||||
|
||||
for file in glob.glob("*.z64"):
|
||||
if Z64Rom.isValidRom(file):
|
||||
roms.append(file)
|
||||
rom = Z64Rom(file)
|
||||
if rom.is_valid:
|
||||
roms.append(rom)
|
||||
|
||||
if not (roms):
|
||||
print("Error: No roms located, place one in the OTRExporter directory", file=os.sys.stderr)
|
||||
@@ -21,23 +22,28 @@ def chooseROM(non_interactive=False):
|
||||
foundMq = False
|
||||
foundOot = False
|
||||
for rom in roms:
|
||||
isMq = Z64Rom.isMqRom(rom)
|
||||
if isMq and not foundMq:
|
||||
if rom.isMq and not foundMq:
|
||||
romsToExtract.append(rom)
|
||||
foundMq = True
|
||||
elif not isMq and not foundOot:
|
||||
elif not rom.isMq and not foundOot:
|
||||
romsToExtract.append(rom)
|
||||
foundOot = True
|
||||
return romsToExtract
|
||||
|
||||
print(str(len(roms))+ " roms found, please select one by pressing 1-"+str(len(roms)))
|
||||
print(f"{len(roms)} roms found, please select one by pressing 1-{len(roms)}")
|
||||
print()
|
||||
|
||||
for i in range(len(roms)):
|
||||
print(str(i+1)+ ". " + roms[i])
|
||||
print(f"[{i+1:>2d}] {roms[i].file_path}")
|
||||
if verbose:
|
||||
print(f" Checksum: {roms[i].checksum.value}, Version XML: {roms[i].version.xml_ver}")
|
||||
print()
|
||||
|
||||
while(1):
|
||||
try:
|
||||
selection = int(input())
|
||||
except KeyboardInterrupt:
|
||||
sys.exit(1)
|
||||
except:
|
||||
print("Bad input. Try again with the number keys.")
|
||||
continue
|
||||
|
||||
@@ -221,7 +221,7 @@ void ZFile::ParseXML(tinyxml2::XMLElement* reader, const std::string& filename)
|
||||
// Check for repeated attributes.
|
||||
if (offsetXml != nullptr)
|
||||
{
|
||||
rawDataIndex = strtol(StringHelper::Split(offsetXml, "0x")[1].c_str(), NULL, 16);
|
||||
rawDataIndex = strtol(StringHelper::Split(std::string(offsetXml), "0x")[1].c_str(), NULL, 16);
|
||||
|
||||
if (offsetSet.find(offsetXml) != offsetSet.end())
|
||||
{
|
||||
@@ -831,7 +831,7 @@ void ZFile::GenerateSourceHeaderFiles()
|
||||
xmlPath = StringHelper::Replace(xmlPath, "\\", "/");
|
||||
auto pathList = StringHelper::Split(xmlPath, "/");
|
||||
std::string outPath = "";
|
||||
|
||||
|
||||
for (int i = 0; i < 3; i++)
|
||||
outPath += pathList[i] + "/";
|
||||
|
||||
@@ -1192,7 +1192,7 @@ std::string ZFile::ProcessTextureIntersections([[maybe_unused]] const std::strin
|
||||
|
||||
if (declarations.find(currentOffset) != declarations.end())
|
||||
declarations.at(currentOffset)->size = currentTex->GetRawDataSize();
|
||||
|
||||
|
||||
currentTex->DeclareVar(GetName(), "");
|
||||
}
|
||||
else
|
||||
|
||||
+1
-1
Submodule libultraship updated: df3a6dd292...7f04a562b2
@@ -32,4 +32,11 @@
|
||||
#define VT_RST VT_SGR("")
|
||||
#define VT_CLS VT_ED(2)
|
||||
|
||||
#ifdef USE_BELL
|
||||
// ASCII BEL character, plays an alert tone
|
||||
#define BEL '\a'
|
||||
#else
|
||||
#define BEL '\0'
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
@@ -29,6 +29,8 @@
|
||||
<string>@CMAKE_PROJECT_VERSION@</string>
|
||||
<key>NSHumanReadableCopyright</key>
|
||||
<string>Copyright 2022 HarbourMasters.</string>
|
||||
<key>LSApplicationCategoryType</key>
|
||||
<string>public.app-category.games</string>
|
||||
<key>LSMinimumSystemVersion</key>
|
||||
<string>10.15</string>
|
||||
</dict>
|
||||
|
||||
@@ -101,7 +101,7 @@ void CrowdControl::Disable() {
|
||||
|
||||
void CrowdControl::ListenToServer() {
|
||||
while (isEnabled) {
|
||||
while (!connected) {
|
||||
while (!connected && isEnabled) {
|
||||
SPDLOG_TRACE("[CrowdControl] Attempting to make connection to server...");
|
||||
tcpsock = SDLNet_TCP_Open(&ip);
|
||||
|
||||
@@ -112,8 +112,10 @@ void CrowdControl::ListenToServer() {
|
||||
}
|
||||
}
|
||||
|
||||
auto socketSet = SDLNet_AllocSocketSet(1);
|
||||
SDLNet_TCP_AddSocket(socketSet, tcpsock);
|
||||
SDLNet_SocketSet socketSet = SDLNet_AllocSocketSet(1);
|
||||
if (tcpsock) {
|
||||
SDLNet_TCP_AddSocket(socketSet, tcpsock);
|
||||
}
|
||||
|
||||
// Listen to socket messages
|
||||
while (connected && tcpsock && isEnabled) {
|
||||
|
||||
@@ -36,6 +36,7 @@ const std::vector<FlagTable> flagTables = {
|
||||
{ 0x09, "Used Deku Tree Blue Warp" },
|
||||
{ 0x0A, "Played Saria's Song for Mido as Adult" },
|
||||
{ 0x0C, "Met Deku Tree" },
|
||||
{ 0x0F, "Spoke to Mido about Saria's whereabouts" },
|
||||
{ 0x10, "Spoke to Child Malon at Castle or Market" },
|
||||
{ 0x11, "Spoke to Ingo at Ranch before Talon returns" },
|
||||
{ 0x12, "Obtained Pocket Egg" },
|
||||
@@ -219,7 +220,7 @@ const std::vector<FlagTable> flagTables = {
|
||||
{ 0x24, "Spoke to Kokiri Boy Cutting Grass" },
|
||||
{ 0x26, "Spoke to Kokiri Girl on Shop Awning" },
|
||||
{ 0x28, "Spoke to Kokiri Girl About Training Center" },
|
||||
{ 0x31, "Spoke to Kokiri Boy on Bed in Mido's House" },
|
||||
{ 0x41, "Spoke to Kokiri Boy on Bed in Mido's House" },
|
||||
{ 0x51, "Spoke to Kokiri Girl in Saria's House" },
|
||||
{ 0x59, "Spoke to Know-It-All Bro. About Temple" },
|
||||
{ 0x61, "Spoke to Know-It-All Bro. About Saria" },
|
||||
|
||||
@@ -55,9 +55,8 @@ void DrawPresetSelector(PresetType presetTypeId) {
|
||||
|
||||
ImGui::PushStyleVar(ImGuiStyleVar_FramePadding, ImVec2(6.0f, 4.0f));
|
||||
if (ImGui::Button(("Apply Preset##" + presetTypeCvar).c_str())) {
|
||||
if (selectedPresetId == 0) {
|
||||
clearCvars(presetTypeDef.cvarsToClear);
|
||||
} else {
|
||||
clearCvars(presetTypeDef.cvarsToClear);
|
||||
if (selectedPresetId != 0) {
|
||||
applyPreset(selectedPresetDef.entries);
|
||||
}
|
||||
SohImGui::RequestCvarSaveOnNextTick();
|
||||
|
||||
@@ -350,7 +350,7 @@ const std::vector<PresetEntry> enhancedPresetEntries = {
|
||||
// Text Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gTextSpeed", 5),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 2),
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 5),
|
||||
// Faster Block Push (+0 to +5)
|
||||
PRESET_ENTRY_S32("gFasterBlockPush", 5),
|
||||
// Better Owl
|
||||
@@ -394,8 +394,6 @@ const std::vector<PresetEntry> enhancedPresetEntries = {
|
||||
PRESET_ENTRY_S32("gBombchusOOB", 1),
|
||||
// Skip save confirmation
|
||||
PRESET_ENTRY_S32("gSkipSaveConfirmation", 1),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 5),
|
||||
// Biggoron Forge Time (0 to 3)
|
||||
PRESET_ENTRY_S32("gForgeTime", 0),
|
||||
// Vine/Ladder Climb speed (+0 to +12)
|
||||
@@ -467,7 +465,7 @@ const std::vector<PresetEntry> randomizerPresetEntries = {
|
||||
// Text Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gTextSpeed", 5),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 2),
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 5),
|
||||
// Faster Block Push (+0 to +5)
|
||||
PRESET_ENTRY_S32("gFasterBlockPush", 5),
|
||||
// Better Owl
|
||||
@@ -480,9 +478,6 @@ const std::vector<PresetEntry> randomizerPresetEntries = {
|
||||
// Inject Item Counts in messages
|
||||
PRESET_ENTRY_S32("gInjectItemCounts", 1),
|
||||
|
||||
// Pause link animation (0 to 16)
|
||||
PRESET_ENTRY_S32("gPauseLiveLink", 1),
|
||||
|
||||
// Dynamic Wallet Icon
|
||||
PRESET_ENTRY_S32("gDynamicWalletIcon", 1),
|
||||
// Always show dungeon entrances
|
||||
@@ -511,8 +506,6 @@ const std::vector<PresetEntry> randomizerPresetEntries = {
|
||||
PRESET_ENTRY_S32("gBombchusOOB", 1),
|
||||
// Skip save confirmation
|
||||
PRESET_ENTRY_S32("gSkipSaveConfirmation", 1),
|
||||
// King Zora Speed (1 to 5)
|
||||
PRESET_ENTRY_S32("gMweepSpeed", 5),
|
||||
// Biggoron Forge Time (0 to 3)
|
||||
PRESET_ENTRY_S32("gForgeTime", 0),
|
||||
// Vine/Ladder Climb speed (+0 to +12)
|
||||
|
||||
@@ -295,8 +295,8 @@ std::vector<uint32_t> GetAccessibleLocations(const std::vector<uint32_t>& allowe
|
||||
if (mode == SearchMode::GeneratePlaythrough && exit.IsShuffled() && !exit.IsAddedToPool() && !noRandomEntrances) {
|
||||
entranceSphere.push_back(&exit);
|
||||
exit.AddToPool();
|
||||
// Don't list a coupled entrance from both directions
|
||||
if (exit.GetReplacement()->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||
// Don't list a two-way coupled entrance from both directions
|
||||
if (exit.GetReverse() != nullptr && exit.GetReplacement()->GetReverse() != nullptr && !Settings::DecoupleEntrances) {
|
||||
exit.GetReplacement()->GetReverse()->AddToPool();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -418,6 +418,10 @@ void HintTable_Init_Exclude_Overworld() {
|
||||
Text{"a #carpet guru# sells", /*french*/"#un marchand du désert# vend", /*spanish*/"el #genio de una alfombra# vende"},
|
||||
});
|
||||
|
||||
hintTable[GC_MEDIGORON] = HintText::Exclude({
|
||||
//obscure text
|
||||
Text{"#Medigoron# sells", /*french*/"#Medigoron# vend", /*spanish*/"#Medigoron# vende"},
|
||||
});
|
||||
|
||||
hintTable[KAK_IMPAS_HOUSE_FREESTANDING_POH] = HintText::Exclude({
|
||||
//obscure text
|
||||
|
||||
@@ -286,6 +286,11 @@ Item& ItemFromGIID(const int giid) {
|
||||
}
|
||||
index++;
|
||||
}
|
||||
|
||||
// there are vanilla items that don't exist in the item table we're reading from here
|
||||
// if we made it this far, it means we didn't find an item in the table
|
||||
// if we don't return anything, the game will crash, so, as a workaround, return greg
|
||||
return itemTable[GREEN_RUPEE];
|
||||
}
|
||||
|
||||
//This function should only be used to place items containing hint text
|
||||
|
||||
@@ -3555,9 +3555,11 @@ void DrawRandoEditor(bool& open) {
|
||||
UIWidgets::InsertHelpHoverText(
|
||||
"Start with - You will start with all Small Keys from all dungeons.\n"
|
||||
"\n"
|
||||
"Vanilla - Small Keys will appear in their vanilla locations.\n"
|
||||
"Vanilla - Small Keys will appear in their vanilla locations. "
|
||||
"You start with 3 keys in Spirit Temple MQ because the vanilla key layout is not beatable in logic.\n"
|
||||
"\n"
|
||||
"Own dungeon - Small Keys can only appear in their respective dungeon.\n"
|
||||
"Own dungeon - Small Keys can only appear in their respective dungeon. "
|
||||
"If Fire Temple is not a Master Quest dungeon, the door to the Boss Key chest will be unlocked.\n"
|
||||
"\n"
|
||||
"Any dungeon - Small Keys can only appear inside of any dungon.\n"
|
||||
"\n"
|
||||
|
||||
@@ -587,8 +587,8 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
|
||||
RC_OBJECT(RC_WATER_TEMPLE_MORPHA_HEART, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_WATER_TEMPLE, ACTOR_ITEM_B_HEART, SCENE_MIZUSIN_BS, 0x00, GI_HEART_CONTAINER, "Morpha Heart Container", "Water Temple Morpha Heart Container"),
|
||||
|
||||
|
||||
RC_OBJECT(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPOT11, 1707, GI_GAUNTLETS_SILVER, "Silver Gauntlets Chest", "Spirit Temple Silver Gauntlets Chest"),
|
||||
RC_OBJECT(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPOT11, 13673, GI_SHIELD_MIRROR, "Mirror Shield Chest", "Spirit Temple Mirror Shield Chest"),
|
||||
RC_OBJECT(RC_SPIRIT_TEMPLE_SILVER_GAUNTLETS_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPOT11, 1707, GI_GAUNTLETS_SILVER, "Silver Gauntlets Chest", "Spirit Temple Silver Gauntlets Chest"),
|
||||
RC_OBJECT(RC_SPIRIT_TEMPLE_MIRROR_SHIELD_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_SPOT11, 13673, GI_SHIELD_MIRROR, "Mirror Shield Chest", "Spirit Temple Mirror Shield Chest"),
|
||||
RC_OBJECT(RC_SPIRIT_TEMPLE_CHILD_BRIDGE_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_JYASINZOU, 21800, GI_SHIELD_DEKU, "Child Bridge Chest", "Spirit Temple Child Bridge Chest"),
|
||||
RC_OBJECT(RC_SPIRIT_TEMPLE_CHILD_EARLY_TORCHES_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_JYASINZOU, -30656, GI_KEY_SMALL, "Child Early Torches Chest", "Spirit Temple Child Early Torches Chest"),
|
||||
RC_OBJECT(RC_SPIRIT_TEMPLE_COMPASS_CHEST, RCVORMQ_VANILLA, RCTYPE_MAP_COMPASS, RCAREA_SPIRIT_TEMPLE, ACTOR_EN_BOX, SCENE_JYASINZOU, 14340, GI_COMPASS, "Compass Chest", "Spirit Temple Compass Chest"),
|
||||
@@ -776,7 +776,7 @@ std::map<RandomizerCheck, RandomizerCheckObject> rcObjects = {
|
||||
RC_OBJECT(RC_GERUDO_TRAINING_GROUND_MQ_HEAVY_BLOCK_CHEST, RCVORMQ_MQ, RCTYPE_STANDARD, RCAREA_GERUDO_TRAINING_GROUND, ACTOR_EN_BOX, SCENE_MEN, 31394, GI_RUPEE_PURPLE, "MQ Heavy Block Chest", "Gerudo Training Grounds MQ Heavy Block Chest"),
|
||||
|
||||
|
||||
RC_OBJECT(RC_GANONS_TOWER_BOSS_KEY_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANON, 10219, GI_KEY_BOSS, "Boss Key Chest", "Ganon's Tower Boss Key Chest"),
|
||||
RC_OBJECT(RC_GANONS_TOWER_BOSS_KEY_CHEST, RCVORMQ_BOTH, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANON, 10219, GI_KEY_BOSS, "Boss Key Chest", "Ganon's Tower Boss Key Chest"),
|
||||
RC_OBJECT(RC_GANONS_CASTLE_FOREST_TRIAL_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, 30857, GI_MAGIC_LARGE, "Forest Trial Chest", "Ganon's Castle Forest Trial Chest"),
|
||||
RC_OBJECT(RC_GANONS_CASTLE_WATER_TRIAL_LEFT_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, 24455, GI_ICE_TRAP, "Water Trial Left Chest", "Ganon's Castle Water Trial Left Chest"),
|
||||
RC_OBJECT(RC_GANONS_CASTLE_WATER_TRIAL_RIGHT_CHEST, RCVORMQ_VANILLA, RCTYPE_STANDARD, RCAREA_GANONS_CASTLE, ACTOR_EN_BOX, SCENE_GANONTIKA, 22790, GI_HEART, "Water Trial Right Chest", "Ganon's Castle Water Trial Right Chest"),
|
||||
|
||||
@@ -198,8 +198,8 @@ s16 Entrance_OverrideNextIndex(s16 nextEntranceIndex) {
|
||||
}
|
||||
|
||||
// Exiting through the crawl space from Hyrule Castle courtyard is the same exit as leaving Ganon's castle
|
||||
// If we came from the Castle courtyard, then don't override the entrance to keep Link in Hyrule Castle area
|
||||
if (gPlayState != NULL && gPlayState->sceneNum == 69 && nextEntranceIndex == 0x023D) {
|
||||
// Don't override the entrance if we came from the Castle courtyard (day and night scenes)
|
||||
if (gPlayState != NULL && (gPlayState->sceneNum == 69 || gPlayState->sceneNum == 70) && nextEntranceIndex == 0x023D) {
|
||||
return nextEntranceIndex;
|
||||
}
|
||||
|
||||
@@ -433,6 +433,10 @@ void Entrance_HandleEponaState(void) {
|
||||
//If Link is riding Epona but he's about to go through an entrance where she can't spawn,
|
||||
//unset the Epona flag to avoid Master glitch, and restore temp B.
|
||||
if (Randomizer_GetSettingValue(RSK_SHUFFLE_OVERWORLD_ENTRANCES) && (player->stateFlags1 & PLAYER_STATE1_23)) {
|
||||
// Allow Master glitch to be performed on the Thieves Hideout entrance
|
||||
if (entrance == Entrance_GetOverride(0x0496)) { // Gerudo Fortress -> Theives Hideout
|
||||
return;
|
||||
}
|
||||
|
||||
static const s16 validEponaEntrances[] = {
|
||||
0x0102, // Hyrule Field -> Lake Hylia
|
||||
@@ -444,12 +448,11 @@ void Entrance_HandleEponaState(void) {
|
||||
0x0157, // Hyrule Field -> Lon Lon Ranch
|
||||
0x01F9, // Lon Lon Ranch -> Hyrule Field
|
||||
0x01FD, // Market Entrance -> Hyrule Field
|
||||
0x00EA, // ZR Front -> Hyrule Field
|
||||
0x0181, // LW Bridge -> Hyrule Field
|
||||
0x0181, // ZR Front -> Hyrule Field
|
||||
0x0185, // LW Bridge -> Hyrule Field
|
||||
0x0129, // GV Fortress Side -> Gerudo Fortress
|
||||
0x022D, // Gerudo Fortress -> GV Fortress Side
|
||||
0x03D0, // GV Carpenter Tent -> GV Fortress Side
|
||||
0x0496, // Gerudo Fortress -> Thieves Hideout
|
||||
0x042F, // LLR Stables -> Lon Lon Ranch
|
||||
0x05D4, // LLR Tower -> Lon Lon Ranch
|
||||
0x0378, // LLR Talons House -> Lon Lon Ranch
|
||||
|
||||
@@ -358,7 +358,7 @@ extern "C" u16 SfxEditor_GetReplacementSeq(u16 seqId) {
|
||||
seqId = NA_BGM_FIELD_LOGIC;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (sfxEditorSequenceMap.find(seqId) == sfxEditorSequenceMap.end()) {
|
||||
return seqId;
|
||||
}
|
||||
@@ -460,7 +460,7 @@ void InitSfxEditor() {
|
||||
}
|
||||
|
||||
extern "C" void SfxEditor_AddSequence(char *otrPath, uint16_t seqNum) {
|
||||
std::vector<std::string> splitName = StringHelper::Split(otrPath, "/");
|
||||
std::vector<std::string> splitName = StringHelper::Split(std::string(otrPath), "/");
|
||||
std::string fileName = splitName[splitName.size() - 1];
|
||||
std::vector<std::string> splitFileName = StringHelper::Split(fileName, "_");
|
||||
std::string sequenceName = splitFileName[0];
|
||||
|
||||
@@ -271,6 +271,10 @@ namespace GameMenuBar {
|
||||
ImGui::PopStyleVar(1);
|
||||
}
|
||||
|
||||
if (SohImGui::supportsWindowedFullscreen()) {
|
||||
UIWidgets::PaddedEnhancementCheckbox("Windowed fullscreen", "gSdlWindowedFullscreen", true, false);
|
||||
}
|
||||
|
||||
if (SohImGui::supportsViewports()) {
|
||||
UIWidgets::PaddedEnhancementCheckbox("Allow multi-windows", "gEnableMultiViewports", true, false);
|
||||
UIWidgets::Tooltip("Allows windows to be able to be dragged off of the main game window. Requires a reload to take effect.");
|
||||
|
||||
+13
-7
@@ -461,6 +461,11 @@ extern "C" void InitOTR() {
|
||||
#ifdef ENABLE_CROWD_CONTROL
|
||||
CrowdControl::Instance = new CrowdControl();
|
||||
CrowdControl::Instance->Init();
|
||||
if (CVar_GetS32("gCrowdControl", 0)) {
|
||||
CrowdControl::Instance->Enable();
|
||||
} else {
|
||||
CrowdControl::Instance->Disable();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -1757,12 +1762,13 @@ extern "C" void AudioPlayer_Play(const uint8_t* buf, uint32_t len) {
|
||||
}
|
||||
}
|
||||
|
||||
extern "C" int Controller_ShouldRumble(size_t i) {
|
||||
extern "C" int Controller_ShouldRumble(size_t slot) {
|
||||
auto controlDeck = Ship::Window::GetInstance()->GetControlDeck();
|
||||
|
||||
for (int i = 0; i < controlDeck->GetNumVirtualDevices(); ++i) {
|
||||
auto physicalDevice = controlDeck->GetPhysicalDeviceFromVirtualSlot(i);
|
||||
if (physicalDevice->CanRumble()) {
|
||||
|
||||
if (slot < controlDeck->GetNumVirtualDevices()) {
|
||||
auto physicalDevice = controlDeck->GetPhysicalDeviceFromVirtualSlot(slot);
|
||||
|
||||
if (physicalDevice->getProfile(slot)->UseRumble && physicalDevice->CanRumble()) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
@@ -1795,11 +1801,11 @@ extern "C" int GetEquipNowMessage(char* buffer, char* src, const int maxBufferSi
|
||||
std::string postfix;
|
||||
|
||||
if (gSaveContext.language == LANGUAGE_FRA) {
|
||||
postfix = "\x04\x1A\x08" "Désirez-vous l'équiper maintenant?" "\x09&&"
|
||||
postfix = "\x04\x1A\x08" "D\x96sirez-vous l'\x96quiper maintenant?" "\x09&&"
|
||||
"\x1B%g" "Oui" "&"
|
||||
"Non" "%w\x02";
|
||||
} else if (gSaveContext.language == LANGUAGE_GER) {
|
||||
postfix = "\x04\x1A\x08" "Möchtest Du es jetzt ausrüsten?" "\x09&&"
|
||||
postfix = "\x04\x1A\x08" "M""\x9A""chtest Du es jetzt ausr\x9Esten?" "\x09&&"
|
||||
"\x1B%g" "Ja!" "&"
|
||||
"Nein!" "%w\x02";
|
||||
} else {
|
||||
|
||||
@@ -104,7 +104,7 @@ int AudioPlayer_Buffered(void);
|
||||
int AudioPlayer_GetDesiredBuffered(void);
|
||||
void AudioPlayer_Play(const uint8_t* buf, uint32_t len);
|
||||
void AudioMgr_CreateNextAudioBuffer(s16* samples, u32 num_samples);
|
||||
int Controller_ShouldRumble(size_t i);
|
||||
int Controller_ShouldRumble(size_t slot);
|
||||
void Controller_BlockGameInput();
|
||||
void Controller_UnblockGameInput();
|
||||
void Hooks_ExecuteAudioInit();
|
||||
|
||||
@@ -168,7 +168,7 @@ void DmaMgr_Error(DmaRequest* req, const char* file, const char* errorName, cons
|
||||
char buff1[80];
|
||||
char buff2[80];
|
||||
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
osSyncPrintf(VT_FGCOL(RED));
|
||||
osSyncPrintf("DMA致命的エラー(%s)\nROM:%X RAM:%X SIZE:%X %s\n",
|
||||
errorDesc != NULL ? errorDesc : (errorName != NULL ? errorName : "???"), vrom, ram, size,
|
||||
@@ -348,7 +348,7 @@ s32 DmaMgr_SendRequestImpl(DmaRequest* req, uintptr_t ram, uintptr_t vrom, size_
|
||||
if (1) {
|
||||
if ((sDmaMgrQueueFullLogged == 0) && (sDmaMgrMsgQueue.validCount >= sDmaMgrMsgQueue.msgCount)) {
|
||||
sDmaMgrQueueFullLogged++;
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
osSyncPrintf(VT_FGCOL(RED));
|
||||
osSyncPrintf("dmaEntryMsgQが一杯です。キューサイズの再検討をおすすめします。");
|
||||
LOG_NUM("(sizeof(dmaEntryMsgBufs) / sizeof(dmaEntryMsgBufs[0]))", ARRAY_COUNT(sDmaMgrMsgs));
|
||||
|
||||
+1
-1
@@ -491,7 +491,7 @@ void GameState_Realloc(GameState* gameState, size_t size) {
|
||||
osSyncPrintf("ハイラル一時解放!!\n"); // "Hyrule temporarily released!!"
|
||||
SystemArena_GetSizes(&systemMaxFree, &systemFree, &systemAlloc);
|
||||
if ((systemMaxFree - 0x10) < size) {
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
osSyncPrintf(VT_FGCOL(RED));
|
||||
|
||||
// "Not enough memory. Change the hyral size to the largest possible value"
|
||||
|
||||
@@ -337,14 +337,14 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
|
||||
|
||||
if (pool->headMagic != GFXPOOL_HEAD_MAGIC) {
|
||||
//! @bug (?) : "problem = true;" may be missing
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
// "Dynamic area head is destroyed"
|
||||
osSyncPrintf(VT_COL(RED, WHITE) "ダイナミック領域先頭が破壊されています\n" VT_RST);
|
||||
Fault_AddHungupAndCrash(__FILE__, __LINE__);
|
||||
}
|
||||
if (pool->tailMagic != GFXPOOL_TAIL_MAGIC) {
|
||||
problem = true;
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
// "Dynamic region tail is destroyed"
|
||||
osSyncPrintf(VT_COL(RED, WHITE) "ダイナミック領域末尾が破壊されています\n" VT_RST);
|
||||
Fault_AddHungupAndCrash(__FILE__, __LINE__);
|
||||
@@ -353,19 +353,19 @@ void Graph_Update(GraphicsContext* gfxCtx, GameState* gameState) {
|
||||
|
||||
if (THGA_IsCrash(&gfxCtx->polyOpa)) {
|
||||
problem = true;
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
// "Zelda 0 is dead"
|
||||
osSyncPrintf(VT_COL(RED, WHITE) "ゼルダ0は死んでしまった(graph_alloc is empty)\n" VT_RST);
|
||||
}
|
||||
if (THGA_IsCrash(&gfxCtx->polyXlu)) {
|
||||
problem = true;
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
// "Zelda 1 is dead"
|
||||
osSyncPrintf(VT_COL(RED, WHITE) "ゼルダ1は死んでしまった(graph_alloc is empty)\n" VT_RST);
|
||||
}
|
||||
if (THGA_IsCrash(&gfxCtx->overlay)) {
|
||||
problem = true;
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
// "Zelda 4 is dead"
|
||||
osSyncPrintf(VT_COL(RED, WHITE) "ゼルダ4は死んでしまった(graph_alloc is empty)\n" VT_RST);
|
||||
}
|
||||
|
||||
@@ -116,7 +116,7 @@ void IrqMgr_CheckStack() {
|
||||
if (StackCheck_Check(NULL) == 0) {
|
||||
osSyncPrintf("スタックは大丈夫みたいです\n"); // "The stack looks ok"
|
||||
} else {
|
||||
osSyncPrintf("%c", 7);
|
||||
osSyncPrintf("%c", BEL);
|
||||
osSyncPrintf(VT_FGCOL(RED));
|
||||
// "Stack overflow or dangerous"
|
||||
osSyncPrintf("スタックがオーバーフローしたか危険な状態です\n");
|
||||
|
||||
@@ -331,7 +331,7 @@ void PadMgr_HandleRetraceMsg(PadMgr* padMgr) {
|
||||
osContGetReadData(padMgr->pads);
|
||||
|
||||
for (i = 0; i < __osMaxControllers; i++) {
|
||||
padMgr->padStatus[i].status = CVar_GetS32("gRumbleEnabled", 0) && Controller_ShouldRumble(i);
|
||||
padMgr->padStatus[i].status = Controller_ShouldRumble(i);
|
||||
}
|
||||
|
||||
if (padMgr->preNMIShutdown) {
|
||||
|
||||
@@ -897,21 +897,17 @@ void Minimap_Draw(PlayState* play) {
|
||||
//No idea why and how Original value work but this does actually fix them all.
|
||||
PosY = PosY+1024;
|
||||
}
|
||||
if ((gMapData->owEntranceFlag[sEntranceIconMapIndex] == 0xFFFF) ||
|
||||
((gMapData->owEntranceFlag[sEntranceIconMapIndex] != 0xFFFF) &&
|
||||
(gSaveContext.infTable[26] & gBitFlags[gMapData->owEntranceFlag[mapIndex]]))) {
|
||||
if (((gMapData->owEntranceFlag[sEntranceIconMapIndex] == 0xFFFF) ||
|
||||
((gMapData->owEntranceFlag[sEntranceIconMapIndex] != 0xFFFF) &&
|
||||
(gSaveContext.infTable[26] & gBitFlags[gMapData->owEntranceFlag[mapIndex]])
|
||||
)) || CVar_GetS32("gAlwaysShowDungeonMinimapIcon", 0)) {
|
||||
if (!Map0 || !CVar_GetS32("gFixDungeonMinimapIcon", 0)) {
|
||||
gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b,
|
||||
IconSize, IconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP,
|
||||
G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
gSPWideTextureRectangle(OVERLAY_DISP++, TopLeftX, TopLeftY, TopLeftW, TopLeftH, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
||||
}
|
||||
} else if (CVar_GetS32("gAlwaysShowDungeonMinimapIcon", 0) != 0){ //Ability to show entrance Before beating the dungeon itself
|
||||
gDPLoadTextureBlock(OVERLAY_DISP++, gMapDungeonEntranceIconTex, G_IM_FMT_RGBA, G_IM_SIZ_16b,
|
||||
IconSize, IconSize, 0, G_TX_NOMIRROR | G_TX_WRAP, G_TX_NOMIRROR | G_TX_WRAP,
|
||||
G_TX_NOMASK, G_TX_NOMASK, G_TX_NOLOD, G_TX_NOLOD);
|
||||
gSPWideTextureRectangle(OVERLAY_DISP++, TopLeftX, TopLeftY, TopLeftW, TopLeftH, G_TX_RENDERTILE, 0, 0, 1 << 10, 1 << 10);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
s16 entranceX = OTRGetRectDimensionFromRightEdge(270 + X_Margins_Minimap);
|
||||
|
||||
+25
-5
@@ -470,8 +470,7 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
GiveLinkRupees(9001);
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
// TODO: If master quest there are different key counts
|
||||
if (Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_BMORI1] = FOREST_TEMPLE_SMALL_KEY_MAX; // Forest
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_BMORI1] = FOREST_TEMPLE_SMALL_KEY_MAX; // Forest
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_HIDAN] = FIRE_TEMPLE_SMALL_KEY_MAX; // Fire
|
||||
@@ -488,6 +487,16 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_MEN] = GERUDO_TRAINING_GROUNDS_SMALL_KEY_MAX; // GTG
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_GANONTIKA] = GANONS_CASTLE_SMALL_KEY_MAX; // Ganon
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_GANONTIKA] = GANONS_CASTLE_SMALL_KEY_MAX; // Ganon
|
||||
} else if (Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_VANILLA) {
|
||||
// Logic cannot handle vanilla key layout in some dungeons
|
||||
// this is because vanilla expects the dungeon major item to be
|
||||
// locked behind the keys, which is not always true in rando.
|
||||
// We can resolve this by starting with some extra keys
|
||||
if (ResourceMgr_IsSceneMasterQuest(SCENE_JYASINZOU)) {
|
||||
// MQ Spirit needs 3 keys
|
||||
gSaveContext.inventory.dungeonKeys[SCENE_JYASINZOU] = 3;
|
||||
gSaveContext.sohStats.dungeonKeys[SCENE_JYASINZOU] = 3;
|
||||
}
|
||||
}
|
||||
|
||||
if(Randomizer_GetSettingValue(RSK_BOSS_KEYSANITY) == RO_DUNGEON_ITEM_LOC_STARTWITH) {
|
||||
@@ -516,12 +525,23 @@ void Sram_InitSave(FileChooseContext* fileChooseCtx) {
|
||||
gSaveContext.infTable[20] |= 4;
|
||||
|
||||
// Go away ruto (water temple first cutscene)
|
||||
gSaveContext.sceneFlags[05].swch |= (1 << 0x10);
|
||||
gSaveContext.sceneFlags[SCENE_MIZUSIN].swch |= (1 << 0x10);
|
||||
|
||||
// Opens locked Water Temple door to prevent softlocks
|
||||
// Open lowest Vanilla Fire Temple locked door (to prevent key logic lockouts)
|
||||
// Not done on keysanity since this lockout is a non issue when Fire keys can be found outside the temple
|
||||
u8 keysanity = Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANYWHERE ||
|
||||
Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_OVERWORLD ||
|
||||
Randomizer_GetSettingValue(RSK_KEYSANITY) == RO_DUNGEON_ITEM_LOC_ANY_DUNGEON;
|
||||
if (!ResourceMgr_IsSceneMasterQuest(SCENE_HIDAN) && !keysanity) {
|
||||
gSaveContext.sceneFlags[SCENE_HIDAN].swch |= (1 << 0x17);
|
||||
}
|
||||
|
||||
// Opens locked Water Temple door in vanilla to prevent softlocks
|
||||
// West door on the middle level that leads to the water raising thing
|
||||
// Happens in 3DS rando and N64 rando as well
|
||||
gSaveContext.sceneFlags[05].swch |= (1 << 0x15);
|
||||
if (!ResourceMgr_IsSceneMasterQuest(SCENE_MIZUSIN)) {
|
||||
gSaveContext.sceneFlags[SCENE_MIZUSIN].swch |= (1 << 0x15);
|
||||
}
|
||||
|
||||
// Skip intro cutscene when bombing mud wall in Dodongo's cavern
|
||||
// this also makes the lower jaw render, and the eyes react to explosives
|
||||
|
||||
@@ -30,6 +30,8 @@ typedef enum {
|
||||
#define WATER_LEVEL_LOWERED (WATER_LEVEL_RAISED - 680)
|
||||
#define WATER_LEVEL_RIVER_LOWERED (WATER_LEVEL_RIVER_RAISED - 80)
|
||||
|
||||
#define WATER_LEVEL_RIVER_LOWER_Z 2203
|
||||
|
||||
void BgSpot06Objects_Init(Actor* thisx, PlayState* play);
|
||||
void BgSpot06Objects_Destroy(Actor* thisx, PlayState* play);
|
||||
void BgSpot06Objects_Update(Actor* thisx, PlayState* play);
|
||||
@@ -210,6 +212,9 @@ void BgSpot06Objects_Destroy(Actor* thisx, PlayState* play) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Due to Ships resource caching, the water box collisions for the river have to be manually reset
|
||||
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z;
|
||||
|
||||
if (gSaveContext.n64ddFlag && Flags_GetRandomizerInf(RAND_INF_DUNGEONS_DONE_WATER_TEMPLE)) {
|
||||
// For randomizer when leaving lake hylia while the water level is lowered,
|
||||
// reset the "raise lake hylia water" flag back to on if the water temple is cleared
|
||||
@@ -591,6 +596,8 @@ void BgSpot06Objects_WaterPlaneCutsceneRise(BgSpot06Objects* this, PlayState* pl
|
||||
// On rando, this is used with the water control system switch to finalize raising the water
|
||||
if (gSaveContext.n64ddFlag) {
|
||||
this->lakeHyliaWaterLevel = 0;
|
||||
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_RAISED;
|
||||
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z;
|
||||
Flags_SetEventChkInf(EVENTCHKINF_RAISED_LAKE_HYLIA_WATER); // Set the "raise lake hylia water" flag
|
||||
play->roomCtx.unk_74[0] = 0; // Apply the moving under water texture to lake hylia ground
|
||||
}
|
||||
@@ -620,12 +627,14 @@ void BgSpot06Objects_WaterPlaneCutsceneLower(BgSpot06Objects* this, PlayState* p
|
||||
play->roomCtx.unk_74[0] = 87; // Remove the moving under water texture from lake hylia ground
|
||||
|
||||
if (this->lakeHyliaWaterLevel <= -681.0f) {
|
||||
this->lakeHyliaWaterLevel = -681.0f;
|
||||
this->dyna.actor.world.pos.y = WATER_LEVEL_RAISED;
|
||||
this->actionFunc = BgSpot06Objects_DoNothing;
|
||||
} else {
|
||||
// Go slightly beyond -681 so the smoothing doesn't slow down too much (matches the reverse of water rise func)
|
||||
Math_SmoothStepToF(&this->lakeHyliaWaterLevel, -682.0f, 0.1f, 1.0f, 0.001f);
|
||||
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].ySurface = WATER_LEVEL_RIVER_LOWERED;
|
||||
play->colCtx.colHeader->waterBoxes[LHWB_GERUDO_VALLEY_RIVER_LOWER].zMin = WATER_LEVEL_RIVER_LOWER_Z - 50;
|
||||
play->colCtx.colHeader->waterBoxes[LHWB_MAIN_1].ySurface = yPos;
|
||||
play->colCtx.colHeader->waterBoxes[LHWB_MAIN_2].ySurface = yPos;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
|
||||
#define MO_WATER_LEVEL(play) play->colCtx.colHeader->waterBoxes[0].ySurface
|
||||
|
||||
#define MO_STARTING_WATER_LEVEL (-60)
|
||||
|
||||
#define HAS_LINK(tent) \
|
||||
((tent != NULL) && \
|
||||
((tent->work[MO_TENT_ACTION_STATE] == MO_TENT_GRAB) || (tent->work[MO_TENT_ACTION_STATE] == MO_TENT_SHAKE)))
|
||||
@@ -338,6 +340,10 @@ void BossMo_Init(Actor* thisx, PlayState* play2) {
|
||||
BossMo* this = (BossMo*)thisx;
|
||||
u16 i;
|
||||
|
||||
// Due to Ships resource caching, the water level for Morpha needs to be reset
|
||||
// to ensure subsequent re-fights in the same running instance start with the correct level
|
||||
MO_WATER_LEVEL(play) = MO_STARTING_WATER_LEVEL;
|
||||
|
||||
Actor_ProcessInitChain(&this->actor, sInitChain);
|
||||
ActorShape_Init(&this->actor.shape, 0.0f, NULL, 0.0f);
|
||||
if (this->actor.params != BOSSMO_TENTACLE) {
|
||||
|
||||
@@ -159,13 +159,6 @@ void EnDoor_SetupType(EnDoor* this, PlayState* play) {
|
||||
}
|
||||
this->actor.world.rot.y = 0x0000;
|
||||
if (doorType == DOOR_LOCKED) {
|
||||
// unlock the door behind the hammer blocks
|
||||
// in the fire temple entryway when rando'd
|
||||
if (gSaveContext.n64ddFlag && play->sceneNum == 4) {
|
||||
// RANDOTODO don't do this when keysanity is enabled
|
||||
Flags_SetSwitch(play, 0x17);
|
||||
}
|
||||
|
||||
if (!Flags_GetSwitch(play, this->actor.params & 0x3F)) {
|
||||
this->lockTimer = 10;
|
||||
}
|
||||
|
||||
@@ -272,6 +272,15 @@ void ObjOshihiki_Init(Actor* thisx, PlayState* play2) {
|
||||
PlayState* play = play2;
|
||||
ObjOshihiki* this = (ObjOshihiki*)thisx;
|
||||
|
||||
// In MQ Spirit, remove the large silver block in the hole as child so the chest in the silver block hallway
|
||||
// can be guaranteed accessible
|
||||
if (gSaveContext.n64ddFlag && LINK_IS_CHILD && ResourceMgr_IsGameMasterQuest() &&
|
||||
play->sceneNum == SCENE_JYASINZOU && thisx->room == 6 && // Spirit Temple silver block hallway
|
||||
thisx->params == 0x9C7) { // Silver block that is marked as in the hole
|
||||
Actor_Kill(thisx);
|
||||
return;
|
||||
}
|
||||
|
||||
ObjOshihiki_CheckType(this, play);
|
||||
|
||||
if ((((this->dyna.actor.params >> 8) & 0xFF) >= 0) && (((this->dyna.actor.params >> 8) & 0xFF) <= 0x3F)) {
|
||||
|
||||
@@ -1295,7 +1295,7 @@ void Select_Main(GameState* thisx) {
|
||||
}
|
||||
|
||||
void Select_Destroy(GameState* thisx) {
|
||||
osSyncPrintf("%c", '\a'); // ASCII BEL character, plays an alert tone
|
||||
osSyncPrintf("%c", BEL);
|
||||
// "view_cleanup will hang, so it won't be called"
|
||||
osSyncPrintf("*** view_cleanupはハングアップするので、呼ばない ***\n");
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user