Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
25 commits
Select commit Hold shift + click to select a range
9397b10
iAdd split ocarina songs mode with part-based progression.
RaccoonCloud Apr 24, 2026
5feddec
iUpdate split songs file headers with creator attribution.
RaccoonCloud Apr 24, 2026
2bd2ea4
Merge develop into feature/split-songs and resolve conflicts
RaccoonCloud Apr 24, 2026
5417774
Apply clang-format to split songs changes
RaccoonCloud Apr 24, 2026
3d0a0f6

RaccoonCloud Apr 26, 2026
0386051
Update split songs option text for progressive behavior.
RaccoonCloud Apr 26, 2026
6d49e4d
Randomizer: pickup textbox icons and progressive split songs
RaccoonCloud May 10, 2026
042e035
Fix clang-format in ItemMessages.cpp
RaccoonCloud May 10, 2026
6a10537
Randomizer: all song textbox icons work for progressive pickup
RaccoonCloud May 17, 2026
bc2027e
Simplify split songs to progressive-only RandInf tracking
RaccoonCloud Jun 4, 2026
72c849f
Address split songs PR review feedback
RaccoonCloud Jun 4, 2026
bd13ce5
Merge upstream develop into feature/split-songs
RaccoonCloud Jun 4, 2026
11a4287
Fix ItemMessages build after develop merge
RaccoonCloud Jun 4, 2026
f8464be
Bump libultraship to match upstream develop after merge
RaccoonCloud Jun 8, 2026
10f462d
Fix split song tracker texture lookup for Fast3dGui API
RaccoonCloud Jun 8, 2026
2340e5a
Fix seed generation crash when regenerating with split songs
RaccoonCloud Jun 8, 2026
3e1aff7
Fix split song part-1 grant and restore key ring icons
RaccoonCloud Jun 8, 2026
2998034
Simplify split songs to RandInf + progressive-only pattern.
RaccoonCloud Jun 9, 2026
600b8d3
Address split songs review: settings, pool, tracker, traps.
RaccoonCloud Jun 9, 2026
39427cc
Fix seed gen crash on progressive songs and clean up split songs menu…
RaccoonCloud Jun 9, 2026
b78aac9
Fix split song pickup icons and stabilize seed/save generation
RaccoonCloud Jun 15, 2026
79b6882
Fix Linux CI: use SaveData string overload for UTF-8 sanitization.
RaccoonCloud Jun 15, 2026
1198703
Merge upstream develop into feature/split-songs
RaccoonCloud Jun 15, 2026
7d146a6
Split PR scope per review: drop icon and UTF-8 side fixes.
RaccoonCloud Jun 18, 2026
2edee8d
Refactor split songs to PART items and static songData maps per review.
RaccoonCloud Jun 23, 2026
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
60 changes: 24 additions & 36 deletions soh/soh/Enhancements/randomizer/3drando/item_pool.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include "random.hpp"
#include "spoiler_log.hpp"
#include "soh/Enhancements/randomizer/Traps.h"
#include "../static_data.h"
#include "z64item.h"
#include <spdlog/spdlog.h>

Expand Down Expand Up @@ -252,42 +253,29 @@ void GenerateItemPool() {
// add extra songs only if song shuffle is anywhere
if (ctx->GetOption(RSK_SHUFFLE_SONGS).IsNot(RO_SONG_SHUFFLE_OFF)) {
bool songAnywhere = ctx->GetOption(RSK_SHUFFLE_SONGS).Is(RO_SONG_SHUFFLE_ANYWHERE);
if (!ctx->GetOption(RSK_STARTING_ZELDAS_LULLABY).Get()) {
AddItemToPool(RG_ZELDAS_LULLABY, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_EPONAS_SONG).Get()) {
AddItemToPool(RG_EPONAS_SONG, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_SARIAS_SONG).Get()) {
AddItemToPool(RG_SARIAS_SONG, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_SUNS_SONG).Get()) {
AddItemToPool(RG_SUNS_SONG, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_SONG_OF_TIME).Get()) {
AddItemToPool(RG_SONG_OF_TIME, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_SONG_OF_STORMS).Get()) {
AddItemToPool(RG_SONG_OF_STORMS, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_MINUET_OF_FOREST).Get()) {
AddItemToPool(RG_MINUET_OF_FOREST, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_BOLERO_OF_FIRE).Get()) {
AddItemToPool(RG_BOLERO_OF_FIRE, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_SERENADE_OF_WATER).Get()) {
AddItemToPool(RG_SERENADE_OF_WATER, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_REQUIEM_OF_SPIRIT).Get()) {
AddItemToPool(RG_REQUIEM_OF_SPIRIT, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_NOCTURNE_OF_SHADOW).Get()) {
AddItemToPool(RG_NOCTURNE_OF_SHADOW, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
if (!ctx->GetOption(RSK_STARTING_PRELUDE_OF_LIGHT).Get()) {
AddItemToPool(RG_PRELUDE_OF_LIGHT, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
}
auto addShuffledSong = [&](RandomizerGet progSong, bool hasStarting) {
if (hasStarting) {
return;
}
SongData song = Rando::StaticData::songData.at(progSong);
if (!ctx->GetOption(RSK_SPLIT_OCARINA_SONGS).Get()) {
AddItemToPool(song.realSong, songAnywhere ? 2 : 1, 1, 1, 1, songAnywhere);
} else {
AddItemToPool(progSong, 3, 2, 2, 2, songAnywhere);
}
};
addShuffledSong(RG_PROGRESSIVE_ZELDAS_LULLABY, ctx->GetOption(RSK_STARTING_ZELDAS_LULLABY).Get());
addShuffledSong(RG_PROGRESSIVE_EPONAS_SONG, ctx->GetOption(RSK_STARTING_EPONAS_SONG).Get());
addShuffledSong(RG_PROGRESSIVE_SARIAS_SONG, ctx->GetOption(RSK_STARTING_SARIAS_SONG).Get());
addShuffledSong(RG_PROGRESSIVE_SUNS_SONG, ctx->GetOption(RSK_STARTING_SUNS_SONG).Get());
addShuffledSong(RG_PROGRESSIVE_SONG_OF_TIME, ctx->GetOption(RSK_STARTING_SONG_OF_TIME).Get());
addShuffledSong(RG_PROGRESSIVE_SONG_OF_STORMS, ctx->GetOption(RSK_STARTING_SONG_OF_STORMS).Get());
addShuffledSong(RG_PROGRESSIVE_MINUET_OF_FOREST, ctx->GetOption(RSK_STARTING_MINUET_OF_FOREST).Get());
addShuffledSong(RG_PROGRESSIVE_BOLERO_OF_FIRE, ctx->GetOption(RSK_STARTING_BOLERO_OF_FIRE).Get());
addShuffledSong(RG_PROGRESSIVE_SERENADE_OF_WATER, ctx->GetOption(RSK_STARTING_SERENADE_OF_WATER).Get());
addShuffledSong(RG_PROGRESSIVE_REQUIEM_OF_SPIRIT, ctx->GetOption(RSK_STARTING_REQUIEM_OF_SPIRIT).Get());
addShuffledSong(RG_PROGRESSIVE_NOCTURNE_OF_SHADOW, ctx->GetOption(RSK_STARTING_NOCTURNE_OF_SHADOW).Get());
addShuffledSong(RG_PROGRESSIVE_PRELUDE_OF_LIGHT, ctx->GetOption(RSK_STARTING_PRELUDE_OF_LIGHT).Get());
} else {
ctx->PlaceItemInLocation(RC_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, false, true);
ctx->PlaceItemInLocation(RC_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, false, true);
Expand Down
4 changes: 4 additions & 0 deletions soh/soh/Enhancements/randomizer/3drando/playthrough.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
Random_Init(seed);

auto ctx = Rando::Context::GetInstance();
ctx->SetSeedGenerated(false);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you explain why you added these?

@RaccoonCloud RaccoonCloud Jun 17, 2026

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you again for your help and patience with me (first timer — I kept messaging Cal).

Every time I ran a new seed or generated one, SoH was crashing because other things (item tracker, spoiler lookups) could read placement data while Fill() was still mid-reset — like a “seed ready” race.

I SetSeedGenerated(false) at the top of Playthrough_Init and only flip to true after SpoilerLog_Write() finishes, so nothing treats the seed as valid until the spoiler JSON is fully written. Before that, things were trying to use spoiler data that wasn’t ready yet and it’d just crash on generate. If there’s a better way I’ll relook and sort.

This showed up most with split songs because the tracker hits song progress during seed generation, but the flag lifecycle fix is general — it just enforces generate → write → consume order.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rebuilt and tested split songs still works (first pickup = part / 1/2 on tracker, second = full song).
Pulled icon hooks and UTF-8 stuff into separate branches like you asked.
Also removed the logic scratch workaround progressive songs go through normal ApplyItemEffect now

ctx->overrides.clear();
ctx->ItemReset();
ctx->HintReset();
Expand Down Expand Up @@ -81,6 +82,9 @@ int Playthrough_Init(uint32_t seed, std::set<RandomizerCheck> excludedLocations,
SPDLOG_INFO("Writing Spoiler Log Done");
}

// Seed is only considered ready after spoiler JSON is fully written.
ctx->SetSeedGenerated(true);

ctx->playthroughLocations.clear();
ctx->playthroughBeatable = false;

Expand Down
24 changes: 12 additions & 12 deletions soh/soh/Enhancements/randomizer/ShuffleSongs.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ void Rando::StaticData::RegisterSongLocations() {
return;
registered = true;
// clang-format off
locationTable[RC_SHEIK_IN_FOREST] = Location::Base(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_MINUET_OF_FOREST, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST), true);
locationTable[RC_SHEIK_IN_CRATER] = Location::Base(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_CRATER, 0x00, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_BOLERO_OF_FIRE, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE), true);
locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Base(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_SERENADE_OF_WATER, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER), true);
locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Base(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_REQUIEM_OF_SPIRIT, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT), true);
locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Base(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_NOCTURNE_OF_SHADOW, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL), true);
locationTable[RC_SHEIK_AT_TEMPLE] = Location::Base(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, 0x00, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PRELUDE_OF_LIGHT, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT), true);
locationTable[RC_SONG_FROM_IMPA] = Location::Base(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_ZELDAS_LULLABY, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY), true);
locationTable[RC_SONG_FROM_MALON] = Location::Base(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_LON_LON_RANCH, 0x00, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_EPONAS_SONG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), true);
locationTable[RC_SONG_FROM_SARIA] = Location::Base(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_SARIAS_SONG, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG), true);
locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Base(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_ROYAL_FAMILYS_TOMB, 0x00, "Song from Royal Family's Tomb", "Song from Royal Family's Tomb", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_SUNS_SONG, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG), true);
locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Base(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_SONG_OF_TIME, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_TIME), true);
locationTable[RC_SONG_FROM_WINDMILL] = Location::Base(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 0x00, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_SONG_OF_STORMS, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), true);
locationTable[RC_SHEIK_IN_FOREST] = Location::Base(RC_SHEIK_IN_FOREST, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, "Sheik in Forest", "Sheik in Forest", RHT_SHEIK_IN_FOREST, RG_PROGRESSIVE_MINUET_OF_FOREST, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_MINUET_OF_FOREST), true);
locationTable[RC_SHEIK_IN_CRATER] = Location::Base(RC_SHEIK_IN_CRATER, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_DEATH_MOUNTAIN_CRATER, 0x00, "Sheik in Crater", "Sheik in Crater", RHT_SHEIK_IN_CRATER, RG_PROGRESSIVE_BOLERO_OF_FIRE, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_BOLERO_OF_FIRE), true);
locationTable[RC_SHEIK_IN_ICE_CAVERN] = Location::Base(RC_SHEIK_IN_ICE_CAVERN, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_ICE_CAVERN, 0x00, "Sheik in Ice Cavern", "Sheik in Ice Cavern", RHT_SHEIK_IN_ICE_CAVERN, RG_PROGRESSIVE_SERENADE_OF_WATER, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SERENADE_OF_WATER), true);
locationTable[RC_SHEIK_AT_COLOSSUS] = Location::Base(RC_SHEIK_AT_COLOSSUS, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_DESERT_COLOSSUS, 0x00, "Sheik at Colossus", "Sheik at Colossus", RHT_SHEIK_AT_COLOSSUS, RG_PROGRESSIVE_REQUIEM_OF_SPIRIT, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_REQUIEM_OF_SPIRIT), true);
locationTable[RC_SHEIK_IN_KAKARIKO] = Location::Base(RC_SHEIK_IN_KAKARIKO, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_KAKARIKO_VILLAGE, 0x00, "Sheik in Kakariko", "Sheik in Kakariko", RHT_SHEIK_IN_KAKARIKO, RG_PROGRESSIVE_NOCTURNE_OF_SHADOW, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_BONGO_BONGO_ESCAPED_FROM_WELL), true);
locationTable[RC_SHEIK_AT_TEMPLE] = Location::Base(RC_SHEIK_AT_TEMPLE, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_TEMPLE_OF_TIME, 0x00, "Sheik at Temple", "Sheik at Temple", RHT_SHEIK_AT_TEMPLE, RG_PROGRESSIVE_PRELUDE_OF_LIGHT, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_PRELUDE_OF_LIGHT), true);
locationTable[RC_SONG_FROM_IMPA] = Location::Base(RC_SONG_FROM_IMPA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_HYRULE_CASTLE, ACTOR_ID_MAX, SCENE_ID_MAX, 0x00, "Song from Impa", "Song from Impa", RHT_SONG_FROM_IMPA, RG_PROGRESSIVE_ZELDAS_LULLABY, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_ZELDAS_LULLABY), true);
locationTable[RC_SONG_FROM_MALON] = Location::Base(RC_SONG_FROM_MALON, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_LON_LON_RANCH, 0x00, "Song from Malon", "Song from Malon", RHT_SONG_FROM_MALON, RG_PROGRESSIVE_EPONAS_SONG, SpoilerCollectionCheck::RandomizerInf(RAND_INF_LEARNED_EPONA_SONG), true);
locationTable[RC_SONG_FROM_SARIA] = Location::Base(RC_SONG_FROM_SARIA, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_SACRED_FOREST_MEADOW, 0x00, "Song from Saria", "Song from Saria", RHT_SONG_FROM_SARIA, RG_PROGRESSIVE_SARIAS_SONG, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SARIAS_SONG), true);
locationTable[RC_SONG_FROM_ROYAL_FAMILYS_TOMB] = Location::Base(RC_SONG_FROM_ROYAL_FAMILYS_TOMB, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_ROYAL_FAMILYS_TOMB, 0x00, "Song from Royal Family's Tomb", "Song from Royal Family's Tomb", RHT_SONG_FROM_ROYAL_FAMILYS_TOMB, RG_PROGRESSIVE_SUNS_SONG, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SUNS_SONG), true);
locationTable[RC_SONG_FROM_OCARINA_OF_TIME] = Location::Base(RC_SONG_FROM_OCARINA_OF_TIME, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, ACTOR_ID_MAX, SCENE_HYRULE_FIELD, 0x00, "Song from Ocarina of Time", "Song from Ocarina of Time", RHT_SONG_FROM_OCARINA_OF_TIME, RG_PROGRESSIVE_SONG_OF_TIME, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_TIME), true);
locationTable[RC_SONG_FROM_WINDMILL] = Location::Base(RC_SONG_FROM_WINDMILL, RCQUEST_BOTH, RCTYPE_SONG_LOCATION, RCAREA_KAKARIKO_VILLAGE, ACTOR_ID_MAX, SCENE_WINDMILL_AND_DAMPES_GRAVE, 0x00, "Song from Windmill", "Song from Windmill", RHT_SONG_FROM_WINDMILL, RG_PROGRESSIVE_SONG_OF_STORMS, SpoilerCollectionCheck::EventChkInf(EVENTCHKINF_LEARNED_SONG_OF_STORMS), true);
// clang-format-on
}

Expand Down
Loading