Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 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
2c91789
start cleanup
Pepper0ni Jun 22, 2026
90f5333
Merge branch 'develop' into SplitSong
Pepper0ni Jun 22, 2026
657ea37
cleaned up and building
Pepper0ni Jun 22, 2026
01c9c15
Merge branch 'develop' into SplitSong
Pepper0ni Jun 22, 2026
1599f1b
Merge branch 'develop' into SplitSong
Pepper0ni Jun 22, 2026
f0c4720
seems to work
Pepper0ni Jun 22, 2026
4b9eb77
forgot to revert this after the move to all progressive didn't work out
Pepper0ni Jun 23, 2026
81dd083
more errors while cleaning up
Pepper0ni 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 @@ -9,6 +9,7 @@
#include "spoiler_log.hpp"
#include "soh/Enhancements/randomizer/Traps.h"
#include "z64item.h"
#include "../static_data.h"
#include <algorithm>
#include <spdlog/spdlog.h>

Expand Down Expand Up @@ -267,42 +268,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) {
SongData song = Rando::StaticData::songData[progSong];
if (hasStarting) {
return;
}
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
14 changes: 14 additions & 0 deletions soh/soh/Enhancements/randomizer/3drando/starting_inventory.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -115,6 +115,20 @@ void GenerateStartingInventory() {
if (ctx->GetOption(RSK_SHUFFLE_WEIRD_EGG)) {
AddItemToInventory(RG_WEIRD_EGG, ctx->GetOption(RSK_STARTING_WEIRD_EGG) ? 1 : 0);
}
if (!ctx->GetOption(RSK_SPLIT_OCARINA_SONGS)) {
AddItemToInventory(RG_PROGRESSIVE_ZELDAS_LULLABY, 1);
AddItemToInventory(RG_PROGRESSIVE_EPONAS_SONG, 1);
AddItemToInventory(RG_PROGRESSIVE_SARIAS_SONG, 1);
AddItemToInventory(RG_PROGRESSIVE_SUNS_SONG, 1);
AddItemToInventory(RG_PROGRESSIVE_SONG_OF_TIME, 1);
AddItemToInventory(RG_PROGRESSIVE_SONG_OF_STORMS, 1);
AddItemToInventory(RG_PROGRESSIVE_MINUET_OF_FOREST, 1);
AddItemToInventory(RG_PROGRESSIVE_BOLERO_OF_FIRE, 1);
AddItemToInventory(RG_PROGRESSIVE_SERENADE_OF_WATER, 1);
AddItemToInventory(RG_PROGRESSIVE_REQUIEM_OF_SPIRIT, 1);
AddItemToInventory(RG_PROGRESSIVE_NOCTURNE_OF_SHADOW, 1);
AddItemToInventory(RG_PROGRESSIVE_PRELUDE_OF_LIGHT, 1);
}
AddItemToInventory(RG_BUNNY_HOOD, ctx->GetOption(RSK_STARTING_BUNNY_HOOD) ? 1 : 0);
AddItemToInventory(RG_CLAIM_CHECK, ctx->GetOption(RSK_STARTING_CLAIM_CHECK) ? 1 : 0);
AddItemToInventory(RG_PROGRESSIVE_OCARINA, ctx->GetOption(RSK_STARTING_OCARINA).Get());
Expand Down
64 changes: 64 additions & 0 deletions soh/soh/Enhancements/randomizer/Traps.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
#include "soh/Enhancements/randomizer/static_data.h"
#include "soh/ShipUtils.h"

#include <spdlog/spdlog.h>
#include "soh/Enhancements/randomizer/3drando/random.hpp"

#include <vector>
Expand Down Expand Up @@ -359,6 +360,69 @@ static void InitTrickNames() {
Text{ "Progressive Flute", "Flûte (prog.)", "Flöte (prog.)" }, // "Flauta progresiva"
Text{ "Progressive Recorder", "Harmonica (prog.)", "Rekorder (prog.)" }, // "Armónica progresiva"
};
trickNameTable[RG_PROGRESSIVE_ZELDAS_LULLABY] = {
Text{ "Progressive Ballad of the Goddess", "Berceuse (prog.)", "Progressives Wiegenlied" },
Text{ "Progressive Song of Healing", "Chant de l'apaisement (prog.)", "Progressives Heilungslied" },
Text{ "Progressive Song of the Hero", "Chant du héros (prog.)", "Progressives Heldenlied" },
};
trickNameTable[RG_PROGRESSIVE_EPONAS_SONG] = {
Text{ "Progressive Song of Birds", "Chant d'Epona (prog.)", "Progressives Eponas Lied" },
Text{ "Progressive Song of Soaring", "Chant de l'envol (prog.)", "Progressives Lied der Schwingen" },
Text{ "Progressive Song of Horse", "Chant du cheval (prog.)", "Progressives Pferdelied" },
};
trickNameTable[RG_PROGRESSIVE_SARIAS_SONG] = {
Text{ "Progressive Mido's Song", "Chant de Saria (prog.)", "Progressives Salias Lied" },
Text{ "Progressive Kass' Theme", "Chant de Kass (prog.)", "Progressives Kashiwas Thema" },
Text{ "Progressive Tune of Echoes", "Chant des Échos (prog.)", "Progressive Melodie des Echos" },
};
trickNameTable[RG_PROGRESSIVE_SUNS_SONG] = {
Text{ "Progressive Song of Passing", "Chant du Soleil (prog.)", "Progressiver Hymne der Sonne" },
Text{ "Progressive Command Melody", "Mambo (prog.)", "Progressive Tag- und Nachtmusik" },
Text{ "Progressive Moon's Song", "Chant de la lune (prog.)", "Progressives Mondlied" },
};
trickNameTable[RG_PROGRESSIVE_SONG_OF_TIME] = {
Text{ "Progressive Song of Double Time", "Chant du Temps (prog.)", "Progressiver Hymne der Zeit" },
Text{ "Progressive Inverted Song of Time", "Chant du temps inversé (prog.)", "Progressive Ballade des Kronos" },
Text{ "Progressive Tune of Ages", "Chant du Temps (prog.)", "Progressive Melodie der Zeit" },
};
trickNameTable[RG_PROGRESSIVE_SONG_OF_STORMS] = {
Text{ "Progressive Ballad of Gales", "Chant des Tempêtes (prog.)", "Progressiver Hymne des Sturms" },
Text{ "Progressive Frog's Song of Soul", "Rap des grenouilles (prog.)", "Progressiver Krötenrap" },
Text{ "Progressive Wind's Requiem", "Mélodie du vent (prog.)", "Progressives Lied des Windes" },
};
trickNameTable[RG_PROGRESSIVE_MINUET_OF_FOREST] = {
Text{ "Progressive Saria's Karaoke", "Menuet des Bois (prog.)", "Progressives Menuett des Waldes" },
Text{ "Progressive Sonata of Awakening", "Sonate de l'éveil (prog.)", "Progressive Sonate des Erwachens" },
Text{ "Progressive Wind God's Aria", "Hymne du dieu du vent (prog.)", "Progressive Hymne des Zephirgottes" },
};
trickNameTable[RG_PROGRESSIVE_BOLERO_OF_FIRE] = {
Text{ "Progressive Darunia's Tango", "Boléro du Feu (prog.)", "Progressives Bolero des Feuers" },
Text{ "Progressive Tune of Currents", "Chants des Flux (prog.)", "Progressives Lied des Zeitstroms" },
Text{ "Progressive Goron Lullaby", "Berceuse des Gorons (prog.)", "Progressives Goronisches Schlummerlied" },
};
trickNameTable[RG_PROGRESSIVE_SERENADE_OF_WATER] = {
Text{ "Progressive Ruto's Blues", "Sérénade de l'Eau (prog.)", "Progressive Serenade des Wassers" },
Text{ "Progressive New Wave Bossa Nova", "Bossa-nova des flots (prog.)",
"Progressive Bossa Nova der Kaskaden" },
Text{ "Progressive Manbo's Mambo", "Mambo de Manbo (prog.)", "Progressives Manbos Mambo" },
};
trickNameTable[RG_PROGRESSIVE_REQUIEM_OF_SPIRIT] = {
Text{ "Progressive Nabooru's Reggae", "Requiem des Esprits (prog.)", "Progressives Requiem der Geister" },
Text{ "Progressive Elegy of Emptiness", "Hymne du vide (prog.)", "Progressive Elegie des leeren Herzens" },
Text{ "Progressive Earth God's Lyric", "Hymne du dieu de la terre (prog.)",
"Progressive Hymne des Terragottes" },
};
trickNameTable[RG_PROGRESSIVE_NOCTURNE_OF_SHADOW] = {
Text{ "Progressive Impa's Death Metal", "Nocturne de l'Ombre (prog.)", "Progressive Nocturne des Schattens" },
Text{ "Progressive Oath to Order", "Ode de l'appel (prog.)", "Progressiver Gesang des Himmels" },
Text{ "Progressive Song of Discovery", "Chant des secrets (prog.)", "Progressives Schatzsucherlied" },
};
trickNameTable[RG_PROGRESSIVE_PRELUDE_OF_LIGHT] = {
Text{ "Progressive Rauru's Sing-Along", "Prélude de la Lumière (prog.)", "Progressive Kantate des Lichts" },
Text{ "Progressive Ballad of the Wind Fish", "Ballade sur Poisson-Rêve (prog.)",
"Progressive Ballade vom Windfisch" },
Text{ "Progressive Song of Light", "Chant de la lumière (prog.)", "Progressives Lied des Lichts" },
};
trickNameTable[RG_PROGRESSIVE_GORONSWORD] = {
Text{ "Progressive Titan Blade", "Lame des Titans (prog.)",
"Titanenklinge (prog.)" }, // "Hoja del Titán progresiva"
Expand Down
20 changes: 20 additions & 0 deletions soh/soh/Enhancements/randomizer/item.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,26 @@ std::shared_ptr<GetItemEntry> Item::GetGIEntry() const { // NOLINT(*-no-recursio
case RG_PROGRESSIVE_GORONSWORD: // todo progressive?
actual = RG_BIGGORON_SWORD;
break;
case RG_PROGRESSIVE_ZELDAS_LULLABY:
case RG_PROGRESSIVE_EPONAS_SONG:
case RG_PROGRESSIVE_SARIAS_SONG:
case RG_PROGRESSIVE_SUNS_SONG:
case RG_PROGRESSIVE_SONG_OF_TIME:
case RG_PROGRESSIVE_SONG_OF_STORMS:
case RG_PROGRESSIVE_MINUET_OF_FOREST:
case RG_PROGRESSIVE_BOLERO_OF_FIRE:
case RG_PROGRESSIVE_SERENADE_OF_WATER:
case RG_PROGRESSIVE_REQUIEM_OF_SPIRIT:
case RG_PROGRESSIVE_NOCTURNE_OF_SHADOW:
case RG_PROGRESSIVE_PRELUDE_OF_LIGHT: {
const SongData* song = &StaticData::songData[randomizerGet];
if (logic->CheckRandoInf(song->randInf)) {
actual = song->realSong;
} else {
actual = song->part;
}
break;
}
case RG_PROGRESSIVE_BOMBCHU_BAG:
if (OTRGlobals::Instance->gRandoContext->GetOption(RSK_BOMBCHU_BAG).Is(RO_BOMBCHU_BAG_SINGLE)) {
if (logic->CurrentInventory(ITEM_BOMBCHU) != ITEM_NONE) {
Expand Down
Loading
Loading