From 7cf071e7b60838139e238b531729e8ec7aa92df3 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 00:45:04 -0500 Subject: [PATCH 001/103] Defines the hook for OnTextLoad --- .../game-interactor/GameInteractor_HookTable.h | 1 + .../Enhancements/game-interactor/GameInteractor_Hooks.cpp | 8 ++++++++ .../Enhancements/game-interactor/GameInteractor_Hooks.h | 3 +++ 3 files changed, 12 insertions(+) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h index 59d511941..15e9855a0 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h @@ -67,3 +67,4 @@ DEFINE_HOOK(OnSetGameLanguage, ()); DEFINE_HOOK(OnFileDropped, (std::string filePath)); DEFINE_HOOK(OnAssetAltChange, ()); DEFINE_HOOK(OnKaleidoUpdate, ()); +DEFINE_HOOK(OnOpenText, (uint16_t* textId, bool* loadFromMessageTable)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 40c47e9a9..fd5b6e60e 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -290,3 +290,11 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) { void GameInteractor_ExecuteOnKaleidoUpdate() { GameInteractor::Instance->ExecuteHooks(); } + +// MARK: Messages +void GameInteractor_ExecuteOnOpenText(uint16_t* textId, bool* loadFromMessageTable) { + LUSLOG_DEBUG("OnOpenText: textId: {}", *textId); + GameInteractor::Instance->ExecuteHooks(textId, loadFromMessageTable); + GameInteractor::Instance->ExecuteHooksForID(*textId, textId, loadFromMessageTable); + GameInteractor::Instance->ExecuteHooksForFilter(textId, loadFromMessageTable); +} diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 10ab3a877..56e91bc1a 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -79,6 +79,9 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)); //Mark: - Pause Menu void GameInteractor_ExecuteOnKaleidoUpdate(); +// MARK: - Messages +void GameInteractor_ExecuteOnOpenText(uint16_t* textId, bool* loadFromMessageTable); + #ifdef __cplusplus } #endif From 907c559ff03824428b267abe8825e36007e2a1e2 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 01:29:47 -0500 Subject: [PATCH 002/103] Intercepts message loading with hooks --- soh/src/code/z_message_PAL.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index e6b944a73..1f140dfb2 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1672,6 +1672,9 @@ void Message_OpenText(PlayState* play, u16 textId) { Font* font = &msgCtx->font; s16 textBoxType; + bool loadFromMessageTable = false; + GameInteractor_ExecuteOnOpenText(&textId, &loadFromMessageTable); + if (msgCtx->msgMode == MSGMODE_NONE) { gSaveContext.unk_13EE = gSaveContext.unk_13EA; } @@ -1730,7 +1733,7 @@ void Message_OpenText(PlayState* play, u16 textId) { } // RANDOTODO: Use this for ice trap messages - if (CustomMessage_RetrieveIfExists(play)) { + if (!loadFromMessageTable) { osSyncPrintf("Found custom message"); } else if (sTextIsCredits) { Message_FindCreditsMessage(play, textId); From 679d0d3c6208f98242dddffda4664f9ee952262f Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 13:54:27 -0500 Subject: [PATCH 003/103] Adds file to handle the CustomMessage creation for items. --- .../Enhancements/randomizer/ItemMessages.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 soh/soh/Enhancements/randomizer/ItemMessages.cpp diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/ItemMessages.cpp new file mode 100644 index 000000000..4bb0b242b --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ItemMessages.cpp @@ -0,0 +1,17 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "variables.h" +} + +void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { + +} + +void RegisterItemMessages () { + COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_CUSTOM_ITEM, IS_RANDO, BuildItemMessage); +} + +static RegisterShipInitFunc initFunc(RegisterItemMessages, { "IS_RANDO" }); \ No newline at end of file From e41cc720dbe956cb361b8cdf697cad0130841f1a Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 18:19:35 -0500 Subject: [PATCH 004/103] Handles Ice Traps, Triforce Pieces, and Custom Items --- .../Enhancements/randomizer/ItemMessages.cpp | 372 +++++++++++++++++- 1 file changed, 370 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/ItemMessages.cpp index 4bb0b242b..39ed4bf8d 100644 --- a/soh/soh/Enhancements/randomizer/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/ItemMessages.cpp @@ -1,13 +1,381 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" #include "soh/ShipInit.hpp" +#include "randomizer.h" extern "C" { -#include "variables.h" +#include +#include +#include +#include +extern PlayState* gPlayState; +} + +static const char* const englishIceTrapMessages[169] = { + "You are a #FOOL#!", + "You are a #FOWL#!", + "#FOOL#!", + "You just got #PUNKED#!", + "Stay #frosty#, @.", + "Take a #chill pill#, @.", + "#Winter# is coming.", + "#ICE# to see you, @.", + "Feeling a little %rhot%w under the collar? #Let's fix that#.", + "It's a #cold day# in the Evil Realm.", + "Getting #cold feet#?", + "Say hello to the #Zoras# for me!", + "Can you keep a #cool head#?", + "Ganondorf used #Ice Trap#!&It's super effective!", + "Allow me to break the #ice#!", + "#Cold pun#.", + "The #Titanic# would be scared of you, @.", + "Oh no!", + "Uh oh!", + "What killed the dinosaurs?&The #ICE# age!", + "Knock knock. Who's there? Ice. Ice who? Ice see that you're a #FOOL#.", + "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", + "Thank you #@#! But your item is in another castle!", + "#FREEZE#! Don't move!", + "Wouldn't it be #ice# if we were colder?", + "Greetings from #Snowhead#! Wish you were here.", + "Too #cool# for you?", + "#Ice#, #ice#, baby...", + "Time to break the #ice#.", + "We wish that you would read this... We wish that you would read this... But we set our bar low.", + "#Freeze# and put your hands in the air!", + "#Ice# to meet you!", + "Do you want to #freeze# a snowman?", + "Isn't there a #mansion# around here?", + "Now you know how #King Zora# feels.", + "May the #Frost# be with you.", + "Carpe diem. #Freeze# the day.", + "There #snow# place like home.", + "That'll do, #ice#. That'll do.", + "All that is #cold# does not glitter. Not all those who wander are #frost#.", + "I Used To Be An Adventurer Like You. Then I Took An #Icetrap# To The Knee.", + "Would you like #ice# with that?", + "You have obtained the #Ice# Medallion!", + "Quick, do a #Zora# impression!", + "One item #on the rocks#!",//would be better if it could display the name of the item + "How much does a polar bear weigh?&Enough to break the #ice#.", + "You got Din's #Ice#!", + "You got Nayru's #Cold#!", + "You got Farore's #Freeze#!", + "KEKW", + "You just got #ICE TRAPPED#! Tag your friends to totally #ICE TRAP# them!", + "Are you okay, @? You're being #cold# today.", + "In a moment, your game might experience some #freezing#.", + "Breeze? Trees? Squeeze? No, it's a #freeze#!", + "After collecting this item, @ was assaulted in #cold# blood.", + "Only #chill# vibes around here!", + "Here's a #cool# gift for you!", + "Aha! You THOUGHT.", + "Stay hydrated and brush your teeth!", + "Isn't it too hot here? Let's turn the #AC# on.", + "One serving of #cold# @, coming right up!", + "Is it #cold# in here or is that just me?", + "Yahaha! You found me!", + "You'd make a great #ice#-tronaut!", + "That's just the tip of the #iceberg#!", + "It's the triforce!&No, just kidding, it's an #ice trap#.", + "WINNER!", + "LOSER!", + "Greetings from #Cold Miser#!", + "Pardon me while I turn up the #AC#.", + "If you can't stand the #cold#, get out of the #freezer#.", + "Oh, goodie! #Frozen @# for the main course!", + "You have #freeze# power!", + "You obtained the #Ice Beam#! No wait, wrong game.", + "Here's to another lousy millenium!", + "You've activated my #trap card#!", + "I love #refrigerators#!", + "You expected an item,&BUT IT WAS I, AN #ICE TRAP#!", + "It's dangerous to go alone! Take #this#!", + "soh.exe has #stopped responding#.", + "Enough! My #Ice Trap# thaws in the morning!", + "Nobody expects the span-#ice# inquisition!", + "This is one #cool# item!", + "Say hello to my #little friend#!", + "We made you an offer you #can't refuse#.", + "Hyrule? More like #Hycool#!", + "Ice puns are #snow# problem!", + "This #ice# is #snow# joke!", + "There's no business like #snow# business!", + "No, dude.", + "N#ice# trap ya got here!", + "Quick do your best impression of #Zoras Domain#!", + "Ganon used #ice beam#, it's super effective!", + "I was #frozen# today.", + "You're not in a #hurry#, right?", + "It's a #trap#!", + "At least it's not a VC crash and only Link is #frozen#!", + "Oh no! #BRAIN FREEZE#!", + "Looks like your game #froze#! Nope just you!", + "PK #FREEZE#!", + "May I interest you in some #iced# Tea?", + "Time for some Netflix and #chill#.", + "I know, I know... #FREEZE#!", + "#Ice# of you to drop by!", + "STOP!&You violated the #Thaw#!", + "I wanted to give you a treasure, but it looks like you got #cold feet#.", + "You told me you wanted to deliver #just ice# to Ganondorf!", + "You got the triforce!&This ancient artifact of divine power can grant any- wait, no, sorry, it's just an ice trap. My bad.", + "Time to #cool off#!", + "The #Ice Cavern# sends its regards.", + "Loading item, please #wait#...", + "Mash A+B to not #die#.", + "Sorry, your item is in another location.", //would be better if it could have the name of the item + "You only wish this was %gGreg%w.", + "Do you want to drink a hot chocolate?", + "The #cold# never bothered me anyway.", + "Hope you're too school for #cool#!", + "Be thankful this isn't #absolute zero#.", + "Did you know the F in ZFG stands for #Freeze#?", + "You got #Ice Age (2002)#!", + "Now you can cast a #spell# you don't know.", + "How's about a hero #on the rocks#?", + "Ain't no tunic for #this#!", + "I knew you were #part metroid#!", + "That's just the #icing on the cake#!", + "You're so #cool#, @!", + "You found #disappointment#!", + "You got #FOOLED#!", + "Start Mashing.", + "This item will #self-destruct# in 5 seconds...", + "Remember, there may be some momentary #discomfort#.", + "In a perfect world #ice traps# like me would not exist, but this is not a perfect world.", + "Gee, it sure is #cold# around here.", + "You tested the item with your #ice detector#, it beeped.", //would be better if it could have the name of the item + "You have found the way of the zero. The #sub-zero#.", + "Mweep... mweep... mweep...", + "Scum, #freezebag#! I mean #freeze#, scumbag!", + "Is it #chilly# in here or is it just #you#?", + "#Proceed#.", + "WHAT'S SHE GONNA DO, MAKE ME AN #[Ice Cream]#!?", + "You've met with a #terrible fate#, haven't you?", + "So I heard you like the Shining, here's how it #ends#.", + "Minor routing mistake. #I win#.", + "Hold this #L#, @.", + "#SKILL ISSUE#.", + "All your heat are belong to us.", + "Wait a second, don't you already have #this item#?", + "#Freeze#! We have you surrounded!", + "Error 404 - Item not #found#.", + "Hydration break! Hey, who #froze# my water?", + "Oops, wrong #item model#.", + "Whoops! You have to put the item #in your inventory#.", + "You dropped the item, shattering it into #shards of ice#!", //would be better if it could have the name of the item + "Is this... golden age Simpsons?&BECAUSE I'M ABOUT TO #CHOKE A CHILD#.", + "You are the weakest @, #goodbye#!", + "Ugh... Why did we even randomize #this item#?", + "The #Frost Moon# is rising...", + "According to all known laws of physics and biology, there is no way that @ should be able to survive #getting fully encased in ice#. The cells in @'s body would all die by the time they #unthaw#. Of course, this is a video game, so @ survives anyway... #Probably#.", + "Okay, so stop me if you've heard this one - a gamer and a bottle of #liquid nitrogen# walk into a milk bar...", + "Lástima, es una #trampa de hielo#...&&Nobody expects the Spanish #ice trap#!", + "Gee, it sure is #BURR#ing around here.", + "Navi? Oh! I thought she was called #Névé#!", + "It's fine, @ knew this was a #trap#, they're just using it to take damage intentionally to manipulate RNG.", + "Unfortunately, the item has #stopped#.", //would be better if it could have the name of the item + "This item is #not available# in your country.", //would be better if it could have the name of the item + "#Ice# try. #;)#", + "D'oh, I #missed#!", + "Where is my #super suit#?", + "#Titanic's revenge#.", +}; + +static const char* const germanIceTrapMessages[23] = { + "Du bist ein #DUMMKOPF#!", + "Du bist eine #Frostbeule#!", + "#DUMMKOPF#!", + "Du wurdest #eiskalt# erwischt!", + "Es läuft Dir #eiskalt# den Rücken hinunter, @.", + "Bleib #cool#, @.", + "Der #Winter# naht.", + "Alles #cool# im Pool?", + "#Abkühlung gefällig#?", + "Es ist ein %kalter%w Tag im Herzen von Hyrule.", + "Bekommst Du etwa #kalte# Füße?", + "Sag den #Zoras# viele Grüße von mir!", + "Bewahre einen #kühlen#! Kopf.", + "Ganondorf setzt #Eisstrahl# ein. Das ist sehr effektiv!", + "Ein Lächeln ist der beste Weg, um das #Eis# zu brechen!", + "#Eiskalt# lässt du meine Seele erfrier'n.", + "Die #Titanic# hätte Angst vor Dir, @.", + "Oh nein!", + "Was die Dinosaurier getötet hat?&Die #Eiszeit#!", + "Nachts ist es #kälter# als draußen.", + "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", + "Danke #@#! Aber der Gegenstand ist in einem anderem Schloß!", + "Kalt. Kalt. Kälter. #EISKALT#!", +}; + +static const char* const frenchIceTrapMessages[83] = { + "#Pauvre fou#...", + "Tu es un #glaçon#, Harry!", + "#Sot# que tu es.", + "Ça me #glace# le sang!", + "#Reste au frais#, @.", + "Et c'est la douche #froide#!", + "L'#hiver# vient.", + "#Glacier#!", + "Ça en jette un #froid#.", + "Est-ce que tu as déjà eu des sueurs #froides#?", + "La vengeance est un plat qui se mange #froid#!", + "Dit bonjour aux #Zoras# pour moi!", + "Il faut parfois savoir garder la tête #froide#!", + "Ganondorf utilise #Piège de Glace#! C'est super efficace!", + "Laisse moi briser la #glace#!", + "Balance man..., Cadence man..., Trace la #glace#..., c'est le Cooooolllll Rasta!", + "Le #Titanic# aurait peur de toi, @.", + "Oh non!", + "Qu'est-ce qui a tué les dinosaures?&L'ère #glacière#!", + "L'imbécile réfléchit uniquement quand il s'observe dans la #glace#.", + "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", + "Merci #@#! Mais ton objet est dans un autre château!", + "J'espère que ça ne te fait ni chaud, ni #froid#.", + "Je voulais t'offrir un trésor, mais il semble que tu aies eu #froid aux pieds#", + "Tu m'as dit que tu voulais livrer #de la glace# à Ganondorf!", + "Tu as obtenu la Triforce!&Cet ancien artefact divin peut exaucer n'importe quel... ah non, désolé, c'est juste un piège de glace.", + "Il est temps de #te rafraîchir#!", + "La #Caverne Polaire# te passe le bonjour.", + "Chargement de l'objet, veuillez #patienter#...", + "Martèle A+B pour ne pas #mourir#.", + "Désolé, ton objet est à un autre endroit.", //would be better if it could have the name of the item + "Tu espérais que ce soit %gGreg%w.", + "Tu veux boire un chocolat chaud?", + "Le #froid# ne m'a jamais dérangé, de toute façon.", + "J'espère que tu es trop cool pour être #cool#!", + "Sois reconnaissant que ce n'est pas le #zéro absolu#.", + "Tu savais que le G de ZFG signifie #Glace#?", + "Tu as obtenu #L'Âge de Glace (2002)#!", + "Maintenant, tu peux lancer un #sort# que tu ne connais pas.", + "Que dirais-tu d'un héros #sur glace# ?", + "Pas de tunique pour #ça#!", + "Je savais que tu étais #partiellement Metroid#!", + "Voilà juste la #cerise sur le gâteau#!", + "Tu es tellement #cool#, @!", + "Tu as trouvé de la #déception#!", + "Tu t'es fait #BERNER#!", + "Commence à marteler.", + "Cet objet va #s'autodétruire# dans 5 secondes...", + "Souviens-toi, il pourrait y avoir un léger #inconfort#.", + "Dans un monde parfait, les #pièges de glace# comme moi n'existeraient pas, mais ce n'est pas un monde parfait.", + "Mon dieu qu'il fait #froid# ici.", + "Tu as testé l'objet avec ton #détecteur de glace#, il a bipé.", //would be better if it could have the name of the item + "Tu as découvert le chemin du zéro. Le #sub-zéro#.", + "Mweep... mweep... mweep...", + "Gelé, #sac à glace#! Je veux dire #gèle-toi#, racaille!", + "Est-ce qu'il fait #frais# ici ou est-ce juste #toi#?", + "#Continue#", + "QU'EST-CE QU'ELLE VA FAIRE, ME FAIRE UNE #[Glace]#!?", + "Tu as rencontré un #terrible destin#, n'est-ce pas?", + "Alors comme ça, tu aimes Shining ? Voici comment ça #finit#.", + "Petite erreur de trajectoire. #Je gagne#.", + "Prends ce #L#, @.", + "#Problème de compétence#", + "Tout ton chauffage nous appartient.", + "Attends une seconde, tu as déjà #cet objet#, non?", + "#Gèle#! Tu es entouré !", + "Erreur 404 - Objet non #trouvé#.", + "Pause hydratation ! Hé, qui a #gelé# mon eau?", + "Oups, mauvais #modèle d'objet#.", + "Oups! Tu dois mettre l'objet #dans ton inventaire#.", + "Tu as fait tomber l'objet, le brisant en #éclats de glace#!", //would be better if it could have the name of the item + "Tu es le maillon faible @, #au revoir#!", + "Ugh... Pourquoi avons-nous même randomisé #cet objet#?", + "La #Lune de Givre# se lève...", + "Selon toutes les lois connues de la physique et de la biologie, @ ne devrait pas survivre à #être complètement enfermé dans la glace#. Les cellules de @ mourraient avant qu'elles ne #dégèlent#. Mais c'est un jeu vidéo, alors @ survit... #Probablement#.", + "OK, arrête-moi si tu l'as déjà entendue - un joueur et une bouteille de #nitrogène liquide# entrent dans un bar à lait...", + "Lástima, c'est un #piège de glace#...&&Personne ne s'attend à un #piège de glace espagnol#!", + "Mon dieu qu'il fait #GLAGLA# ici.", + "C'est bon, @ savait que c'était un #piège#, il l'utilise juste pour prendre des dégâts intentionnellement et manipuler la RNG.", + "Cet objet n'est #pas disponible# dans votre pays.", //would be better if it could have the name of the item + "#Bonne# tentative. #;)#", + "Où est mon #Super Costume#?", + "#La revanche du Titanic#.", +}; + +void BuildIceTrapMessage(CustomMessage& msg) { + if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { + msg = CustomMessage( + /*english*/ "This year for Christmas, all you get is #COAL#!", + /*german*/ "This year for Christmas, all you get is #COAL#!", + /*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", + { QM_BLUE } + ); + } else { + msg = CustomMessage( + RandomElement(englishIceTrapMessages), + RandomElement(germanIceTrapMessages), + RandomElement(frenchIceTrapMessages), + { QM_BLUE, QM_BLUE, QM_BLUE } + ); + } + + msg.AutoFormat(); +} + +void BuildTriforcePieceMessage(CustomMessage& msg) { + uint8_t current = gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected + 1; + uint8_t required = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) + 1; + uint8_t remaining = required - current; + float percentageCollected = (float)current / (float)required; + + if (percentageCollected <= 0.25) { + msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", + "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est un début!" }; + } else if (percentageCollected <= 0.5) { + msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", + "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Ça avance!" }; + } else if (percentageCollected <= 0.75) { + msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", + "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über die Hälfte!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" }; + } else if (percentageCollected < 1.0) { + msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", + "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est presque&terminé!" }; + } else if (current == required) { + msg = { "You completed the %yTriforce of&Courage%w! %gGG%w!", + "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", + "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }; + } else { + msg = { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", + "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", + "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, mais vous en avez %g[[current]]%w en&tout!" }; + } + msg.Replace("[[current]]", std::to_string(current)); + msg.Replace("[[remaining]]", std::to_string(remaining)); + msg.Replace("[[required]]", std::to_string(required)); + msg.Format(); +} + +void BuildCustomItemMessage(Player* player, CustomMessage& msg) { + int16_t rgid; + msg = CustomMessage("You found the %g[[name]]%w!", "Du erhältst das %g[[name]]%w!", "Vous ebtenez %g[[name]]%w!", TEXTBOX_TYPE_BLUE); + if (player->getItemEntry.objectId != OBJECT_INVALID) { + rgid = player->getItemEntry.getItemId; + } else { + rgid = player->getItemId; + } + CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); + name.Replace("[[name]]", name); + name.AutoFormat(); } void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { - + Player* player = GET_PLAYER(gPlayState); + CustomMessage messageEntry; + + if (player->getItemEntry.getItemId == RG_ICE_TRAP) { + BuildIceTrapMessage(messageEntry); + } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { + BuildTriforcePieceMessage(messageEntry); + } else { + BuildCustomItemMessage(player, messageEntry); + } } void RegisterItemMessages () { From 26230e2a3eae16664c5e02a57495faf7fc8e3508 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 19:25:24 -0500 Subject: [PATCH 005/103] Handle maps, compasses, and keys --- soh/include/macros.h | 10 +- .../Enhancements/randomizer/ItemMessages.cpp | 92 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 38 +------- 3 files changed, 99 insertions(+), 41 deletions(-) diff --git a/soh/include/macros.h b/soh/include/macros.h index 325fb91b6..f9d787633 100644 --- a/soh/include/macros.h +++ b/soh/include/macros.h @@ -330,10 +330,12 @@ extern GraphicsContext* __gfxCtx; #define GANONS_CASTLE_SMALL_KEY_MAX (ResourceMgr_IsSceneMasterQuest(SCENE_INSIDE_GANONS_CASTLE) ? 3 : 2) #define TREASURE_GAME_SMALL_KEY_MAX 6 -#define DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(randomizerSettingsKey) \ - (Randomizer_GetSettingValue(randomizerSettingsKey) != RO_DUNGEON_ITEM_LOC_STARTWITH && \ - Randomizer_GetSettingValue(randomizerSettingsKey) != RO_DUNGEON_ITEM_LOC_VANILLA && \ - Randomizer_GetSettingValue(randomizerSettingsKey) != RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) +#ifdef __cplusplus +#define DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(rsk) \ + (OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_STARTWITH) && \ + OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_VANILLA) && \ + OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON)) +#endif // #endregion #endif diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/ItemMessages.cpp index 39ed4bf8d..a879f5d87 100644 --- a/soh/soh/Enhancements/randomizer/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/ItemMessages.cpp @@ -8,6 +8,7 @@ extern "C" { #include #include #include +#include extern PlayState* gPlayState; } @@ -376,10 +377,101 @@ void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { } else { BuildCustomItemMessage(player, messageEntry); } + *loadFromMessageTable = false; +} + +void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { + GetItemEntry itemEntry = GET_PLAYER(gPlayState)->getItemEntry; + auto ctx = OTRGlobals::Instance->gRandoContext; + CustomMessage msg = CustomMessage( + "You found the %g[[name]]%w! [[typeHint]]", + "Du erhältst das %g[[name]]%w! [[typeHint]]", + "Vous ebtenez %g[[name]]%w! [[typeHint]]", + TEXTBOX_TYPE_BLUE + ); + int sceneNum; + switch (itemEntry.getItemId) { + case RG_DEKU_TREE_MAP: + sceneNum = SCENE_DEKU_TREE; + break; + case RG_DODONGOS_CAVERN_MAP: + sceneNum = SCENE_DODONGOS_CAVERN; + break; + case RG_JABU_JABUS_BELLY_MAP: + sceneNum = SCENE_JABU_JABU; + break; + case RG_FOREST_TEMPLE_MAP: + sceneNum = SCENE_FOREST_TEMPLE; + break; + case RG_FIRE_TEMPLE_MAP: + sceneNum = SCENE_FIRE_TEMPLE; + break; + case RG_WATER_TEMPLE_MAP: + sceneNum = SCENE_WATER_TEMPLE; + break; + case RG_SPIRIT_TEMPLE_MAP: + sceneNum = SCENE_SPIRIT_TEMPLE; + break; + case RG_SHADOW_TEMPLE_MAP: + sceneNum = SCENE_SHADOW_TEMPLE; + break; + case RG_BOTTOM_OF_THE_WELL_MAP: + sceneNum = SCENE_BOTTOM_OF_THE_WELL; + break; + case RG_ICE_CAVERN_MAP: + sceneNum = SCENE_ICE_CAVERN; + break; + } + if ( + ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_NONE) || + (ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_SET_NUMBER) && + ctx->GetOption(RSK_MQ_DUNGEON_COUNT).Is(12)) + ) { + msg.Replace("[[typeHint]]", ""); + } else if (ResourceMgr_IsSceneMasterQuest(sceneNum)) { + msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_MASTERFUL].GetHintMessage()); + } else { + msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage()); + } + *loadFromMessageTable = false; +} + +void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { + Player* player = GET_PLAYER(gPlayState); + if (player->getItemEntry.getItemId == RG_GANONS_CASTLE_BOSS_KEY && !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)) { + return; + } + if (player->getItemEntry.getItemId != RG_GANONS_CASTLE_BOSS_KEY && !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY)) { + return; + } + CustomMessage msg; + BuildCustomItemMessage(player, msg); + *loadFromMessageTable = false; +} + +void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { + Player* player = GET_PLAYER(gPlayState); + if (player->getItemEntry.getItemId == RG_GERUDO_FORTRESS_SMALL_KEY && OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_VANILLA)) { + return; + } + if (player->getItemEntry.getItemId != RG_GERUDO_FORTRESS_SMALL_KEY && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)) { + return; + } + CustomMessage msg; + BuildCustomItemMessage(player, msg); + *loadFromMessageTable = false; } void RegisterItemMessages () { COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_CUSTOM_ITEM, IS_RANDO, BuildItemMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_DUNGEON_MAP, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), BuildMapMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_COMPASS, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), BuildItemMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_BOSS, + (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY) || + DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)), BuildBossKeyMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_SMALL, + (OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).IsNot(RO_GERUDO_KEYS_VANILLA) || + DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)), BuildSmallKeyMessage); } static RegisterShipInitFunc initFunc(RegisterItemMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index ee98a70b3..2296cc1a3 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2121,43 +2121,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); Player* player = GET_PLAYER(play); - if (textId == TEXT_RANDOMIZER_CUSTOM_ITEM) { - if (player->getItemEntry.getItemId == RG_ICE_TRAP) { - messageEntry = Randomizer::GetIceTrapMessage(); - } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { - messageEntry = Randomizer::GetTriforcePieceMessage(); - } else { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } else if (textId == TEXT_ITEM_DUNGEON_MAP || textId == TEXT_ITEM_COMPASS) { - if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS)) { - if (textId == TEXT_ITEM_DUNGEON_MAP) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMapGetItemMessageWithHint(player->getItemEntry); - } else { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } - } else if (textId == TEXT_ITEM_KEY_BOSS) { - if (player->getItemEntry.getItemId == RG_GANONS_CASTLE_BOSS_KEY) { - if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)) { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } else { - if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY)) { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } - } else if (textId == TEXT_ITEM_KEY_SMALL) { - if (player->getItemEntry.getItemId == RG_GERUDO_FORTRESS_SMALL_KEY) { - if (Randomizer_GetSettingValue(RSK_GERUDO_KEYS) != RO_GERUDO_KEYS_VANILLA) { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } else { - if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)) { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } - } else if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != RO_GOSSIP_STONES_NONE && + if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != RO_GOSSIP_STONES_NONE && (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_NOTHING || (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_TRUTH && Player_GetMask(play) == PLAYER_MASK_TRUTH) || From 7e23c279cbc46859767dd5507bca85c2701bfcd9 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 20:20:04 -0500 Subject: [PATCH 006/103] Set up actual loading of messages into memory Only for the items, other things previously covered by CustomMessage_Retrieve if exists have not yet been covered as of this commit and will either load their vanilla text or crash. --- .../custom-message/CustomMessageManager.cpp | 34 +++++++++++++++++++ .../custom-message/CustomMessageManager.h | 2 ++ .../Enhancements/randomizer/ItemMessages.cpp | 24 +++++++------ soh/src/code/z_message_PAL.c | 2 +- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 1b993dab2..0745c6fc0 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace std::literals::string_literals; @@ -270,6 +271,39 @@ bool CustomMessage::operator!=(const CustomMessage& operand) const { return !operator==(operand); } +int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) { + if (!inputStr.empty()) { + // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents negatives. + memset(buffer, 0, std::max(0, maxBufferSize)); + // Gaurentee that this value will be greater than 0, regardless of passed variables. + const int copiedCharLen = std::min(std::max(0, maxBufferSize - 1), inputStr.length()); + memcpy(buffer, inputStr.c_str(), copiedCharLen); + return copiedCharLen; + } + + return 0; +} + +void CustomMessage::LoadIntoFont() { + MessageContext* msgCtx = &gPlayState->msgCtx; + Font* font = &msgCtx->font; + char* buffer = font->msgBuf; + const int maxBufferSize = sizeof(font->msgBuf); + font->charTexBuf[0] = (type << 4) | position; + switch (gSaveContext.language) { + case LANGUAGE_FRA: + msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetFrench(MF_RAW), buffer, maxBufferSize); + break; + case LANGUAGE_GER: + msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetGerman(MF_RAW), buffer, maxBufferSize); + break; + case LANGUAGE_ENG: + default: + msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetEnglish(MF_RAW), buffer, maxBufferSize); + break; + } +} + void CustomMessage::Replace(std::string&& oldStr, std::string&& newStr) { for (std::string& str : messages) { size_t position = str.find(oldStr); diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 0720d8ac4..506c2c43c 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -80,6 +80,8 @@ class CustomMessage { bool operator==(const std::string& operand) const; bool operator!=(const CustomMessage& right) const; + void LoadIntoFont(); + /** * @brief Finds an instance of oldStr in each language of the CustomMessage * and replaces it with newStr. Typically used for dynamic variable replacement diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/ItemMessages.cpp index a879f5d87..828958937 100644 --- a/soh/soh/Enhancements/randomizer/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/ItemMessages.cpp @@ -1,14 +1,12 @@ -#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" #include "soh/ShipInit.hpp" -#include "randomizer.h" +#include extern "C" { #include #include -#include -#include -#include extern PlayState* gPlayState; } @@ -362,22 +360,23 @@ void BuildCustomItemMessage(Player* player, CustomMessage& msg) { rgid = player->getItemId; } CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); - name.Replace("[[name]]", name); - name.AutoFormat(); + msg.Replace("[[name]]", name); + msg.AutoFormat(); } void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { Player* player = GET_PLAYER(gPlayState); - CustomMessage messageEntry; + CustomMessage msg; if (player->getItemEntry.getItemId == RG_ICE_TRAP) { - BuildIceTrapMessage(messageEntry); + BuildIceTrapMessage(msg); } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { - BuildTriforcePieceMessage(messageEntry); + BuildTriforcePieceMessage(msg); } else { - BuildCustomItemMessage(player, messageEntry); + BuildCustomItemMessage(player, msg); } *loadFromMessageTable = false; + msg.LoadIntoFont(); } void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { @@ -434,6 +433,7 @@ void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage()); } *loadFromMessageTable = false; + msg.LoadIntoFont(); } void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { @@ -447,6 +447,7 @@ void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; BuildCustomItemMessage(player, msg); *loadFromMessageTable = false; + msg.LoadIntoFont(); } void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { @@ -460,6 +461,7 @@ void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; BuildCustomItemMessage(player, msg); *loadFromMessageTable = false; + msg.LoadIntoFont(); } void RegisterItemMessages () { diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index 1f140dfb2..666256eb4 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -1672,7 +1672,7 @@ void Message_OpenText(PlayState* play, u16 textId) { Font* font = &msgCtx->font; s16 textBoxType; - bool loadFromMessageTable = false; + bool loadFromMessageTable = true; GameInteractor_ExecuteOnOpenText(&textId, &loadFromMessageTable); if (msgCtx->msgMode == MSGMODE_NONE) { From fc96ef3b93db4145e2448cc6f306f6dbd74b0510 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 20:58:51 -0500 Subject: [PATCH 007/103] Remove now-unused code --- .../Enhancements/randomizer/randomizer.cpp | 870 ------------------ soh/soh/Enhancements/randomizer/randomizer.h | 3 - soh/soh/OTRGlobals.cpp | 26 - 3 files changed, 899 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 8809d8691..ecea64dcb 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2699,68 +2699,6 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerCheck rc, TextIDs textId, return messageEntry; } -CustomMessage Randomizer::GetMapGetItemMessageWithHint(GetItemEntry itemEntry) { - CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, itemEntry.getItemId); - int sceneNum; - switch (itemEntry.getItemId) { - case RG_DEKU_TREE_MAP: - sceneNum = SCENE_DEKU_TREE; - break; - case RG_DODONGOS_CAVERN_MAP: - sceneNum = SCENE_DODONGOS_CAVERN; - break; - case RG_JABU_JABUS_BELLY_MAP: - sceneNum = SCENE_JABU_JABU; - break; - case RG_FOREST_TEMPLE_MAP: - sceneNum = SCENE_FOREST_TEMPLE; - break; - case RG_FIRE_TEMPLE_MAP: - sceneNum = SCENE_FIRE_TEMPLE; - break; - case RG_WATER_TEMPLE_MAP: - sceneNum = SCENE_WATER_TEMPLE; - break; - case RG_SPIRIT_TEMPLE_MAP: - sceneNum = SCENE_SPIRIT_TEMPLE; - break; - case RG_SHADOW_TEMPLE_MAP: - sceneNum = SCENE_SHADOW_TEMPLE; - break; - case RG_BOTTOM_OF_THE_WELL_MAP: - sceneNum = SCENE_BOTTOM_OF_THE_WELL; - break; - case RG_ICE_CAVERN_MAP: - sceneNum = SCENE_ICE_CAVERN; - break; - } - - if (GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_NONE || - (GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SET_NUMBER && - GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12) - ) { - messageEntry.Replace("[[typeHint]]", ""); - } else if (ResourceMgr_IsSceneMasterQuest(sceneNum)) { - messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_MASTERFUL].GetHintMessage()); - } else { - messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage()); - } - - return messageEntry; -} - -template -void CreateGetItemMessages(const std::array& messageEntries) { - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(Randomizer::getItemMessageTableID); - for (const GetItemMessage& messageEntry : messageEntries) { - customMessageManager->CreateGetItemMessage( - Randomizer::getItemMessageTableID, messageEntry.giid, messageEntry.iid, - CustomMessage(messageEntry.english, messageEntry.german, messageEntry.french, TEXTBOX_TYPE_BLUE, - TEXTBOX_POS_BOTTOM)); - } -} - void CreateRupeeMessages() { CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); @@ -2798,71 +2736,6 @@ CustomMessage Randomizer::GetRupeeMessage(u16 rupeeTextId) { return messageEntry; } -void CreateTriforcePieceMessages() { - CustomMessage TriforcePieceMessages[NUM_TRIFORCE_PIECE_MESSAGES] = { - - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", - "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est un début!" }, - - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", - "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Ça avance!" }, - - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", - "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über die Hälfte!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" }, - - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", - "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est presque&terminé!" }, - - { "You completed the %yTriforce of&Courage%w! %gGG%w!", - "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", - "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }, - - { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", - "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", - "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, mais vous en avez %g[[current]]%w en&tout!" }, - }; - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(Randomizer::triforcePieceMessageTableID); - for (unsigned int i = 0; i <= (NUM_TRIFORCE_PIECE_MESSAGES - 1); i++) { - customMessageManager->CreateMessage(Randomizer::triforcePieceMessageTableID, i, TriforcePieceMessages[i]); - } -} - -CustomMessage Randomizer::GetTriforcePieceMessage() { - // Item is only given after the textbox, so reflect that inside the textbox. - uint8_t current = gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected + 1; - uint8_t required = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) + 1; - uint8_t remaining = required - current; - float percentageCollected = (float)current / (float)required; - uint8_t messageIndex; - - if (percentageCollected <= 0.25) { - messageIndex = TH_MESSAGE_START; - } else if (percentageCollected <= 0.5) { - messageIndex = TH_MESSAGE_PROGRESS; - } else if (percentageCollected <= 0.75) { - messageIndex = TH_MESSAGE_HALFWAY; - } else if (percentageCollected < 1) { - messageIndex = TH_MESSAGE_ALMOSTDONE; - } else if (current == required) { - messageIndex = TH_MESSAGE_FINISHED; - } else { - messageIndex = TH_MESSAGE_SURPLUS; - } - - CustomMessage messageEntry = - CustomMessageManager::Instance->RetrieveMessage(Randomizer::triforcePieceMessageTableID, messageIndex); - messageEntry.Replace("[[current]]", std::to_string(current)); - messageEntry.Replace("[[remaining]]", std::to_string(remaining)); - messageEntry.Replace("[[required]]", std::to_string(required)); - messageEntry.Format(); - return messageEntry; -} - void CreateNaviRandoMessages() { CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { @@ -2975,313 +2848,6 @@ void CreateNaviRandoMessages() { } } -CustomMessage Randomizer::GetIceTrapMessage() { - static const char* const englishIceTrapMessages[169] = { - "You are a #FOOL#!", - "You are a #FOWL#!", - "#FOOL#!", - "You just got #PUNKED#!", - "Stay #frosty#, @.", - "Take a #chill pill#, @.", - "#Winter# is coming.", - "#ICE# to see you, @.", - "Feeling a little %rhot%w under the collar? #Let's fix that#.", - "It's a #cold day# in the Evil Realm.", - "Getting #cold feet#?", - "Say hello to the #Zoras# for me!", - "Can you keep a #cool head#?", - "Ganondorf used #Ice Trap#!&It's super effective!", - "Allow me to break the #ice#!", - "#Cold pun#.", - "The #Titanic# would be scared of you, @.", - "Oh no!", - "Uh oh!", - "What killed the dinosaurs?&The #ICE# age!", - "Knock knock. Who's there? Ice. Ice who? Ice see that you're a #FOOL#.", - "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", - "Thank you #@#! But your item is in another castle!", - "#FREEZE#! Don't move!", - "Wouldn't it be #ice# if we were colder?", - "Greetings from #Snowhead#! Wish you were here.", - "Too #cool# for you?", - "#Ice#, #ice#, baby...", - "Time to break the #ice#.", - "We wish that you would read this... We wish that you would read this... But we set our bar low.", - "#Freeze# and put your hands in the air!", - "#Ice# to meet you!", - "Do you want to #freeze# a snowman?", - "Isn't there a #mansion# around here?", - "Now you know how #King Zora# feels.", - "May the #Frost# be with you.", - "Carpe diem. #Freeze# the day.", - "There #snow# place like home.", - "That'll do, #ice#. That'll do.", - "All that is #cold# does not glitter. Not all those who wander are #frost#.", - "I Used To Be An Adventurer Like You. Then I Took An #Icetrap# To The Knee.", - "Would you like #ice# with that?", - "You have obtained the #Ice# Medallion!", - "Quick, do a #Zora# impression!", - "One item #on the rocks#!",//would be better if it could display the name of the item - "How much does a polar bear weigh?&Enough to break the #ice#.", - "You got Din's #Ice#!", - "You got Nayru's #Cold#!", - "You got Farore's #Freeze#!", - "KEKW", - "You just got #ICE TRAPPED#! Tag your friends to totally #ICE TRAP# them!", - "Are you okay, @? You're being #cold# today.", - "In a moment, your game might experience some #freezing#.", - "Breeze? Trees? Squeeze? No, it's a #freeze#!", - "After collecting this item, @ was assaulted in #cold# blood.", - "Only #chill# vibes around here!", - "Here's a #cool# gift for you!", - "Aha! You THOUGHT.", - "Stay hydrated and brush your teeth!", - "Isn't it too hot here? Let's turn the #AC# on.", - "One serving of #cold# @, coming right up!", - "Is it #cold# in here or is that just me?", - "Yahaha! You found me!", - "You'd make a great #ice#-tronaut!", - "That's just the tip of the #iceberg#!", - "It's the triforce!&No, just kidding, it's an #ice trap#.", - "WINNER!", - "LOSER!", - "Greetings from #Cold Miser#!", - "Pardon me while I turn up the #AC#.", - "If you can't stand the #cold#, get out of the #freezer#.", - "Oh, goodie! #Frozen @# for the main course!", - "You have #freeze# power!", - "You obtained the #Ice Beam#! No wait, wrong game.", - "Here's to another lousy millenium!", - "You've activated my #trap card#!", - "I love #refrigerators#!", - "You expected an item,&BUT IT WAS I, AN #ICE TRAP#!", - "It's dangerous to go alone! Take #this#!", - "soh.exe has #stopped responding#.", - "Enough! My #Ice Trap# thaws in the morning!", - "Nobody expects the span-#ice# inquisition!", - "This is one #cool# item!", - "Say hello to my #little friend#!", - "We made you an offer you #can't refuse#.", - "Hyrule? More like #Hycool#!", - "Ice puns are #snow# problem!", - "This #ice# is #snow# joke!", - "There's no business like #snow# business!", - "No, dude.", - "N#ice# trap ya got here!", - "Quick do your best impression of #Zoras Domain#!", - "Ganon used #ice beam#, it's super effective!", - "I was #frozen# today.", - "You're not in a #hurry#, right?", - "It's a #trap#!", - "At least it's not a VC crash and only Link is #frozen#!", - "Oh no! #BRAIN FREEZE#!", - "Looks like your game #froze#! Nope just you!", - "PK #FREEZE#!", - "May I interest you in some #iced# Tea?", - "Time for some Netflix and #chill#.", - "I know, I know... #FREEZE#!", - "#Ice# of you to drop by!", - "STOP!&You violated the #Thaw#!", - "I wanted to give you a treasure, but it looks like you got #cold feet#.", - "You told me you wanted to deliver #just ice# to Ganondorf!", - "You got the triforce!&This ancient artifact of divine power can grant any- wait, no, sorry, it's just an ice trap. My bad.", - "Time to #cool off#!", - "The #Ice Cavern# sends its regards.", - "Loading item, please #wait#...", - "Mash A+B to not #die#.", - "Sorry, your item is in another location.", //would be better if it could have the name of the item - "You only wish this was %gGreg%w.", - "Do you want to drink a hot chocolate?", - "The #cold# never bothered me anyway.", - "Hope you're too school for #cool#!", - "Be thankful this isn't #absolute zero#.", - "Did you know the F in ZFG stands for #Freeze#?", - "You got #Ice Age (2002)#!", - "Now you can cast a #spell# you don't know.", - "How's about a hero #on the rocks#?", - "Ain't no tunic for #this#!", - "I knew you were #part metroid#!", - "That's just the #icing on the cake#!", - "You're so #cool#, @!", - "You found #disappointment#!", - "You got #FOOLED#!", - "Start Mashing.", - "This item will #self-destruct# in 5 seconds...", - "Remember, there may be some momentary #discomfort#.", - "In a perfect world #ice traps# like me would not exist, but this is not a perfect world.", - "Gee, it sure is #cold# around here.", - "You tested the item with your #ice detector#, it beeped.", //would be better if it could have the name of the item - "You have found the way of the zero. The #sub-zero#.", - "Mweep... mweep... mweep...", - "Scum, #freezebag#! I mean #freeze#, scumbag!", - "Is it #chilly# in here or is it just #you#?", - "#Proceed#.", - "WHAT'S SHE GONNA DO, MAKE ME AN #[Ice Cream]#!?", - "You've met with a #terrible fate#, haven't you?", - "So I heard you like the Shining, here's how it #ends#.", - "Minor routing mistake. #I win#.", - "Hold this #L#, @.", - "#SKILL ISSUE#.", - "All your heat are belong to us.", - "Wait a second, don't you already have #this item#?", - "#Freeze#! We have you surrounded!", - "Error 404 - Item not #found#.", - "Hydration break! Hey, who #froze# my water?", - "Oops, wrong #item model#.", - "Whoops! You have to put the item #in your inventory#.", - "You dropped the item, shattering it into #shards of ice#!", //would be better if it could have the name of the item - "Is this... golden age Simpsons?&BECAUSE I'M ABOUT TO #CHOKE A CHILD#.", - "You are the weakest @, #goodbye#!", - "Ugh... Why did we even randomize #this item#?", - "The #Frost Moon# is rising...", - "According to all known laws of physics and biology, there is no way that @ should be able to survive #getting fully encased in ice#. The cells in @'s body would all die by the time they #unthaw#. Of course, this is a video game, so @ survives anyway... #Probably#.", - "Okay, so stop me if you've heard this one - a gamer and a bottle of #liquid nitrogen# walk into a milk bar...", - "Lástima, es una #trampa de hielo#...&&Nobody expects the Spanish #ice trap#!", - "Gee, it sure is #BURR#ing around here.", - "Navi? Oh! I thought she was called #Névé#!", - "It's fine, @ knew this was a #trap#, they're just using it to take damage intentionally to manipulate RNG.", - "Unfortunately, the item has #stopped#.", //would be better if it could have the name of the item - "This item is #not available# in your country.", //would be better if it could have the name of the item - "#Ice# try. #;)#", - "D'oh, I #missed#!", - "Where is my #super suit#?", - "#Titanic's revenge#.", - }; - - static const char* const germanIceTrapMessages[23] = { - "Du bist ein #DUMMKOPF#!", - "Du bist eine #Frostbeule#!", - "#DUMMKOPF#!", - "Du wurdest #eiskalt# erwischt!", - "Es läuft Dir #eiskalt# den Rücken hinunter, @.", - "Bleib #cool#, @.", - "Der #Winter# naht.", - "Alles #cool# im Pool?", - "#Abkühlung gefällig#?", - "Es ist ein %kalter%w Tag im Herzen von Hyrule.", - "Bekommst Du etwa #kalte# Füße?", - "Sag den #Zoras# viele Grüße von mir!", - "Bewahre einen #kühlen#! Kopf.", - "Ganondorf setzt #Eisstrahl# ein. Das ist sehr effektiv!", - "Ein Lächeln ist der beste Weg, um das #Eis# zu brechen!", - "#Eiskalt# lässt du meine Seele erfrier'n.", - "Die #Titanic# hätte Angst vor Dir, @.", - "Oh nein!", - "Was die Dinosaurier getötet hat?&Die #Eiszeit#!", - "Nachts ist es #kälter# als draußen.", - "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", - "Danke #@#! Aber der Gegenstand ist in einem anderem Schloß!", - "Kalt. Kalt. Kälter. #EISKALT#!", - }; - - static const char* const frenchIceTrapMessages[83] = { - "#Pauvre fou#...", - "Tu es un #glaçon#, Harry!", - "#Sot# que tu es.", - "Ça me #glace# le sang!", - "#Reste au frais#, @.", - "Et c'est la douche #froide#!", - "L'#hiver# vient.", - "#Glacier#!", - "Ça en jette un #froid#.", - "Est-ce que tu as déjà eu des sueurs #froides#?", - "La vengeance est un plat qui se mange #froid#!", - "Dit bonjour aux #Zoras# pour moi!", - "Il faut parfois savoir garder la tête #froide#!", - "Ganondorf utilise #Piège de Glace#! C'est super efficace!", - "Laisse moi briser la #glace#!", - "Balance man..., Cadence man..., Trace la #glace#..., c'est le Cooooolllll Rasta!", - "Le #Titanic# aurait peur de toi, @.", - "Oh non!", - "Qu'est-ce qui a tué les dinosaures?&L'ère #glacière#!", - "L'imbécile réfléchit uniquement quand il s'observe dans la #glace#.", - "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", - "Merci #@#! Mais ton objet est dans un autre château!", - "J'espère que ça ne te fait ni chaud, ni #froid#.", - "Je voulais t'offrir un trésor, mais il semble que tu aies eu #froid aux pieds#", - "Tu m'as dit que tu voulais livrer #de la glace# à Ganondorf!", - "Tu as obtenu la Triforce!&Cet ancien artefact divin peut exaucer n'importe quel... ah non, désolé, c'est juste un piège de glace.", - "Il est temps de #te rafraîchir#!", - "La #Caverne Polaire# te passe le bonjour.", - "Chargement de l'objet, veuillez #patienter#...", - "Martèle A+B pour ne pas #mourir#.", - "Désolé, ton objet est à un autre endroit.", //would be better if it could have the name of the item - "Tu espérais que ce soit %gGreg%w.", - "Tu veux boire un chocolat chaud?", - "Le #froid# ne m'a jamais dérangé, de toute façon.", - "J'espère que tu es trop cool pour être #cool#!", - "Sois reconnaissant que ce n'est pas le #zéro absolu#.", - "Tu savais que le G de ZFG signifie #Glace#?", - "Tu as obtenu #L'Âge de Glace (2002)#!", - "Maintenant, tu peux lancer un #sort# que tu ne connais pas.", - "Que dirais-tu d'un héros #sur glace# ?", - "Pas de tunique pour #ça#!", - "Je savais que tu étais #partiellement Metroid#!", - "Voilà juste la #cerise sur le gâteau#!", - "Tu es tellement #cool#, @!", - "Tu as trouvé de la #déception#!", - "Tu t'es fait #BERNER#!", - "Commence à marteler.", - "Cet objet va #s'autodétruire# dans 5 secondes...", - "Souviens-toi, il pourrait y avoir un léger #inconfort#.", - "Dans un monde parfait, les #pièges de glace# comme moi n'existeraient pas, mais ce n'est pas un monde parfait.", - "Mon dieu qu'il fait #froid# ici.", - "Tu as testé l'objet avec ton #détecteur de glace#, il a bipé.", //would be better if it could have the name of the item - "Tu as découvert le chemin du zéro. Le #sub-zéro#.", - "Mweep... mweep... mweep...", - "Gelé, #sac à glace#! Je veux dire #gèle-toi#, racaille!", - "Est-ce qu'il fait #frais# ici ou est-ce juste #toi#?", - "#Continue#", - "QU'EST-CE QU'ELLE VA FAIRE, ME FAIRE UNE #[Glace]#!?", - "Tu as rencontré un #terrible destin#, n'est-ce pas?", - "Alors comme ça, tu aimes Shining ? Voici comment ça #finit#.", - "Petite erreur de trajectoire. #Je gagne#.", - "Prends ce #L#, @.", - "#Problème de compétence#", - "Tout ton chauffage nous appartient.", - "Attends une seconde, tu as déjà #cet objet#, non?", - "#Gèle#! Tu es entouré !", - "Erreur 404 - Objet non #trouvé#.", - "Pause hydratation ! Hé, qui a #gelé# mon eau?", - "Oups, mauvais #modèle d'objet#.", - "Oups! Tu dois mettre l'objet #dans ton inventaire#.", - "Tu as fait tomber l'objet, le brisant en #éclats de glace#!", //would be better if it could have the name of the item - "Tu es le maillon faible @, #au revoir#!", - "Ugh... Pourquoi avons-nous même randomisé #cet objet#?", - "La #Lune de Givre# se lève...", - "Selon toutes les lois connues de la physique et de la biologie, @ ne devrait pas survivre à #être complètement enfermé dans la glace#. Les cellules de @ mourraient avant qu'elles ne #dégèlent#. Mais c'est un jeu vidéo, alors @ survit... #Probablement#.", - "OK, arrête-moi si tu l'as déjà entendue - un joueur et une bouteille de #nitrogène liquide# entrent dans un bar à lait...", - "Lástima, c'est un #piège de glace#...&&Personne ne s'attend à un #piège de glace espagnol#!", - "Mon dieu qu'il fait #GLAGLA# ici.", - "C'est bon, @ savait que c'était un #piège#, il l'utilise juste pour prendre des dégâts intentionnellement et manipuler la RNG.", - "Cet objet n'est #pas disponible# dans votre pays.", //would be better if it could have the name of the item - "#Bonne# tentative. #;)#", - "Où est mon #Super Costume#?", - "#La revanche du Titanic#.", - }; - - CustomMessage msg; - - if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { - msg = CustomMessage( - /*english*/ "This year for Christmas, all you get is #COAL#!", - /*german*/ "This year for Christmas, all you get is #COAL#!", - /*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", - { QM_BLUE } - ); - } else { - msg = CustomMessage( - RandomElement(englishIceTrapMessages), - RandomElement(germanIceTrapMessages), - RandomElement(frenchIceTrapMessages), - { QM_BLUE, QM_BLUE, QM_BLUE } - ); - } - - msg.AutoFormat(); - return msg; -} - static int goronIDs[9] = { TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME, TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET, TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET, @@ -3383,443 +2949,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { } void Randomizer::CreateCustomMessages() { - // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED - // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = {{ - GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, - "You found %gGreg%w!", - "%gGreg%w! Du hast ihn wirklich gefunden!", - "Félicitation! Vous avez trouvé %gGreg%w!"), - GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, - "You found the %gMaster Sword%w!", - "Du erhältst das %gMaster-Schwert%w!", - "Vous obtenez %gl'Épée de Légende%w!"), - GIMESSAGE(RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, - "You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!", - "Du erhältst eine %rFlasche mit&blauem Feuer%w! Nutze es um&%rRotes Eis%w zu schmelzen!", - "Vous obtenez une %rBouteille avec&une Flamme Bleue%w! Utilisez-la&pour faire fondre la %rGlace&Rouge%w!"), - GIMESSAGE(RG_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE, - "You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!", - "Du hast einen %rNachtschwärmer%w&in einer Flasche gefangen!&Gehe zum %rGespenstermarkt%w&und verkaufe ihn!", - "Vous obtenez une %rBouteille avec&une Âme%w! Vendez-la au Marchand&d'Âme"), - GIMESSAGE(RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, - "You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!", - "Du erhältst ein %rBlaues Elixier%w!&Nutze es, um Deine %rMagie- und&Energieleiste%w komplett&aufzufüllen!", - "Vous obtenez une %rBouteille avec&une Potion Bleue%w! Buvez-la pour&restaurer votre %rénergie vitale%w&ainsi que votre %gmagie%w!"), - GIMESSAGE(RG_BOTTLE_WITH_FISH, ITEM_FISH, - "You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!", - "Du hast jetzt einen %rFisch in&einer Flasche%w! Er sieht richtig&frisch aus! Man sagt,&Lord Jabu-Jabu liebt Fische!", - "Vous obtenez une %rBouteille avec&un Poisson%w! Il a l'air délicieux!&Il paraîtrait que %bJabu-Jabu %wen&serait friand!"), - GIMESSAGE(RG_BOTTLE_WITH_BUGS, ITEM_BUG, - "You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!", - "Du hast jetzt %rKäfer in einer&Flasche&%w!&Sie graben gerne&in Erdlöchern.", - "Vous obtenez une %rBouteille avec&des Insectes%w! Ils adorent creuser&dans la terre meuble!"), - GIMESSAGE(RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY, - "You got a %rFairy in a Bottle%w!&Use it wisely!", - "Du hast jetzt eine %rFee in einer&Flasche%w! Nutze sie weise!", - "Vous obtenez une %rBouteille avec&une Fée%w! Faites-en bon usage!"), - GIMESSAGE(RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, - "You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!", - "Du erhältst ein %rRotes Elixier%w!&Nutze es, um Deine %rEnergieleiste&%weinmalig komplett aufzufüllen!", - "Vous obtenez une %rBouteille avec&une Potion Rouge%w! Buvez-la pour&restaurer votre %rénergie vitale%w!"), - GIMESSAGE(RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, - "You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!", - "Du erhältst ein %rGrünes Elixier%w!&Nutze es, um Deine %bMagieleiste&%weinmalig komplett aufzufüllen!", - "Vous obtenez une %rBouteille avec&une Potion Verte%w! Buvez-la pour&restaurer votre %gmagie%w!"), - GIMESSAGE(RG_BOTTLE_WITH_POE, ITEM_POE, - "You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this...", - "Du hast jetzt ein %rIrrlicht in einer&Flasche%w! Der %rGespenstermarkt%w&interessiert sich für vielleicht&dafür...", - "Vous obtenez une %rBouteille avec&un Esprit%w! Ça intéresserait&peut-être le vendeur d'Âme "), - - GIMESSAGE(RG_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %yThieves Hideout &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %yDiebesversteck%w!", - "Vous obtenez une %rPetite Clé %w&du %yRepaire des Voleurs%w!"), - GIMESSAGE(RG_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %gForest Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gWaldtempel%w!", - "Vous obtenez une %rPetite Clé %w&du %gTemple de la Forêt%w!"), - GIMESSAGE(RG_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %rFire Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %rFeuertempel%w!", - "Vous obtenez une %rPetite Clé %w&du %rTemple du Feu%w!"), - GIMESSAGE(RG_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %bWater Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %bWassertempel%w!", - "Vous obtenez une %rPetite Clé %w&du %bTemple de l'Eau%w!"), - GIMESSAGE(RG_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %ySpirit Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %yGeistertempel%w!", - "Vous obtenez une %rPetite Clé %w&du %yTemple de l'Esprit%w!"), - GIMESSAGE(RG_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %pShadow Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %pSchattentempel%w!", - "Vous obtenez une %rPetite Clé %w&du %pTemple de l'Ombre%w!"), - GIMESSAGE(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %pBottom of the &Well %wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %pGrund des Brunnens%w!", - "Vous obtenez une %rPetite Clé %w&du %pPuits%w!"), - GIMESSAGE(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %yGerudo Training &Grounds %wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %yGerudo-Trainingsarena%w!", - "Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"), - GIMESSAGE(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %rGanon's Castle &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für %rGanons Schloß%w!", - "Vous obtenez une %rPetite Clé %w&du %rChâteau de Ganon%w!"), - GIMESSAGE(RG_GUARD_HOUSE_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gGuard House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus der Wachen%w!", - "Vous obtenez la %rClé %wde la&%gMaison des Gardes%w!"), - GIMESSAGE(RG_MARKET_BAZAAR_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gMarket Bazaar%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar des Marktes%w!", - "Vous obtenez la %rClé %wdu %gBazar&de la Place du Marché%w!"), - GIMESSAGE(RG_MARKET_POTION_SHOP_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gMarket Potion Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden des Marktes%w!", - "Vous obtenez la %rClé %wde la&%gPlace du Marché%w!"), - GIMESSAGE(RG_MASK_SHOP_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gMask Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gMaskenladen%w!", - "Vous obtenez la %rClé %wde la&%gFoire aux Masques%w!"), - GIMESSAGE(RG_MARKET_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gMarket Shooting Gallery%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude des Marktes%w!", - "Vous obtenez la %rClé %wdu %gStand de&Tir de la Place du Marché%w!"), - GIMESSAGE(RG_BOMBCHU_BOWLING_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gBombchu Bowling Alley%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gMinenbowlingbahn%w!", - "Vous obtenez la %rClé %wdu %gBowling&Teigneux%w!"), - GIMESSAGE(RG_TREASURE_CHEST_GAME_BUILDING_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gTreasure Chest Game Building%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Schatzkisten-Pokers%w!", - "Vous obtenez la %rClé %wdu %gJeu de la&Chasse au Trésor%w!"), - GIMESSAGE(RG_BOMBCHU_SHOP_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gBombchu Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gKrabbelminenladen%w!", - "Vous obtenez la %rClé %wdu %gMagasin&de Missiles%w!"), - GIMESSAGE(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL, - "You found the key to&%gRichard's House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Richard%w!", - "Vous obtenez la %rClé %wde la %gMaison&de Kiki%w!"), - GIMESSAGE(RG_ALLEY_HOUSE_KEY, ITEM_KEY_SMALL, - "You found the key to&the %gAlley House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus in der Gasse%w!", - "Vous obtenez la %rClé %wde la %gMaison&de la Ruelle%w!"), - GIMESSAGE(RG_KAK_BAZAAR_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gKakariko Bazaar%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar von Kakariko%w!", - "Vous obtenez la %rClé %wdu %gBazar&de Cocorico%w!"), - GIMESSAGE(RG_KAK_POTION_SHOP_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gKakariko Potion Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden von Kakariko%w!", - "Vous obtenez la %rClé %wdu %gMagasin de&Potions de Cocorico%w!"), - GIMESSAGE(RG_BOSS_HOUSE_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gBoss's House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Chefs%w!", - "Vous obtenez la %rClé %wde la %gMaison&du chef des ouvriers%w!"), - GIMESSAGE(RG_GRANNYS_POTION_SHOP_KEY, ITEM_KEY_SMALL, - "You found the key to&%gGranny's Potion Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für %gAsas Hexenladen%w!", - "Vous obtenez la %rClé %wde&l'%gApothicaire%w!"), - GIMESSAGE(RG_SKULLTULA_HOUSE_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gSkulltula House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gSkulltula-Haus%w!", - "Vous obtenez la %rClé %wde la %gMaison&des Araignées%w!"), - GIMESSAGE(RG_IMPAS_HOUSE_KEY, ITEM_KEY_SMALL, - "You found the key to&%gImpa's House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Impa%w!", - "Vous obtenez la %rClé %wde la %gMaison&d'Impa%w!"), - GIMESSAGE(RG_WINDMILL_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gWindmill%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gWindmühle%w!", - "Vous obtenez la %rClé %w du %gMoulin%w!"), - GIMESSAGE(RG_KAK_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gKakariko Shooting Gallery%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude von Kakariko%w!", - "Vous obtenez la %rClé %w du %gStand de&Tir de Cocorico%w!"), - GIMESSAGE(RG_DAMPES_HUT_KEY, ITEM_KEY_SMALL, - "You found the key to&%gDampe's Hut%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gHütte von Boris%w!", - "Vous obtenez la %rClé %wde la %gCabane&d'Igor%w!"), - GIMESSAGE(RG_TALONS_HOUSE_KEY, ITEM_KEY_SMALL, - "You found the key to&%gTalon's House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Talon%w!", - "Vous obtenez la %rClé %wde la %gMaison&de Talon%w!"), - GIMESSAGE(RG_STABLES_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gStables%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gStälle%w!", - "Vous obtenez la %rClé %wdes %gÉcuries%w!"), - GIMESSAGE(RG_BACK_TOWER_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gBack Tower%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %ghinteren Turm%w!", - "Vous obtenez la %rClé %wdu %gSilo%w!"), - GIMESSAGE(RG_HYLIA_LAB_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gHylia Laboratory%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHylia-Labor%w!", - "Vous obtenez la %rClé %wdu %gLaboratoire&du Lac Hylia%w!"), - GIMESSAGE(RG_FISHING_HOLE_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gPond%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gFischweiher%w!", - "Vous obtenez la %rClé %wde l'%gÉtang%w!"), - - GIMESSAGE(RG_GERUDO_FORTRESS_KEY_RING, ITEM_KEY_SMALL, - "You found a %yThieves Hideout&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für das %yDiebesversteck%w!", - "Vous obtenez le trousseau de&clés du %yRepaire des Voleurs%w!"), - GIMESSAGE(RG_FOREST_TEMPLE_KEY_RING, ITEM_KEY_SMALL, - "You found a %gForest Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %gWaldtempel%w!", - "Vous obtenez le trousseau de&clés du %gTemple de la Forêt%w!"), - GIMESSAGE(RG_FIRE_TEMPLE_KEY_RING, ITEM_KEY_SMALL, - "You found a %rFire Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %rFeuertempel%w!", - "Vous obtenez le trousseau de&clés du %rTemple du Feu%w!"), - GIMESSAGE(RG_WATER_TEMPLE_KEY_RING, ITEM_KEY_SMALL, - "You found a %bWater Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %bWassertempel%w!", - "Vous obtenez le trousseau de&clés du %bTemple de l'Eau%w!"), - GIMESSAGE(RG_SPIRIT_TEMPLE_KEY_RING, ITEM_KEY_SMALL, - "You found a %ySpirit Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %yGeistertempel%w!", - "Vous obtenez le trousseau de&clés du %yTemple de l'Esprit%w!"), - GIMESSAGE(RG_SHADOW_TEMPLE_KEY_RING, ITEM_KEY_SMALL, - "You found a %pShadow Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %pSchattentempel%w!", - "Vous obtenez le trousseau de&clés du %pTemple de l'Ombre%w!"), - GIMESSAGE(RG_BOTTOM_OF_THE_WELL_KEY_RING, ITEM_KEY_SMALL, - "You found a %pBottom of the&Well %wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %pGrund des Brunnens%w!", - "Vous obtenez le trousseau de&clés du %pPuits%w!"), - GIMESSAGE(RG_GERUDO_TRAINING_GROUND_KEY_RING, ITEM_KEY_SMALL, - "You found a %yGerudo Training&Grounds %wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für die %yGerudo-Trainingsarena%w!", - "Vous obtenez le trousseau de&clés du %yGymnase Gerudo%w!"), - GIMESSAGE(RG_GANONS_CASTLE_KEY_RING, ITEM_KEY_SMALL, - "You found a %rGanon's Castle&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für %rGanons Schloß%w!", - "Vous obtenez le trousseau de&clés du %rChâteau de Ganon%w!"), - GIMESSAGE(RG_TREASURE_GAME_KEY_RING, ITEM_KEY_SMALL, - "You found a %rTreasure Chest Game&%wKeyring!", - "!!!", - "Vous obtenez le trousseau de&clés du %rJeu de la Chasse au Trésor%w!"), - - GIMESSAGE(RG_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, - "You found the %gForest Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %gWaldtempel%w!", - "Vous obtenez la %rClé d'or %wdu&%gTemple de la Forêt%w!"), - GIMESSAGE(RG_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, - "You found the %rFire Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %rFeuertempel%w!", - "Vous obtenez la %rClé d'or %wdu&%rTemple du Feu%w!"), - GIMESSAGE(RG_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, - "You found the %bWater Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %bWassertempel%w!", - "Vous obtenez la %rClé d'or %wdu&%bTemple de l'Eau%w!"), - GIMESSAGE(RG_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, - "You found the %ySpirit Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %yGeistertempel%w!", - "Vous obtenez la %rClé d'or %wdu&%yTemple de l'Esprit%w!"), - GIMESSAGE(RG_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, - "You found the %pShadow Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %pSchattentempel%w!", - "Vous obtenez la %rClé d'or %wdu&%pTemple de l'Ombre%w!"), - GIMESSAGE(RG_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, - "You found the %rGanon's Castle&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für %rGanons Schloß%w!", - "Vous obtenez la %rClé d'or %wdu&%rChâteau de Ganon%w!"), - - GIMESSAGE(RG_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, - "You found the %gDeku Tree&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%gDeku-Baum%w![[typeHint]]", - "Vous obtenez la %rCarte %wde&l'%gArbre Mojo%w![[typeHint]]"), - GIMESSAGE(RG_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, - "You found the %rDodongo's Cavern&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für&%rDodongos Höhle%w![[typeHint]]", - "Vous obtenez la %rCarte %wde la&%rCaverne Dodongo%w![[typeHint]]"), - GIMESSAGE(RG_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, - "You found the %bJabu Jabu's Belly&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für&%bJabu-Jabus Bauch%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%bVentre de Jabu-Jabu%w![[typeHint]]"), - GIMESSAGE(RG_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %gForest Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%gWaldtempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%gTemple de la Forêt%w![[typeHint]]"), - GIMESSAGE(RG_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %rFire Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%rFeuertempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%rTemple du Feu%w![[typeHint]]"), - GIMESSAGE(RG_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %bWater Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%bWassertempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%bTemple de l'Eau%w![[typeHint]]"), - GIMESSAGE(RG_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %ySpirit Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%yGeistertempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%yTemple de l'Esprit%w![[typeHint]]"), - GIMESSAGE(RG_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, - "You found the %pShadow Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%pSchattentempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%pTemple de l'Ombre%w![[typeHint]]"), - GIMESSAGE(RG_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, - "You found the %pBottom of the&Well %wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%pGrund des Brunnens%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%pPuits%w![[typeHint]]"), - GIMESSAGE(RG_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, - "You found the %cIce Cavern&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für die&%cEishöhle%w![[typeHint]]", - "Vous obtenez la %rCarte %wde&la %cCaverne Polaire%w![[typeHint]]"), - - GIMESSAGE(RG_DEKU_TREE_COMPASS, ITEM_COMPASS, - "You found the %gDeku Tree&%wCompass!", - "Du erhältst den %rKompaß%w für den&%gDeku-Baum%w!", - "Vous obtenez la %rBoussole %wde&l'%gArbre Mojo%w!"), - GIMESSAGE(RG_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, - "You found the %rDodongo's Cavern&%wCompass!", - "Du erhältst den %rKompaß%w für&%rDodongos Höhle%w!", - "Vous obtenez la %rBoussole %wde la&%rCaverne Dodongo%w!"), - GIMESSAGE(RG_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, - "You found the %bJabu Jabu's Belly&%wCompass!", - "Du erhältst den %rKompaß%w für den&%bJabu-Jabus Bauch%w!", - "Vous obtenez la %rBoussole %wdu&%bVentre de Jabu-Jabu%w!"), - GIMESSAGE(RG_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, - "You found the %gForest Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%gWaldtempel%w!", - "Vous obtenez la %rBoussole %wdu&%gTemple de la Forêt%w!"), - GIMESSAGE(RG_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, - "You found the %rFire Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%rFeuertempel%w!", - "Vous obtenez la %rBoussole %wdu&%rTemple du Feu%w!"), - GIMESSAGE(RG_WATER_TEMPLE_COMPASS, ITEM_COMPASS, - "You found the %bWater Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%bWassertempel%w!", - "Vous obtenez la %rBoussole %wdu&%bTemple de l'Eau%w!"), - GIMESSAGE(RG_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, - "You found the %ySpirit Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%yGeistertempel%w!", - "Vous obtenez la %rBoussole %wdu&%yTemple de l'Esprit%w!"), - GIMESSAGE(RG_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, - "You found the %pShadow Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%pSchattentempel%w!", - "Vous obtenez la %rBoussole %wdu&%pTemple de l'Ombre%w!"), - GIMESSAGE(RG_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS, - "You found the %pBottom of the&Well %wCompass!", - "Du erhältst den %rKompaß%w für den&%pGrund des Brunnens%w!", - "Vous obtenez la %rBoussole %wdu&%pPuits%w!"), - GIMESSAGE(RG_ICE_CAVERN_COMPASS, ITEM_COMPASS, - "You found the %cIce Cavern&%wCompass!", - "Du erhältst den %rKompaß%w für die&%cEishöhle%w!", - "Vous obtenez la %rBoussole %wde&la %cCaverne Polaire%w!"), - - GIMESSAGE(RG_MAGIC_BEAN_PACK, ITEM_BEAN, - "You got a %rPack of Magic Beans%w!&Find a suitable spot for a garden&and plant them. Then, wait for&something fun to happen!", - "Du erhältst eine %rPackung&Wundererbsen%w! Suche nach einer&Stelle um sie einzupflanzen.&Warte ab, was passiert!", - "Vous obtenez un %rPaquet de&Haricots Magiques%w! Trouvez&un endroit approprié pour un&jardin et plantez-les.^Attendez ensuite que quelque&chose d'amusant se produise!"), - GIMESSAGE(RG_TYCOON_WALLET, ITEM_WALLET_GIANT, - "You got a %rTycoon's Wallet%w!&It's gigantic! Now you can carry&up to %y999 rupees%w!", - "Du erhältst die %rGoldene&Geldbörse%w! Die größte aller&Geldbörsen! Jetzt kannst Du bis&zu %y999 Rubine%w mit Dir führen!", - "Vous obtenez la %rBourse de Magnat%w!&Elle peut contenir jusqu'à %y999 rubis%w!&C'est gigantesque!"), - GIMESSAGE(RG_CHILD_WALLET, ITEM_WALLET_ADULT, - "You got a %rChild's Wallet%w!&Now you can carry&up to %y99 rupees%w!", - "Du erhältst die %rKindergeldbörse%w!&Jetzt kannst Du bis&zu %y99 Rubine%w mit Dir führen!", - "Vous obtenez la %rPetite Bourse%w!&Elle peut contenir jusqu'à %y99 rubis%w!"), - - GIMESSAGE_NO_GERMAN(RG_GOHMA_SOUL, ITEM_BIG_POE, - "You found the soul for %gGohma%w!", - "Vous obtenez l'âme de %gGohma%w!"), - GIMESSAGE_NO_GERMAN(RG_KING_DODONGO_SOUL, ITEM_BIG_POE, - "You found the soul for %rKing&Dodongo%w!", - "Vous obtenez l'âme du %rRoi Dodongo%w!"), - GIMESSAGE_NO_GERMAN(RG_BARINADE_SOUL, ITEM_BIG_POE, - "You found the soul for %bBarinade%w!", - "Vous obtenez l'âme de %bBarinade%w!"), - GIMESSAGE_NO_GERMAN(RG_PHANTOM_GANON_SOUL, ITEM_BIG_POE, - "You found the soul for %gPhantom&Ganon%w!", - "Vous obtenez l'âme de %gGanon&Spectral%w!"), - GIMESSAGE_NO_GERMAN(RG_VOLVAGIA_SOUL, ITEM_BIG_POE, - "You found the soul for %rVolvagia%w!", - "Vous obtenez l'âme de %rVulcania%w!"), - GIMESSAGE_NO_GERMAN(RG_MORPHA_SOUL, ITEM_BIG_POE, - "You found the soul for %bMorpha%w!", - "Vous obtenez l'âme de %bMorpha%w!"), - GIMESSAGE_NO_GERMAN(RG_BONGO_BONGO_SOUL, ITEM_BIG_POE, - "You found the soul for %pBongo&Bongo%w!", - "Vous obtenez l'âme de %pBongo&Bongo%w!"), - GIMESSAGE_NO_GERMAN(RG_TWINROVA_SOUL, ITEM_BIG_POE, - "You found the soul for %yTwinrova%w!", - "Vous obtenez l'âme du %yDuo&Maléfique%w!"), - GIMESSAGE_NO_GERMAN(RG_GANON_SOUL, ITEM_BIG_POE, - "You found the soul for %cGanon%w!", - "Vous obtenez l'âme de %cGanon%w!"), - - GIMESSAGE(RG_OCARINA_A_BUTTON, ITEM_OCARINA_TIME, - "You got the %b\x9f%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %b\x9f%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %b\x9f%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), - GIMESSAGE(RG_OCARINA_C_LEFT_BUTTON, ITEM_OCARINA_TIME, - "You got the %y\xa7%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %y\xa7%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %y\xa7%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), - GIMESSAGE(RG_OCARINA_C_RIGHT_BUTTON, ITEM_OCARINA_TIME, - "You got the %y\xa8%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %y\xa8%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %y\xa8%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), - GIMESSAGE(RG_OCARINA_C_UP_BUTTON, ITEM_OCARINA_TIME, - "You got the %y\xa5%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %y\xa5%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %y\xa5%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), - GIMESSAGE(RG_OCARINA_C_DOWN_BUTTON, ITEM_OCARINA_TIME, - "You got the %y\xa6%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %y\xa6%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en jouez!"), - - GIMESSAGE_NO_GERMAN(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, - "You got the %rBronze Scale%w!&The power of buoyancy is yours!", - "Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"), - GIMESSAGE_NO_GERMAN(RG_FISHING_POLE, ITEM_FISHING_POLE, - "You found a lost %rFishing Pole%w!&Time to hit the pond!", - "Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"), - GIMESSAGE_NO_GERMAN(RG_BOMBCHU_BAG, ITEM_BOMBCHU, - "You found the %rBombchu Bag%w!", - "Vous obtenez un %rSac de Missiles&Teigneux%w!"), - GIMESSAGE_NO_GERMAN(RG_BOMB_BAG_INF, ITEM_BOMB_BAG_40, - "You got an %rInfinite Bomb Bag%w!&Now you have %yinfinite bombs%w!", - "Vous obtenez un %rSac de Bombes&sans fond%w!&Vous avez maintenant des %ybombes&en quantité illimitée%w!"), - GIMESSAGE_NO_GERMAN(RG_QUIVER_INF, ITEM_QUIVER_50, - "You got an %rInfinite Quiver%w!&Now you have %yinfinite arrows%w!", - "Vous obtenez un %rCarquois Infini%w!&Vous avez maintenant des %yflèches&de manière illimitée%w!"), - GIMESSAGE_NO_GERMAN(RG_BULLET_BAG_INF, ITEM_BULLET_BAG_50, - "You got an %rInfinite Bullet Bag%w!&Now you have %yinfinite&slingshot seeds%w!", - "Vous obtenez un %rSac de Graines&sans fond%w!&Vous avez maintenant des %ygraines&de lance-pierres à l'infini%w!"), - GIMESSAGE_NO_GERMAN(RG_STICK_UPGRADE_INF, ITEM_STICK, - "You now have %yinfinite%w %rDeku Sticks%w!", - "Vous avez maintenant des %yBâtons&Mojo de manière illimitée%w!"), - GIMESSAGE_NO_GERMAN(RG_NUT_UPGRADE_INF, ITEM_NUT, - "You now have %yinfinite%w %rDeku Nuts%w!", - "Vous avez maintenant des %yNoix&Mojo de manière illimitée%w!"), - GIMESSAGE_NO_GERMAN(RG_MAGIC_INF, ITEM_MAGIC_LARGE, - "You now have %yinfinite%w %rMagic%w!", - "Vous avez maintenant une quantité&de %ymagie illimitée%w!"), - GIMESSAGE_NO_GERMAN(RG_BOMBCHU_INF, ITEM_BOMBCHU, - "You now have %yinfinite%w %rBombchus%w!", - "Vous avez maintenant des %yMissiles&Teigneux en quantité illimités%w!"), - GIMESSAGE_NO_GERMAN(RG_WALLET_INF, ITEM_WALLET_GIANT, - "You now have %yinfinite%w %rmoney%w!", - "Vous avez maintenant des %yRubis en& quantité illimitée%w!"), - GIMESSAGE_NO_GERMAN(RG_SKELETON_KEY, ITEM_KEY_SMALL, - "You found the %rSkeleton Key%w!", - "Vous avez trouvé la %rClé Squelette%w!"), - GIMESSAGE_NO_GERMAN(RG_DEKU_STICK_BAG, ITEM_STICK, - "You found the %rDeku Stick Bag%w!&You can now hold deku sticks!", - "Vous avez trouvé le %rSac de Bâtons&Mojo%w!&Vous pouvez maintenant porter des&Bâtons Mojo!"), - GIMESSAGE_NO_GERMAN(RG_DEKU_NUT_BAG, ITEM_NUT, - "You found the %rDeku Nut Bag%w!&You can now hold deku nuts!", - "Vous avez trouvé le %rSac de Noix& Mojo%w!&Vous pouvez maintenant porter des&Noix Mojo!"), - }}; - CreateGetItemMessages(getItemMessages); CreateRupeeMessages(); - CreateTriforcePieceMessages(); CreateNaviRandoMessages(); CreateFireTempleGoronMessages(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 76bde6a4f..a7d56be53 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -63,11 +63,8 @@ class Randomizer { CustomMessage GetMerchantMessage(RandomizerCheck rc, TextIDs textId, TextIDs freeTextId = TEXT_NONE, bool mysterious = false); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); - CustomMessage GetMapGetItemMessageWithHint(GetItemEntry itemEntry); static void CreateCustomMessages(); static CustomMessage GetRupeeMessage(u16 rupeeTextId); - static CustomMessage GetIceTrapMessage(); - static CustomMessage GetTriforcePieceMessage(); }; #ifdef __cplusplus diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 2296cc1a3..c0d0e682e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1695,19 +1695,6 @@ std::wstring StringToU16(const std::string& s) { return utf16; } -int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) { - if (!inputStr.empty()) { - // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents negatives. - memset(buffer, 0, std::max(0, maxBufferSize)); - // Gaurentee that this value will be greater than 0, regardless of passed variables. - const int copiedCharLen = std::min(std::max(0, maxBufferSize - 1), inputStr.length()); - memcpy(buffer, inputStr.c_str(), copiedCharLen); - return copiedCharLen; - } - - return 0; -} - extern "C" void OTRGfxPrint(const char* str, void* printer, void (*printImpl)(void*, char)) { const std::vector hira1 = { u'を', u'ぁ', u'ぃ', u'ぅ', u'ぇ', u'ぉ', u'ゃ', u'ゅ', u'ょ', u'っ', u'-', u'あ', u'い', @@ -2379,19 +2366,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE, MF_FORMATTED); } - font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); - switch (gSaveContext.language) { - case LANGUAGE_FRA: - return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetFrench(MF_RAW), buffer, maxBufferSize); - case LANGUAGE_GER: - return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetGerman(MF_RAW), buffer, maxBufferSize); - case LANGUAGE_ENG: - default: - return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetEnglish(MF_RAW), buffer, maxBufferSize); - } return false; } From 6d451d6e3659ff5b23e45339e2699464b45d18d9 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 23:14:43 -0500 Subject: [PATCH 008/103] Converts gossip stone hints to hook --- .../randomizer/GossipStoneHints.cpp | 52 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 35 +------------ 2 files changed, 53 insertions(+), 34 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/GossipStoneHints.cpp diff --git a/soh/soh/Enhancements/randomizer/GossipStoneHints.cpp b/soh/soh/Enhancements/randomizer/GossipStoneHints.cpp new file mode 100644 index 000000000..17960c313 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/GossipStoneHints.cpp @@ -0,0 +1,52 @@ +#include + +extern "C" { +extern PlayState* gPlayState; +#include +#include +#include +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) + +void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) { + if ( + (RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_TRUTH) && Player_GetMask(gPlayState) == PLAYER_MASK_TRUTH) || + (RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_STONE) && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY) == 0) + ) { + return; + } + CustomMessage msg; + Actor* stone = GET_PLAYER(gPlayState)->talkActor; + RandomizerHint stoneHint = RH_NONE; + int16_t hintParams = stone->params & 0xFF; + + if (Rando::StaticData::stoneParamsToHint.contains(hintParams)) { + stoneHint = Rando::StaticData::stoneParamsToHint[hintParams]; + } else if (hintParams == 0x18) { + int numOfActorLists = sizeof(gPlayState->actorCtx.actorLists) / sizeof(gPlayState->actorCtx.actorLists[0]); + for (int i = 0; i < numOfActorLists; i++) { + if (gPlayState->actorCtx.actorLists[i].length) { + if ( + gPlayState->actorCtx.actorLists[i].head->id == 10 && + Rando::StaticData::grottoChestParamsToHint.contains(gPlayState->actorCtx.actorLists[i].head->params) + ) { + stoneHint = Rando::StaticData::grottoChestParamsToHint[gPlayState->actorCtx.actorLists[i].head->params]; + } + } + } + } + if (stoneHint == RH_NONE) { + msg = CustomMessage("INVALID STONE. PARAMS: " + std::to_string(hintParams)); + } else { + msg = OTRGlobals::Instance->gRandoContext->GetHint(stoneHint)->GetHintMessage(MF_AUTO_FORMAT); + } + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterGossipStoneHints() { + COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_GOSSIP_STONE_HINTS, RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE), BuildHintStoneMessage); +} + +static RegisterShipInitFunc initFunc(RegisterGossipStoneHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index c0d0e682e..348ded142 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2107,40 +2107,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { auto ctx = Rando::Context::GetInstance(); bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); - Player* player = GET_PLAYER(play); - if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != RO_GOSSIP_STONES_NONE && - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_NOTHING || - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_TRUTH && - Player_GetMask(play) == PLAYER_MASK_TRUTH) || - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_STONE && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { - - Actor* stone = GET_PLAYER(play)->talkActor; - RandomizerHint stoneHint = RH_NONE; - s16 hintParams = stone->params & 0xFF; - - if (Rando::StaticData::stoneParamsToHint.contains(hintParams)){ - stoneHint = Rando::StaticData::stoneParamsToHint[hintParams]; - } else if (hintParams == 0x18){ - // look for the chest in the actorlist to determine - // which grotto we're in - int numOfActorLists = - sizeof(play->actorCtx.actorLists) / sizeof(play->actorCtx.actorLists[0]); - for (int i = 0; i < numOfActorLists; i++) { - if (play->actorCtx.actorLists[i].length) { - if (play->actorCtx.actorLists[i].head->id == 10 && - Rando::StaticData::grottoChestParamsToHint.contains(play->actorCtx.actorLists[i].head->params)) { - //use the chest params to find the stone hint - stoneHint = Rando::StaticData::grottoChestParamsToHint[play->actorCtx.actorLists[i].head->params]; - } - } - } - } - if (stoneHint == RH_NONE){ - messageEntry = CustomMessage("INVALID STONE. PARAMS: " + std::to_string(hintParams)); - } else { - messageEntry = ctx->GetHint(stoneHint)->GetHintMessage(MF_AUTO_FORMAT); - } - } else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { + if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); } else if (textId == TEXT_GANONDORF) { From 9e8785af099220195888ccd95657b0bc5484689c Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 26 Feb 2025 19:28:59 -0500 Subject: [PATCH 009/103] Moved into "Messages" folder --- .../Enhancements/randomizer/{ => Messages}/GossipStoneHints.cpp | 0 soh/soh/Enhancements/randomizer/{ => Messages}/ItemMessages.cpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename soh/soh/Enhancements/randomizer/{ => Messages}/GossipStoneHints.cpp (100%) rename soh/soh/Enhancements/randomizer/{ => Messages}/ItemMessages.cpp (100%) diff --git a/soh/soh/Enhancements/randomizer/GossipStoneHints.cpp b/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp similarity index 100% rename from soh/soh/Enhancements/randomizer/GossipStoneHints.cpp rename to soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp similarity index 100% rename from soh/soh/Enhancements/randomizer/ItemMessages.cpp rename to soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp From 6f8704af3245044849026209094ed94efc74afed Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 26 Feb 2025 20:06:48 -0500 Subject: [PATCH 010/103] Handle one-off merchant messages --- .../randomizer/Messages/MerchantMessages.cpp | 114 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 63 ---------- soh/soh/OTRGlobals.cpp | 28 +---- 3 files changed, 116 insertions(+), 89 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp new file mode 100644 index 000000000..4f03af228 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -0,0 +1,114 @@ +#include + +extern "C" { +extern PlayState* gPlayState; +#include +#include +#include +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) +#define RAND_GET_ITEM(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) +#define RAND_GET_OVERRIDE(rc) OTRGlobals::Instance->gRandoContext->overrides[rc] +#define NON_BEAN_MERCHANTS (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || \ + RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) + +void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) { + RandomizerGet rgid = RAND_GET_ITEM(rc)->GetPlacedRandomizerGet(); + uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); + CustomMessage itemName; + bool mysterious = RAND_GET_OPTION(RSK_MERCHANT_TEXT_HINT).Is(RO_GENERIC_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); + if (mysterious) { + itemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage(); + } else if (rgid == RG_ICE_TRAP) { + rgid = RAND_GET_OVERRIDE(rc).LooksLike(); + itemName = CustomMessage(RAND_GET_OVERRIDE(rc).GetTrickName()); + } else { + itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName()); + } + msg.InsertNames({ itemName , CustomMessage(std::to_string(price))}); +} + +void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { + msg = CustomMessage( + "I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no less.\x1B%gYes&No%w", + "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 Rubine%w.\x1B&%gJa&Nein%w", + "Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w" + ); + msg.Format(); + } else if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) { + msg = CustomMessage( + "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + ); + BuildMerchantMessage(msg, RC_ZR_MAGIC_BEAN_SALESMAN); + msg.AutoFormat(); + } + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + ); + BuildMerchantMessage(msg, RC_GC_MEDIGORON); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildGrannyMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && + (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) || + INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { + CustomMessage msg = CustomMessage( + "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + ); + BuildMerchantMessage(msg, RC_KAK_GRANNYS_SHOP); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; + } +} + +void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (*textId == TEXT_CARPET_SALESMAN_ARMS_DEALER) { + msg = CustomMessage("Finally! Now I can go back to being an %rarms dealer%w!", + /*german*/"Endlich! Schon bald kann ich wieder %rKrabbelminen-Händler%w sein!", + /*french*/"Squalala! Je vais enfin pouvoir %rprendre des vacances%w!"); + } else if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { + msg = CustomMessage( + "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + ); + BuildMerchantMessage(msg, RC_WASTELAND_BOMBCHU_SALESMAN); + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterMerchantMessages() { + COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_10, + (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || + RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)), + BuildBeanGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_100, IS_RANDO, BuildBeanGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_MEDIGORON, NON_BEAN_MERCHANTS, BuildMedigoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_GRANNYS_SHOP, NON_BEAN_MERCHANTS, BuildGrannyMessage); + COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_1, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_ARMS_DEALER, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); +} + +static RegisterShipInitFunc initFunc(RegisterMerchantMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ecea64dcb..6f1841267 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -312,14 +312,6 @@ void Randomizer::LoadMerchantMessages() { "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un #[[1]]#? Ça fera #[[2]] Rubis#!\x07\x10\xA3", {QM_GREEN, QM_YELLOW})); - //Carpet Salesman - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_ARMS_DEALER, - CustomMessage("Finally! Now I can go back to being an #arms dealer#!", - /*german*/"Endlich! Schon bald kann ich wieder #Krabbelminen-Händler# sein!", - /*french*/"Squalala! Je vais enfin pouvoir #prendre des vacances#!", - {QM_RED})); - // Each shop item has two messages, one for when the cursor is over it, and one for when you select it and are // prompted buy/don't buy CustomMessageManager::Instance->CreateMessage( @@ -335,30 +327,6 @@ void Randomizer::LoadMerchantMessages() { "\x08#[[1]]# #[[2]]_Rubine#\x09\x1B#Kaufen&Nicht kaufen#\x09\x02", "\x08#[[1]]# #[[2]]_Rubis#\x09\x1B#Acheter&Ne pas acheter#\x09\x02", {QM_GREEN, QM_YELLOW, QM_GREEN})); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_10, - CustomMessage("I tried to be a #magic bean# salesman, but it turns out my marketing skills weren't worth " - "beans!^Anyway, want to buy #[[1]]# for #[[2]] Rupees#?\x1B#Yes&No#", - /*german*/ "Möchten Sie #[[1]]# für #[[2]] Rubine# kaufen?\x1B#Ja&Nein#", - /*french*/ "J'ai essayé d'être un vendeur de #haricots magiques#, mais j'étais mauvais au niveau du marketing et ça " - "me courait sur le haricot...^Enfin bref, ça te dirait de m'acheter #[[1]]# pour #[[2]] Rubis#?\x1B#Oui&Non#", - {QM_RED, QM_GREEN, QM_YELLOW, QM_GREEN})); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100, - CustomMessage("I never thought I'd say this, but I'm selling the last #Magic Bean#.^#99 Rupees#, no less.\x1B#Yes&No#", - "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^#Wundererbse# für #99 Rubine#.\x1B&#Ja&Nein#", - "Je te vends mon dernier #Haricot&magique# pour #99 Rubis#.\x1B&#AcheterNe pas acheter#", - {QM_RED, QM_YELLOW, QM_GREEN})); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_MEDIGORON, - CustomMessage("How about buying #[[1]]# for #[[2]] Rupees#?\x1B#Buy&Don't buy#", - /*german*/ "Möchtest Du #[[1]]# für #[[2]] Rubine# kaufen?\x1B#Klar!&Nie im Leben!#", - /*french*/ "Veux-tu acheter #[[1]]# pour #[[2]] rubis#?\x1B#Acheter&Ne pas acheter#", - {QM_GREEN, QM_YELLOW, QM_GREEN})); - /*spanish*/ // ¿Me compras #[[1]]# por #[[2]] rupias#?\x1B#Comprar&No comprar# CustomMessage firstCarpet = CustomMessage("Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special is...^", /*german*/ "Sei gegrüßt!^Ich verkaufe allerlei Kuriositäten. Stets sonderliche und seltene Ware aus " @@ -366,37 +334,6 @@ void Randomizer::LoadMerchantMessages() { /*french*/ "Bienvenue!^Je vends des objets rares et merveilleux du monde entier. En spécial aujourd'hui...^"); /*spanish*/ // ¡Acércate!^Vendo productos extraños y difíciles de encontrar... De todo el mundo a todo el mundo. La oferta de hoy es...^#¡ - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_MYSTERIOUS, - firstCarpet + - CustomMessage("Terrifying! I won't tell you what it is until I see the #money#...^How about #[[2]] Rupees#?&&" - "\x1B#Buy&Don't buy#", - /*german*/ "Furchterregend, oder? Ich erzähle Euch mehr, wenn ich #Geld# sehe...^Wie wär's mit #[[2]] Rubinen#?&&" - "\x1B#Aber sicher!&Ich bin weg!#", - /*french*/ "Terrible! Mais montre tes #rubis# avant que je te dise ce que c'est...^Disons #[[2]] " - "rubis#?&&\x1B#Acheter&Ne pas acheter#", - {QM_RED, QM_YELLOW, QM_GREEN})); - /*spanish*/ // ¡Terrorífico! No te revelaré su nombre hasta que vea el #dinero#...^#[[2]] rupias#, ¿qué te parece?&&" - // "\x1B#Comprar&No comprar# - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_1, - firstCarpet + - CustomMessage("#[[1]]!# It's real, I promise! A lonely man such as myself wouldn't #lie# to you, hmm?^" - "How about #[[2]] Rupees#?\x1B#Buy&Don't buy#", - /*german*/ "#[[1]]#! Ich kann versichern, es ist ein aufrichtiges Angebot!^Ein einsamer Mann wie ich würde Dich doch " - "nicht #anlügen#, oder?^Wie wär's mit #[[2]] Rubinen#?\x1B#Aber sicher!&Ich bin weg!#", - /*french*/ "#[[1]]!# C'est vrai! J'te jure! Un gars comme moi ne te #mentirai# pas tu ne crois pas?^Disons #[[2]] " - "rubis#?\x1B#Acheter&Ne pas acheter#", - {QM_GREEN, QM_RED, QM_YELLOW})); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_GRANNYS_SHOP, - CustomMessage("#[[1]]#! How about #[[2]] Rupees#?\x1B#Buy&Don't buy#", - /*german*/ "#[[1]]#! Sagen wir #[[2]] Rubine#?\x1B#Gerne!&Auf keinen Fall!#", - /*french*/ "#[[1]]#! Que dis-tu de #[[2]] rubis#?\x1B#Acheter&Ne pas acheter#", - {QM_GREEN, QM_YELLOW, QM_GREEN}, {true})); - // /*spanish*/#[[1]]#. Vendo por #[[2]] rupias#.&\x1B#Comprar&No comprar# } std::map trialFlagToTrialKey = { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 348ded142..0de13e1f7 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2145,32 +2145,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); - } - else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_10 && - (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || - ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL))) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(RC_ZR_MAGIC_BEAN_SALESMAN, TEXT_BEAN_SALESMAN_BUY_FOR_10, TEXT_NONE, Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } - else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100, MF_AUTO_FORMAT); - } - else if (textId == TEXT_GRANNYS_SHOP && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && nonBeanMerchants && - (ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)){ - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(RC_KAK_GRANNYS_SHOP, TEXT_GRANNYS_SHOP, TEXT_NONE, Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } - else if (textId == TEXT_MEDIGORON && nonBeanMerchants){ - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(RC_GC_MEDIGORON, TEXT_MEDIGORON, TEXT_NONE, Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } - else if (textId == TEXT_CARPET_SALESMAN_1 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN) && nonBeanMerchants){ - if (Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT)){ - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(RC_WASTELAND_BOMBCHU_SALESMAN, TEXT_CARPET_SALESMAN_1, TEXT_NONE, Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } else { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(RC_WASTELAND_BOMBCHU_SALESMAN, TEXT_CARPET_SALESMAN_MYSTERIOUS, TEXT_NONE, Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } - } - else if (textId == TEXT_CARPET_SALESMAN_ARMS_DEALER){ - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId, MF_AUTO_FORMAT); - } else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { + } + else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { actorParams = GET_PLAYER(play)->talkActor->params; if (actorParams == 1 && ctx->GetOption(RSK_KAK_10_SKULLS_HINT)){ messageEntry = ctx->GetHint(RH_KAK_10_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); From 4b0cbcd6816549f4febff8b1898368c5e89e8d92 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 26 Feb 2025 22:30:16 -0500 Subject: [PATCH 011/103] Convert scrubs and shop text and remove now-unused code --- .../randomizer/Messages/MerchantMessages.cpp | 45 ++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 69 ------------------- soh/soh/Enhancements/randomizer/randomizer.h | 2 - soh/soh/OTRGlobals.cpp | 16 ----- soh/soh/OTRGlobals.h | 1 - .../ovl_file_choose/z_file_choose.c | 1 - 6 files changed, 45 insertions(+), 89 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 4f03af228..4248912d5 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -5,6 +5,7 @@ extern PlayState* gPlayState; #include #include #include +#include } #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) @@ -99,6 +100,48 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { + EnDns* enDns = reinterpret_cast(GET_PLAYER(gPlayState)->talkActor); + RandomizerCheck rc = enDns->sohScrubIdentity.randomizerCheck; + uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); + CustomMessage msg; + if (price == 0) { + msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will give you a %g[[1]]%w!&Please, take it!\x07\x10\xA3", + "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w geben!\x07\x10\xA3", + "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3"); + } else { + msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %g[[2]] Rupees%w it is!\x07\x10\xA3", + "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", + "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); + } + BuildMerchantMessage(msg, rc); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + RandomizerCheck rc; + if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { + rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); + msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", + "\x08%g[[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", + "\x08%g[[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); + } else if (*textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && *textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END) { + rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); + msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w\x09\x1B%gBuy&Don't buy%w\x09\x02", + "\x08%g[[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", + "\x08%g[[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); + } else { + return; + } + BuildMerchantMessage(msg, rc); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterMerchantMessages() { COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_10, (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || @@ -109,6 +152,8 @@ void RegisterMerchantMessages() { COND_ID_HOOK(OnOpenText, TEXT_GRANNYS_SHOP, NON_BEAN_MERCHANTS, BuildGrannyMessage); COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_1, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_ARMS_DEALER, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_SCRUB_RANDOM, IS_RANDO, BuildScrubMessage); + COND_HOOK(OnOpenText, RAND_GET_OPTION(RSK_SHOPSANITY).IsNot(RO_SHOPSANITY_OFF), BuildShopMessage); } static RegisterShipInitFunc initFunc(RegisterMerchantMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 6f1841267..9d8fc0b02 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -295,47 +295,6 @@ std::unordered_map randomizerGetToEnGirlShopItem { RG_BUY_RED_POTION_50, SI_RED_POTION_R50 }, }; -void Randomizer::LoadMerchantMessages() { - auto ctx = Rando::Context::GetInstance(); - CustomMessageManager::Instance->ClearMessageTable(Randomizer::merchantMessageTableID); - CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::merchantMessageTableID); - - // Prices have a chance of being 0, and the "sell" message below doesn't really make sense for a free item, so adding a "free" variation here - CustomMessageManager::Instance->CreateMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM_FREE, - CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will give you a #[[1]]#!&Please, take it!\x07\x10\xA3", - "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen #[[1]]# geben!\x07\x10\xA3", - "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un #[[1]]#! Vas-y prends le!\x07\x10\xA3", - {QM_GREEN})); - CustomMessageManager::Instance->CreateMessage(Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM, - CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a #[[1]]#! #[[2]] Rupees# it is!\x07\x10\xA3", - "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen #[[1]]# für #[[2]] Rubine#!\x07\x10\xA3", - "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un #[[1]]#? Ça fera #[[2]] Rubis#!\x07\x10\xA3", - {QM_GREEN, QM_YELLOW})); - - // Each shop item has two messages, one for when the cursor is over it, and one for when you select it and are - // prompted buy/don't buy - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM, - CustomMessage("\x08#[[1]]# #[[2]]_Rupees#&Special deal! #ONE LEFT#!&Get it while it lasts!\x0A\x02", - "\x08#[[1]]# #[[2]]_Rubine#&Sonderangebot! #NUR NOCH EINES VERFÜGBAR#!&Beeilen Sie sich!\x0A\x02", - "\x08#[[1]]# #[[2]]_Rubis#&Offre spéciale! #DERNIER EN STOCK#!&Faites vite!\x0A\x02", - {QM_GREEN, QM_YELLOW, QM_RED})); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM_CONFIRM, - CustomMessage("\x08#[[1]]# #[[2]]_Rupees#\x09\x1B#Buy&Don't buy#\x09\x02", - "\x08#[[1]]# #[[2]]_Rubine#\x09\x1B#Kaufen&Nicht kaufen#\x09\x02", - "\x08#[[1]]# #[[2]]_Rubis#\x09\x1B#Acheter&Ne pas acheter#\x09\x02", - {QM_GREEN, QM_YELLOW, QM_GREEN})); - - CustomMessage firstCarpet = CustomMessage("Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special is...^", - /*german*/ "Sei gegrüßt!^Ich verkaufe allerlei Kuriositäten. Stets sonderliche und seltene Ware aus " - "aller Welt für jedermann. Das heutige Angebot bleibt...^", - /*french*/ "Bienvenue!^Je vends des objets rares et merveilleux du monde entier. En spécial aujourd'hui...^"); - /*spanish*/ // ¡Acércate!^Vendo productos extraños y difíciles de encontrar... De todo el mundo a todo el mundo. La oferta de hoy es...^#¡ - -} - std::map trialFlagToTrialKey = { { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, TK_LIGHT_TRIAL, }, { EVENTCHKINF_COMPLETED_FOREST_TRIAL, TK_FOREST_TRIAL, }, @@ -2608,34 +2567,6 @@ CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { return messageEntry; } -CustomMessage Randomizer::GetMerchantMessage(RandomizerCheck rc, TextIDs textId, TextIDs freeTextId, bool mysterious) { - auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry; - RandomizerGet shopItemGet = ctx->GetItemLocation(rc)->GetPlacedRandomizerGet(); - CustomMessage shopItemName; - u16 shopItemPrice = ctx->GetItemLocation(rc)->GetPrice(); - - if (mysterious || CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { - shopItemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage(); - } else if (shopItemGet == RG_ICE_TRAP) { - shopItemGet = ctx->overrides[rc].LooksLike(); - shopItemName = CustomMessage(ctx->overrides[rc].GetTrickName()); - } else { - auto shopItem = Rando::StaticData::RetrieveItem(shopItemGet); - shopItemName = {shopItem.GetName()}; - } - - if (freeTextId != TEXT_NONE && shopItemPrice == 0) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, freeTextId, MF_RAW); - } else { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId, MF_RAW); - } - - messageEntry.InsertNames({shopItemName, {std::to_string(shopItemPrice)}}); - messageEntry.AutoFormat(); - return messageEntry; -} - void CreateRupeeMessages() { CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index a7d56be53..d32c2b600 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -41,7 +41,6 @@ class Randomizer { static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); - void LoadMerchantMessages(); void LoadHintMessages(); bool IsTrialRequired(s32 trialFlag); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); @@ -60,7 +59,6 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); CustomMessage GetSheikMessage(s16 scene, u16 originalTextId); CustomMessage GetFishingPondOwnerMessage(u16 originalTextId); - CustomMessage GetMerchantMessage(RandomizerCheck rc, TextIDs textId, TextIDs freeTextId = TEXT_NONE, bool mysterious = false); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); static void CreateCustomMessages(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0de13e1f7..e94358007 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1976,10 +1976,6 @@ extern "C" void Randomizer_LoadHintMessages() { OTRGlobals::Instance->gRandomizer->LoadHintMessages(); } -extern "C" void Randomizer_LoadMerchantMessages() { - OTRGlobals::Instance->gRandomizer->LoadMerchantMessages(); -} - extern "C" bool Randomizer_IsTrialRequired(s32 trialFlag) { return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag); } @@ -2105,8 +2101,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || - ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); @@ -2127,16 +2121,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) - } else if (textId >= TEXT_SHOP_ITEM_RANDOM && textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { - RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)((textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(rc, TEXT_SHOP_ITEM_RANDOM); - } else if (textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END){ - RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)((textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(rc, TEXT_SHOP_ITEM_RANDOM_CONFIRM); - } else if (textId == TEXT_SCRUB_RANDOM) { - EnDns* enDns = (EnDns*)GET_PLAYER(play)->talkActor; - RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf((RandomizerInf)enDns->sohScrubIdentity.randomizerInf); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(rc, TEXT_SCRUB_RANDOM, TEXT_SCRUB_RANDOM_FREE, Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF); } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 2f20b0b15..4853bf5da 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -134,7 +134,6 @@ CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ); FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams); void Randomizer_ParseSpoiler(const char* fileLoc); void Randomizer_LoadHintMessages(); -void Randomizer_LoadMerchantMessages(); bool Randomizer_IsTrialRequired(s32 trialFlag); GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 664a9dcfc..7b345ce86 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -3133,7 +3133,6 @@ void FileChoose_LoadGame(GameState* thisx) { this->state.running = false; Randomizer_LoadHintMessages(); - Randomizer_LoadMerchantMessages(); gSaveContext.respawn[0].entranceIndex = ENTR_LOAD_OPENING; gSaveContext.respawnFlag = 0; From a9528af3768d38635d943fff8c5bd8a0169f239c Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 10:01:01 -0500 Subject: [PATCH 012/103] Moves comment about shops --- soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp | 3 +++ soh/soh/OTRGlobals.cpp | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 4248912d5..234fc1a79 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -123,6 +123,9 @@ void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; RandomizerCheck rc; + // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS + // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index e94358007..09722775e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2118,9 +2118,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); - // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS - // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) - // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { From fea0ea80a442f30e59ba9b7bda3ae52268106029 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 10:01:33 -0500 Subject: [PATCH 013/103] Convert Sheik and Ganondorf hint text --- .../randomizer/Messages/StaticHints.cpp | 87 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 14 --- 2 files changed, 87 insertions(+), 14 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp new file mode 100644 index 000000000..6f1044210 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -0,0 +1,87 @@ +#include + +extern "C" { +extern PlayState* gPlayState; +#include +#include +#include +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) +#define RAND_GET_HINT(rh) OTRGlobals::Instance->gRandoContext->GetHint(rh) +#define RAND_GET_ITEM_LOC(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) + +void BuildGanondorfHint(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { + if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) { + msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); + } else { + msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); + } + } else { + if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) { + msg = RAND_GET_HINT(RH_GANONDORF_JOKE)->GetHintMessage(MF_AUTO_FORMAT); + } else { + msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); + } + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildSheikMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + switch (gPlayState->sceneNum) { + case SCENE_TEMPLE_OF_TIME: + if (RAND_GET_OPTION(RSK_OOT_HINT) && !RAND_GET_ITEM_LOC(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()){ + msg = RAND_GET_HINT(RH_OOT_HINT)->GetHintMessage(MF_RAW); + } else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { + msg = CustomMessage( + "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", + "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.", + "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w."); + } else { + msg = CustomMessage( + "The time has come. Prepare yourself.", + "Die Zeit ist gekommen.&Mach Dich bereit.", + "Le moment est venu @.&Tu ferais bien de te préparer."); + } + break; + case SCENE_INSIDE_GANONS_CASTLE: + if (RAND_GET_OPTION(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) { + msg = RAND_GET_HINT(RH_SHEIK_HINT)->GetHintMessage(MF_RAW); + } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && + CUR_CAPACITY(UPG_QUIVER) >= 30 && gSaveContext.isMagicAcquired)) { + msg = CustomMessage("You are still ill-equipped to face %rGanondorf%w." + "^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the %ylight%w.", + "Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^" + "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", + "@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^" + "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour invoquer la %ylumière%w."); + } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && !RAND_GET_OPTION(RSK_TRIAL_COUNT).Is(0)){ + msg = CustomMessage( + "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still stands.^Complete the remaining %gtrials%w to destroy it.", + "Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.", + "@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours actives.^Termine les épreuves restantes pour les détruire."); + } else { + msg = CustomMessage( + "If you're ready, then proceed.^Good luck.", + "Wenn Du bereit bist, so schreite&voran.^Viel Glück.", + "Si tu es prêt, tu peux y aller.^Bonne chance."); + } + break; + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterStaticHints() { + COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); + COND_ID_HOOK(OnOpenText, TEXT_SHEIK_NEED_HOOK, IS_RANDO, BuildSheikMessage); + COND_ID_HOOK(OnOpenText, TEXT_SHEIK_HAVE_HOOK, IS_RANDO, BuildSheikMessage); +} + +RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 09722775e..4629ae4d5 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2104,20 +2104,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); - } else if (textId == TEXT_GANONDORF) { - if (ctx->GetOption(RSK_GANONDORF_HINT)){ - if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)){ - messageEntry = INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT ? - ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1): - ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); - } else { - messageEntry = INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT ? - ctx->GetHint(RH_GANONDORF_JOKE)->GetHintMessage(MF_AUTO_FORMAT): - ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); - } - } - } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { From 511e5856f8625c8878c17700ebb640fedbea7c04 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 10:47:35 -0500 Subject: [PATCH 014/103] Convert skulltula people messages --- .../randomizer/Messages/StaticHints.cpp | 50 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 23 +-------- 2 files changed, 52 insertions(+), 21 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 6f1044210..3656f3c28 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -10,6 +10,11 @@ extern PlayState* gPlayState; #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) #define RAND_GET_HINT(rh) OTRGlobals::Instance->gRandoContext->GetHint(rh) #define RAND_GET_ITEM_LOC(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) +#define ANY_SKULLTULA_HINTS RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT) void BuildGanondorfHint(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; @@ -78,10 +83,55 @@ void BuildSheikMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildChildAltarMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_ALTAR_CHILD)->GetHintMessage(); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildAdultAltarMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_ALTAR_ADULT)->GetHintMessage(); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + int16_t actorParams = GET_PLAYER(gPlayState)->talkActor->params; + if (actorParams == 1 && RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_10_SKULLS_HINT)->GetHintMessage(); + } else if (actorParams == 2 && RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_20_SKULLS_HINT)->GetHintMessage(); + } else if (actorParams == 3 && RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_30_SKULLS_HINT)->GetHintMessage(); + } else if (actorParams == 4 && RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_40_SKULLS_HINT)->GetHintMessage(); + } else if (actorParams == 5 && RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_50_SKULLS_HINT)->GetHintMessage(); + } else { + return; + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_KAK_100_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); COND_ID_HOOK(OnOpenText, TEXT_SHEIK_NEED_HOOK, IS_RANDO, BuildSheikMessage); COND_ID_HOOK(OnOpenText, TEXT_SHEIK_HAVE_HOOK, IS_RANDO, BuildSheikMessage); + COND_ID_HOOK(OnOpenText, TEXT_ALTAR_CHILD, IS_RANDO, BuildChildAltarMessage); + COND_ID_HOOK(OnOpenText, TEXT_ALTAR_ADULT, IS_RANDO, BuildAdultAltarMessage); + COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_IM_CURSED, ANY_SKULLTULA_HINTS, BuildSkulltulaPeopleMessage); + COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT), Build100SkullsHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 4629ae4d5..bf41d2742 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2101,10 +2101,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { - // rando hints at altar - messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); - } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { messageEntry = Randomizer::GetRupeeMessage(textId); @@ -2113,20 +2110,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } - else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { - actorParams = GET_PLAYER(play)->talkActor->params; - if (actorParams == 1 && ctx->GetOption(RSK_KAK_10_SKULLS_HINT)){ - messageEntry = ctx->GetHint(RH_KAK_10_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (actorParams == 2 && ctx->GetOption(RSK_KAK_20_SKULLS_HINT)){ - messageEntry = ctx->GetHint(RH_KAK_20_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (actorParams == 3 && ctx->GetOption(RSK_KAK_30_SKULLS_HINT)){ - messageEntry = ctx->GetHint(RH_KAK_30_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (actorParams == 4 && ctx->GetOption(RSK_KAK_40_SKULLS_HINT)){ - messageEntry = ctx->GetHint(RH_KAK_40_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (ctx->GetOption(RSK_KAK_50_SKULLS_HINT)){ - messageEntry = ctx->GetHint(RH_KAK_50_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } - } else if (textId == TEXT_DAMPES_DIARY && ctx->GetOption(RSK_DAMPES_DIARY_HINT)) { + else if (textId == TEXT_DAMPES_DIARY && ctx->GetOption(RSK_DAMPES_DIARY_HINT)) { messageEntry = ctx->GetHint(RH_DAMPES_DIARY)->GetHintMessage(MF_AUTO_FORMAT); } else if ((textId == TEXT_CHEST_GAME_PROCEED || textId == TEXT_CHEST_GAME_REAL_GAMBLER || textId == TEXT_CHEST_GAME_THANKS_A_LOT) && @@ -2214,9 +2198,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { else if (textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED && ctx->GetOption(RSK_MALON_HINT)){ messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); } - else if (ctx->GetOption(RSK_KAK_100_SKULLS_HINT) && textId == TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH) { - messageEntry = ctx->GetHint(RH_KAK_100_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (textId == TEXT_GF_HBA_SIGN && ctx->GetOption(RSK_HBA_HINT)) { messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); } From a535a53a096834e8521cb89dc5e9a5936e41968e Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 11:52:04 -0500 Subject: [PATCH 015/103] Convert more static hints Specifically Dampe, Greg, Warp Songs, Frogs, Loach, Fishing Pole, and Saria --- .../randomizer/Messages/StaticHints.cpp | 142 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 26 ---- soh/soh/Enhancements/randomizer/randomizer.h | 1 - soh/soh/OTRGlobals.cpp | 56 ------- 4 files changed, 142 insertions(+), 83 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 3656f3c28..cf4597921 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -124,14 +124,156 @@ void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildDampesDiaryMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_DAMPES_DIARY)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildGregHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildMinuetWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_MINUET_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildBoleroWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_BOLERO_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildSerenadeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_SERENADE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildRequiemWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_REQUIEM_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildNocturneWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_NOCTURNE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildPreludeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_PRELUDE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildFrogsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_FROGS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildLoachHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_LOACH_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildFishingPoleHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND)) { + return; + } + CustomMessage msg = CustomMessage( + "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!", + "Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht fischen!", + "Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!" + ); + if (RAND_GET_OPTION(RSK_FISHING_POLE_HINT)) { + msg = msg + RAND_GET_HINT(RH_FISHING_POLE)->GetHintMessage(); + } + if (*textId == TEXT_FISHING_POND_START_MET) { + msg = CustomMessage( + "Hey, mister! I remember you!&It's been a long time!^", + "Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!", + "Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!" + ) + msg; + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildSariaMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (*textId == TEXT_SARIA_SFM) { + msg = RAND_GET_HINT(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); + } else { + msg = RAND_GET_HINT(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); + } + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { + // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); + // Sheik COND_ID_HOOK(OnOpenText, TEXT_SHEIK_NEED_HOOK, IS_RANDO, BuildSheikMessage); COND_ID_HOOK(OnOpenText, TEXT_SHEIK_HAVE_HOOK, IS_RANDO, BuildSheikMessage); + // Altar COND_ID_HOOK(OnOpenText, TEXT_ALTAR_CHILD, IS_RANDO, BuildChildAltarMessage); COND_ID_HOOK(OnOpenText, TEXT_ALTAR_ADULT, IS_RANDO, BuildAdultAltarMessage); + //Skulltula COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_IM_CURSED, ANY_SKULLTULA_HINTS, BuildSkulltulaPeopleMessage); COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT), Build100SkullsHintMessage); + // Dampe's Diary + COND_ID_HOOK(OnOpenText, TEXT_DAMPES_DIARY, RAND_GET_OPTION(RSK_DAMPES_DIARY_HINT), BuildDampesDiaryMessage); + // Chest Game + COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_PROCEED, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_REAL_GAMBLER, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_THANKS_A_LOT, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage); + // Warp + COND_ID_HOOK(OnOpenText, TEXT_WARP_MINUET_OF_FOREST, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildMinuetWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_BOLERO_OF_FIRE, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildBoleroWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_SERENADE_OF_WATER, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildSerenadeWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_REQUIEM_OF_SPIRIT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildRequiemWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_NOCTURNE_OF_SHADOW, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildNocturneWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_PRELUDE_OF_LIGHT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildPreludeWarpMessage); + // Frogs + COND_ID_HOOK(OnOpenText, TEXT_FROGS_UNDERWATER, RAND_GET_OPTION(RSK_FROGS_HINT), BuildFrogsHintMessage); + // Loach + COND_ID_HOOK(OnOpenText, TEXT_FISHING_CLOUDY, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_SECRETS, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_GOOD_FISHERMAN, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_DIFFERENT_POND, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_SCRATCHING, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + // Fishing Pole + COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), BuildFishingPoleHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START_MET, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), BuildFishingPoleHintMessage); + // Saria + COND_ID_HOOK(OnOpenText, TEXT_SARIA_SFM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FACE_TO_FACE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FOREST_SOUNDS, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_MR_DARUNIA, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_SPIRITUAL_WATER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_SPIRITUAL_FIRE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DREAD_CASTLE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DIFFERENT_OCARINA, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_EYES_DARKNESS_STORM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DESERT_GODDESS, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_TEMPLES, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FOREST_TEMPLE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_GLAD_NOW, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 9d8fc0b02..1d94c10ca 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2541,32 +2541,6 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { return messageEntry; } -CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { - auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry = CustomMessage( - "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!", - "Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht fischen!", - "Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!" - ); - - if (Rando::Context::GetInstance()->GetOption(RSK_FISHING_POLE_HINT)) { - messageEntry = messageEntry + CustomMessage(ctx->GetHint(RH_FISHING_POLE)->GetHintMessage()); - } - - // if the fishing pond guy doesnt remember me i will cry :( - if (originalTextId == TEXT_FISHING_POND_START_MET) { - messageEntry = CustomMessage( - "Hey, mister! I remember you!&It's been a long time!^", - "Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!", - "Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!" - ) + messageEntry; - } - - messageEntry.Format(); //RANDOTODO why is this needed when it's not elsewhere.... - - return messageEntry; -} - void CreateRupeeMessages() { CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index d32c2b600..94345c0e6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -58,7 +58,6 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); CustomMessage GetSheikMessage(s16 scene, u16 originalTextId); - CustomMessage GetFishingPondOwnerMessage(u16 originalTextId); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); static void CreateCustomMessages(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index bf41d2742..21422b9c3 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2110,35 +2110,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } - else if (textId == TEXT_DAMPES_DIARY && ctx->GetOption(RSK_DAMPES_DIARY_HINT)) { - messageEntry = ctx->GetHint(RH_DAMPES_DIARY)->GetHintMessage(MF_AUTO_FORMAT); - } - else if ((textId == TEXT_CHEST_GAME_PROCEED || textId == TEXT_CHEST_GAME_REAL_GAMBLER || textId == TEXT_CHEST_GAME_THANKS_A_LOT) && - play->sceneNum == SCENE_TREASURE_BOX_SHOP && ctx->GetOption(RSK_GREG_HINT)) { - messageEntry = ctx->GetHint(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); - } - else if (textId == TEXT_WARP_MINUET_OF_FOREST && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_MINUET_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } - else if (textId == TEXT_WARP_BOLERO_OF_FIRE && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_BOLERO_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } - else if (textId == TEXT_WARP_SERENADE_OF_WATER && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_SERENADE_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } - else if (textId == TEXT_WARP_REQUIEM_OF_SPIRIT && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } - else if (textId == TEXT_WARP_NOCTURNE_OF_SHADOW && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } - else if (textId == TEXT_WARP_PRELUDE_OF_LIGHT && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } - else if (textId >= TEXT_WARP_MINUET_OF_FOREST && textId <= TEXT_WARP_PRELUDE_OF_LIGHT - && ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_WARP_MINUET_OF_FOREST, MF_FORMATTED); - } else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId, MF_AUTO_FORMAT); } @@ -2149,33 +2120,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (textId == TEXT_FROGS_UNDERWATER && ctx->GetOption(RSK_FROGS_HINT)) { - messageEntry = ctx->GetHint(RH_FROGS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } - else if ( - Randomizer_GetSettingValue(RSK_LOACH_HINT) && - ( - textId == TEXT_FISHING_CLOUDY || - textId == TEXT_FISHING_TRY_ANOTHER_LURE || - textId == TEXT_FISHING_SECRETS || - textId == TEXT_FISHING_GOOD_FISHERMAN || - textId == TEXT_FISHING_DIFFERENT_POND || - textId == TEXT_FISHING_SCRATCHING || - textId == TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE - ) - ) { - messageEntry = ctx->GetHint(RH_LOACH_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } - else if ((textId == TEXT_FISHING_POND_START || textId == TEXT_FISHING_POND_START_MET) && - ctx->GetOption(RSK_SHUFFLE_FISHING_POLE) && !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetFishingPondOwnerMessage(textId); - } - else if (textId == TEXT_SARIA_SFM && gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && ctx->GetOption(RSK_SARIA_HINT)){ - messageEntry = ctx->GetHint(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); - } - else if ((textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER) && ctx->GetOption(RSK_SARIA_HINT)){ - messageEntry = ctx->GetHint(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); - } else if (ctx->GetOption(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS || textId == TEXT_BIGGORON_I_MAAAADE_THISSSS)) { messageEntry = ctx->GetHint(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); From 5a429b19f62cea6a30079450ef74979a7b8abdec Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 11:53:32 -0500 Subject: [PATCH 016/103] Remove now-unused Sheik hint functions --- .../Enhancements/randomizer/randomizer.cpp | 47 ------------------- soh/soh/Enhancements/randomizer/randomizer.h | 1 - 2 files changed, 48 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 1d94c10ca..ff75b20a7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2494,53 +2494,6 @@ void RandomizerSettingsWindow::UpdateElement() { } } -CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { - auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry; - switch (scene) { - case SCENE_TEMPLE_OF_TIME: - if (ctx->GetOption(RSK_OOT_HINT) && !ctx->GetItemLocation(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()){ - messageEntry = ctx->GetHint(RH_OOT_HINT)->GetHintMessage(MF_RAW); - } else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { - messageEntry = CustomMessage( - "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", - "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.", - "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w."); - } else { - messageEntry = CustomMessage( - "The time has come. Prepare yourself.", - "Die Zeit ist gekommen.&Mach Dich bereit.", - "Le moment est venu @.&Tu ferais bien de te préparer."); - } - break; - case SCENE_INSIDE_GANONS_CASTLE: - if (ctx->GetOption(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) { - messageEntry = ctx->GetHint(RH_SHEIK_HINT)->GetHintMessage(MF_RAW); - } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && - CUR_CAPACITY(UPG_QUIVER) >= 30 && gSaveContext.isMagicAcquired)) { - messageEntry = CustomMessage("You are still ill-equipped to face %rGanondorf%w." - "^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the %ylight%w.", - "Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^" - "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", - "@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^" - "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour invoquer la %ylumière%w."); - } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && !ctx->GetOption(RSK_TRIAL_COUNT).Is(0)){ - messageEntry = CustomMessage( - "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still stands.^Complete the remaining %gtrials%w to destroy it.", - "Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.", - "@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours actives.^Termine les épreuves restantes pour les détruire."); - } else { - messageEntry = CustomMessage( - "If you're ready, then proceed.^Good luck.", - "Wenn Du bereit bist, so schreite&voran.^Viel Glück.", - "Si tu es prêt, tu peux y aller.^Bonne chance."); - } - break; - } - messageEntry.AutoFormat(); - return messageEntry; -} - void CreateRupeeMessages() { CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 94345c0e6..0f18bbdd9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -57,7 +57,6 @@ class Randomizer { GetItemEntry GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogItemId, bool checkObtainability = true); ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); - CustomMessage GetSheikMessage(s16 scene, u16 originalTextId); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); static void CreateCustomMessages(); From a602ecf6c7c45ee5259c09d2fa0f8d43660b8b1d Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 11:58:40 -0500 Subject: [PATCH 017/103] Convert Biggoron Hint --- .../Enhancements/randomizer/Messages/StaticHints.cpp | 12 +++++++++++- soh/soh/OTRGlobals.cpp | 4 ---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index cf4597921..ffad5d524 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -219,6 +219,12 @@ void BuildSariaMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildBiggoronHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -273,7 +279,11 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_GLAD_NOW, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); - + //Biggoron + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 21422b9c3..349f527f8 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2120,10 +2120,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (ctx->GetOption(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || - textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS || textId == TEXT_BIGGORON_I_MAAAADE_THISSSS)) { - messageEntry = ctx->GetHint(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (ctx->GetOption(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { messageEntry = ctx->GetHint(RH_BIG_POES_HINT)->GetHintMessage(MF_AUTO_FORMAT); } From 27880135ec05c8545ef5a8554256a59a12c4c8ce Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:01:57 -0500 Subject: [PATCH 018/103] Convert Big Poes hint --- .../Enhancements/randomizer/Messages/StaticHints.cpp | 11 ++++++++++- soh/soh/OTRGlobals.cpp | 3 --- 2 files changed, 10 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index ffad5d524..0d3eaa96b 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -225,6 +225,12 @@ void BuildBiggoronHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildBigPoesHintMessage(uint16_t * textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -279,11 +285,14 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_GLAD_NOW, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); - //Biggoron + // Biggoron COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + // Big Poes + COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_EXPLAINATION, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 349f527f8..b8aa0b914 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2120,9 +2120,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (ctx->GetOption(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { - messageEntry = ctx->GetHint(RH_BIG_POES_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (ctx->GetOption(RSK_CHICKENS_HINT) && (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { messageEntry = ctx->GetHint(RH_CHICKENS_HINT)->GetHintMessage(MF_AUTO_FORMAT); } From f64778b0d85f5e58488f06c95ef154d0341c9a4a Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:06:37 -0500 Subject: [PATCH 019/103] Adds TODO comment about breaking these up later. --- soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp | 2 ++ soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 234fc1a79..9f27e4a52 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -1,3 +1,5 @@ +// RANDOTODO: Consider breaking this up into the different actors +// That speak these hints, like 2Ship does with ActorBehavior #include extern "C" { diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 0d3eaa96b..98a3fde2d 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -1,3 +1,5 @@ +// RANDOTODO: Consider breaking this up into the different actors +// That speak these hints, like 2Ship does with ActorBehavior #include extern "C" { From 49ced2df0c70d6d986503e0058950779cb49573f Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:08:11 -0500 Subject: [PATCH 020/103] Convert Anju hint dialogue --- .../Enhancements/randomizer/Messages/StaticHints.cpp | 12 ++++++++++++ soh/soh/OTRGlobals.cpp | 3 --- 2 files changed, 12 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 98a3fde2d..cf4f36436 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -233,6 +233,12 @@ void BuildBigPoesHintMessage(uint16_t * textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildChickensHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_CHICKENS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -295,6 +301,12 @@ void RegisterStaticHints() { // Big Poes COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_EXPLAINATION, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); + // Anju + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_4_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index b8aa0b914..1c64132c3 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2120,9 +2120,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (ctx->GetOption(RSK_CHICKENS_HINT) && (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { - messageEntry = ctx->GetHint(RH_CHICKENS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if ((textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG)&& ctx->GetOption(RSK_MALON_HINT)){ messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); } From d301ce1d2d1ab1f81b163943a6906b20ebe44869 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:19:15 -0500 Subject: [PATCH 021/103] Convert Malon hint --- .../randomizer/Messages/StaticHints.cpp | 26 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 12 --------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index cf4f36436..56dbd6743 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -239,6 +239,26 @@ void BuildChickensHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildMalonHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + int id; + if (*textId == TEXT_MALON_EVERYONE_TURNING_EVIL || *textId == TEXT_MALON_I_SING_THIS_SONG) { + id = 0; + } else if (*textId == TEXT_MALON_HOW_IS_EPONA_DOING) { + id = 1; + } else if (*textId == TEXT_MALON_OBSTICLE_COURSE) { + id = 2; + } else if (*textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED) { + id = 3; + } else { + assert(!"This should not be reachable"); + return; + } + msg = RAND_GET_HINT(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, id); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -307,6 +327,12 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + // Malon + COND_ID_HOOK(OnOpenText, TEXT_MALON_EVERYONE_TURNING_EVIL, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_I_SING_THIS_SONG, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_HOW_IS_EPONA_DOING, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_OBSTICLE_COURSE, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 1c64132c3..c5fb8d71c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2120,18 +2120,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if ((textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG)&& ctx->GetOption(RSK_MALON_HINT)){ - messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); - } - else if (textId == TEXT_MALON_HOW_IS_EPONA_DOING && ctx->GetOption(RSK_MALON_HINT)){ - messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); - } - else if (textId == TEXT_MALON_OBSTICLE_COURSE && ctx->GetOption(RSK_MALON_HINT)){ - messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); - } - else if (textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED && ctx->GetOption(RSK_MALON_HINT)){ - messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); - } else if (textId == TEXT_GF_HBA_SIGN && ctx->GetOption(RSK_HBA_HINT)) { messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); } From 7289e3dd337f0a79f4bf45684243a62ddd49a4e6 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:25:17 -0500 Subject: [PATCH 022/103] Convert Horseback Archery hints --- .../randomizer/Messages/StaticHints.cpp | 25 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 12 --------- 2 files changed, 25 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 56dbd6743..65f591ba5 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -259,6 +259,26 @@ void BuildMalonHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildHorsebackArcheryMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + int id; + if (*textId == TEXT_GF_HBA_SIGN) { + id = 0; + } else if (*textId == TEXT_HBA_NOT_ON_HORSE) { + id = 1; + } else if (*textId == TEXT_HBA_INITIAL_EXPLAINATION) { + id = 2; + } else if (*textId == TEXT_HBA_ALREADY_HAVE_1000) { + id = 3; + } else { + assert(!"This should not be reachable"); + return; + } + msg = RAND_GET_HINT(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, id); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -333,6 +353,11 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_MALON_HOW_IS_EPONA_DOING, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_OBSTICLE_COURSE, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + // Horseback Archery + COND_ID_HOOK(OnOpenText, TEXT_GF_HBA_SIGN, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + COND_ID_HOOK(OnOpenText, TEXT_HBA_NOT_ON_HORSE, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + COND_ID_HOOK(OnOpenText, TEXT_HBA_ALREADY_HAVE_1000, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index c5fb8d71c..d9ac4c9c6 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2120,18 +2120,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (textId == TEXT_GF_HBA_SIGN && ctx->GetOption(RSK_HBA_HINT)) { - messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); - } - else if (textId == TEXT_HBA_NOT_ON_HORSE && ctx->GetOption(RSK_HBA_HINT)) { - messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); - } - else if (textId == TEXT_HBA_INITIAL_EXPLAINATION && ctx->GetOption(RSK_HBA_HINT)) { - messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); - } - else if (textId == TEXT_HBA_ALREADY_HAVE_1000 && ctx->GetOption(RSK_HBA_HINT)) { - messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); - } else if (textId == TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY){ messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); } From eeca34c4b8859472ef717ef1e323d58638e2b96b Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:29:31 -0500 Subject: [PATCH 023/103] Convert Mask Shop SIgn hint This is the last of the static hints --- soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 8 ++++++++ soh/soh/OTRGlobals.cpp | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 65f591ba5..56544ee21 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -279,6 +279,12 @@ void BuildHorsebackArcheryMessage(uint16_t* textId, bool* loadFromMessageTable) *loadFromMessageTable = false; } +void BuildMaskShopSignMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -358,6 +364,8 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_HBA_NOT_ON_HORSE, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_ALREADY_HAVE_1000, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + // Mask Shop Sign + COND_ID_HOOK(OnOpenText, TEXT_MASK_SHOP_SIGN, RAND_GET_OPTION(RSK_MASK_SHOP_HINT), BuildMaskShopSignMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index d9ac4c9c6..96cd9293e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2123,9 +2123,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { else if (textId == TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY){ messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); } - else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) { - messageEntry = ctx->GetHint(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { From f6935ef8921afb38e16af137b50ac7ab72c614bd Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:37:24 -0500 Subject: [PATCH 024/103] Add some documentation comments --- .../Enhancements/randomizer/Messages/GossipStoneHints.cpp | 4 ++++ soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp | 7 +++++++ .../Enhancements/randomizer/Messages/MerchantMessages.cpp | 6 ++++++ soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp b/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp index 17960c313..ebad2bd3e 100644 --- a/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp @@ -1,3 +1,7 @@ +/** + * This file handles the custom messages for Gossip Stone + * hints. + */ #include extern "C" { diff --git a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp index 828958937..1ce898437 100644 --- a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp @@ -1,3 +1,10 @@ +// RANDOTODO: Consider putting Ice Traps in their own file. +/** + * This file handles custom messages relating to Items, + * such as Get Item messages for non-vanilla items, + * Vanilla/MQ hints when collecting Maps, Ice Trap messages, + * etc. + */ #include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 9f27e4a52..b9d716293 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -1,5 +1,11 @@ // RANDOTODO: Consider breaking this up into the different actors // That speak these hints, like 2Ship does with ActorBehavior + +/** + * This file handles the custom messages for merchants, + * including both shops and one-off merchants (i.e. Medigoron, Bean Guy, + * and Carpet Salesman) + */ #include extern "C" { diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 56544ee21..a12bda6e2 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -1,5 +1,10 @@ // RANDOTODO: Consider breaking this up into the different actors // That speak these hints, like 2Ship does with ActorBehavior + +/** + * File for registering hooks for "Static" hints, i.e. hints that + * are always given by a specific NPC and/or for a specific item. + */ #include extern "C" { From 6597ba7b95e97dc4376de6f91541d2d533e67580 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:46:59 -0500 Subject: [PATCH 025/103] Handles previously missed Carpet Guy can't buy message. --- .../randomizer/Messages/MerchantMessages.cpp | 11 +++++++++++ soh/soh/OTRGlobals.cpp | 3 --- soh/soh/z_message_OTR.cpp | 4 ---- 3 files changed, 11 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index b9d716293..2c281d55b 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -108,6 +108,16 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildCarpetGuyFailToBuyMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "I'm sorry I can't sell you these fine specimens, they need an %rexperienced owner%w.^" + "Come back when you have had %gBombchus%w of your own." + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { EnDns* enDns = reinterpret_cast(GET_PLAYER(gPlayState)->talkActor); RandomizerCheck rc = enDns->sohScrubIdentity.randomizerCheck; @@ -165,6 +175,7 @@ void RegisterMerchantMessages() { COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_ARMS_DEALER, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); COND_ID_HOOK(OnOpenText, TEXT_SCRUB_RANDOM, IS_RANDO, BuildScrubMessage); COND_HOOK(OnOpenText, RAND_GET_OPTION(RSK_SHOPSANITY).IsNot(RO_SHOPSANITY_OFF), BuildShopMessage); + COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY, IS_RANDO, BuildCarpetGuyFailToBuyMessage); } static RegisterShipInitFunc initFunc(RegisterMerchantMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 96cd9293e..a15e279b2 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2120,9 +2120,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (textId == TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY){ - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); - } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 215975662..22c217182 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -187,8 +187,4 @@ extern "C" void OTRMessage_Init() CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w")); //TODO Used AI translation as placeholder - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY, - CustomMessage("I'm sorry I can't sell you these fine specimens, they need an #experienced owner#.^" - "Come back when you have had #Bombchus# of your own.", {QM_RED, QM_GREEN})); } From 03e6cccba945a161c67630af12d620572924d992 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:55:30 -0500 Subject: [PATCH 026/103] Removes some more unused stuff --- soh/soh/Enhancements/randomizer/randomizer.cpp | 17 ----------------- soh/soh/Enhancements/randomizer/randomizer.h | 4 ---- soh/soh/OTRGlobals.cpp | 11 ----------- 3 files changed, 32 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ff75b20a7..c4a1e864e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -56,14 +56,9 @@ std::set enabledGlitches; u8 generated; char* seedString; -const std::string Randomizer::getItemMessageTableID = "Randomizer"; const std::string Randomizer::hintMessageTableID = "RandomizerHints"; -const std::string Randomizer::merchantMessageTableID = "RandomizerMerchants"; const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; -const std::string Randomizer::triforcePieceMessageTableID = "RandomizerTriforcePiece"; const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; -const std::string Randomizer::IceTrapRandoMessageTableID = "RandomizerIceTrap"; -const std::string Randomizer::randoMiscHintsTableID = "RandomizerMiscHints"; static const char* englishRupeeNames[175] = { "[P]", "Bad RNG Rolls", "Bananas", "Beanbean Coins", "Beans", @@ -232,11 +227,6 @@ void Randomizer::LoadHintMessages() { CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID); CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID); - //Extra Hints - CustomMessageManager::Instance->ClearMessageTable(Randomizer::randoMiscHintsTableID); - CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::randoMiscHintsTableID); - - // Bow Shooting Gallery reminder CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, CustomMessage("Come back when you have your own bow and you'll get a #different prize#!", @@ -244,13 +234,6 @@ void Randomizer::LoadHintMessages() { "J'aurai #une autre récompense# pour toi lorsque tu auras ton propre arc.", {QM_RED})); - // Warp Song Mysterious text - CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_WARP_MINUET_OF_FOREST, - CustomMessage("Warp to&#a mysterious place?#&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", - "Zu&#einem mysteriösen Ort#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", - "Se téléporter vers&#un endroit mystérieux#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK!&Non#", - {QM_RED, QM_GREEN})); - // Lake Hylia water level system CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, CustomMessage("Water level control system.&Keep away!", diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 0f18bbdd9..d27f33ea7 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -32,12 +32,8 @@ class Randomizer { static const std::string getItemMessageTableID; static const std::string hintMessageTableID; - static const std::string merchantMessageTableID; static const std::string rupeeMessageTableID; - static const std::string triforcePieceMessageTableID; static const std::string NaviRandoMessageTableID; - static const std::string IceTrapRandoMessageTableID; - static const std::string randoMiscHintsTableID; static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index a15e279b2..642bcc917 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2080,17 +2080,6 @@ extern "C" void Randomizer_ShowRandomizerMenu() { SohGui::ShowRandomizerSettingsMenu(); } -CustomMessage Randomizer_GetCustomGetItemMessage(Player* player) { - s16 giid; - if (player->getItemEntry.objectId != OBJECT_INVALID) { - giid = player->getItemEntry.getItemId; - } else { - giid = player->getItemId; - } - const CustomMessage getItemText = CustomMessageManager::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, giid); - return getItemText; -} - extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { MessageContext* msgCtx = &play->msgCtx; uint16_t textId = msgCtx->textId; From f2a8960581eea0e8e352a46dcda171423084f187 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 13:12:48 -0500 Subject: [PATCH 027/103] Convert Lake Hylia Switch related text --- .../randomizer/Messages/Miscellaneous.cpp | 37 +++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 10 ----- soh/soh/OTRGlobals.cpp | 3 -- 3 files changed, 37 insertions(+), 13 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp new file mode 100644 index 000000000..e97178f89 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp @@ -0,0 +1,37 @@ +// RANDOTODO: Consider breaking these up by actor similar +// to how 2Ship does ActorBehavior stuff. +/** + * This file is intended to handle some rando-specific + * text changes that don't really fit anywhere else. + */ + +#include + +extern "C" { +#include +} + +void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI) { + msg = CustomMessage( + "%cThis switch is rustier than you think.^%cSomething must be wrong with the pipe system in the %bWater Temple%c.", + "%cDieser Schalter scheint rostiger zu sein als er aussieht.^%cEtwas muss mit dem Leitungssystem im %bWassertempel%c nicht stimmen.", + "%cCet interrupteur est très rouillé.^%cIl doit y avoir un problème avec la tuyauterie du %bTemple de l'Eau%c." + ); + } else if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { + msg = CustomMessage( + "Water level control system.&Keep away!", + "Wasserstand Kontrollsystem&Finger weg!", + "Système de contrôle du niveau&d'eau.&Ne pas toucher!" + ); + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterMiscellaneousMessages() { + COND_ID_HOOK(OnOpenText, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI, IS_RANDO, BuildWaterSwitchMessage); + COND_ID_HOOK(OnOpenText, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, IS_RANDO, BuildWaterSwitchMessage); +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index c4a1e864e..ab60630a8 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -233,16 +233,6 @@ void Randomizer::LoadHintMessages() { "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen #speziellen Preis# zu erhalten!", "J'aurai #une autre récompense# pour toi lorsque tu auras ton propre arc.", {QM_RED})); - - // Lake Hylia water level system - CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, - CustomMessage("Water level control system.&Keep away!", - "Wasserstand Kontrollsystem&Finger weg!", - "Système de contrôle du niveau&d'eau.&Ne pas toucher!")); - CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI, - CustomMessage("%cThis switch is rustier than you think.^%cSomething must be wrong with the pipe system in the %bWater Temple%c.", - "%cDieser Schalter scheint rostiger zu sein als er aussieht.^%cEtwas muss mit dem Leitungssystem im %bWassertempel%c nicht stimmen.", - "%cCet interrupteur est très rouillé.^%cIl doit y avoir un problème avec la tuyauterie du %bTemple de l'Eau%c.")); } // Reference soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.h diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 642bcc917..c098faca8 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2099,9 +2099,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } - else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId, MF_AUTO_FORMAT); - } else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, MF_AUTO_FORMAT); } From 05e52dd72042c0ca29813967baae0eaf21baef79 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 13:13:05 -0500 Subject: [PATCH 028/103] Convert Shooting Gallery bow reminder message --- .../randomizer/Messages/Miscellaneous.cpp | 16 +++++++++++++++- soh/soh/Enhancements/randomizer/randomizer.cpp | 7 ------- soh/soh/OTRGlobals.cpp | 3 --- 3 files changed, 15 insertions(+), 11 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp index e97178f89..f9264db1f 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp @@ -31,7 +31,21 @@ void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildShootingGalleryNoBowMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "Come back when you have your own bow and you'll get a %rdifferent prize%w!", + "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen %rspeziellen Preis%w zu erhalten!", + "J'aurai %rune autre récompense%w pour toi lorsque tu auras ton propre arc." + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterMiscellaneousMessages() { COND_ID_HOOK(OnOpenText, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI, IS_RANDO, BuildWaterSwitchMessage); COND_ID_HOOK(OnOpenText, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, IS_RANDO, BuildWaterSwitchMessage); -} \ No newline at end of file + COND_ID_HOOK(OnOpenText, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, IS_RANDO, BuildShootingGalleryNoBowMessage); +} + +RegisterShipInitFunc initFunc(RegisterMiscellaneousMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index ab60630a8..b3d024d2b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -226,13 +226,6 @@ void Randomizer::LoadHintMessages() { CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID); CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID); - - // Bow Shooting Gallery reminder - CustomMessageManager::Instance->CreateMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, - CustomMessage("Come back when you have your own bow and you'll get a #different prize#!", - "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen #speziellen Preis# zu erhalten!", - "J'aurai #une autre récompense# pour toi lorsque tu auras ton propre arc.", - {QM_RED})); } // Reference soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.h diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index c098faca8..9dfc9add1 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2099,9 +2099,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } - else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, MF_AUTO_FORMAT); - } else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); From 41f7ceedec4c771375b727e8d378a57ce18af363 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 13:14:53 -0500 Subject: [PATCH 029/103] Removes now-unused stuff for hint messages --- soh/soh/Enhancements/randomizer/randomizer.cpp | 7 ------- soh/soh/Enhancements/randomizer/randomizer.h | 1 - soh/soh/OTRGlobals.cpp | 4 ---- soh/soh/OTRGlobals.h | 1 - .../overlays/gamestates/ovl_file_choose/z_file_choose.c | 2 -- 5 files changed, 15 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b3d024d2b..4877d56c2 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -221,13 +221,6 @@ bool Randomizer::SpoilerFileExists(const char* spoilerFileName) { #pragma GCC pop_options #pragma optimize("", on) -void Randomizer::LoadHintMessages() { - auto ctx = Rando::Context::GetInstance(); - - CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID); - CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID); -} - // Reference soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.h std::unordered_map randomizerGetToEnGirlShopItem = { { RG_BUY_DEKU_NUTS_5, SI_DEKU_NUTS_5 }, diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index d27f33ea7..636482593 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -37,7 +37,6 @@ class Randomizer { static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); - void LoadHintMessages(); bool IsTrialRequired(s32 trialFlag); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 9dfc9add1..86a574783 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1972,10 +1972,6 @@ extern "C" void Randomizer_ParseSpoiler(const char* fileLoc) { OTRGlobals::Instance->gRandoContext->ParseSpoiler(fileLoc); } -extern "C" void Randomizer_LoadHintMessages() { - OTRGlobals::Instance->gRandomizer->LoadHintMessages(); -} - extern "C" bool Randomizer_IsTrialRequired(s32 trialFlag) { return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag); } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 4853bf5da..1bb982913 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -133,7 +133,6 @@ ShopItemIdentity Randomizer_IdentifyShopItem(s32 sceneNum, u8 slotIndex); CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ); FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams); void Randomizer_ParseSpoiler(const char* fileLoc); -void Randomizer_LoadHintMessages(); bool Randomizer_IsTrialRequired(s32 trialFlag); GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 7b345ce86..23c79c0e7 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -3132,8 +3132,6 @@ void FileChoose_LoadGame(GameState* thisx) { this->state.running = false; - Randomizer_LoadHintMessages(); - gSaveContext.respawn[0].entranceIndex = ENTR_LOAD_OPENING; gSaveContext.respawnFlag = 0; gSaveContext.seqId = (u8)NA_BGM_DISABLED; From 3a4e9c0db6091df9a58a5e5128abe1be18d83832 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 13:56:10 -0500 Subject: [PATCH 030/103] Convert random rupee names --- .../randomizer/Messages/Rupees.cpp | 124 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 103 --------------- soh/soh/Enhancements/randomizer/randomizer.h | 1 - soh/soh/OTRGlobals.cpp | 7 +- 4 files changed, 125 insertions(+), 110 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/Rupees.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp new file mode 100644 index 000000000..e8b02a57b --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp @@ -0,0 +1,124 @@ +/** + * This file is for handling the Randomize Rupee Names + * enhancement + */ +#include + +extern "C" { +#include "variables.h" +} + +static const char* englishRupeeNames[175] = { + "[P]", "Bad RNG Rolls", "Bananas", "Beanbean Coins", "Beans", + "Beli", "Bells", "Berries", "Bison Dollars", "Bitcoin", + "Blue Essence", "Bolts", "Bones", "Boondollars", "Bottle Caps", + "Bratwürste", "Bucks", "BugFrags", "Canadian Dollars", "Cards", + "Chaos Orbs", "Clams", "Coal", "Cocoa Beans", "Coins", + "Cookies", "Copper", "Cor", "Cornflakes", "Credits", + "Crimebucks", "Crystal Shards", "Cubits", "Cucumbers", "Dalmations", + "Dampécoin", "Dark Elixir", "Darseks", "Dead Memes", "Diamonds", + "DNA", "Doge", "Dogecoin", "Doll Hairs", "Dollars", + "Dollarydoos", "Dosh", "Doubloons", "Dwarfbucks", "Elexit", + "Emeralds", "Energon", "Eris", "Ether", "Euro", + "Experience", "Extinction Points", "Floopies", "Flurbos", "FPS", + "Friends", "Frog Coins", "Gald", "Gekz", "Gems", + "Geo", "Gil", "Glimmer", "Glitches", "Gold", + "Gold Dragons", "Goober Dollars", "Green Herbs", "Greg Siblings", "Grouses", + "Gummybears", "Hell", "Hyrule Loaches", "Ice Traps", "ISK", + "Jiggies", "KF7 Ammo", "Kinstones", "Kremcoins", "Kroner", + "Leaves", "Lemmings", "Lien", "Lira", "Lumber", + "Lungmen Dollars", "Macca", "Mana", "Mann Co. Keys", "Meat", + "Meat Stacks", "Medaparts", "Meseta", "Mesetas", "Minerals", + "Monopoly Money", "Moons", "Mora", "Mumbo Tokens", "Munny", + "Mushrooms", "Mysteries", "Neopoints", "Notes", "Nuyen", + "Orbs", "Ore", "Pix", "Pixels", "Plastyks", + "Platinum", "Pokédollars", "Pokémon", "Poko", "Pokos", + "Potch", "Pounds", "Power Pellets", "Primogems", "Réals", + "Refined Metal", "Remote Mines", "Retweets", "Rhinu", "Rings", + "Riot Points", "Robux", "Rubies", "Rubles", "Runite Ore", + "Rupees", "Saint Quartz", "Septims", "Shekels", "Shillings", + "Silver", "Simoleons", "Smackaroos", "Social Credit", "Souls", + "Spent Casings", "Spice", "Spondulicks", "Spoons", "Star Bits", + "Star Chips", "Stars", "Stones of Jordan", "Store Credit", "Strawbs", + "Studs", "Super Sea Snails", "Talent", "Teef", "Telecrystals", + "Tiberium", "TokKul", "Toys", "Turnips", "Upvotes", + "V-Bucks", "Vespene Gas", "Watts", "Widgets", "Woolongs", + "World Dollars", "Wumpa Fruit", "Yen", "Zenny", "Zorkmids" +}; + +static const char* germanRupeeNames[65] = { + "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", + "Brötchen", "Cent", "Diamanten", "Diridari", "Dogecoin", + "ECU", "Elexit", "Erz", "Erzbrocken", "Euro", + "EXP", "Forint", "Franken", "Freunde", "Gil", + "Gold", "Groschen", "Gulden", "Gummibären", "Heller", + "Juwelen", "Karolin", "Kartoffeln", "Kies", "Knete", + "Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", + "Kronkorken", "Kröten", "Mark", "Mäuse", "Monde", + "Moorhühner", "Moos", "Münzen", "Penunze", "Pesa", + "Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks", + "Pokédollar", "Radieschen", "Rappen", "Rubine", "Saphire", + "Schilling", "Seelen", "Smaragde", "Steine", "Sterne", + "Sternis", "Tael", "Taler", "Wagenchips", "Zenny" +}; + +static const char* frenchRupeeNames[40] = { + "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", + "Blés", "Bling", "Capsules", "Centimes", "Champignons", + "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", + "Dollars", "Émeraudes", "Éthers", "Étoiles", "Euros", + "Florens", "Francs", "Galds", "Gils", "Grouses", + "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", + "Orbes", "Orens", "Pépètes", "Pièces", "Plastyks", + "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies" +}; + +void BuildRupeeMessage(uint16_t* textId, bool *loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You found [[color]][[amount]] [[rupee]]\x05\x00!", + "Du hast [[color]][[amount]] [[rupee]]\x05\x00 gefunden!", + "Vous obtenez [[color]][[amount]] [[rupee]]\x05\x00!", + TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM + ); + std::string color; + std::string amount; + CustomMessage rupee = CustomMessage(RandomElement(englishRupeeNames), + RandomElement(germanRupeeNames), + RandomElement(frenchRupeeNames)); + switch (*textId) { + case TEXT_BLUE_RUPEE: + color = "\x05\x03"; + amount = "5"; + break; + case TEXT_RED_RUPEE: + color = "\x05\x01"; + amount = "20"; + break; + case TEXT_PURPLE_RUPEE: + color = "\x05\x05"; + amount = "50"; + break; + case TEXT_HUGE_RUPEE: + color = "\x05\x06"; + amount = "200"; + break; + default: + assert(!"This should not be reachable"); + return; + } + msg.Replace("[[color]]", color); + msg.Replace("[[amount]]", amount); + msg.Replace("[[rupee]]", rupee); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterRandomRupeeNames() { + COND_ID_HOOK(OnOpenText, TEXT_BLUE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_RED_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_PURPLE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_HUGE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); +} + +RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 4877d56c2..e88c92f74 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -60,71 +60,6 @@ const std::string Randomizer::hintMessageTableID = "RandomizerHints"; const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; -static const char* englishRupeeNames[175] = { - "[P]", "Bad RNG Rolls", "Bananas", "Beanbean Coins", "Beans", - "Beli", "Bells", "Berries", "Bison Dollars", "Bitcoin", - "Blue Essence", "Bolts", "Bones", "Boondollars", "Bottle Caps", - "Bratwürste", "Bucks", "BugFrags", "Canadian Dollars", "Cards", - "Chaos Orbs", "Clams", "Coal", "Cocoa Beans", "Coins", - "Cookies", "Copper", "Cor", "Cornflakes", "Credits", - "Crimebucks", "Crystal Shards", "Cubits", "Cucumbers", "Dalmations", - "Dampécoin", "Dark Elixir", "Darseks", "Dead Memes", "Diamonds", - "DNA", "Doge", "Dogecoin", "Doll Hairs", "Dollars", - "Dollarydoos", "Dosh", "Doubloons", "Dwarfbucks", "Elexit", - "Emeralds", "Energon", "Eris", "Ether", "Euro", - "Experience", "Extinction Points", "Floopies", "Flurbos", "FPS", - "Friends", "Frog Coins", "Gald", "Gekz", "Gems", - "Geo", "Gil", "Glimmer", "Glitches", "Gold", - "Gold Dragons", "Goober Dollars", "Green Herbs", "Greg Siblings", "Grouses", - "Gummybears", "Hell", "Hyrule Loaches", "Ice Traps", "ISK", - "Jiggies", "KF7 Ammo", "Kinstones", "Kremcoins", "Kroner", - "Leaves", "Lemmings", "Lien", "Lira", "Lumber", - "Lungmen Dollars", "Macca", "Mana", "Mann Co. Keys", "Meat", - "Meat Stacks", "Medaparts", "Meseta", "Mesetas", "Minerals", - "Monopoly Money", "Moons", "Mora", "Mumbo Tokens", "Munny", - "Mushrooms", "Mysteries", "Neopoints", "Notes", "Nuyen", - "Orbs", "Ore", "Pix", "Pixels", "Plastyks", - "Platinum", "Pokédollars", "Pokémon", "Poko", "Pokos", - "Potch", "Pounds", "Power Pellets", "Primogems", "Réals", - "Refined Metal", "Remote Mines", "Retweets", "Rhinu", "Rings", - "Riot Points", "Robux", "Rubies", "Rubles", "Runite Ore", - "Rupees", "Saint Quartz", "Septims", "Shekels", "Shillings", - "Silver", "Simoleons", "Smackaroos", "Social Credit", "Souls", - "Spent Casings", "Spice", "Spondulicks", "Spoons", "Star Bits", - "Star Chips", "Stars", "Stones of Jordan", "Store Credit", "Strawbs", - "Studs", "Super Sea Snails", "Talent", "Teef", "Telecrystals", - "Tiberium", "TokKul", "Toys", "Turnips", "Upvotes", - "V-Bucks", "Vespene Gas", "Watts", "Widgets", "Woolongs", - "World Dollars", "Wumpa Fruit", "Yen", "Zenny", "Zorkmids" -}; - -static const char* germanRupeeNames[65] = { - "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", - "Brötchen", "Cent", "Diamanten", "Diridari", "Dogecoin", - "ECU", "Elexit", "Erz", "Erzbrocken", "Euro", - "EXP", "Forint", "Franken", "Freunde", "Gil", - "Gold", "Groschen", "Gulden", "Gummibären", "Heller", - "Juwelen", "Karolin", "Kartoffeln", "Kies", "Knete", - "Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", - "Kronkorken", "Kröten", "Mark", "Mäuse", "Monde", - "Moorhühner", "Moos", "Münzen", "Penunze", "Pesa", - "Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks", - "Pokédollar", "Radieschen", "Rappen", "Rubine", "Saphire", - "Schilling", "Seelen", "Smaragde", "Steine", "Sterne", - "Sternis", "Tael", "Taler", "Wagenchips", "Zenny" -}; - -static const char* frenchRupeeNames[40] = { - "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", - "Blés", "Bling", "Capsules", "Centimes", "Champignons", - "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", - "Dollars", "Émeraudes", "Éthers", "Étoiles", "Euros", - "Florens", "Francs", "Galds", "Gils", "Grouses", - "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", - "Orbes", "Orens", "Pépètes", "Pièces", "Plastyks", - "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies" -}; - Randomizer::Randomizer() { Rando::StaticData::InitItemTable(); Rando::StaticData::InitLocationTable(); @@ -2453,43 +2388,6 @@ void RandomizerSettingsWindow::UpdateElement() { } } -void CreateRupeeMessages() { - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); - const std::vector rupees = { TEXT_BLUE_RUPEE, TEXT_RED_RUPEE, TEXT_PURPLE_RUPEE, TEXT_HUGE_RUPEE }; - std::string rupeeText = " "; - for (u8 rupee : rupees) { - switch (rupee) { - case TEXT_BLUE_RUPEE: - rupeeText = "\x05\x03 5 [[rupee]]\x05\x00"; - break; - case TEXT_RED_RUPEE: - rupeeText = "\x05\x01 20 [[rupee]]\x05\x00"; - break; - case TEXT_PURPLE_RUPEE: - rupeeText = "\x05\x05 50 [[rupee]]\x05\x00"; - break; - case TEXT_HUGE_RUPEE: - rupeeText = "\x05\x06 200 [[rupee]]\x05\x00"; - break; - } - customMessageManager->CreateMessage( - Randomizer::rupeeMessageTableID, rupee, - CustomMessage( - "You found" + rupeeText + " !", - "Du hast" + rupeeText + " gefunden!", - "Vous obtenez" + rupeeText + " !", TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM)); - } -} - -CustomMessage Randomizer::GetRupeeMessage(u16 rupeeTextId) { - CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::rupeeMessageTableID, rupeeTextId, MF_AUTO_FORMAT); - messageEntry.Replace("[[rupee]]", CustomMessage(RandomElement(englishRupeeNames), - RandomElement(germanRupeeNames), - RandomElement(frenchRupeeNames))); - return messageEntry; -} - void CreateNaviRandoMessages() { CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { @@ -2703,7 +2601,6 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { } void Randomizer::CreateCustomMessages() { - CreateRupeeMessages(); CreateNaviRandoMessages(); CreateFireTempleGoronMessages(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 636482593..13b822e85 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -55,7 +55,6 @@ class Randomizer { RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); static void CreateCustomMessages(); - static CustomMessage GetRupeeMessage(u16 rupeeTextId); }; #ifdef __cplusplus diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 86a574783..7da3a3bbc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2086,12 +2086,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && - (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || - textId == TEXT_HUGE_RUPEE)) { - messageEntry = Randomizer::GetRupeeMessage(textId); - // In rando, replace Navi's general overworld hints with rando-related gameplay tips - } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } From 6632ff6ee3a35bd532affe2c9b4d639f134a9e3d Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 14:14:01 -0500 Subject: [PATCH 031/103] Convert Rando-Relevant Navi Enhancement --- .../Enhancements/randomizer/Messages/Navi.cpp | 153 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 113 ------------- soh/soh/Enhancements/randomizer/randomizer.h | 1 - soh/soh/OTRGlobals.cpp | 6 +- 4 files changed, 154 insertions(+), 119 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/Navi.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/Navi.cpp b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp new file mode 100644 index 000000000..0daf51f94 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp @@ -0,0 +1,153 @@ +/** + * This file is responsible for the messages + * for the Rando-Relevant Navi Hints enhancement. + */ +#include + +extern "C" { +#include +} + +#define NUM_NAVI_MESSAGES 18 +CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { + + { "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!", + "%cFehlt Dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!", + "%cIl te manque une %wPetite Clé %cdans&un donjon? C'est peut-être le %rboss&%cqui l'a!" }, + + { "%cSometimes you can use the %rMegaton&Hammer %cinstead of bombs!", + "%cManchmal kannst Du den %rStahlhammer&%cstatt Bomben verwenden!", + "%cParfois, tu peux utiliser la %rMasse&des Titans %cau lieu de tes bombes!" }, + + { "%cStuck on this seed? You could &throw in the towel and check the&%wspoiler log%c...", + "%cHängst Du bei diesem Seed fest?&Du könntest die Flinte ins Korn&werfen und ins %wSpoiler Log %cschauen...", + "%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." }, + + { "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?", + "%cWußtest Du, daß Du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", + "%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables " + "mouvants%c?" }, + + { "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!", + "%cDu kannst den Balkon von %wImpas&Haus %cerreichen indem Du von&der Baustelle aus mit einem " + "%rHuhn&%cspringst!", + "%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec " + "une&%rcocotte%c!" }, + + { "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?", + "%cDie %yGeister-Prüfung %cin %pGanons&Schloß %chat irgendwo eine&%wversteckte Kiste%c. Weißt Du schon&wo?", + "%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu " + "le savais&déjà?" }, + + { "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is " + "junk!", + "%cKennst Du die %wMinenbowlingbahn%c?&Ich habe gehört, daß sich nur &%wzwei der Preise%c lohnen. Der " + "Rest&ist Krimskrams!", + "%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont " + "intéréssant?" }, + + { "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!", + "%cBenutzt Du auch genügend %wDeku-Nüsse%c?&Ich habe mal gesehen, daß&man damit %rKrabbelminen " + "%cdetonieren&lassen kann!", + "%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" }, + + { "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your " + "safety!", + "%cVielleicht verbleibt Dir im&%bWassertempel %coder %rFeuertempel %cein&%wzusätzlicher Schlüssel%c. " + "Dies&ist zu Deiner Sicherheit!", + "%cIl se peut que tu aies une %wPetite&Clé %cen trop dans le %bTemple de l'Eau&%cou le %rTemple du Feu%c. " + "C'est pour ta&propre sécurité!" }, + + { "%cIf you can't pick up a %rbomb&flower %cwith your hands, you can&still detonate it with %rfire %cor&with " + "%warrows%c!", + "%cNur weil Du eine %rDonnerblume&%cnicht hochheben kannst, so kannst&Du sie noch immer mit %rFeuer " + "%coder&%wPfeilen %cdetonieren lassen!", + "%cSi tu ne peux pas ramasser&un %rChoux-Péteur %cavec tes mains, tu&peux toujours le faire exploser&avec du " + "%rFeu %cou avec des %wflèches%c!" }, + + { "%cEven an adult can't push large&blocks without some %wextra&strength%c!", + "%cSelbst ein Erwachsener kann ohne&etwas %wzusätzliche Kraft %ckeine&großen Blöcke verschieben!", + "%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" }, + + { "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?", + "%cIch habe gehört, daß der&%rFlammenderwisch %ceine Schwäche für&das %wMaster-Schwert %caufweist. Hast Du&es " + "schon einmal versucht einzusetzen?", + "%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as " + "essayé?" }, + + { "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!", + "%cFehlt Dir die Waffe um gegen&eine %rSkulltula %czu kämpfen? Versuche&sie mit einem %wKrug %cabzuwerfen!", + "%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une " + "%wjarre&%cà la figure?" }, + + { "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!", + "%cIch habe gehört, daß die Stelle&%wfeuchten Bodens %cim %bZora-Fluß %cals&einzige keine %rSkulltula " + "%cbeherbergt.", + "%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne " + "contienne pas&d'%raraignée%c." }, + + { "%cThe people of Hyrule sometimes&have %witems %cfor you, but they won't&like it if you're %wwearing a " + "mask%c!", + "%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür Dich, aber sie mögen&es nicht, wenn Du %wMasken " + "trägst%c!", + "%cIl se peut que les habitants d'Hyrule&aient des %wobjets %cpour toi. Par contre,&ils risquent de ne pas " + "trop apprécier&le fait que tu %wportes un masque%c!" }, + + { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&%wreset%c!", + "%cSolltest Du irgendwo eingeschlossen&sein, mußt Du vielleicht Dein %wSpiel&speichern %cund %wneu starten%c!", + "%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" }, + + { "%cSheik will meet you in a %rburning&village %conce you have %gForest%c,&%rFire%c, and %bWater " + "%cMedallions!", + "%cShiek wird Dich in einem %rbrennenden&Dorf %ctreffen, sobald Du das Amulett&des %gWaldes%c, %rFeuers %cund " + "%bWassers&%cbesitzt.", + "%cSheik t'attendra dans un %rvillage&en feu %clorsque tu auras récupéré&les médaillons de la %gForêt%c, du " + "%rFeu&%cet de l'%bEau%c!" }, + + { "%cIf you don't have a %wsword %cas a&child, try buying %wDeku Sticks%c!&They're effective against your " + "foes!", + "%cSolltest Du als Kind kein %wSchwert&%cbesitzen, empfehle ich %wDeku-Stäbe&%czu kaufen! Diese sind " + "effektiv gegen&Widersacher!", + "%cSi tu n'as pas d'%wépée %cen tant&qu'enfant, pourquoi n'irais-tu pas&acheter quelques %wBâtons Mojo%c? " + "Ils&sont efficaces contre tes ennemis!" } +}; + +void BuildNaviMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = NaviMessages[Random(0, NUM_NAVI_MESSAGES)]; + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterNaviMessages() { + COND_ID_HOOK(OnOpenText, TEXT_NAVI_DEKU_TREE_SUMMONS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CMON_BE_BRAVE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_VISIT_THE_PRINCESS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_MALONS_FATHER, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_THE_PRINCESS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHAT_WOULD_SARIA_SAY, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IMPA_SAID_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_USE_BOMB_FLOWER, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FAIRY_LIVES_ON_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SARIA_KNOWS_ABOUT_STONES, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_RUTO_INSIDE_JABUS_BELLY, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_COLLECTED_THREE_STONES, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_THREW_SOMETHING_IN_MOAT, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CHECK_TEMPLE_OF_TIME, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SHOULD_WE_BELIEVE_SHEIK, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHATS_GOING_ON_IN_FOREST, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CLOUD_OVER_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_ARTIC_WIND_IS_BLOWING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IRON_BOOTS_WEIGH_A_TON, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_LOOK_FOR_SOMONE_WHO_KNOWS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IT_CAME_OUT_OF_THE_WELL, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_BUILT_THE_SPIRIT_TEMPLE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_HAVE_YOU_EVER_PLAYED_NOCTURNE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHERE_GANONDORF_WAS_BORN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_EQUIP_THE_SILVER_GAUNTLETS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_IS_WAITING_FOR_US, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SAVE_PRINCESS_ZELDA, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_TRY_TO_KEEP_MOVING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); +} + +RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index e88c92f74..9d6e72043 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2388,118 +2388,6 @@ void RandomizerSettingsWindow::UpdateElement() { } } -void CreateNaviRandoMessages() { - CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { - - { "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!", - "%cFehlt Dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!", - "%cIl te manque une %wPetite Clé %cdans&un donjon? C'est peut-être le %rboss&%cqui l'a!" }, - - { "%cSometimes you can use the %rMegaton&Hammer %cinstead of bombs!", - "%cManchmal kannst Du den %rStahlhammer&%cstatt Bomben verwenden!", - "%cParfois, tu peux utiliser la %rMasse&des Titans %cau lieu de tes bombes!" }, - - { "%cStuck on this seed? You could &throw in the towel and check the&%wspoiler log%c...", - "%cHängst Du bei diesem Seed fest?&Du könntest die Flinte ins Korn&werfen und ins %wSpoiler Log %cschauen...", - "%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." }, - - { "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?", - "%cWußtest Du, daß Du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", - "%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables " - "mouvants%c?" }, - - { "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!", - "%cDu kannst den Balkon von %wImpas&Haus %cerreichen indem Du von&der Baustelle aus mit einem " - "%rHuhn&%cspringst!", - "%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec " - "une&%rcocotte%c!" }, - - { "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?", - "%cDie %yGeister-Prüfung %cin %pGanons&Schloß %chat irgendwo eine&%wversteckte Kiste%c. Weißt Du schon&wo?", - "%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu " - "le savais&déjà?" }, - - { "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is " - "junk!", - "%cKennst Du die %wMinenbowlingbahn%c?&Ich habe gehört, daß sich nur &%wzwei der Preise%c lohnen. Der " - "Rest&ist Krimskrams!", - "%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont " - "intéréssant?" }, - - { "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!", - "%cBenutzt Du auch genügend %wDeku-Nüsse%c?&Ich habe mal gesehen, daß&man damit %rKrabbelminen " - "%cdetonieren&lassen kann!", - "%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" }, - - { "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your " - "safety!", - "%cVielleicht verbleibt Dir im&%bWassertempel %coder %rFeuertempel %cein&%wzusätzlicher Schlüssel%c. " - "Dies&ist zu Deiner Sicherheit!", - "%cIl se peut que tu aies une %wPetite&Clé %cen trop dans le %bTemple de l'Eau&%cou le %rTemple du Feu%c. " - "C'est pour ta&propre sécurité!" }, - - { "%cIf you can't pick up a %rbomb&flower %cwith your hands, you can&still detonate it with %rfire %cor&with " - "%warrows%c!", - "%cNur weil Du eine %rDonnerblume&%cnicht hochheben kannst, so kannst&Du sie noch immer mit %rFeuer " - "%coder&%wPfeilen %cdetonieren lassen!", - "%cSi tu ne peux pas ramasser&un %rChoux-Péteur %cavec tes mains, tu&peux toujours le faire exploser&avec du " - "%rFeu %cou avec des %wflèches%c!" }, - - { "%cEven an adult can't push large&blocks without some %wextra&strength%c!", - "%cSelbst ein Erwachsener kann ohne&etwas %wzusätzliche Kraft %ckeine&großen Blöcke verschieben!", - "%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" }, - - { "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?", - "%cIch habe gehört, daß der&%rFlammenderwisch %ceine Schwäche für&das %wMaster-Schwert %caufweist. Hast Du&es " - "schon einmal versucht einzusetzen?", - "%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as " - "essayé?" }, - - { "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!", - "%cFehlt Dir die Waffe um gegen&eine %rSkulltula %czu kämpfen? Versuche&sie mit einem %wKrug %cabzuwerfen!", - "%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une " - "%wjarre&%cà la figure?" }, - - { "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!", - "%cIch habe gehört, daß die Stelle&%wfeuchten Bodens %cim %bZora-Fluß %cals&einzige keine %rSkulltula " - "%cbeherbergt.", - "%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne " - "contienne pas&d'%raraignée%c." }, - - { "%cThe people of Hyrule sometimes&have %witems %cfor you, but they won't&like it if you're %wwearing a " - "mask%c!", - "%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür Dich, aber sie mögen&es nicht, wenn Du %wMasken " - "trägst%c!", - "%cIl se peut que les habitants d'Hyrule&aient des %wobjets %cpour toi. Par contre,&ils risquent de ne pas " - "trop apprécier&le fait que tu %wportes un masque%c!" }, - - { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&%wreset%c!", - "%cSolltest Du irgendwo eingeschlossen&sein, mußt Du vielleicht Dein %wSpiel&speichern %cund %wneu starten%c!", - "%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" }, - - { "%cSheik will meet you in a %rburning&village %conce you have %gForest%c,&%rFire%c, and %bWater " - "%cMedallions!", - "%cShiek wird Dich in einem %rbrennenden&Dorf %ctreffen, sobald Du das Amulett&des %gWaldes%c, %rFeuers %cund " - "%bWassers&%cbesitzt.", - "%cSheik t'attendra dans un %rvillage&en feu %clorsque tu auras récupéré&les médaillons de la %gForêt%c, du " - "%rFeu&%cet de l'%bEau%c!" }, - - { "%cIf you don't have a %wsword %cas a&child, try buying %wDeku Sticks%c!&They're effective against your " - "foes!", - "%cSolltest Du als Kind kein %wSchwert&%cbesitzen, empfehle ich %wDeku-Stäbe&%czu kaufen! Diese sind " - "effektiv gegen&Widersacher!", - "%cSi tu n'as pas d'%wépée %cen tant&qu'enfant, pourquoi n'irais-tu pas&acheter quelques %wBâtons Mojo%c? " - "Ils&sont efficaces contre tes ennemis!" } - }; - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(Randomizer::NaviRandoMessageTableID); - for (unsigned int i = 0; i <= (NUM_NAVI_MESSAGES - 1); i++) { - customMessageManager->CreateMessage( - Randomizer::NaviRandoMessageTableID, i, - NaviMessages[i]); - } -} - static int goronIDs[9] = { TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME, TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET, TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET, @@ -2601,7 +2489,6 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { } void Randomizer::CreateCustomMessages() { - CreateNaviRandoMessages(); CreateFireTempleGoronMessages(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 13b822e85..58290fed1 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -19,7 +19,6 @@ #define MAX_SEED_STRING_SIZE 1024 #define NUM_TRIFORCE_PIECE_MESSAGES 6 -#define NUM_NAVI_MESSAGES 18 #define NUM_GORON_MESSAGES 9 class Randomizer { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7da3a3bbc..0afd8861c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2086,11 +2086,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { - u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); - } - else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { + if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } From d8ed60892e2f578adb0f9edd34e55dfeab1ce653 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 14:34:27 -0500 Subject: [PATCH 032/103] Convert Random Goron messages --- .../randomizer/Messages/Goron.cpp | 110 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 105 ----------------- soh/soh/Enhancements/randomizer/randomizer.h | 3 - 3 files changed, 110 insertions(+), 108 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/Goron.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/Goron.cpp b/soh/soh/Enhancements/randomizer/Messages/Goron.cpp new file mode 100644 index 000000000..e0791ade3 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/Goron.cpp @@ -0,0 +1,110 @@ +/** + * Handles the randomized silly messages that the Fire Temple + * trapped Gorons have when you free them. + */ +#include + +extern "C" { +#include +} + +#define NUM_GORON_MESSAGES 9 +static CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = { + { + "Are you the one they call %g@%w?^You look really weird for %rDarunia's kid.%w&Are you adopted?", + "Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst Du&%rDarunias Kind.%w Bist Du " + "adoptiert?", + "C'est toi qu'on appelle %g@%w?^Tu es vraiment bizarre pour être&le %rfils du Chef%w. Tu as été adopté?", + }, + { + "Thank Hylia! I was so worried about&when my teacher would let me get&out of detention.^I gotta go home " + "and see my parents.", + "Ich wollte nur dieses Ding hier wieder&in seine Truhe zurücklegen, weil...^...gehört mir ja eigentlich " + "nicht,&weißt Du?^Doch dann ging plötzlich dieses&Tor hinter mir zu.&Danke für die Rettung.", + "Par les déesses!&Mon Frère?!&C'est bien toi?&Comment ça on ne se connaît pas?^Tu trouves vraiment que " + "je&ressemble à n'importe quel Goron?", + }, + { + "How long has it been, do you know?^%r[[days]]%w days!?^Oh no, and it's %r\x1F%w?&I have to check on my " + "cake!!", + "Weißt Du zufällig, wie viele Tage&vergangen sind?^%r[[days]]%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? " + "Ich&muss dringend nach meinem Kuchen&sehen!!!", + "Cela fait combien de temps que&je suis enfermé ici?&Non mais je ne vais pas crier.^COMBIEN?! %r[[days]]%w " + "JOURS!?^En plus il est %r\x1F%w...&Il faut vraiment que je rentre...", + }, + { + // 0x39C7 - ganon laugh + "\x12\x39\xC7You fell into my %rtrap!%w&Foolish boy, it was me, Ganondorf!!!^...whoa, where am I?&What " + "happened?^Weird.", + "\x12\x39\xC7" + "Du bist mir in die %rFalle%w gegangen!&Du Narr, ich bin es, %rGanondorf%w!!!^...Huch? Wo bin ich? Was ist " + "passiert?^Seltsam...", + "\x12\x39\xC7Tu es tombé dans mon %rpiège%w!&Tu croyais que j'étais un Goron mais,&c'était moi! " + "%rGanondorf%w!^...Hein? Où suis-je?&Que s'est-il passé?", + }, + { + "Thanks, but I don't know if I wanna go&just yet...^Hmm...^...^...^...^...^...maybe I can come back " + "later.&Bye bye.", + "Danke für die Rettung, aber&eigentlich finde ich es hier ganz&nett...^Hmm...^...^...^...^...^...Naja, ich " + "kann ja jederzeit&wiederkommen. Man sieht sich.", + "Merci, mais je me sens plus en&sécurité ici...^...^...^...^...^Hmm...^...Tout compte fait, je vais y " + "aller.&A plus tard.", + }, + { + "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " + "pressed it %b[[a_btn]]%w times.^Wow.", + "Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " + "erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", + "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " + "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." + }, + { + "\x13\x1A" + "Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w " + "rupees!", + "\x13\x1A" + "Hey, ist Dir nicht zu warm?&Besorge Dir doch eine Flasche&%rLon Lon-Milch%w, um Dich&abzukühlen.^Kostet " + "Dich auch nur %g30%w Rubine!", + "\x13\x1A" + "Woah! Tu dois avoir chaud!&Tu savais que tu pouvais acheter&du %rLait de Lon Lon%w pour&seulement %g30 " + "rubis%w?^Il n'y a rien de mieux pour s'hydrater!", + }, + { + "In that case, I'll help you out!^They say that %rthe thing you're&looking for%w can only be found%g " + "when&you're not looking for it.%w^Hope that helps!", + "Pass auf, ich gebe Dir einen Tipp!^Man sagt, man findet %rdas was&man sucht%w nur, und wirklich nur&dann, " + "%gwenn man gerade nicht danach&sucht%w.^Du kannst mich jederzeit wieder für&mehr hilfreiche Tipps " + "aufsuchen!", + "Dans ce cas, je vais t'aider!&On dit que l'objet que tu cherches&ne peut être trouvé que lorsque&tu ne le " + "cherches pas.", + }, + { + "I dunno why I was thrown in here,&truth be told.&I'm just a %g\"PR\"%w person.", + "Wat weiß'n ich, wieso ich hier&eingepfercht wurd. Ich mach&doch nur %g\"Pull&Requests\"%w.", + "Je ne sais pas comment on m'a jeté&ici. Il faut croire que je dors comme&une pierre.", + }, +}; + +void BuildGoronMessage(uint16_t* textId, bool* loadFromMessageTable) { + uint16_t choice = Random(0, NUM_GORON_MESSAGES); + CustomMessage msg = FireTempleGoronMessages[choice]; + msg.Replace("[[days]]", std::to_string(gSaveContext.totalDays)); + msg.Replace("[[a_btn]]", std::to_string(gSaveContext.ship.stats.count[COUNT_BUTTON_PRESSES_A])); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterGoronMessages() { + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_FLAME_DANCER_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_SWITCH_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_FLAME_DANCER_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_SWITCH_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_OCARINA_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_PILLAR_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_HIDDEN_DOOR_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET, IS_RANDO, BuildGoronMessage); +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 9d6e72043..3d4d2aebd 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -2388,110 +2388,6 @@ void RandomizerSettingsWindow::UpdateElement() { } } -static int goronIDs[9] = { TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME, - TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET, - TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET, - TEXT_FIRE_TEMPLE_GORON_FLAME_DANCER_SECRET, - TEXT_FIRE_TEMPLE_GORON_SWITCH_SECRET, - TEXT_FIRE_TEMPLE_GORON_OCARINA_SECRET, - TEXT_FIRE_TEMPLE_GORON_PILLAR_SECRET, - TEXT_FIRE_TEMPLE_GORON_HIDDEN_DOOR_SECRET, - TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET}; - -void CreateFireTempleGoronMessages() { - CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = { - { - "Are you the one they call %g@%w?^You look really weird for %rDarunia's kid.%w&Are you adopted?", - "Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst Du&%rDarunias Kind.%w Bist Du " - "adoptiert?", - "C'est toi qu'on appelle %g@%w?^Tu es vraiment bizarre pour être&le %rfils du Chef%w. Tu as été adopté?", - }, - { - "Thank Hylia! I was so worried about&when my teacher would let me get&out of detention.^I gotta go home " - "and see my parents.", - "Ich wollte nur dieses Ding hier wieder&in seine Truhe zurücklegen, weil...^...gehört mir ja eigentlich " - "nicht,&weißt Du?^Doch dann ging plötzlich dieses&Tor hinter mir zu.&Danke für die Rettung.", - "Par les déesses!&Mon Frère?!&C'est bien toi?&Comment ça on ne se connaît pas?^Tu trouves vraiment que " - "je&ressemble à n'importe quel Goron?", - }, - { - "How long has it been, do you know?^%r[[days]]%w days!?^Oh no, and it's %r\x1F%w?&I have to check on my " - "cake!!", - "Weißt Du zufällig, wie viele Tage&vergangen sind?^%r[[days]]%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? " - "Ich&muss dringend nach meinem Kuchen&sehen!!!", - "Cela fait combien de temps que&je suis enfermé ici?&Non mais je ne vais pas crier.^COMBIEN?! %r[[days]]%w " - "JOURS!?^En plus il est %r\x1F%w...&Il faut vraiment que je rentre...", - }, - { - // 0x39C7 - ganon laugh - "\x12\x39\xC7You fell into my %rtrap!%w&Foolish boy, it was me, Ganondorf!!!^...whoa, where am I?&What " - "happened?^Weird.", - "\x12\x39\xC7" - "Du bist mir in die %rFalle%w gegangen!&Du Narr, ich bin es, %rGanondorf%w!!!^...Huch? Wo bin ich? Was ist " - "passiert?^Seltsam...", - "\x12\x39\xC7Tu es tombé dans mon %rpiège%w!&Tu croyais que j'étais un Goron mais,&c'était moi! " - "%rGanondorf%w!^...Hein? Où suis-je?&Que s'est-il passé?", - }, - { - "Thanks, but I don't know if I wanna go&just yet...^Hmm...^...^...^...^...^...maybe I can come back " - "later.&Bye bye.", - "Danke für die Rettung, aber&eigentlich finde ich es hier ganz&nett...^Hmm...^...^...^...^...^...Naja, ich " - "kann ja jederzeit&wiederkommen. Man sieht sich.", - "Merci, mais je me sens plus en&sécurité ici...^...^...^...^...^Hmm...^...Tout compte fait, je vais y " - "aller.&A plus tard.", - }, - { "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " - "pressed it %b[[a_btn]]%w times.^Wow.", - "Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " - "erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", - "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " - "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." }, - { - "\x13\x1A" - "Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w " - "rupees!", - "\x13\x1A" - "Hey, ist Dir nicht zu warm?&Besorge Dir doch eine Flasche&%rLon Lon-Milch%w, um Dich&abzukühlen.^Kostet " - "Dich auch nur %g30%w Rubine!", - "\x13\x1A" - "Woah! Tu dois avoir chaud!&Tu savais que tu pouvais acheter&du %rLait de Lon Lon%w pour&seulement %g30 " - "rubis%w?^Il n'y a rien de mieux pour s'hydrater!", - }, - { - "In that case, I'll help you out!^They say that %rthe thing you're&looking for%w can only be found%g " - "when&you're not looking for it.%w^Hope that helps!", - "Pass auf, ich gebe Dir einen Tipp!^Man sagt, man findet %rdas was&man sucht%w nur, und wirklich nur&dann, " - "%gwenn man gerade nicht danach&sucht%w.^Du kannst mich jederzeit wieder für&mehr hilfreiche Tipps " - "aufsuchen!", - "Dans ce cas, je vais t'aider!&On dit que l'objet que tu cherches&ne peut être trouvé que lorsque&tu ne le " - "cherches pas.", - }, - { - "I dunno why I was thrown in here,&truth be told.&I'm just a %g\"PR\"%w person.", - "Wat weiß'n ich, wieso ich hier&eingepfercht wurd. Ich mach&doch nur %g\"Pull&Requests\"%w.", - "Je ne sais pas comment on m'a jeté&ici. Il faut croire que je dors comme&une pierre.", - }, - }; - - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(customMessageTableID); - for (u8 i = 0; i <= NUM_GORON_MESSAGES - 1; i++) { - customMessageManager->CreateMessage(customMessageTableID, goronIDs[i], FireTempleGoronMessages[i]); - } -} - -CustomMessage Randomizer::GetGoronMessage(u16 index) { - CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, goronIDs[index]); - messageEntry.Replace("[[days]]", std::to_string(gSaveContext.totalDays)); - messageEntry.Replace("[[a_btn]]", std::to_string(gSaveContext.ship.stats.count[COUNT_BUTTON_PRESSES_A])); - messageEntry.Format(); - return messageEntry; -} - -void Randomizer::CreateCustomMessages() { - CreateFireTempleGoronMessages(); -} - class ExtendedVanillaTableInvalidItemIdException: public std::exception { private: s16 itemID; @@ -2506,7 +2402,6 @@ class ExtendedVanillaTableInvalidItemIdException: public std::exception { void RandomizerSettingsWindow::InitElement() { mSettings = Rando::Settings::GetInstance(); - Randomizer::CreateCustomMessages(); seedString = (char*)calloc(MAX_SEED_STRING_SIZE, sizeof(char)); mSettings->UpdateOptionProperties(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 58290fed1..c9e19e47a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -19,7 +19,6 @@ #define MAX_SEED_STRING_SIZE 1024 #define NUM_TRIFORCE_PIECE_MESSAGES 6 -#define NUM_GORON_MESSAGES 9 class Randomizer { private: @@ -52,8 +51,6 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); - CustomMessage GetGoronMessage(u16 index); - static void CreateCustomMessages(); }; #ifdef __cplusplus From f847e438bd22b4d4707d0846c5be325140ddd4b6 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 14:36:23 -0500 Subject: [PATCH 033/103] Removes final randomizer message unused stuff --- soh/soh/Enhancements/randomizer/randomizer.cpp | 4 ---- soh/soh/Enhancements/randomizer/randomizer.h | 8 +------- soh/soh/OTRGlobals.cpp | 7 ------- 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 3d4d2aebd..d8aff7788 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -56,10 +56,6 @@ std::set enabledGlitches; u8 generated; char* seedString; -const std::string Randomizer::hintMessageTableID = "RandomizerHints"; -const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; -const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; - Randomizer::Randomizer() { Rando::StaticData::InitItemTable(); Rando::StaticData::InitLocationTable(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index c9e19e47a..695be1481 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -18,7 +18,6 @@ #include "soh/Enhancements/randomizer/fishsanity.h" #define MAX_SEED_STRING_SIZE 1024 -#define NUM_TRIFORCE_PIECE_MESSAGES 6 class Randomizer { private: @@ -27,12 +26,7 @@ class Randomizer { public: Randomizer(); ~Randomizer(); - - static const std::string getItemMessageTableID; - static const std::string hintMessageTableID; - static const std::string rupeeMessageTableID; - static const std::string NaviRandoMessageTableID; - + static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); bool IsTrialRequired(s32 trialFlag); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0afd8861c..f1dc1dc72 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2084,13 +2084,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { const int maxBufferSize = sizeof(font->msgBuf); CustomMessage messageEntry; s16 actorParams = 0; - if (IS_RANDO) { - auto ctx = Rando::Context::GetInstance(); - if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { - u16 choice = Random(0, NUM_GORON_MESSAGES); - messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); - } - } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { // The freeze text cannot be manually dismissed and must be auto-dismissed. From feaa821ac3baf3bab39d14097f7c4b3c443604fa Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:04:13 -0500 Subject: [PATCH 034/103] Convert Injecting Skull token counts --- soh/soh/Enhancements/InjectItemCounts.cpp | 43 +++++++++++++++++++++++ soh/soh/OTRGlobals.cpp | 27 +------------- soh/soh/z_message_OTR.cpp | 16 --------- 3 files changed, 44 insertions(+), 42 deletions(-) create mode 100644 soh/soh/Enhancements/InjectItemCounts.cpp diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp new file mode 100644 index 000000000..e5888b6f3 --- /dev/null +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -0,0 +1,43 @@ +#include + +extern "C" { +#include "variables.h" +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) + +void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!", + "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " + "Skulltula-Symbole&gesammelt!", + "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en " + "tout!", + TEXTBOX_TYPE_BLUE); + // The freeze text cannot be manually dismissed and must be auto-dismissed. + // This is fine and even wanted when skull tokens are not shuffled, but when + // when they are shuffled we don't want to be able to manually dismiss the box. + // Otherwise if we get a token from a chest or an NPC we get stuck in the ItemGet + // animation until the text box auto-dismisses. + // RANDOTODO: Implement a way to determine if an item came from a skulltula and + // inject the auto-dismiss control code if it did. + if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && + !(IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_TOKENS).IsNot(RO_TOKENSANITY_OFF))) { + // Auto dismiss textbox after 0x3C (60) frames (about 3 seconds for OoT) + msg = msg + "\x0E\x3C"; + } + int16_t gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); + msg.Replace("[[gscount]]", std::to_string(gsCount)); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void InjectItemCounts_Register() { + COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), BuildSkulltulaMessage); +} + +RegisterShipInitFunc initFunc(InjectItemCounts_Register, { + CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), +}); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index f1dc1dc72..01f8b0ebb 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2084,32 +2084,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { const int maxBufferSize = sizeof(font->msgBuf); CustomMessage messageEntry; s16 actorParams = 0; - if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { - if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { - // The freeze text cannot be manually dismissed and must be auto-dismissed. - // This is fine and even wanted when skull tokens are not shuffled, but when - // when they are shuffled we want to be able to manually dismiss the box. - // Otherwise if we get a token from a chest or an NPC we get stuck in the ItemGet - // animation until the text box auto-dismisses. - // RANDOTODO: Implement a way to determine if an item came from a skulltula and - // inject the auto-dismiss control code if it did. - if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && - !(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) { - textId = TEXT_GS_NO_FREEZE; - } else { - textId = TEXT_GS_FREEZE; - } - // In vanilla, GS token count is incremented prior to the text box displaying - // In rando we need to bump the token count by one to show the correct count - s16 gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - messageEntry.Replace("[[gsCount]]", std::to_string(gsCount)); - } else if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && (!IS_RANDO || Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) == RO_TOKENSANITY_OFF)) { - messageEntry = CustomMessage::LoadVanillaMessageTableEntry(TEXT_GS_FREEZE); - messageEntry.Replace(CustomMessage::MESSAGE_END(), "\x0E\x3C"); - messageEntry += CustomMessage::MESSAGE_END(); - } - } else if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && + if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); } else if (textId == TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0)) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 22c217182..5b89d3eb8 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -135,22 +135,6 @@ extern "C" void OTRMessage_Init() } CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); - CustomMessageManager::Instance->CreateGetItemMessage( - customMessageTableID, (GetItemID)TEXT_GS_NO_FREEZE, ITEM_SKULL_TOKEN, - CustomMessage("You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!\x0E\x3C", - "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " - "Skulltula-Symbole&gesammelt!\x0E\x3C", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en " - "tout!\x0E\x3C", - TEXTBOX_TYPE_BLUE)); - CustomMessageManager::Instance->CreateGetItemMessage( - customMessageTableID, (GetItemID)TEXT_GS_FREEZE, ITEM_SKULL_TOKEN, - CustomMessage( - "You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!", - "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " - "Skulltula-Symbole&gesammelt!", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en tout!", - TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_BUY_BOMBCHUS_10_DESC, CustomMessage("\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " From a513a422b0c0b43a036d41806e01880394fd34b3 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:36:06 -0500 Subject: [PATCH 035/103] Add in a way to AutoFormat with an item icon. --- .../custom-message/CustomMessageManager.cpp | 12 ++++++++++-- .../custom-message/CustomMessageManager.h | 1 + 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 0745c6fc0..b5e4163cd 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -353,6 +353,14 @@ void CustomMessage::AutoFormat() { } } +void CustomMessage::AutoFormat(ItemID iid) { + for (std::string &str : messages) { + str.insert(0, ITEM_OBTAINED(iid)); + } + AutoFormat(); + Replace(WAIT_FOR_INPUT(), WAIT_FOR_INPUT() + ITEM_OBTAINED(iid)); +} + void CustomMessage::Clean() { for (std::string& str : messages) { CleanString(str); @@ -408,7 +416,7 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin // Skip over control codes if (textStr->at(currentPos) == '%') { nextPosJump = 2; - } else if (textStr->at(currentPos) == '$') { + } else if (textStr->at(currentPos) == '\x13') { nextPosJump = 2; } else if (textStr->at(currentPos) == '@') { nextPosJump = 1; @@ -512,7 +520,7 @@ void CustomMessage::AutoFormatString(std::string& str) const { ReplaceColors(str); // insert newlines either manually or when encountering a '&' size_t lastNewline = 0; - const bool hasIcon = str.find('$', 0) != std::string::npos; + const bool hasIcon = str.find('\x13') != std::string::npos; size_t lineLength = NextLineLength(&str, lastNewline, hasIcon); size_t lineCount = 1; size_t yesNo = str.find("\x1B"s[0], lastNewline); diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 506c2c43c..943b18970 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -163,6 +163,7 @@ class CustomMessage { * textboxes, and use it's formatting. */ void AutoFormat(); + void AutoFormat(ItemID iid); /** * @brief Removes all OoT formatting from the message, From faa21513c4cbc4714f52c433ec6d056880a78a7d Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:38:23 -0500 Subject: [PATCH 036/103] Fix some errors with skull tokens and apply icon --- soh/soh/Enhancements/InjectItemCounts.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index e5888b6f3..6ae327e0c 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -28,14 +28,15 @@ void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { } int16_t gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); msg.Replace("[[gscount]]", std::to_string(gsCount)); + msg.AutoFormat(ITEM_SKULL_TOKEN); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } void InjectItemCounts_Register() { - COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), BuildSkulltulaMessage); - COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); } RegisterShipInitFunc initFunc(InjectItemCounts_Register, { From c21aecf17acf696c092ca83c4b4c94f4a10df8ff Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:38:45 -0500 Subject: [PATCH 037/103] Convert heart container item counts --- soh/soh/Enhancements/InjectItemCounts.cpp | 15 ++++++++++++++- soh/soh/OTRGlobals.cpp | 3 --- soh/soh/z_message_OTR.cpp | 6 ------ 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index 6ae327e0c..ee5131ada 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -29,7 +29,18 @@ void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { int16_t gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); msg.Replace("[[gscount]]", std::to_string(gsCount)); msg.AutoFormat(ITEM_SKULL_TOKEN); - msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildHeartContainerMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You got a %rHeart Container%w!&You've collected %r[[heartContainerCount]]%w containers&in total!", + "Ein %rHerzcontainer%w!&Du hast nun insgesamt %r[[heartContainerCount]]%w&Herzcontainer gesammelt!", + "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!" + ); + msg.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.ship.stats.heartContainers + 1)); + msg.AutoFormat(ITEM_HEART_CONTAINER); msg.LoadIntoFont(); *loadFromMessageTable = false; } @@ -37,8 +48,10 @@ void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { void InjectItemCounts_Register() { COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_CONTAINER, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0), BuildHeartContainerMessage); } RegisterShipInitFunc initFunc(InjectItemCounts_Register, { CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), + CVAR_ENHANCEMENT("InjectItemCounts.HeartContainers"), }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 01f8b0ebb..3513e69a3 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2087,9 +2087,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - } else if (textId == TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_CONTAINER, MF_FORMATTED); - messageEntry.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.ship.stats.heartContainers + 1)); } else if (textId >= TEXT_HEART_PIECE && textId < TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_PIECE, MF_FORMATTED); messageEntry.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1)); diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 5b89d3eb8..98c77d939 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -149,12 +149,6 @@ extern "C" void OTRMessage_Init() "Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w")); - CustomMessageManager::Instance->CreateGetItemMessage( - customMessageTableID, (GetItemID)TEXT_HEART_CONTAINER, ITEM_HEART_CONTAINER, - CustomMessage( - "You got a %rHeart Container%w!&You've collected %r[[heartContainerCount]]%w containers&in total!", - "Ein %rHerzcontainer%w!&Du hast nun insgesamt %r[[heartContainerCount]]%w&Herzcontainer gesammelt!", - "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!")); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_HEART_PIECE, ITEM_HEART_PIECE, CustomMessage("You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", From d9f7cb170118ba5a43d261bba7e5b2ff83e5ea18 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:49:00 -0500 Subject: [PATCH 038/103] Convert Inject Item Count for Heart Pieces. --- soh/soh/Enhancements/InjectItemCounts.cpp | 22 +++++++++++++++++++++- soh/soh/OTRGlobals.cpp | 3 --- soh/soh/z_message_OTR.cpp | 6 ------ 3 files changed, 21 insertions(+), 10 deletions(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index ee5131ada..0b6670668 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -45,13 +45,33 @@ void BuildHeartContainerMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildHeartPieceMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", + "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!", + "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", + TEXTBOX_TYPE_BLUE + ); + msg.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1)); + msg.AutoFormat(ITEM_HEART_PIECE); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void InjectItemCounts_Register() { COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); COND_ID_HOOK(OnOpenText, TEXT_HEART_CONTAINER, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0), BuildHeartContainerMessage); + // Heart Pieces don't have documented text IDs after the first one, but + // there are 3 more in between TEXT_HEART_PIECE and TEXT_HEART_CONTAINER. + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 1, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 2, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 3, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); } RegisterShipInitFunc initFunc(InjectItemCounts_Register, { CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), - CVAR_ENHANCEMENT("InjectItemCounts.HeartContainers"), + CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), + CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece") }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 3513e69a3..b266000bb 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2087,9 +2087,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - } else if (textId >= TEXT_HEART_PIECE && textId < TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_PIECE, MF_FORMATTED); - messageEntry.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1)); } else if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT, MF_FORMATTED); } diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 98c77d939..fb7415d11 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -149,12 +149,6 @@ extern "C" void OTRMessage_Init() "Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w")); - CustomMessageManager::Instance->CreateGetItemMessage( - customMessageTableID, (GetItemID)TEXT_HEART_PIECE, ITEM_HEART_PIECE, - CustomMessage("You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", - "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!", - "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", - TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_MARKET_GUARD_NIGHT, CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", From e491dfa171fac85e8e7ed0d847a1fe9ad9f34277 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 17:06:07 -0500 Subject: [PATCH 039/103] Port Better Bombchu Shopping --- .../Items/BetterBombchuShopping.cpp | 39 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 5 +-- soh/soh/z_message_OTR.cpp | 14 ------- 3 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 soh/soh/Enhancements/Items/BetterBombchuShopping.cpp diff --git a/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp new file mode 100644 index 000000000..918b5bba2 --- /dev/null +++ b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp @@ -0,0 +1,39 @@ +#include + +extern "C" { +#include +} + +//RANDOTODO: Port the rest of the behavior associated with this option here. + +void BuildShopDescMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " + "self-propelled time&bomb!\x09\x0A", + "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als " + "Distanzwaffe&einsetzen kannst!\x09\x0A", + "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est " + "&destructrice!!!\x09\x0A" + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildShopPromptMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "\x08Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", + "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", + "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w" + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BetterBombchuShopping_Register() { + COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_DESC, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopDescMessage); + COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_PROMPT, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopPromptMessage); +} + +RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index b266000bb..57fbe82dc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2084,10 +2084,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { const int maxBufferSize = sizeof(font->msgBuf); CustomMessage messageEntry; s16 actorParams = 0; - if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && - (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - } else if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { + if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT, MF_FORMATTED); } if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index fb7415d11..d22779d70 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -135,20 +135,6 @@ extern "C" void OTRMessage_Init() } CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_BUY_BOMBCHUS_10_DESC, - CustomMessage("\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " - "self-propelled time&bomb!\x09\x0A", - "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als " - "Distanzwaffe&einsetzen kannst!\x09\x0A", - "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est " - "&destructrice!!!\x09\x0A")); - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_BUY_BOMBCHUS_10_PROMPT, - CustomMessage("\x08" - "Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", - "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", - "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w")); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_MARKET_GUARD_NIGHT, CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", From 642c77638f5907fead616dd785658fd5eb8f123c Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 17:15:28 -0500 Subject: [PATCH 040/103] Convert Market Sneak --- .../Enhancements/TimeSavers/MarketSneak.cpp | 24 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 3 --- soh/soh/z_message_OTR.cpp | 5 ---- 3 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 soh/soh/Enhancements/TimeSavers/MarketSneak.cpp diff --git a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp new file mode 100644 index 000000000..c22d7b9b5 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp @@ -0,0 +1,24 @@ +#include + +extern "C" { +#include +} + +// RANDOTODO: Port the rest of the behavior for this enhancement here. + +void BuildNightGuardMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", + "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", + "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w" + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void MarketSneak_Register() { + COND_ID_HOOK(OnOpenText, TEXT_MARKET_GUARD_NIGHT, CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0), BuildNightGuardMessage); +} + +RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 57fbe82dc..07017529c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2084,9 +2084,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { const int maxBufferSize = sizeof(font->msgBuf); CustomMessage messageEntry; s16 actorParams = 0; - if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT, MF_FORMATTED); - } if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE, MF_FORMATTED); } diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index d22779d70..398451614 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -135,11 +135,6 @@ extern "C" void OTRMessage_Init() } CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_MARKET_GUARD_NIGHT, - CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", - "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", - "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w")); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_FISHERMAN_LEAVE, CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", From a7cb00d3bb314ca4cd1e0969d6315ef298208e2f Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 17:25:08 -0500 Subject: [PATCH 041/103] Port Quit Fishing At Door and clean up unused stuff --- .../TimeSavers/QuitFishingAtDoor.cpp | 26 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 14 ---------- soh/soh/OTRGlobals.h | 2 -- soh/soh/z_message_OTR.cpp | 7 ----- 4 files changed, 26 insertions(+), 23 deletions(-) create mode 100644 soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp diff --git a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp new file mode 100644 index 000000000..4da206159 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp @@ -0,0 +1,26 @@ +#include + +extern "C" { +#include +} + +// TODO: Port the rest of the behavior for this enhancement here. + +void BuildQuitFishingMessage(uint16_t* textId, bool* loadFromMessageTable) { + // TODO: See about loading the vanilla message and manipulating that instead of + // a brand new one. Might not be worth it. + CustomMessage msg = CustomMessage( + "Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", + "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", + "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w" + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void QuitFishingAtDoor_Register() { + COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0), BuildQuitFishingMessage); +} + +RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 07017529c..0e2d38572 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2076,20 +2076,6 @@ extern "C" void Randomizer_ShowRandomizerMenu() { SohGui::ShowRandomizerSettingsMenu(); } -extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { - MessageContext* msgCtx = &play->msgCtx; - uint16_t textId = msgCtx->textId; - Font* font = &msgCtx->font; - char* buffer = font->msgBuf; - const int maxBufferSize = sizeof(font->msgBuf); - CustomMessage messageEntry; - s16 actorParams = 0; - if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE, MF_FORMATTED); - } - return false; -} - extern "C" void Overlay_DisplayText(float duration, const char* text) { Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(duration, true, text); } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 1bb982913..5a59f0e29 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -30,7 +30,6 @@ struct ExtensionEntry { extern std::unordered_map ExtensionCache; #include "Enhancements/randomizer/settings.h" -const std::string customMessageTableID = "BaseGameOverrides"; const std::string appShortName = "soh"; #ifdef __WIIU__ @@ -148,7 +147,6 @@ uint8_t Randomizer_IsSpoilerLoaded(); void Randomizer_SetSpoilerLoaded(bool spoilerLoaded); uint8_t Randomizer_GenerateRandomizer(); void Randomizer_ShowRandomizerMenu(); -int CustomMessage_RetrieveIfExists(PlayState* play); void Overlay_DisplayText(float duration, const char* text); void Overlay_DisplayText_Seconds(int seconds, const char* text); GetItemEntry ItemTable_Retrieve(int16_t getItemID); diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 398451614..079537408 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -133,11 +133,4 @@ extern "C" void OTRMessage_Init() // Assert staff credits start at the first credits ID assert(sStaffMessageEntryTablePtr[0].textId == 0x0500); } - - CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_FISHERMAN_LEAVE, - CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", - "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", - "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w")); //TODO Used AI translation as placeholder } From 434db89760b9ab9b8f6d0b1d906b92b21037f8ee Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 18:26:39 -0500 Subject: [PATCH 042/103] Fix an overlap on Greg with Potion shop guy --- soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index a12bda6e2..b0a47f0ea 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -138,9 +138,11 @@ void BuildDampesDiaryMessage(uint16_t* textId, bool* loadFromMessageTable) { } void BuildGregHintMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = RAND_GET_HINT(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); - msg.LoadIntoFont(); - *loadFromMessageTable = false; + if (gPlayState->sceneNum == SCENE_TREASURE_BOX_SHOP) { + CustomMessage msg = RAND_GET_HINT(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; + } } void BuildMinuetWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { From b0bd040a90f6d1e7c44a16d7b56f742335f59915 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 18:29:25 -0500 Subject: [PATCH 043/103] Fixes an incorrect color for the Scrub text --- soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 2c281d55b..016b9060c 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -128,7 +128,7 @@ void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w geben!\x07\x10\xA3", "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3"); } else { - msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %g[[2]] Rupees%w it is!\x07\x10\xA3", + msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %y[[2]] Rupees%w it is!\x07\x10\xA3", "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); } From 965f87b6eb707fb3f37539d70591e35f7c96fe67 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 18:44:41 -0500 Subject: [PATCH 044/103] Reintroduce missing Mysterious warp song hint --- .../custom-message/CustomMessageManager.cpp | 4 ++ .../custom-message/CustomMessageManager.h | 1 + .../randomizer/Messages/StaticHints.cpp | 39 +++++++++++++++++++ 3 files changed, 44 insertions(+) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index b5e4163cd..be152cf4b 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -744,6 +744,10 @@ std::string CustomMessage::PLAYER_NAME() { return "\x0F"s; } +std::string CustomMessage::TWO_WAY_CHOICE() { + return "\x1B"s; +} + bool CustomMessageManager::InsertCustomMessage(std::string tableID, uint16_t textID, CustomMessage messages) { auto foundMessageTable = messageTables.find(tableID); if (foundMessageTable == messageTables.end()) { diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 943b18970..d9b3ed29b 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -56,6 +56,7 @@ class CustomMessage { static std::string POINTS(std::string x) ;//HIGH_SCORE is also a macro static std::string WAIT_FOR_INPUT() ; static std::string PLAYER_NAME() ; + static std::string TWO_WAY_CHOICE(); const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const; const std::string GetFrench(MessageFormat format = MF_FORMATTED) const; diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index b0a47f0ea..6aa9dbb08 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -145,37 +145,76 @@ void BuildGregHintMessage(uint16_t* textId, bool* loadFromMessageTable) { } } +void BuildMysteriousWarpMessage() { + CustomMessage msg = CustomMessage( + "Warp to&%ra mysterious place?%w&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w", + "Zu&%reinem mysteriösen Ort%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w", + "Se téléporter vers&%run endroit mystérieux%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%rOK!&Non%w" + ); + msg.LoadIntoFont(); +} + void BuildMinuetWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_MINUET_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildBoleroWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_BOLERO_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildSerenadeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_SERENADE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildRequiemWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_REQUIEM_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildNocturneWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_NOCTURNE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildPreludeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_PRELUDE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; From 80dc3afcca1857dc8a59ee684cb8e0aeb961d77a Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 22:17:15 -0500 Subject: [PATCH 045/103] Make the the ShipInitFuncs static --- soh/soh/Enhancements/Items/BetterBombchuShopping.cpp | 2 +- soh/soh/Enhancements/TimeSavers/MarketSneak.cpp | 2 +- soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp | 2 +- soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp | 2 +- soh/soh/Enhancements/randomizer/Messages/Navi.cpp | 2 +- soh/soh/Enhancements/randomizer/Messages/Rupees.cpp | 2 +- soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp index 918b5bba2..67445741e 100644 --- a/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp +++ b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp @@ -36,4 +36,4 @@ void BetterBombchuShopping_Register() { COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_PROMPT, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopPromptMessage); } -RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp index c22d7b9b5..16a0099a8 100644 --- a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp +++ b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp @@ -21,4 +21,4 @@ void MarketSneak_Register() { COND_ID_HOOK(OnOpenText, TEXT_MARKET_GUARD_NIGHT, CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0), BuildNightGuardMessage); } -RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp index 4da206159..ab0ffd807 100644 --- a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp +++ b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp @@ -23,4 +23,4 @@ void QuitFishingAtDoor_Register() { COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0), BuildQuitFishingMessage); } -RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp index f9264db1f..7c512af63 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp @@ -48,4 +48,4 @@ void RegisterMiscellaneousMessages() { COND_ID_HOOK(OnOpenText, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, IS_RANDO, BuildShootingGalleryNoBowMessage); } -RegisterShipInitFunc initFunc(RegisterMiscellaneousMessages, { "IS_RANDO" }); \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterMiscellaneousMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/Navi.cpp b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp index 0daf51f94..1863a64dd 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Navi.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp @@ -150,4 +150,4 @@ void RegisterNaviMessages() { COND_ID_HOOK(OnOpenText, TEXT_NAVI_TRY_TO_KEEP_MOVING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); } -RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp index e8b02a57b..3cb3d9e98 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp @@ -121,4 +121,4 @@ void RegisterRandomRupeeNames() { COND_ID_HOOK(OnOpenText, TEXT_HUGE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); } -RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 6aa9dbb08..fdedbac47 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -414,4 +414,4 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_MASK_SHOP_SIGN, RAND_GET_OPTION(RSK_MASK_SHOP_HINT), BuildMaskShopSignMessage); } -RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file From a0cd565b4025142c579bc1ce8fa1f7d9be5d1887 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 22:30:39 -0500 Subject: [PATCH 046/103] One more missed static initFunc --- soh/soh/Enhancements/InjectItemCounts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index 0b6670668..8be115362 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -70,7 +70,7 @@ void InjectItemCounts_Register() { COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 3, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); } -RegisterShipInitFunc initFunc(InjectItemCounts_Register, { +static RegisterShipInitFunc initFunc(InjectItemCounts_Register, { CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece") From cb20098b029297c8f2d8301850df28c47b5512ed Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 11 Mar 2025 22:33:07 -0400 Subject: [PATCH 047/103] Adds and uses per-item articles for get item messages --- .../randomizer/Messages/ItemMessages.cpp | 4 +- soh/soh/Enhancements/randomizer/item.cpp | 15 +- soh/soh/Enhancements/randomizer/item.h | 7 +- soh/soh/Enhancements/randomizer/item_list.cpp | 456 +++++++++--------- 4 files changed, 247 insertions(+), 235 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp index 1ce898437..fd2acbcdd 100644 --- a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp @@ -360,13 +360,15 @@ void BuildTriforcePieceMessage(CustomMessage& msg) { void BuildCustomItemMessage(Player* player, CustomMessage& msg) { int16_t rgid; - msg = CustomMessage("You found the %g[[name]]%w!", "Du erhältst das %g[[name]]%w!", "Vous ebtenez %g[[name]]%w!", TEXTBOX_TYPE_BLUE); + msg = CustomMessage("You found [[article]] %g[[name]]%w!", "Du erhältst [[article]] %g[[name]]%w gefunden!", "Vous avez trouvé [[article]] %g[[name]]%w!", TEXTBOX_TYPE_BLUE); if (player->getItemEntry.objectId != OBJECT_INVALID) { rgid = player->getItemEntry.getItemId; } else { rgid = player->getItemId; } CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); + CustomMessage article = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetArticle(), TEXTBOX_TYPE_BLUE); + msg.Replace("[[article]]", article); msg.Replace("[[name]]", name); msg.AutoFormat(); } diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 1c315b47f..5faf94c34 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -17,9 +17,10 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const uint16_t itemId_, const uint16_t objectId_, const uint16_t gid_, const uint16_t textId_, const uint16_t field_, const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_, - const bool progressive_, const uint16_t price_) + Text article_, const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), article(std::move(article_)), + progressive(progressive_), price(price_) { if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) { giEntry = std::make_shared(GetItemEntry{ itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_RANDOMIZER, static_cast(randomizerGet_), gid_, true, ITEM_FROM_NPC, category_, static_cast(randomizerGet_), MOD_RANDOMIZER, NULL }); } @@ -29,10 +30,12 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, } Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const bool progressive_, + const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, Text article_, + const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), article(std::move(article_)), + progressive(progressive_), price(price_) { } Item::~Item() = default; @@ -53,6 +56,10 @@ const Text& Item::GetName() const { return name; } +const Text& Item::GetArticle() const { + return article; +} + bool Item::IsAdvancement() const { return advancement; } diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index f0df0f1bf..db60e7846 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -33,9 +33,10 @@ class Item { Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, LogicVal logicVal_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_, uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, - bool progressive_ = false, uint16_t price_ = 0); + Text article_ = {}, bool progressive_ = false, uint16_t price_ = 0); Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - LogicVal logicVal_, RandomizerHintTextKey hintKey_, bool progressive_ = false, uint16_t price_ = 0); + LogicVal logicVal_, RandomizerHintTextKey hintKey_, Text article_ = {}, bool progressive_ = false, + uint16_t price_ = 0); ~Item(); void ApplyEffect() const; @@ -43,6 +44,7 @@ class Item { const Text& GetName() const; + const Text& GetArticle() const; bool IsAdvancement() const; int GetItemID() const; ItemType GetItemType() const; @@ -70,6 +72,7 @@ class Item { bool advancement; LogicVal logicVal; RandomizerHintTextKey hintKey; + Text article; bool progressive; uint16_t price; bool playthrough = false; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 45516ef18..026a18f05 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -14,253 +14,253 @@ void Rando::StaticData::InitItemTable() { auto logic = Context::GetInstance()->GetLogic(); itemTable[RG_NONE] = Item(RG_NONE, Text{ "No Item", "Rien", "Kein Artikel" }, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_NONE, 0, 0, 0, 0, 0, ITEM_CATEGORY_JUNK, MOD_NONE); // Randomizer Get Randomizer Get Name Text Type Get Item ID Adv. Logic Value Hint Text Key Item ID Object ID Draw ID Text ID field Chest Animation Item Category Mod Index - itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_KOKIRI, true, LOGIC_KOKIRI_SWORD, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MASTER_SWORD] = Item(RG_MASTER_SWORD, Text{ "Master Sword", "Épée de Legende", "Master-Schwert"}, ITEMTYPE_EQUIP, 0xE0, true, LOGIC_MASTER_SWORD, RHT_MASTER_SWORD, ITEM_SWORD_MASTER, OBJECT_TOKI_OBJECTS, GID_SWORD_BGS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_KOKIRI, true, LOGIC_KOKIRI_SWORD, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_MASTER_SWORD] = Item(RG_MASTER_SWORD, Text{ "Master Sword", "Épée de Legende", "Master-Schwert"}, ITEMTYPE_EQUIP, 0xE0, true, LOGIC_MASTER_SWORD, RHT_MASTER_SWORD, ITEM_SWORD_MASTER, OBJECT_TOKI_OBJECTS, GID_SWORD_BGS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "das", "le"}); itemTable[RG_MASTER_SWORD].SetCustomDrawFunc(Randomizer_DrawMasterSword); - itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Langschwert" }, ITEMTYPE_EQUIP, GI_SWORD_KNIFE, true, LOGIC_NONE, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_BGS, true, LOGIC_BIGGORON_SWORD, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegelschild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein des Wissens" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Langschwert" }, ITEMTYPE_EQUIP, GI_SWORD_KNIFE, true, LOGIC_NONE, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_BGS, true, LOGIC_BIGGORON_SWORD, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "einen", "un"}); + itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "einen", "un"}); + itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegelschild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); + itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); + itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); + itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein des Wissens" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "la"}); itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrow", "Flèche de Feu", "Feuerpfeil" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrow", "Flèche de Glace", "Eispfeil" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrow", "Flèche de Lumière", "Lichtpfeil" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Pass" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrows", "Flèches de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrows", "Flèches de Glace", "Eispfeile" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrows", "Flèches de Lumière", "Lichtpfeile" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Pass" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); + itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a", "eine", "un"}); + itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "das", "le"}); itemTable[RG_DOUBLE_DEFENSE] = Item(RG_DOUBLE_DEFENSE, Text{ "Double Defense", "Double Défence", "Doppelte Verteidigung" }, ITEMTYPE_ITEM, RG_DOUBLE_DEFENSE, true, LOGIC_DOUBLE_DEFENSE, RHT_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xE9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DOUBLE_DEFENSE].SetCustomDrawFunc(Randomizer_DrawDoubleDefense); // Trade Quest Items - itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, LOGIC_WEIRD_EGG, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, LOGIC_WEIRD_EGG, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); itemTable[RG_ZELDAS_LETTER] = Item(RG_ZELDAS_LETTER, Text{ "Zelda's Letter", "Lettre de Zelda", "Zeldas Brief" }, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, LOGIC_ZELDAS_LETTER, RHT_ZELDAS_LETTER, ITEM_LETTER_ZELDA, OBJECT_GI_LETTER, GID_LETTER_ZELDA, 0x69, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Ei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, LOGIC_POCKET_EGG, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Ei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, LOGIC_POCKET_EGG, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); itemTable[RG_COJIRO] = Item(RG_COJIRO, Text{ "Cojiro", "P'tit Poulet", "Henni" }, ITEMTYPE_ITEM, GI_COJIRO, true, LOGIC_COJIRO, RHT_COJIRO, ITEM_COJIRO, OBJECT_GI_NIWATORI, GID_COJIRO, 0x02, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Schimmelpilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Modertrank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, LOGIC_ODD_POULTICE, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Säge" }, ITEMTYPE_ITEM, GI_SAW, true, LOGIC_POACHERS_SAW, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Zerbrochenes Goronen-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Rezept" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, LOGIC_PRESCRIPTION, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Glotzfrosch" }, ITEMTYPE_ITEM, GI_FROG, true, LOGIC_EYEBALL_FROG, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Augentropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, LOGIC_EYEDROPS, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Zertifikat" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, LOGIC_CLAIM_CHECK, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Schimmelpilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Modertrank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, LOGIC_ODD_POULTICE, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "la"}); + itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Säge" }, ITEMTYPE_ITEM, GI_SAW, true, LOGIC_POACHERS_SAW, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); + itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Zerbrochenes Goronen-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Rezept" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, LOGIC_PRESCRIPTION, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "la"}); + itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Glotzfrosch" }, ITEMTYPE_ITEM, GI_FROG, true, LOGIC_EYEBALL_FROG, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "la"}); + itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Augentropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, LOGIC_EYEDROPS, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); + itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Zertifikat" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, LOGIC_CLAIM_CHECK, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); // Skulltula Token - itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE); + itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE, {"a", "ein", "un"}); // Progressive Items - itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, true); - itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, true); - itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, true); - itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, true); - itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, true); - itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, true); - itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, true); - itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, true); - itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, true); - itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, true); - itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, true); - itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, true); - itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, true); + itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, {"a", "einen", "un"}, true); + itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, {"a", "ein", "une"}, true); + itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, {"a", "eine", "un"}, true); + itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, {"a", "einen", "un"}, true); + itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, {"a", "eine", "un"}, true); + itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, {"a", "ein", "un"}, true); + itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, {"a", "eine", "une"}, true); + itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, {"a", "eine", "une"}, true); + itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, {"a", "eine", "un"}, true); + itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, {"a", "einen", "un"}, true); + itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, {"a", "ein", "un"}, true); + itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, {"a", "eine", "un"}, true); + itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, {"a", "ein", "une"}, true); // Bottles - itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER, GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"an", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); + itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); + itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER, GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a", "einen", "un"}); + itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "einen", "un"}); // Songs itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Salias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Hymne der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "la"}); + itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); + itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); // Maps and Compasses - itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_DEKU_TREE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_DODONGOS_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_JABU_JABUS_BELLY_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_FOREST_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_FIRE_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_WATER_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_SPIRIT_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_SHADOW_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_BOTTOM_OF_THE_WELL_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); itemTable[RG_ICE_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys - itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_FIRE_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_WATER_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_SHADOW_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_GANONS_CASTLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_FOREST_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_FIRE_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_WATER_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE); - itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE, {"a", "einen", "une"}); + itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_GUARD_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_MARKET_BAZAAR_KEY] = Item(RG_MARKET_BAZAAR_KEY, Text{ "Market Bazaar Key", "", "Schlüssel für den Basar des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_MARKET_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_MARKET_BAZAAR_KEY] = Item(RG_MARKET_BAZAAR_KEY, Text{ "Market Bazaar Key", "", "Schlüssel für den Basar des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_MARKET_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_MARKET_BAZAAR_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_MARKET_POTION_SHOP_KEY] = Item(RG_MARKET_POTION_SHOP_KEY, Text{ "Market Potion Shop Key", "", "Schlüssel für den Magie-Laden des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MARKET_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_MARKET_POTION_SHOP_KEY] = Item(RG_MARKET_POTION_SHOP_KEY, Text{ "Market Potion Shop Key", "", "Schlüssel für den Magie-Laden des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MARKET_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_MARKET_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_MASK_SHOP_KEY] = Item(RG_MASK_SHOP_KEY, Text{ "Mask Shop Key", "", "Schlüssel für den Maskenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MASK_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MASK_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_MASK_SHOP_KEY] = Item(RG_MASK_SHOP_KEY, Text{ "Mask Shop Key", "", "Schlüssel für den Maskenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MASK_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MASK_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_MASK_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_MARKET_SHOOTING_GALLERY_KEY] = Item(RG_MARKET_SHOOTING_GALLERY_KEY, Text{ "Market Shooting Gallery Key", "", "Schlüssel für die Schießbude des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_MARKET_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_MARKET_SHOOTING_GALLERY_KEY] = Item(RG_MARKET_SHOOTING_GALLERY_KEY, Text{ "Market Shooting Gallery Key", "", "Schlüssel für die Schießbude des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_MARKET_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_MARKET_SHOOTING_GALLERY_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_BOMBCHU_BOWLING_KEY] = Item(RG_BOMBCHU_BOWLING_KEY, Text{ "Bombchu Bowling Alley Key", "", "Schlüssel für die Minenbowlingbahn" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_BOWLING_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_BOWLING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOMBCHU_BOWLING_KEY] = Item(RG_BOMBCHU_BOWLING_KEY, Text{ "Bombchu Bowling Alley Key", "", "Schlüssel für die Minenbowlingbahn" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_BOWLING_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_BOWLING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_BOMBCHU_BOWLING_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY] = Item(RG_TREASURE_CHEST_GAME_BUILDING_KEY, Text{ "Treasure Chest Game Building Key", "", "Schlüssel für das Haus des Schatzkisten-Pokers" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TREASURE_CHEST_GAME_BUILDING_KEY,RHT_OVERWORLD_KEY, RG_TREASURE_CHEST_GAME_BUILDING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY] = Item(RG_TREASURE_CHEST_GAME_BUILDING_KEY, Text{ "Treasure Chest Game Building Key", "", "Schlüssel für das Haus des Schatzkisten-Pokers" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TREASURE_CHEST_GAME_BUILDING_KEY,RHT_OVERWORLD_KEY, RG_TREASURE_CHEST_GAME_BUILDING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_BOMBCHU_SHOP_KEY] = Item(RG_BOMBCHU_SHOP_KEY, Text{ "Bombchu Shop Key", "", "Schlüssel für den Krabbelminenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_SHOP_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOMBCHU_SHOP_KEY] = Item(RG_BOMBCHU_SHOP_KEY, Text{ "Bombchu Shop Key", "", "Schlüssel für den Krabbelminenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_SHOP_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_BOMBCHU_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_RICHARDS_HOUSE_KEY] = Item(RG_RICHARDS_HOUSE_KEY, Text{ "Richard's House Key", "", "Schlüssel für das Haus von Richard" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_RICHARDS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_RICHARDS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_RICHARDS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_ALLEY_HOUSE_KEY] = Item(RG_ALLEY_HOUSE_KEY, Text{ "Alley House Key", "", "Schlüssel für das Gäßchenhaus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_ALLEY_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_ALLEY_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_ALLEY_HOUSE_KEY] = Item(RG_ALLEY_HOUSE_KEY, Text{ "Alley House Key", "", "Schlüssel für das Gäßchenhaus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_ALLEY_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_ALLEY_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_ALLEY_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_KAK_BAZAAR_KEY] = Item(RG_KAK_BAZAAR_KEY, Text{ "Kakariko Bazaar Key", "", "Schlüssel für den Basar von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_KAK_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_KAK_BAZAAR_KEY] = Item(RG_KAK_BAZAAR_KEY, Text{ "Kakariko Bazaar Key", "", "Schlüssel für den Basar von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_KAK_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_KAK_BAZAAR_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_KAK_POTION_SHOP_KEY] = Item(RG_KAK_POTION_SHOP_KEY, Text{ "Kakariko Potion Shop Key", "", "Schlüssel für den Magie-Laden von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_KAK_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_KAK_POTION_SHOP_KEY] = Item(RG_KAK_POTION_SHOP_KEY, Text{ "Kakariko Potion Shop Key", "", "Schlüssel für den Magie-Laden von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_KAK_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_KAK_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_BOSS_HOUSE_KEY] = Item(RG_BOSS_HOUSE_KEY, Text{ "Boss's House Key", "", "Schlüssel für das Haus des Chefs" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOSS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_BOSS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOSS_HOUSE_KEY] = Item(RG_BOSS_HOUSE_KEY, Text{ "Boss's House Key", "", "Schlüssel für das Haus des Chefs" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOSS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_BOSS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_BOSS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_GRANNYS_POTION_SHOP_KEY] = Item(RG_GRANNYS_POTION_SHOP_KEY, Text{ "Granny's Potion Shop Key", "", "Schlüssel für Asas Hexenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GRANNYS_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_GRANNYS_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GRANNYS_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_SKULLTULA_HOUSE_KEY] = Item(RG_SKULLTULA_HOUSE_KEY, Text{ "Skulltula House Key", "", "Schlüssel für das Skulltula-Haus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_SKULLTULA_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_SKULLTULA_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SKULLTULA_HOUSE_KEY] = Item(RG_SKULLTULA_HOUSE_KEY, Text{ "Skulltula House Key", "", "Schlüssel für das Skulltula-Haus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_SKULLTULA_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_SKULLTULA_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_SKULLTULA_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_IMPAS_HOUSE_KEY] = Item(RG_IMPAS_HOUSE_KEY, Text{ "Impa's House Key", "", "Schlüssel für das Haus von Impa" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_IMPAS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_IMPAS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_IMPAS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_WINDMILL_KEY] = Item(RG_WINDMILL_KEY, Text{ "Windmill Key", "", "Schlüssel für die Windmühle" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_WINDMILL_KEY, RHT_OVERWORLD_KEY, RG_WINDMILL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_WINDMILL_KEY] = Item(RG_WINDMILL_KEY, Text{ "Windmill Key", "", "Schlüssel für die Windmühle" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_WINDMILL_KEY, RHT_OVERWORLD_KEY, RG_WINDMILL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_WINDMILL_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_KAK_SHOOTING_GALLERY_KEY] = Item(RG_KAK_SHOOTING_GALLERY_KEY, Text{ "Kakariko Shooting Gallery Key", "", "Schlüssel für die Schießbude von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_KAK_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_KAK_SHOOTING_GALLERY_KEY] = Item(RG_KAK_SHOOTING_GALLERY_KEY, Text{ "Kakariko Shooting Gallery Key", "", "Schlüssel für die Schießbude von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_KAK_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_KAK_SHOOTING_GALLERY_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_DAMPES_HUT_KEY] = Item(RG_DAMPES_HUT_KEY, Text{ "Dampe's Hut Key", "", "Schlüssel für die Hütte von Boris" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_DAMPES_HUT_KEY, RHT_OVERWORLD_KEY, RG_DAMPES_HUT_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_DAMPES_HUT_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_TALONS_HOUSE_KEY] = Item(RG_TALONS_HOUSE_KEY, Text{ "Talon's House Key", "", "Schlüssel für das Haus von Talon" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TALONS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_TALONS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_TALONS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_STABLES_KEY] = Item(RG_STABLES_KEY, Text{ "Stables Key", "", "Schlüssel für die Ställe" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_STABLES_KEY, RHT_OVERWORLD_KEY, RG_STABLES_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_STABLES_KEY] = Item(RG_STABLES_KEY, Text{ "Stables Key", "", "Schlüssel für die Ställe" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_STABLES_KEY, RHT_OVERWORLD_KEY, RG_STABLES_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_STABLES_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_BACK_TOWER_KEY] = Item(RG_BACK_TOWER_KEY, Text{ "Back Tower Key", "", "Schlüssel für den hinteren Turm" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BACK_TOWER_KEY, RHT_OVERWORLD_KEY, RG_BACK_TOWER_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BACK_TOWER_KEY] = Item(RG_BACK_TOWER_KEY, Text{ "Back Tower Key", "", "Schlüssel für den hinteren Turm" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BACK_TOWER_KEY, RHT_OVERWORLD_KEY, RG_BACK_TOWER_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_BACK_TOWER_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_HYLIA_LAB_KEY] = Item(RG_HYLIA_LAB_KEY, Text{ "Hylia Laboratory Key", "", "Schlüssel für das Hylia-Labor" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_HYLIA_LAB_KEY, RHT_OVERWORLD_KEY, RG_HYLIA_LAB_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_HYLIA_LAB_KEY] = Item(RG_HYLIA_LAB_KEY, Text{ "Hylia Laboratory Key", "", "Schlüssel für das Hylia-Labor" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_HYLIA_LAB_KEY, RHT_OVERWORLD_KEY, RG_HYLIA_LAB_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_HYLIA_LAB_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_FISHING_HOLE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); // Key Rings - itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_FIRE_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_WATER_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_SHADOW_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); + itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_TREASURE_GAME_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); // Dungeon Rewards - itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); // Generic Items - itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüner Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "ein", "un"}); + itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüner Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, LOGIC_GREG, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herzcontainer" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "ein", "un"}); + itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herzcontainer" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "einen", "un"}); itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, LOGIC_NONE, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MILK] = Item(RG_MILK, Text{ "Milk", "Lait", "Milch" }, ITEMTYPE_ITEM, GI_MILK, false, LOGIC_NONE, RHT_NONE, ITEM_MILK, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Fisch" }, ITEMTYPE_ITEM, GI_FISH, false, LOGIC_NONE, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Fisch" }, ITEMTYPE_ITEM, GI_FISH, false, LOGIC_NONE, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "einen", "un"}); // Refills itemTable[RG_BOMBS_5] = Item(RG_BOMBS_5, Text{ "Bombs (5)", "Bombes (5)", "Bomben (5)" }, ITEMTYPE_REFILL, GI_BOMBS_5, false, LOGIC_NONE, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_BOMBS_10] = Item(RG_BOMBS_10, Text{ "Bombs (10)", "Bombes (10)", "Bomben (10)" }, ITEMTYPE_REFILL, GI_BOMBS_10, false, LOGIC_NONE, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); @@ -275,44 +275,44 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_NUTS_5] = Item(RG_DEKU_NUTS_5, Text{ "Deku Nuts (5)", "Noix Mojo (5)", "Deku-Nüsse (5)" }, ITEMTYPE_REFILL, GI_NUTS_5, false, LOGIC_NONE, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, LOGIC_NONE, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, LOGIC_NONE, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stab (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); + itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stab (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "einen", "un"}); + itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); // Treasure Game - itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); + itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "das", "le"}); itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüner Rubin (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); // Shop - itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuß kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 15); - itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 60); - itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 90); - itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 25); - itemTable[RG_BUY_DEKU_NUTS_10] = Item(RG_BUY_DEKU_NUTS_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuß kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, LOGIC_NUTS, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stab kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, LOGIC_STICKS, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); - itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, LOGIC_BUY_BOMB, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, LOGIC_FISH_ACCESS, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 200); - itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 100); - itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylia-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 80); - itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, false, 40); - itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 200); - itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, false, 300); - itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 10); - itemTable[RG_BUY_BOMBCHUS_10] = Item(RG_BUY_BOMBCHUS_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Krabbelminen kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 99); - itemTable[RG_BUY_BOMBCHUS_20] = Item(RG_BUY_BOMBCHUS_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Krabbelminen kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 180); - itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, LOGIC_BUY_SEED, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, false, 0); - itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, LOGIC_BLUE_FIRE_ACCESS, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 300); - itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, LOGIC_BUGS_ACCESS, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, LOGIC_NONE, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 30); - itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, LOGIC_FAIRY_ACCESS, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); - itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, LOGIC_BUY_ARROW, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 20); - itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 80); - itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 120); - itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, false, 35); - itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 40); - itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, false, 50); + itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuß kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 15); + itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 60); + itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 90); + itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 25); + itemTable[RG_BUY_DEKU_NUTS_10] = Item(RG_BUY_DEKU_NUTS_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuß kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, LOGIC_NUTS, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); + itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stab kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, LOGIC_STICKS, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 10); + itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, LOGIC_BUY_BOMB, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 50); + itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, LOGIC_FISH_ACCESS, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 200); + itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); + itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); + itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 100); + itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylia-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {}, false, 80); + itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {}, false, 40); + itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {}, false, 200); + itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {}, false, 300); + itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 10); + itemTable[RG_BUY_BOMBCHUS_10] = Item(RG_BUY_BOMBCHUS_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Krabbelminen kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 99); + itemTable[RG_BUY_BOMBCHUS_20] = Item(RG_BUY_BOMBCHUS_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Krabbelminen kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 180); + itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, LOGIC_BUY_SEED, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); + itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, {}, false, 0); + itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, LOGIC_BLUE_FIRE_ACCESS, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 300); + itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, LOGIC_BUGS_ACCESS, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 50); + itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, LOGIC_NONE, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); + itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, LOGIC_FAIRY_ACCESS, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 50); + itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, LOGIC_BUY_ARROW, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 20); + itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 80); + itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 120); + itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 35); + itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 40); + itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 50); // Misc. itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "Âme de Gohma", "Gohmas Seele" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_CAN_SUMMON_GOHMA, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_GOHMA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); @@ -332,75 +332,75 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_TWINROVA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "Âme de Ganon", "Ganons Seele" }, ITEMTYPE_ITEM, 0xE8, true, LOGIC_CAN_SUMMON_GANON, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Angelrute" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Angelrute" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "das", "le"}); itemTable[RG_FISHING_POLE].SetCustomDrawFunc(Randomizer_DrawFishingPoleGI); - itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Taste A der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_A_BUTTON, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Taste A der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_A_BUTTON, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_OCARINA_A_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Taste C-Oben der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_UP_BUTTON, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Taste C-Oben der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_UP_BUTTON, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_OCARINA_C_UP_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Taste C-Unten der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Taste C-Unten der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_OCARINA_C_DOWN_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Taste C-Links der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Taste C-Links der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_OCARINA_C_LEFT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Taste C-Rechts der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Taste C-Rechts der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "die", "le"}); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "Sac de Missiles Teigneux" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "Sac de Missiles Teigneux" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "un"}); itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); - itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "Sac de Bombes Infini", "Unendliche Bombentasche" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "Sac de Graines Infinis", "Unendliche Samentasche" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "Bâtons Mojo Infinis", "Unendliche Stab-Kapazität" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_NUT_UPGRADE_INF] = Item(RG_NUT_UPGRADE_INF, Text{ "Infinite Nut Capacity", "Noix Mojo Infinies", "Unendliche Nuß-Kapazität" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "Magie Infinie", "Unendliches Magisches Maß" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "Missiles Teigneux Infinis", "Unendliche Krabbelminen" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "Sac de Bombes Infini", "Unendliche Bombentasche" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); + itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "Sac de Graines Infinis", "Unendliche Samentasche" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); + itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "Bâtons Mojo Infinis", "Unendliche Stab-Kapazität" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_NUT_UPGRADE_INF] = Item(RG_NUT_UPGRADE_INF, Text{ "Infinite Nut Capacity", "Noix Mojo Infinies", "Unendliche Nuß-Kapazität" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "Magie Infinie", "Unendliches Magisches Maß" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); + itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "Missiles Teigneux Infinis", "Unendliche Krabbelminen" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "les"}); itemTable[RG_BOMBCHU_INF].SetCustomDrawFunc(Randomizer_DrawBombchuBag); - itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "Bourse Infinie", "Unendliche Geldbörse" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); + itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "Bourse Infinie", "Unendliche Geldbörse" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); - itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "Clé Squelette", "Skelettschlüssel" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "Clé Squelette", "Skelettschlüssel" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "la"}); itemTable[RG_SKELETON_KEY].SetCustomDrawFunc(Randomizer_DrawSkeletonKey); - itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "Sac de Bâton Mojo", "Deku-Stab-Tasche" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "Sac de Bâton Mojo", "Deku-Stab-Tasche" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "un"}); - itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "Sac de Noix Mojo", "Deku-Nuß-Tasche" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "Sac de Noix Mojo", "Deku-Nuß-Tasche" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "un"}); - itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE); + itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE, {"the", "die", "la"}); itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE); // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) - itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, LOGIC_PROGRESSIVE_OCARINA, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, LOGIC_PROGRESSIVE_OCARINA, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, LOGIC_PROGRESSIVE_BOW, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, LOGIC_PROGRESSIVE_BOW, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, LOGIC_PROGRESSIVE_BOW, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Große Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER, 0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_GOLDEN, true, LOGIC_PROGRESSIVE_SCALE, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsenengeldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Goldene Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Petite Bourse", "Kindergeldbörse" }, ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, LOGIC_PROGRESSIVE_OCARINA, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); + itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, LOGIC_PROGRESSIVE_OCARINA, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "ddie", "le"}); + itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, LOGIC_PROGRESSIVE_BOW, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, LOGIC_PROGRESSIVE_BOW, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, LOGIC_PROGRESSIVE_BOW, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Große Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER, 0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); + itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); + itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_GOLDEN, true, LOGIC_PROGRESSIVE_SCALE, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsenengeldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); + itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Goldene Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); + itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Petite Bourse", "Kindergeldbörse" }, ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "die", "le"}); itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku-Nuß-Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku-Nuß-Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku-Stab-Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku-Stab-Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbessertes Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); - itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Fragment" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "das", "le"}); + itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbessertes Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "das", "le"}); + itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Fragment" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "ein", "un"}); // Init itemNameToEnum for (auto& item : itemTable) { From f657741336491670df079e08b9e67052ef1b65ee Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 11 Mar 2025 23:18:49 -0400 Subject: [PATCH 048/103] Add spaces to articles --- .../randomizer/Messages/ItemMessages.cpp | 2 +- soh/soh/Enhancements/randomizer/item_list.cpp | 390 +++++++++--------- 2 files changed, 196 insertions(+), 196 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp index fd2acbcdd..222ccea75 100644 --- a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp @@ -360,7 +360,7 @@ void BuildTriforcePieceMessage(CustomMessage& msg) { void BuildCustomItemMessage(Player* player, CustomMessage& msg) { int16_t rgid; - msg = CustomMessage("You found [[article]] %g[[name]]%w!", "Du erhältst [[article]] %g[[name]]%w gefunden!", "Vous avez trouvé [[article]] %g[[name]]%w!", TEXTBOX_TYPE_BLUE); + msg = CustomMessage("You found [[article]]%g[[name]]%w!", "Du erhältst [[article]]%g[[name]]%w gefunden!", "Vous avez trouvé [[article]]%g[[name]]%w!", TEXTBOX_TYPE_BLUE); if (player->getItemEntry.objectId != OBJECT_INVALID) { rgid = player->getItemEntry.getItemId; } else { diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 026a18f05..0e3d132c7 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -14,253 +14,253 @@ void Rando::StaticData::InitItemTable() { auto logic = Context::GetInstance()->GetLogic(); itemTable[RG_NONE] = Item(RG_NONE, Text{ "No Item", "Rien", "Kein Artikel" }, ITEMTYPE_EVENT, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_NONE, 0, 0, 0, 0, 0, ITEM_CATEGORY_JUNK, MOD_NONE); // Randomizer Get Randomizer Get Name Text Type Get Item ID Adv. Logic Value Hint Text Key Item ID Object ID Draw ID Text ID field Chest Animation Item Category Mod Index - itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_KOKIRI, true, LOGIC_KOKIRI_SWORD, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_MASTER_SWORD] = Item(RG_MASTER_SWORD, Text{ "Master Sword", "Épée de Legende", "Master-Schwert"}, ITEMTYPE_EQUIP, 0xE0, true, LOGIC_MASTER_SWORD, RHT_MASTER_SWORD, ITEM_SWORD_MASTER, OBJECT_TOKI_OBJECTS, GID_SWORD_BGS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "das", "le"}); + itemTable[RG_KOKIRI_SWORD] = Item(RG_KOKIRI_SWORD, Text{ "Kokiri Sword", "Épée Kokiri", "Kokiri-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_KOKIRI, true, LOGIC_KOKIRI_SWORD, RHT_KOKIRI_SWORD, ITEM_SWORD_KOKIRI, OBJECT_GI_SWORD_1, GID_SWORD_KOKIRI, 0xA4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_MASTER_SWORD] = Item(RG_MASTER_SWORD, Text{ "Master Sword", "Épée de Legende", "Master-Schwert"}, ITEMTYPE_EQUIP, 0xE0, true, LOGIC_MASTER_SWORD, RHT_MASTER_SWORD, ITEM_SWORD_MASTER, OBJECT_TOKI_OBJECTS, GID_SWORD_BGS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "das ", "le "}); itemTable[RG_MASTER_SWORD].SetCustomDrawFunc(Randomizer_DrawMasterSword); - itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Langschwert" }, ITEMTYPE_EQUIP, GI_SWORD_KNIFE, true, LOGIC_NONE, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_BGS, true, LOGIC_BIGGORON_SWORD, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "einen", "un"}); - itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "einen", "un"}); - itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegelschild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); - itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); - itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); - itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein des Wissens" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "la"}); + itemTable[RG_GIANTS_KNIFE] = Item(RG_GIANTS_KNIFE, Text{ "Giant's Knife", "Lame des Géants", "Langschwert" }, ITEMTYPE_EQUIP, GI_SWORD_KNIFE, true, LOGIC_NONE, RHT_GIANTS_KNIFE, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x4B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_BIGGORON_SWORD] = Item(RG_BIGGORON_SWORD, Text{ "Biggoron's Sword", "Épée de Biggoron", "Biggoron-Schwert" }, ITEMTYPE_EQUIP, GI_SWORD_BGS, true, LOGIC_BIGGORON_SWORD, RHT_BIGGORON_SWORD, ITEM_SWORD_BGS, OBJECT_GI_LONGSWORD, GID_SWORD_BGS, 0x0C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); + itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); + itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegelschild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); + itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); + itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); + itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein des Wissens" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "la "}); itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrows", "Flèches de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrows", "Flèches de Glace", "Eispfeile" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrows", "Flèches de Lumière", "Lichtpfeile" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Pass" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); - itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a", "eine", "un"}); - itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "das", "le"}); + itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Pass" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); + itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "eine ", "un "}); + itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "das ", "le "}); itemTable[RG_DOUBLE_DEFENSE] = Item(RG_DOUBLE_DEFENSE, Text{ "Double Defense", "Double Défence", "Doppelte Verteidigung" }, ITEMTYPE_ITEM, RG_DOUBLE_DEFENSE, true, LOGIC_DOUBLE_DEFENSE, RHT_DOUBLE_DEFENSE, RG_DOUBLE_DEFENSE, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xE9, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER); itemTable[RG_DOUBLE_DEFENSE].SetCustomDrawFunc(Randomizer_DrawDoubleDefense); // Trade Quest Items - itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, LOGIC_WEIRD_EGG, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_WEIRD_EGG] = Item(RG_WEIRD_EGG, Text{ "Weird Egg", "Oeuf Curieux", "Seltsames Ei" }, ITEMTYPE_ITEM, GI_WEIRD_EGG, true, LOGIC_WEIRD_EGG, RHT_WEIRD_EGG, ITEM_WEIRD_EGG, OBJECT_GI_EGG, GID_EGG, 0x9A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); itemTable[RG_ZELDAS_LETTER] = Item(RG_ZELDAS_LETTER, Text{ "Zelda's Letter", "Lettre de Zelda", "Zeldas Brief" }, ITEMTYPE_ITEM, GI_LETTER_ZELDA, true, LOGIC_ZELDAS_LETTER, RHT_ZELDAS_LETTER, ITEM_LETTER_ZELDA, OBJECT_GI_LETTER, GID_LETTER_ZELDA, 0x69, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Ei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, LOGIC_POCKET_EGG, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_POCKET_EGG] = Item(RG_POCKET_EGG, Text{ "Pocket Egg", "Oeuf de poche", "Ei" }, ITEMTYPE_ITEM, GI_POCKET_EGG, true, LOGIC_POCKET_EGG, RHT_POCKET_EGG, ITEM_POCKET_EGG, OBJECT_GI_EGG, GID_EGG, 0x01, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); itemTable[RG_COJIRO] = Item(RG_COJIRO, Text{ "Cojiro", "P'tit Poulet", "Henni" }, ITEMTYPE_ITEM, GI_COJIRO, true, LOGIC_COJIRO, RHT_COJIRO, ITEM_COJIRO, OBJECT_GI_NIWATORI, GID_COJIRO, 0x02, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Schimmelpilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Modertrank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, LOGIC_ODD_POULTICE, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "la"}); - itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Säge" }, ITEMTYPE_ITEM, GI_SAW, true, LOGIC_POACHERS_SAW, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); - itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Zerbrochenes Goronen-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Rezept" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, LOGIC_PRESCRIPTION, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "la"}); - itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Glotzfrosch" }, ITEMTYPE_ITEM, GI_FROG, true, LOGIC_EYEBALL_FROG, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "la"}); - itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Augentropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, LOGIC_EYEDROPS, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); - itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Zertifikat" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, LOGIC_CLAIM_CHECK, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); + itemTable[RG_ODD_MUSHROOM] = Item(RG_ODD_MUSHROOM, Text{ "Odd Mushroom", "Champigon Suspect", "Schimmelpilz" }, ITEMTYPE_ITEM, GI_ODD_MUSHROOM, true, LOGIC_ODD_MUSHROOM, RHT_ODD_MUSHROOM, ITEM_ODD_MUSHROOM, OBJECT_GI_MUSHROOM, GID_ODD_MUSHROOM, 0x03, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_ODD_POTION] = Item(RG_ODD_POTION, Text{ "Odd Potion", "Mixture Suspecte", "Modertrank" }, ITEMTYPE_ITEM, GI_ODD_POTION, true, LOGIC_ODD_POULTICE, RHT_ODD_POTION, ITEM_ODD_POTION, OBJECT_GI_POWDER, GID_ODD_POTION, 0x04, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "la "}); + itemTable[RG_POACHERS_SAW] = Item(RG_POACHERS_SAW, Text{ "Poacher's Saw", "Scie du Chasseur", "Säge" }, ITEMTYPE_ITEM, GI_SAW, true, LOGIC_POACHERS_SAW, RHT_POACHERS_SAW, ITEM_SAW, OBJECT_GI_SAW, GID_SAW, 0x05, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); + itemTable[RG_BROKEN_SWORD] = Item(RG_BROKEN_SWORD, Text{ "Broken Goron's Sword", "Épée Brisée de Goron", "Zerbrochenes Goronen-Schwert" }, ITEMTYPE_ITEM, GI_SWORD_BROKEN, true, LOGIC_BROKEN_SWORD, RHT_BROKEN_SWORD, ITEM_SWORD_BROKEN, OBJECT_GI_BROKENSWORD, GID_SWORD_BROKEN, 0x08, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_PRESCRIPTION] = Item(RG_PRESCRIPTION, Text{ "Prescription", "Ordonnance", "Rezept" }, ITEMTYPE_ITEM, GI_PRESCRIPTION, true, LOGIC_PRESCRIPTION, RHT_PRESCRIPTION, ITEM_PRESCRIPTION, OBJECT_GI_PRESCRIPTION, GID_PRESCRIPTION, 0x09, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "la "}); + itemTable[RG_EYEBALL_FROG] = Item(RG_EYEBALL_FROG, Text{ "Eyeball Frog", "Crapaud-qui-louche", "Glotzfrosch" }, ITEMTYPE_ITEM, GI_FROG, true, LOGIC_EYEBALL_FROG, RHT_EYEBALL_FROG, ITEM_FROG, OBJECT_GI_FROG, GID_FROG, 0x0D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "la "}); + itemTable[RG_EYEDROPS] = Item(RG_EYEDROPS, Text{ "World's Finest Eyedrops", "Super Gouttes", "Augentropfen" }, ITEMTYPE_ITEM, GI_EYEDROPS, true, LOGIC_EYEDROPS, RHT_EYEDROPS, ITEM_EYEDROPS, OBJECT_GI_EYE_LOTION, GID_EYEDROPS, 0x0E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); + itemTable[RG_CLAIM_CHECK] = Item(RG_CLAIM_CHECK, Text{ "Claim Check", "Certificat", "Zertifikat" }, ITEMTYPE_ITEM, GI_CLAIM_CHECK, true, LOGIC_CLAIM_CHECK, RHT_CLAIM_CHECK, ITEM_CLAIM_CHECK, OBJECT_GI_TICKETSTONE, GID_CLAIM_CHECK, 0x0A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); // Skulltula Token - itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE, {"a", "ein", "un"}); + itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE, {"a ", "ein ", "un "}); // Progressive Items - itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, {"a", "einen", "un"}, true); - itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, {"a", "ein", "une"}, true); - itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, {"a", "eine", "un"}, true); - itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, {"a", "einen", "un"}, true); - itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, {"a", "eine", "un"}, true); - itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, {"a", "ein", "un"}, true); - itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, {"a", "eine", "une"}, true); - itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, {"a", "eine", "une"}, true); - itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, {"a", "eine", "un"}, true); - itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, {"a", "einen", "un"}, true); - itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, {"a", "ein", "un"}, true); - itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, {"a", "eine", "un"}, true); - itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, {"a", "ein", "une"}, true); + itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, {"a ", "einen ", " un"}, true); + itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, {"a ", "ein ", "une "}, true); + itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, {"a ", "eine ", "un "}, true); + itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, {"a ", "einen ", "un "}, true); + itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, {"a ", "eine ", "un "}, true); + itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, {"a ", "ein ", "un "}, true); + itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, {"a ", "eine ", "une "}, true); + itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, {"a ", "eine ", "une "}, true); + itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, {"a ", "eine ", "un "}, true); + itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, {"a ", "einen ", "un "}, true); + itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, {"a ", "ein ", "un "}, true); + itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, {"a ", "eine ", "un "}, true); + itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, {"a ", "ein ", "une "}, true); // Bottles - itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"an", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); - itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "une"}); - itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER, GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a", "einen", "un"}); - itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "einen", "un"}); + itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"an ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_BUGS] = Item(RG_BOTTLE_WITH_BUGS, Text{ "Bottle with Bugs", "Bouteille avec des Insectes", "Flasche mit Wanzen" }, ITEMTYPE_ITEM, 0x92, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BUGS, RG_BOTTLE_WITH_BUGS, OBJECT_GI_INSECT, GID_BUG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_POE] = Item(RG_BOTTLE_WITH_POE, Text{ "Bottle with Poe", "Bouteille avec un Esprit", "Flasche mit einem Geist" }, ITEMTYPE_ITEM, 0x94, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_POE, RG_BOTTLE_WITH_POE, OBJECT_GI_GHOST, GID_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER, GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "einen ", "un "}); + itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "einen ", "un "}); // Songs itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Salias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Hymne der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "la"}); - itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); - itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "la "}); + itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); + itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); // Maps and Compasses - itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", " die ", "la "}); itemTable[RG_DEKU_TREE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_DODONGOS_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_JABU_JABUS_BELLY_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_FOREST_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_FIRE_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_WATER_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_SPIRIT_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_SHADOW_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_BOTTOM_OF_THE_WELL_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); + itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); itemTable[RG_ICE_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys - itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FIRE_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_WATER_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SHADOW_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_GANONS_CASTLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_FOREST_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_FIRE_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_WATER_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a", "einen", "une"}); + itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE, {"a", "einen", "une"}); - itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE, {"a ", "einen ", "une "}); + itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_GUARD_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_MARKET_BAZAAR_KEY] = Item(RG_MARKET_BAZAAR_KEY, Text{ "Market Bazaar Key", "", "Schlüssel für den Basar des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_MARKET_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_MARKET_BAZAAR_KEY] = Item(RG_MARKET_BAZAAR_KEY, Text{ "Market Bazaar Key", "", "Schlüssel für den Basar des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_MARKET_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_MARKET_BAZAAR_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_MARKET_POTION_SHOP_KEY] = Item(RG_MARKET_POTION_SHOP_KEY, Text{ "Market Potion Shop Key", "", "Schlüssel für den Magie-Laden des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MARKET_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_MARKET_POTION_SHOP_KEY] = Item(RG_MARKET_POTION_SHOP_KEY, Text{ "Market Potion Shop Key", "", "Schlüssel für den Magie-Laden des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MARKET_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_MARKET_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_MASK_SHOP_KEY] = Item(RG_MASK_SHOP_KEY, Text{ "Mask Shop Key", "", "Schlüssel für den Maskenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MASK_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MASK_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_MASK_SHOP_KEY] = Item(RG_MASK_SHOP_KEY, Text{ "Mask Shop Key", "", "Schlüssel für den Maskenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MASK_SHOP_KEY, RHT_OVERWORLD_KEY, RG_MASK_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_MASK_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_MARKET_SHOOTING_GALLERY_KEY] = Item(RG_MARKET_SHOOTING_GALLERY_KEY, Text{ "Market Shooting Gallery Key", "", "Schlüssel für die Schießbude des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_MARKET_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_MARKET_SHOOTING_GALLERY_KEY] = Item(RG_MARKET_SHOOTING_GALLERY_KEY, Text{ "Market Shooting Gallery Key", "", "Schlüssel für die Schießbude des Marktes" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_MARKET_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_MARKET_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_MARKET_SHOOTING_GALLERY_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_BOMBCHU_BOWLING_KEY] = Item(RG_BOMBCHU_BOWLING_KEY, Text{ "Bombchu Bowling Alley Key", "", "Schlüssel für die Minenbowlingbahn" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_BOWLING_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_BOWLING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_BOMBCHU_BOWLING_KEY] = Item(RG_BOMBCHU_BOWLING_KEY, Text{ "Bombchu Bowling Alley Key", "", "Schlüssel für die Minenbowlingbahn" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_BOWLING_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_BOWLING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_BOMBCHU_BOWLING_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY] = Item(RG_TREASURE_CHEST_GAME_BUILDING_KEY, Text{ "Treasure Chest Game Building Key", "", "Schlüssel für das Haus des Schatzkisten-Pokers" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TREASURE_CHEST_GAME_BUILDING_KEY,RHT_OVERWORLD_KEY, RG_TREASURE_CHEST_GAME_BUILDING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY] = Item(RG_TREASURE_CHEST_GAME_BUILDING_KEY, Text{ "Treasure Chest Game Building Key", "", "Schlüssel für das Haus des Schatzkisten-Pokers" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TREASURE_CHEST_GAME_BUILDING_KEY,RHT_OVERWORLD_KEY, RG_TREASURE_CHEST_GAME_BUILDING_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_TREASURE_CHEST_GAME_BUILDING_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_BOMBCHU_SHOP_KEY] = Item(RG_BOMBCHU_SHOP_KEY, Text{ "Bombchu Shop Key", "", "Schlüssel für den Krabbelminenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_SHOP_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_BOMBCHU_SHOP_KEY] = Item(RG_BOMBCHU_SHOP_KEY, Text{ "Bombchu Shop Key", "", "Schlüssel für den Krabbelminenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOMBCHU_SHOP_KEY, RHT_OVERWORLD_KEY, RG_BOMBCHU_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_BOMBCHU_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_RICHARDS_HOUSE_KEY] = Item(RG_RICHARDS_HOUSE_KEY, Text{ "Richard's House Key", "", "Schlüssel für das Haus von Richard" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_RICHARDS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_RICHARDS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_RICHARDS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_ALLEY_HOUSE_KEY] = Item(RG_ALLEY_HOUSE_KEY, Text{ "Alley House Key", "", "Schlüssel für das Gäßchenhaus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_ALLEY_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_ALLEY_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_ALLEY_HOUSE_KEY] = Item(RG_ALLEY_HOUSE_KEY, Text{ "Alley House Key", "", "Schlüssel für das Gäßchenhaus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_ALLEY_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_ALLEY_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_ALLEY_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_KAK_BAZAAR_KEY] = Item(RG_KAK_BAZAAR_KEY, Text{ "Kakariko Bazaar Key", "", "Schlüssel für den Basar von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_KAK_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_KAK_BAZAAR_KEY] = Item(RG_KAK_BAZAAR_KEY, Text{ "Kakariko Bazaar Key", "", "Schlüssel für den Basar von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_BAZAAR_KEY, RHT_OVERWORLD_KEY, RG_KAK_BAZAAR_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_KAK_BAZAAR_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_KAK_POTION_SHOP_KEY] = Item(RG_KAK_POTION_SHOP_KEY, Text{ "Kakariko Potion Shop Key", "", "Schlüssel für den Magie-Laden von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_KAK_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_KAK_POTION_SHOP_KEY] = Item(RG_KAK_POTION_SHOP_KEY, Text{ "Kakariko Potion Shop Key", "", "Schlüssel für den Magie-Laden von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_KAK_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_KAK_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_BOSS_HOUSE_KEY] = Item(RG_BOSS_HOUSE_KEY, Text{ "Boss's House Key", "", "Schlüssel für das Haus des Chefs" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOSS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_BOSS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_BOSS_HOUSE_KEY] = Item(RG_BOSS_HOUSE_KEY, Text{ "Boss's House Key", "", "Schlüssel für das Haus des Chefs" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BOSS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_BOSS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_BOSS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_GRANNYS_POTION_SHOP_KEY] = Item(RG_GRANNYS_POTION_SHOP_KEY, Text{ "Granny's Potion Shop Key", "", "Schlüssel für Asas Hexenladen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GRANNYS_POTION_SHOP_KEY, RHT_OVERWORLD_KEY, RG_GRANNYS_POTION_SHOP_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_GRANNYS_POTION_SHOP_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_SKULLTULA_HOUSE_KEY] = Item(RG_SKULLTULA_HOUSE_KEY, Text{ "Skulltula House Key", "", "Schlüssel für das Skulltula-Haus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_SKULLTULA_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_SKULLTULA_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_SKULLTULA_HOUSE_KEY] = Item(RG_SKULLTULA_HOUSE_KEY, Text{ "Skulltula House Key", "", "Schlüssel für das Skulltula-Haus" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_SKULLTULA_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_SKULLTULA_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SKULLTULA_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_IMPAS_HOUSE_KEY] = Item(RG_IMPAS_HOUSE_KEY, Text{ "Impa's House Key", "", "Schlüssel für das Haus von Impa" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_IMPAS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_IMPAS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_IMPAS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_WINDMILL_KEY] = Item(RG_WINDMILL_KEY, Text{ "Windmill Key", "", "Schlüssel für die Windmühle" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_WINDMILL_KEY, RHT_OVERWORLD_KEY, RG_WINDMILL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_WINDMILL_KEY] = Item(RG_WINDMILL_KEY, Text{ "Windmill Key", "", "Schlüssel für die Windmühle" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_WINDMILL_KEY, RHT_OVERWORLD_KEY, RG_WINDMILL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_WINDMILL_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_KAK_SHOOTING_GALLERY_KEY] = Item(RG_KAK_SHOOTING_GALLERY_KEY, Text{ "Kakariko Shooting Gallery Key", "", "Schlüssel für die Schießbude von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_KAK_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_KAK_SHOOTING_GALLERY_KEY] = Item(RG_KAK_SHOOTING_GALLERY_KEY, Text{ "Kakariko Shooting Gallery Key", "", "Schlüssel für die Schießbude von Kakariko" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_KAK_SHOOTING_GALLERY_KEY, RHT_OVERWORLD_KEY, RG_KAK_SHOOTING_GALLERY_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_KAK_SHOOTING_GALLERY_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_DAMPES_HUT_KEY] = Item(RG_DAMPES_HUT_KEY, Text{ "Dampe's Hut Key", "", "Schlüssel für die Hütte von Boris" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_DAMPES_HUT_KEY, RHT_OVERWORLD_KEY, RG_DAMPES_HUT_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_DAMPES_HUT_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); itemTable[RG_TALONS_HOUSE_KEY] = Item(RG_TALONS_HOUSE_KEY, Text{ "Talon's House Key", "", "Schlüssel für das Haus von Talon" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_TALONS_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_TALONS_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER); itemTable[RG_TALONS_HOUSE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_STABLES_KEY] = Item(RG_STABLES_KEY, Text{ "Stables Key", "", "Schlüssel für die Ställe" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_STABLES_KEY, RHT_OVERWORLD_KEY, RG_STABLES_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_STABLES_KEY] = Item(RG_STABLES_KEY, Text{ "Stables Key", "", "Schlüssel für die Ställe" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_STABLES_KEY, RHT_OVERWORLD_KEY, RG_STABLES_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_STABLES_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_BACK_TOWER_KEY] = Item(RG_BACK_TOWER_KEY, Text{ "Back Tower Key", "", "Schlüssel für den hinteren Turm" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BACK_TOWER_KEY, RHT_OVERWORLD_KEY, RG_BACK_TOWER_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_BACK_TOWER_KEY] = Item(RG_BACK_TOWER_KEY, Text{ "Back Tower Key", "", "Schlüssel für den hinteren Turm" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_BACK_TOWER_KEY, RHT_OVERWORLD_KEY, RG_BACK_TOWER_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_BACK_TOWER_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_HYLIA_LAB_KEY] = Item(RG_HYLIA_LAB_KEY, Text{ "Hylia Laboratory Key", "", "Schlüssel für das Hylia-Labor" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_HYLIA_LAB_KEY, RHT_OVERWORLD_KEY, RG_HYLIA_LAB_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_HYLIA_LAB_KEY] = Item(RG_HYLIA_LAB_KEY, Text{ "Hylia Laboratory Key", "", "Schlüssel für das Hylia-Labor" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_HYLIA_LAB_KEY, RHT_OVERWORLD_KEY, RG_HYLIA_LAB_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_HYLIA_LAB_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); - itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FISHING_HOLE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); // Key Rings - itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_FIRE_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_WATER_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_SHADOW_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_TREASURE_GAME_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); // Dungeon Rewards - itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", " le"}); + itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); // Generic Items - itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "ein", "un"}); - itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüner Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "ein ", "un "}); + itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüner Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, LOGIC_GREG, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "ein", "un"}); - itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herzcontainer" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a", "einen", "un"}); + itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "ein ", "un "}); + itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herzcontainer" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, LOGIC_NONE, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_MILK] = Item(RG_MILK, Text{ "Milk", "Lait", "Milch" }, ITEMTYPE_ITEM, GI_MILK, false, LOGIC_NONE, RHT_NONE, ITEM_MILK, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Fisch" }, ITEMTYPE_ITEM, GI_FISH, false, LOGIC_NONE, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "einen", "un"}); + itemTable[RG_FISH] = Item(RG_FISH, Text{ "Fish", "Poisson", "Fisch" }, ITEMTYPE_ITEM, GI_FISH, false, LOGIC_NONE, RHT_NONE, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "einen ", "un "}); // Refills itemTable[RG_BOMBS_5] = Item(RG_BOMBS_5, Text{ "Bombs (5)", "Bombes (5)", "Bomben (5)" }, ITEMTYPE_REFILL, GI_BOMBS_5, false, LOGIC_NONE, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_BOMBS_10] = Item(RG_BOMBS_10, Text{ "Bombs (10)", "Bombes (10)", "Bomben (10)" }, ITEMTYPE_REFILL, GI_BOMBS_10, false, LOGIC_NONE, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); @@ -275,12 +275,12 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_NUTS_5] = Item(RG_DEKU_NUTS_5, Text{ "Deku Nuts (5)", "Noix Mojo (5)", "Deku-Nüsse (5)" }, ITEMTYPE_REFILL, GI_NUTS_5, false, LOGIC_NONE, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, LOGIC_NONE, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, LOGIC_NONE, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); - itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stab (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "einen", "un"}); - itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); - itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a", "eine", "une"}); + itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stab (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "einen ", "un "}); + itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); // Treasure Game - itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "das", "le"}); + itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "das ", "le "}); itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüner Rubin (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); // Shop itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuß kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 15); @@ -332,75 +332,75 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_TWINROVA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "Âme de Ganon", "Ganons Seele" }, ITEMTYPE_ITEM, 0xE8, true, LOGIC_CAN_SUMMON_GANON, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); itemTable[RG_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Angelrute" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "das", "le"}); + itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Angelrute" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "das ", "le "}); itemTable[RG_FISHING_POLE].SetCustomDrawFunc(Randomizer_DrawFishingPoleGI); - itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Taste A der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_A_BUTTON, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_OCARINA_A_BUTTON] = Item(RG_OCARINA_A_BUTTON, Text{ "Ocarina A Button", "Touche A de l'Ocarina", "Taste A der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_A_BUTTON, RHT_OCARINA_A_BUTTON, RG_OCARINA_A_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_OCARINA_A_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Taste C-Oben der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_UP_BUTTON, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_OCARINA_C_UP_BUTTON] = Item(RG_OCARINA_C_UP_BUTTON, Text{ "Ocarina C Up Button", "Touche C-Haut de l'Ocarina", "Taste C-Oben der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_UP_BUTTON, RHT_OCARINA_C_UP_BUTTON, RG_OCARINA_C_UP_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_OCARINA_C_UP_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Taste C-Unten der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_OCARINA_C_DOWN_BUTTON] = Item(RG_OCARINA_C_DOWN_BUTTON, Text{ "Ocarina C Down Button", "Touche C-Bas de l'Ocarina", "Taste C-Unten der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_DOWN_BUTTON, RHT_OCARINA_C_DOWN_BUTTON, RG_OCARINA_C_DOWN_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_OCARINA_C_DOWN_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Taste C-Links der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_OCARINA_C_LEFT_BUTTON] = Item(RG_OCARINA_C_LEFT_BUTTON, Text{ "Ocarina C Left Button", "Touche C-Gauche de l'Ocarina", "Taste C-Links der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_LEFT_BUTTON, RHT_OCARINA_C_LEFT_BUTTON, RG_OCARINA_C_LEFT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_OCARINA_C_LEFT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Taste C-Rechts der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "le"}); + itemTable[RG_OCARINA_C_RIGHT_BUTTON] = Item(RG_OCARINA_C_RIGHT_BUTTON, Text{ "Ocarina C Right Button", "Touche C-Droit de l'Ocarina", "Taste C-Rechts der Okarina" }, ITEMTYPE_ITEM, GI_MAP, true, LOGIC_OCARINA_C_RIGHT_BUTTON, RHT_OCARINA_C_RIGHT_BUTTON, RG_OCARINA_C_RIGHT_BUTTON, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_OCARINA_C_RIGHT_BUTTON].SetCustomDrawFunc(Randomizer_DrawOcarinaButton); - itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "die", "le"}); + itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "die ", "le "}); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "Sac de Missiles Teigneux" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "un"}); + itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "Sac de Missiles Teigneux" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); - itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "le"}); - itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "Sac de Bombes Infini", "Unendliche Bombentasche" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); - itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "Sac de Graines Infinis", "Unendliche Samentasche" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); - itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "Bâtons Mojo Infinis", "Unendliche Stab-Kapazität" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); - itemTable[RG_NUT_UPGRADE_INF] = Item(RG_NUT_UPGRADE_INF, Text{ "Infinite Nut Capacity", "Noix Mojo Infinies", "Unendliche Nuß-Kapazität" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "la"}); - itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "Magie Infinie", "Unendliches Magisches Maß" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); - itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "Missiles Teigneux Infinis", "Unendliche Krabbelminen" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "den", "les"}); + itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_BOMB_BAG_INF] = Item(RG_BOMB_BAG_INF, Text{ "Infinite Bomb Bag", "Sac de Bombes Infini", "Unendliche Bombentasche" }, ITEMTYPE_ITEM, RG_BOMB_BAG_INF, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG_INF, RG_BOMB_BAG_INF, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "le "}); + itemTable[RG_BULLET_BAG_INF] = Item(RG_BULLET_BAG_INF, Text{ "Infinite Bullet Bag", "Sac de Graines Infinis", "Unendliche Samentasche" }, ITEMTYPE_ITEM, RG_BULLET_BAG_INF, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BULLET_BAG_INF, RG_BULLET_BAG_INF, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "le "}); + itemTable[RG_STICK_UPGRADE_INF] = Item(RG_STICK_UPGRADE_INF, Text{ "Infinite Stick Capacity", "Bâtons Mojo Infinis", "Unendliche Stab-Kapazität" }, ITEMTYPE_ITEM, RG_STICK_UPGRADE_INF, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_STICK_UPGRADE_INF, RG_STICK_UPGRADE_INF, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_NUT_UPGRADE_INF] = Item(RG_NUT_UPGRADE_INF, Text{ "Infinite Nut Capacity", "Noix Mojo Infinies", "Unendliche Nuß-Kapazität" }, ITEMTYPE_ITEM, RG_NUT_UPGRADE_INF, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NUT_UPGRADE_INF, RG_NUT_UPGRADE_INF, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_MAGIC_INF] = Item(RG_MAGIC_INF, Text{ "Infinite Magic Meter", "Magie Infinie", "Unendliches Magisches Maß" }, ITEMTYPE_ITEM, RG_MAGIC_INF, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_INF, RG_MAGIC_INF, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "le "}); + itemTable[RG_BOMBCHU_INF] = Item(RG_BOMBCHU_INF, Text{ "Infinite Bombchus", "Missiles Teigneux Infinis", "Unendliche Krabbelminen" }, ITEMTYPE_ITEM, RG_BOMBCHU_INF, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_INF, RG_BOMBCHU_INF, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "les "}); itemTable[RG_BOMBCHU_INF].SetCustomDrawFunc(Randomizer_DrawBombchuBag); - itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "Bourse Infinie", "Unendliche Geldbörse" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); + itemTable[RG_WALLET_INF] = Item(RG_WALLET_INF, Text{ "Infinite Wallet", "Bourse Infinie", "Unendliche Geldbörse" }, ITEMTYPE_ITEM, RG_WALLET_INF, true, LOGIC_PROGRESSIVE_WALLET, RHT_WALLET_INF, RG_WALLET_INF, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "le "}); - itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "Clé Squelette", "Skelettschlüssel" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "den", "la"}); + itemTable[RG_SKELETON_KEY] = Item(RG_SKELETON_KEY, Text{ "Skeleton Key", "Clé Squelette", "Skelettschlüssel" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_SKELETON_KEY, RHT_SKELETON_KEY, RG_SKELETON_KEY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SKELETON_KEY].SetCustomDrawFunc(Randomizer_DrawSkeletonKey); - itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "Sac de Bâton Mojo", "Deku-Stab-Tasche" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "un"}); + itemTable[RG_DEKU_STICK_BAG] = Item(RG_DEKU_STICK_BAG, Text{ "Deku Stick Bag", "Sac de Bâton Mojo", "Deku-Stab-Tasche" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_NONE, RG_DEKU_STICK_BAG, OBJECT_GI_STICK, GID_STICK, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); - itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "Sac de Noix Mojo", "Deku-Nuß-Tasche" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "eine", "un"}); + itemTable[RG_DEKU_NUT_BAG] = Item(RG_DEKU_NUT_BAG, Text{ "Deku Nut Bag", "Sac de Noix Mojo", "Deku-Nuß-Tasche" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_NONE, RG_DEKU_NUT_BAG, OBJECT_GI_NUTS, GID_NUTS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); - itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE, {"the", "die", "la"}); + itemTable[RG_TRIFORCE] = Item(RG_TRIFORCE, Text{ "Triforce", "Triforce", "Triforce" }, ITEMTYPE_EVENT, RG_TRIFORCE, false, LOGIC_NONE, RHT_NONE, {"the ", "die ", "la "}); itemTable[RG_HINT] = Item(RG_HINT, Text{ "Hint", "Indice", "Hinweis" }, ITEMTYPE_EVENT, RG_HINT, false, LOGIC_NONE, RHT_NONE); // Individual stages of progressive items (only here for GetItemEntry purposes, not for use in seed gen) - itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, LOGIC_PROGRESSIVE_OCARINA, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "la"}); - itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, LOGIC_PROGRESSIVE_OCARINA, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "ddie", "le"}); - itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, LOGIC_PROGRESSIVE_BOW, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, LOGIC_PROGRESSIVE_BOW, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, LOGIC_PROGRESSIVE_BOW, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Große Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the", "den", "le"}); - itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "das", "le"}); - itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER, 0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); - itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "les"}); - itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_GOLDEN, true, LOGIC_PROGRESSIVE_SCALE, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsenengeldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the", "die", "le"}); - itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Goldene Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "die", "le"}); - itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Petite Bourse", "Kindergeldbörse" }, ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "die", "le"}); + itemTable[RG_HOOKSHOT] = Item(RG_HOOKSHOT, Text{ "Hookshot", "Grappin", "Fanghaken" }, ITEMTYPE_ITEM, GI_HOOKSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_HOOKSHOT, ITEM_HOOKSHOT, OBJECT_GI_HOOKSHOT, GID_HOOKSHOT, 0x36, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_LONGSHOT] = Item(RG_LONGSHOT, Text{ "Longshot", "Super-Grappin", "Enterhaken" }, ITEMTYPE_ITEM, GI_LONGSHOT, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_LONGSHOT, ITEM_LONGSHOT, OBJECT_GI_HOOKSHOT, GID_LONGSHOT, 0x4F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_FAIRY_OCARINA] = Item(RG_FAIRY_OCARINA, Text{ "Fairy Ocarina", "Ocarina des fées", "Feen-Okarina" }, ITEMTYPE_ITEM, GI_OCARINA_FAIRY, true, LOGIC_PROGRESSIVE_OCARINA, RHT_FAIRY_OCARINA, ITEM_OCARINA_FAIRY, OBJECT_GI_OCARINA_0, GID_OCARINA_FAIRY, 0x4A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); + itemTable[RG_OCARINA_OF_TIME] = Item(RG_OCARINA_OF_TIME, Text{ "Ocarina of Time", "Ocarina du Temps", "Okarina der Zeit" }, ITEMTYPE_ITEM, GI_OCARINA_OOT, true, LOGIC_PROGRESSIVE_OCARINA, RHT_OCARINA_OF_TIME, ITEM_OCARINA_TIME, OBJECT_GI_OCARINA, GID_OCARINA_TIME, 0x3A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_BOMB_BAG] = Item(RG_BOMB_BAG, Text{ "Bomb Bag", "Sac de Bombes", "Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_20, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BOMB_BAG, ITEM_BOMB_BAG_20, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_20, 0x58, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_BIG_BOMB_BAG] = Item(RG_BIG_BOMB_BAG, Text{ "Big Bomb Bag", "Grand Sac de Bombes", "Große Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_30, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIG_BOMB_BAG, ITEM_BOMB_BAG_30, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_30, 0x59, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_BIGGEST_BOMB_BAG] = Item(RG_BIGGEST_BOMB_BAG, Text{ "Biggest Bomb Bag", "Énorme Sac de Bombes", "Größte Bombentasche" }, ITEMTYPE_ITEM, GI_BOMB_BAG_40, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_BIGGEST_BOMB_BAG, ITEM_BOMB_BAG_40, OBJECT_GI_BOMBPOUCH, GID_BOMB_BAG_40, 0x5A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_FAIRY_BOW] = Item(RG_FAIRY_BOW, Text{ "Fairy Bow", "Arc des Fées", "Feen-Bogen" }, ITEMTYPE_ITEM, GI_BOW, true, LOGIC_PROGRESSIVE_BOW, RHT_FAIRY_BOW, ITEM_BOW, OBJECT_GI_BOW, GID_BOW, 0x31, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_BIG_QUIVER] = Item(RG_BIG_QUIVER, Text{ "Big Quiver", "Grand carquois", "Großer Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_40, true, LOGIC_PROGRESSIVE_BOW, RHT_BIG_QUIVER, ITEM_QUIVER_40, OBJECT_GI_ARROWCASE, GID_QUIVER_40, 0x56, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_BIGGEST_QUIVER] = Item(RG_BIGGEST_QUIVER, Text{ "Biggest Quiver", "Énorme carquois", "Größter Köcher" }, ITEMTYPE_ITEM, GI_QUIVER_50, true, LOGIC_PROGRESSIVE_BOW, RHT_BIGGEST_QUIVER, ITEM_QUIVER_50, OBJECT_GI_ARROWCASE, GID_QUIVER_50, 0x57, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_FAIRY_SLINGSHOT] = Item(RG_FAIRY_SLINGSHOT, Text{ "Fairy Slingshot", "Lance-Pierre des Fées", "Feen-Schleuder" }, ITEMTYPE_ITEM, GI_SLINGSHOT, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_FAIRY_SLINGSHOT, ITEM_SLINGSHOT, OBJECT_GI_PACHINKO, GID_SLINGSHOT, 0x30, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_BIG_BULLET_BAG] = Item(RG_BIG_BULLET_BAG, Text{ "Big Deku Seed Bullet Bag", "Grand sac de graines mojo", "Große Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_40, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIG_BULLET_BAG, ITEM_BULLET_BAG_40, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_BIGGEST_BULLET_BAG] = Item(RG_BIGGEST_BULLET_BAG, Text{ "Biggest Deku Seed Bullet Bag", "Énorme sac de graines mojo", "Größte Deku-Samentasche" }, ITEMTYPE_ITEM, GI_BULLET_BAG_50, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_BIGGEST_BULLET_BAG, ITEM_BULLET_BAG_50, OBJECT_GI_DEKUPOUCH, GID_BULLET_BAG, 0x07, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_GORONS_BRACELET] = Item(RG_GORONS_BRACELET, Text{ "Goron's Bracelet", "Bracelet Goron", "Goronen-Armband" }, ITEMTYPE_ITEM, GI_BRACELET, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GORONS_BRACELET, ITEM_BRACELET, OBJECT_GI_BRACELET, GID_BRACELET, 0x79, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_SILVER_GAUNTLETS] = Item(RG_SILVER_GAUNTLETS, Text{ "Silver Gauntlets", "Gantelets d'argent", "Silberhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_SILVER, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_SILVER_GAUNTLETS, ITEM_GAUNTLETS_SILVER, OBJECT_GI_GLOVES, GID_GAUNTLETS_SILVER, 0x5B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); + itemTable[RG_GOLDEN_GAUNTLETS] = Item(RG_GOLDEN_GAUNTLETS, Text{ "Golden Gauntlets", "Gantelets d'or", "Goldhandschuhe" }, ITEMTYPE_ITEM, GI_GAUNTLETS_GOLD, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_GOLDEN_GAUNTLETS, ITEM_GAUNTLETS_GOLD, OBJECT_GI_GLOVES, GID_GAUNTLETS_GOLD, 0x5C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); + itemTable[RG_SILVER_SCALE] = Item(RG_SILVER_SCALE, Text{ "Silver Scale", "Écaille d'argent", "Silberne Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_SCALE, RHT_SILVER_SCALE, ITEM_SCALE_SILVER, OBJECT_GI_SCALE, GID_SCALE_SILVER, 0xCD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_GOLDEN_SCALE] = Item(RG_GOLDEN_SCALE, Text{ "Golden Scale", "Écaille d'or", "Goldene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_GOLDEN, true, LOGIC_PROGRESSIVE_SCALE, RHT_GOLDEN_SCALE, ITEM_SCALE_GOLDEN, OBJECT_GI_SCALE, GID_SCALE_GOLDEN, 0xCE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_ADULT_WALLET] = Item(RG_ADULT_WALLET, Text{ "Adult Wallet", "Grande Bourse", "Erwachsenengeldbörse" }, ITEMTYPE_ITEM, GI_WALLET_ADULT, true, LOGIC_PROGRESSIVE_WALLET, RHT_ADULT_WALLET, ITEM_WALLET_ADULT, OBJECT_GI_PURSE, GID_WALLET_ADULT, 0x5E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_GIANT_WALLET] = Item(RG_GIANT_WALLET, Text{ "Giant Wallet", "Bourse de Géant", "Riesige Geldbörse" }, ITEMTYPE_ITEM, GI_WALLET_GIANT, true, LOGIC_PROGRESSIVE_WALLET, RHT_GIANT_WALLET, ITEM_WALLET_GIANT, OBJECT_GI_PURSE, GID_WALLET_GIANT, 0x5F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_TYCOON_WALLET] = Item(RG_TYCOON_WALLET, Text{ "Tycoon Wallet", "Bourse de Magnat", "Goldene Geldbörse" }, ITEMTYPE_ITEM, RG_TYCOON_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_TYCOON_WALLET, RG_TYCOON_WALLET, OBJECT_GI_PURSE, GID_WALLET_GIANT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "le "}); + itemTable[RG_CHILD_WALLET] = Item(RG_CHILD_WALLET, Text{ "Child Wallet", "Petite Bourse", "Kindergeldbörse" }, ITEMTYPE_ITEM, RG_CHILD_WALLET, true, LOGIC_PROGRESSIVE_WALLET, RHT_CHILD_WALLET, RG_CHILD_WALLET, OBJECT_GI_PURSE, GID_WALLET_ADULT, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "die ", "le "}); itemTable[RG_DEKU_NUT_CAPACITY_30] = Item(RG_DEKU_NUT_CAPACITY_30, Text{ "Deku Nut Capacity (30)", "Capacité de noix Mojo (30)", "Deku-Nuß-Kapazität (30)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_30, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_30, ITEM_NUT_UPGRADE_30, OBJECT_GI_NUTS, GID_NUTS, 0xA7, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_DEKU_NUT_CAPACITY_40] = Item(RG_DEKU_NUT_CAPACITY_40, Text{ "Deku Nut Capacity (40)", "Capacité de noix Mojo (40)", "Deku-Nuß-Kapazität (40)" }, ITEMTYPE_ITEM, GI_NUT_UPGRADE_40, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_DEKU_NUT_CAPACITY_40, ITEM_NUT_UPGRADE_40, OBJECT_GI_NUTS, GID_NUTS, 0xA8, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_DEKU_STICK_CAPACITY_20] = Item(RG_DEKU_STICK_CAPACITY_20, Text{ "Deku Stick Capacity (20)", "Capacité de Bâtons Mojo (20)", "Deku-Stab-Kapazität (20)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_20, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_20, ITEM_STICK_UPGRADE_20, OBJECT_GI_STICK, GID_STICK, 0x90, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); itemTable[RG_DEKU_STICK_CAPACITY_30] = Item(RG_DEKU_STICK_CAPACITY_30, Text{ "Deku Stick Capacity (30)", "Capacité de Bâtons Mojo (30)", "Deku-Stab-Kapazität (30)" }, ITEMTYPE_ITEM, GI_STICK_UPGRADE_30, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_DEKU_STICK_CAPACITY_30, ITEM_STICK_UPGRADE_30, OBJECT_GI_STICK, GID_STICK, 0x91, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE); - itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the", "das", "le"}); - itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbessertes Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", "das", "le"}); - itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Fragment" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a", "ein", "un"}); + itemTable[RG_MAGIC_SINGLE] = Item(RG_MAGIC_SINGLE, Text{ "Magic Meter", "Jauge de Magie", "Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_SINGLE, RG_MAGIC_SINGLE, OBJECT_GI_MAGICPOT, GID_MAGIC_SMALL, 0xE4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "das ", "le "}); + itemTable[RG_MAGIC_DOUBLE] = Item(RG_MAGIC_DOUBLE, Text{ "Enhanced Magic Meter", "Jauge de Magie améliorée", "Verbessertes Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_MAGIC_DOUBLE, RG_MAGIC_DOUBLE, OBJECT_GI_MAGICPOT, GID_MAGIC_LARGE, 0xE8, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "das ", "le "}); + itemTable[RG_TRIFORCE_PIECE] = Item(RG_TRIFORCE_PIECE, Text{ "Triforce Piece", "Triforce Piece", "Triforce-Fragment" }, ITEMTYPE_ITEM, 0xDF, true, LOGIC_TRIFORCE_PIECES, RHT_TRIFORCE_PIECE, RG_TRIFORCE_PIECE, OBJECT_GI_BOMB_2, GID_TRIFORCE_PIECE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "ein ", "un "}); // Init itemNameToEnum for (auto& item : itemTable) { From f5c4948b4e16db22cb846165c70276050217a388 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 11 Mar 2025 23:37:02 -0400 Subject: [PATCH 049/103] Fix skulltula hint messages --- soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 2 +- soh/soh/Enhancements/randomizer/hint.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index fdedbac47..80dd460bc 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -120,7 +120,7 @@ void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) { } else { return; } - msg.AutoFormat(); + // msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } diff --git a/soh/soh/Enhancements/randomizer/hint.cpp b/soh/soh/Enhancements/randomizer/hint.cpp index 2648c4623..f0455de35 100644 --- a/soh/soh/Enhancements/randomizer/hint.cpp +++ b/soh/soh/Enhancements/randomizer/hint.cpp @@ -516,7 +516,7 @@ const HintText Hint::GetItemHintText(uint8_t slot, bool mysterious) const { } else if (!ctx->GetOption(RSK_HINT_CLARITY).Is(RO_HINT_CLARITY_AMBIGUOUS) && targetRG == RG_ICE_TRAP) { //RANDOTODO store in item hint instead of item return HintText(CustomMessage({ctx->overrides[hintedCheck].GetTrickName()})); } else { - return ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetHint(); + return HintText(ctx->GetItemLocation(hintedCheck)->GetPlacedItem().GetName()); } } From 75a968cef8f8f3c73b79b518892187bede8787db Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 12 Mar 2025 20:17:03 -0400 Subject: [PATCH 050/103] Add text colors to items and respect them in most messages --- .../randomizer/Messages/ItemMessages.cpp | 3 +- .../randomizer/Messages/MerchantMessages.cpp | 52 ++-- .../randomizer/Messages/StaticHints.cpp | 36 ++- soh/soh/Enhancements/randomizer/item.cpp | 13 +- soh/soh/Enhancements/randomizer/item.h | 8 +- soh/soh/Enhancements/randomizer/item_list.cpp | 272 +++++++++--------- 6 files changed, 207 insertions(+), 177 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp index 222ccea75..e3401d0c6 100644 --- a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp @@ -360,7 +360,7 @@ void BuildTriforcePieceMessage(CustomMessage& msg) { void BuildCustomItemMessage(Player* player, CustomMessage& msg) { int16_t rgid; - msg = CustomMessage("You found [[article]]%g[[name]]%w!", "Du erhältst [[article]]%g[[name]]%w gefunden!", "Vous avez trouvé [[article]]%g[[name]]%w!", TEXTBOX_TYPE_BLUE); + msg = CustomMessage("You found [[article]][[color]][[name]]%w!", "Du erhältst [[article]][[color]][[name]]%w gefunden!", "Vous avez trouvé [[article]][[color]][[name]]%w!", TEXTBOX_TYPE_BLUE); if (player->getItemEntry.objectId != OBJECT_INVALID) { rgid = player->getItemEntry.getItemId; } else { @@ -369,6 +369,7 @@ void BuildCustomItemMessage(Player* player, CustomMessage& msg) { CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); CustomMessage article = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetArticle(), TEXTBOX_TYPE_BLUE); msg.Replace("[[article]]", article); + msg.Replace("[[color]]", Rando::StaticData::RetrieveItem(static_cast(rgid)).GetColor()); msg.Replace("[[name]]", name); msg.AutoFormat(); } diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 016b9060c..c643ab0c7 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -26,16 +26,20 @@ void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) { RandomizerGet rgid = RAND_GET_ITEM(rc)->GetPlacedRandomizerGet(); uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); CustomMessage itemName; + std::string color = Rando::StaticData::RetrieveItem(static_cast(rgid)).GetColor(); bool mysterious = RAND_GET_OPTION(RSK_MERCHANT_TEXT_HINT).Is(RO_GENERIC_OFF) || CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); if (mysterious) { itemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage(); + color = "%g"; } else if (rgid == RG_ICE_TRAP) { rgid = RAND_GET_OVERRIDE(rc).LooksLike(); itemName = CustomMessage(RAND_GET_OVERRIDE(rc).GetTrickName()); + color = "%g"; } else { itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName()); } + msg.Replace("[[color]]", color); msg.InsertNames({ itemName , CustomMessage(std::to_string(price))}); } @@ -50,9 +54,9 @@ void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { msg.Format(); } else if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) { msg = CustomMessage( - "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + "Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" ); BuildMerchantMessage(msg, RC_ZR_MAGIC_BEAN_SALESMAN); msg.AutoFormat(); @@ -63,9 +67,9 @@ void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg = CustomMessage( - "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + "Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" ); BuildMerchantMessage(msg, RC_GC_MEDIGORON); msg.AutoFormat(); @@ -78,9 +82,9 @@ void BuildGrannyMessage(uint16_t* textId, bool* loadFromMessageTable) { (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { CustomMessage msg = CustomMessage( - "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + "Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" ); BuildMerchantMessage(msg, RC_KAK_GRANNYS_SHOP); msg.AutoFormat(); @@ -97,9 +101,9 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { /*french*/"Squalala! Je vais enfin pouvoir %rprendre des vacances%w!"); } else if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { msg = CustomMessage( - "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + "Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" ); BuildMerchantMessage(msg, RC_WASTELAND_BOMBCHU_SALESMAN); } @@ -124,13 +128,13 @@ void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); CustomMessage msg; if (price == 0) { - msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will give you a %g[[1]]%w!&Please, take it!\x07\x10\xA3", - "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w geben!\x07\x10\xA3", - "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3"); + msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will give you a [[color]][[1]]%w!&Please, take it!\x07\x10\xA3", + "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen [[color]][[1]]%w geben!\x07\x10\xA3", + "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un [[color]][[1]]%w! Vas-y prends le!\x07\x10\xA3"); } else { - msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %y[[2]] Rupees%w it is!\x07\x10\xA3", - "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", - "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); + msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a [[color]][[1]]%w! %y[[2]] Rupees%w it is!\x07\x10\xA3", + "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen [[color]][[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", + "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un [[color]][[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); } BuildMerchantMessage(msg, rc); msg.AutoFormat(); @@ -146,14 +150,14 @@ void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) { // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); - msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", - "\x08%g[[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", - "\x08%g[[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); + msg = CustomMessage("\x08[[color]][[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", + "\x08[[color]][[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", + "\x08[[color]][[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); } else if (*textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && *textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END) { rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); - msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w\x09\x1B%gBuy&Don't buy%w\x09\x02", - "\x08%g[[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", - "\x08%g[[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); + msg = CustomMessage("\x08[[color]][[1]]%w %y[[2]]_Rupees%w\x09\x1B%gBuy&Don't buy%w\x09\x02", + "\x08[[color]][[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", + "\x08[[color]][[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); } else { return; } diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 80dd460bc..b252cf089 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -105,28 +105,48 @@ void BuildAdultAltarMessage(uint16_t* textId, bool* loadFromMessageTable) { } void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg; + uint8_t count = 0; + RandomizerCheck rc = RC_UNKNOWN_CHECK; int16_t actorParams = GET_PLAYER(gPlayState)->talkActor->params; if (actorParams == 1 && RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT)) { - msg = RAND_GET_HINT(RH_KAK_10_SKULLS_HINT)->GetHintMessage(); + rc = RC_KAK_10_GOLD_SKULLTULA_REWARD; + count = 10; } else if (actorParams == 2 && RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT)) { - msg = RAND_GET_HINT(RH_KAK_20_SKULLS_HINT)->GetHintMessage(); + rc = RC_KAK_20_GOLD_SKULLTULA_REWARD; + count = 20; } else if (actorParams == 3 && RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT)) { - msg = RAND_GET_HINT(RH_KAK_30_SKULLS_HINT)->GetHintMessage(); + rc = RC_KAK_30_GOLD_SKULLTULA_REWARD; + count = 30; } else if (actorParams == 4 && RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT)) { - msg = RAND_GET_HINT(RH_KAK_40_SKULLS_HINT)->GetHintMessage(); + rc = RC_KAK_40_GOLD_SKULLTULA_REWARD; + count = 40; } else if (actorParams == 5 && RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT)) { - msg = RAND_GET_HINT(RH_KAK_50_SKULLS_HINT)->GetHintMessage(); + rc = RC_KAK_50_GOLD_SKULLTULA_REWARD; + count = 50; } else { return; } - // msg.AutoFormat(); + Rando::Item& item = Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(rc)->GetPlacedRandomizerGet()); + CustomMessage msg = CustomMessage( + "Yeaaarrgh! I'm cursed!!^Please save me by destroying %y[[d]] Spiders of the Curse%w and I will give you my [[color]][[1]]%w!", + /*german*/ "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du %y[[d]] Skulltulas%w zerstörst und ich werde Dir dafür [[color]][[1]]%w geben!", + /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore %y[[d]] Araignées de la Malédiction%w et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); + msg.InsertNumber(count); + msg.Replace("[[color]]", item.GetColor()); + msg.InsertNames({ item.GetName() }); + msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = RAND_GET_HINT(RH_KAK_100_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + CustomMessage msg = CustomMessage( + "Yeaaarrgh! I'm cursed!!^Please save me by destroying %y100 Spiders of the Curse%w and I will give you my [[color]][[1]]%w!", + /*german*/ "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du %y100 Skulltulas%w zerstörst und ich werde Dir dafür [[color]][[1]]%w geben!", + /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore %y100 Araignées de la Malédiction%w et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); + msg.Replace("[[color]]", Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()).GetColor()); + msg.InsertNames({ Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()).GetName() }); + msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 5faf94c34..b0610e682 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -17,10 +17,10 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const uint16_t itemId_, const uint16_t objectId_, const uint16_t gid_, const uint16_t textId_, const uint16_t field_, const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_, - Text article_, const bool progressive_, const uint16_t price_) + Text article_, const std::string color_, const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), article(std::move(article_)), - progressive(progressive_), price(price_) { + color(std::move(color_)), progressive(progressive_), price(price_) { if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) { giEntry = std::make_shared(GetItemEntry{ itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, objectId_, modIndex_, TABLE_RANDOMIZER, static_cast(randomizerGet_), gid_, true, ITEM_FROM_NPC, category_, static_cast(randomizerGet_), MOD_RANDOMIZER, NULL }); } @@ -31,11 +31,10 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, Text article_, - const bool progressive_, - const uint16_t price_) + const std::string color_, const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), article(std::move(article_)), - progressive(progressive_), price(price_) { + color(std::move(color_)), progressive(progressive_), price(price_) { } Item::~Item() = default; @@ -60,6 +59,10 @@ const Text& Item::GetArticle() const { return article; } +const std::string& Item::GetColor() const { + return color; +} + bool Item::IsAdvancement() const { return advancement; } diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index db60e7846..dda2065d3 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -33,10 +33,10 @@ class Item { Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, LogicVal logicVal_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_, uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, - Text article_ = {}, bool progressive_ = false, uint16_t price_ = 0); + Text article_ = {}, std::string color_ = "%g", bool progressive_ = false, uint16_t price_ = 0); Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - LogicVal logicVal_, RandomizerHintTextKey hintKey_, Text article_ = {}, bool progressive_ = false, - uint16_t price_ = 0); + LogicVal logicVal_, RandomizerHintTextKey hintKey_, Text article_ = {}, std::string color_ = "%g", + bool progressive_ = false, uint16_t price_ = 0); ~Item(); void ApplyEffect() const; @@ -45,6 +45,7 @@ class Item { const Text& GetName() const; const Text& GetArticle() const; + const std::string& GetColor() const; bool IsAdvancement() const; int GetItemID() const; ItemType GetItemType() const; @@ -73,6 +74,7 @@ class Item { LogicVal logicVal; RandomizerHintTextKey hintKey; Text article; + std::string color; bool progressive; uint16_t price; bool playthrough = false; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 0e3d132c7..ba1e71d65 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -22,20 +22,20 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegelschild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); - itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); - itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}, "%r"); + itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}, "%b"); itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein des Wissens" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "la "}); - itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrows", "Flèches de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrows", "Flèches de Glace", "Eispfeile" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrows", "Flèches de Lumière", "Lichtpfeile" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%r"); + itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%g"); + itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%b"); + itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrows", "Flèches de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%r"); + itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrows", "Flèches de Glace", "Eispfeile" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%c"); + itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrows", "Flèches de Lumière", "Lichtpfeile" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%y"); itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Pass" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "eine ", "un "}); itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "das ", "le "}); @@ -57,25 +57,25 @@ void Rando::StaticData::InitItemTable() { // Skulltula Token itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE, {"a ", "ein ", "un "}); // Progressive Items - itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, {"a ", "einen ", " un"}, true); - itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, {"a ", "ein ", "une "}, true); - itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, {"a ", "eine ", "un "}, true); - itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, {"a ", "einen ", "un "}, true); - itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, {"a ", "eine ", "un "}, true); - itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, {"a ", "ein ", "un "}, true); - itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, {"a ", "eine ", "une "}, true); - itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, {"a ", "eine ", "une "}, true); - itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, {"a ", "eine ", "un "}, true); - itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, {"a ", "einen ", "un "}, true); - itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, {"a ", "ein ", "un "}, true); - itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, {"a ", "eine ", "un "}, true); - itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, {"a ", "ein ", "une "}, true); + itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, {"a ", "einen ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, {"a ", "ein ", "une "}, "%g", true); + itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, {"a ", "eine ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, {"a ", "einen ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_SLINGSHOT] = Item(RG_PROGRESSIVE_SLINGSHOT, Text{ "Progressive Slingshot", "Lance-Pierre (prog.)", "Progressive Steinschleuder" }, ITEMTYPE_ITEM, 0x84, true, LOGIC_PROGRESSIVE_BULLET_BAG, RHT_PROGRESSIVE_SLINGSHOT, {"a ", "eine ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_WALLET] = Item(RG_PROGRESSIVE_WALLET, Text{ "Progressive Wallet", "Bourse (prog.)", "Progressive Geldbörse" }, ITEMTYPE_ITEM, 0x85, true, LOGIC_PROGRESSIVE_WALLET, RHT_PROGRESSIVE_WALLET, {"a ", "ein ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_SCALE] = Item(RG_PROGRESSIVE_SCALE, Text{ "Progressive Scale", "Écaille (prog.)", "Progressive Schuppe" }, ITEMTYPE_ITEM, 0x86, true, LOGIC_PROGRESSIVE_SCALE, RHT_PROGRESSIVE_SCALE, {"a ", "eine ", "une "}, "%g", true); + itemTable[RG_PROGRESSIVE_NUT_UPGRADE] = Item(RG_PROGRESSIVE_NUT_UPGRADE, Text{ "Progressive Nut Capacity", "Capacité de Noix (prog.)", "Progressive Nuß-Kapazität" }, ITEMTYPE_ITEM, 0x87, true, LOGIC_PROGRESSIVE_NUT_BAG, RHT_PROGRESSIVE_NUT_UPGRADE, {"a ", "eine ", "une "}, "%g", true); + itemTable[RG_PROGRESSIVE_STICK_UPGRADE] = Item(RG_PROGRESSIVE_STICK_UPGRADE, Text{ "Progressive Stick Capacity", "Capacité de Bâtons (prog.)", "Progressive Stab-Kapazität" }, ITEMTYPE_ITEM, 0x88, true, LOGIC_PROGRESSIVE_STICK_BAG, RHT_PROGRESSIVE_STICK_UPGRADE, {"a ", "eine ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_BOMBCHUS] = Item(RG_PROGRESSIVE_BOMBCHUS, Text{ "Progressive Bombchu", "Missiles (prog.)", "Progressive Krabbelminen" }, ITEMTYPE_ITEM, 0x89, true, LOGIC_BOMBCHUS, RHT_PROGRESSIVE_BOMBCHUS, {"a ", "einen ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_MAGIC_METER] = Item(RG_PROGRESSIVE_MAGIC_METER, Text{ "Progressive Magic Meter", "Jauge de Magie (prog.)", "Progressives Magisches Maß" }, ITEMTYPE_ITEM, 0x8A, true, LOGIC_PROGRESSIVE_MAGIC, RHT_PROGRESSIVE_MAGIC_METER, {"a ", "ein ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_OCARINA] = Item(RG_PROGRESSIVE_OCARINA, Text{ "Progressive Ocarina", "Ocarina (prog.)", "Progressive Okarina" }, ITEMTYPE_ITEM, 0x8B, true, LOGIC_PROGRESSIVE_OCARINA, RHT_PROGRESSIVE_OCARINA, {"a ", "eine ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_GORONSWORD] = Item(RG_PROGRESSIVE_GORONSWORD, Text{ "Progressive Goron Sword", "Épée Goron (prog.)", "Progressives Goronen-Schwert" }, ITEMTYPE_ITEM, 0xD4, true, LOGIC_PROGRESSIVE_GIANT_KNIFE, RHT_PROGRESSIVE_GORONSWORD, {"a ", "ein ", "une "}, "%g", true); // Bottles itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"an ", "eine ", "une "}); itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "eine ", "une "}); - itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); - itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); - itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}, "%r"); + itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}, "%g"); + itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}, "%b"); itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); @@ -84,89 +84,89 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER, GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "einen ", "un "}); // Songs - itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Salias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Hymne der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); - itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "la "}); - itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); - itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); - itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); - itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%p"); + itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%y"); + itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Salias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%g"); + itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Hymne der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%y"); + itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "la "}, "%c"); + itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%b"); + itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%g"); + itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}, "%r"); + itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}, "%b"); + itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}, "%p"); + itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); + itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); // Maps and Compasses - itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", " die ", "la "}); + itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", " die ", "la "}, "%g"); itemTable[RG_DEKU_TREE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%r"); itemTable[RG_DODONGOS_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%b"); itemTable[RG_JABU_JABUS_BELLY_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%g"); itemTable[RG_FOREST_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%r"); itemTable[RG_FIRE_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%b"); itemTable[RG_WATER_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%p"); itemTable[RG_SHADOW_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%p"); itemTable[RG_BOTTOM_OF_THE_WELL_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%c"); itemTable[RG_ICE_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%b"); itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%b"); itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%c"); itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys - itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); itemTable[RG_FIRE_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%b"); itemTable[RG_WATER_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); itemTable[RG_SHADOW_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); itemTable[RG_GANONS_CASTLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%g"); itemTable[RG_FOREST_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%r"); itemTable[RG_FIRE_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%b"); itemTable[RG_WATER_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%p"); itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%p"); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%r"); itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE, {"a ", "einen ", "une "}); itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); @@ -218,44 +218,44 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FISHING_HOLE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); // Key Rings - itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%g"); itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%r"); itemTable[RG_FIRE_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%b"); itemTable[RG_WATER_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%p"); itemTable[RG_SHADOW_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%p"); itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%r"); itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_TREASURE_GAME_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); // Dungeon Rewards - itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); - itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); - itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", " le"}); - itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}, "%g"); + itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}, "%r"); + itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", " le"}, "%b"); + itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%g"); + itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%r"); + itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%b"); + itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); + itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%p"); + itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); // Generic Items itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "ein ", "un "}); itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüner Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, LOGIC_GREG, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); - itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); - itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); - itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%b"); + itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%r"); + itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%p"); + itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}, "%y"); itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "ein ", "un "}); itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herzcontainer" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, LOGIC_NONE, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); @@ -276,61 +276,61 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, LOGIC_NONE, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, LOGIC_NONE, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stab (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "einen ", "un "}); - itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); - itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); - itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%r"); + itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%g"); + itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%b"); // Treasure Game itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüner Rubin (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüner Rubin (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%g"); // Shop - itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuß kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 15); - itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 60); - itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 90); - itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 25); - itemTable[RG_BUY_DEKU_NUTS_10] = Item(RG_BUY_DEKU_NUTS_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuß kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, LOGIC_NUTS, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); - itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stab kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, LOGIC_STICKS, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 10); - itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, LOGIC_BUY_BOMB, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 50); - itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, LOGIC_FISH_ACCESS, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 200); - itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); - itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); - itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 100); - itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylia-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {}, false, 80); - itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {}, false, 40); - itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {}, false, 200); - itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {}, false, 300); - itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 10); - itemTable[RG_BUY_BOMBCHUS_10] = Item(RG_BUY_BOMBCHUS_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Krabbelminen kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 99); - itemTable[RG_BUY_BOMBCHUS_20] = Item(RG_BUY_BOMBCHUS_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Krabbelminen kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 180); - itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, LOGIC_BUY_SEED, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); - itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, {}, false, 0); - itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, LOGIC_BLUE_FIRE_ACCESS, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 300); - itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, LOGIC_BUGS_ACCESS, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 50); - itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, LOGIC_NONE, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 30); - itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, LOGIC_FAIRY_ACCESS, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 50); - itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, LOGIC_BUY_ARROW, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 20); - itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 80); - itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 120); - itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 35); - itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 40); - itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, false, 50); + itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuß kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 15); + itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 60); + itemTable[RG_BUY_ARROWS_50] = Item(RG_BUY_ARROWS_50, Text{ "Buy Arrows (50)", "Acheter: Flèches (50)", "Pfeile kaufen (50)" }, ITEMTYPE_SHOP, GI_ARROWS_LARGE, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_LARGE, OBJECT_GI_ARROW, GID_ARROWS_LARGE, 0xE6, 0x4A, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 90); + itemTable[RG_BUY_BOMBS_525] = Item(RG_BUY_BOMBS_525, Text{ "Buy Bombs (5) [25]", "Acheter: Bombes (5) [25]", "Bomben kaufen (5) [25]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 25); + itemTable[RG_BUY_DEKU_NUTS_10] = Item(RG_BUY_DEKU_NUTS_10, Text{ "Buy Deku Nut (10)", "Acheter: Noix Mojo (10)", "Deku-Nuß kaufen (10)" }, ITEMTYPE_SHOP, GI_NUTS_10, true, LOGIC_NUTS, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 30); + itemTable[RG_BUY_DEKU_STICK_1] = Item(RG_BUY_DEKU_STICK_1, Text{ "Buy Deku Stick (1)", "Acheter: Bâton Mojo (1)", "Deku-Stab kaufen (1)" }, ITEMTYPE_SHOP, GI_STICKS_1, true, LOGIC_STICKS, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 10); + itemTable[RG_BUY_BOMBS_10] = Item(RG_BUY_BOMBS_10, Text{ "Buy Bombs (10)", "Acheter: Bombes (10)", "Bomben kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBS_10, true, LOGIC_BUY_BOMB, RHT_BOMBS_10, ITEM_BOMBS_10, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 50); + itemTable[RG_BUY_FISH] = Item(RG_BUY_FISH, Text{ "Buy Fish", "Acheter: Poisson", "Fisch kaufen" }, ITEMTYPE_SHOP, GI_FISH, true, LOGIC_FISH_ACCESS, RHT_BOTTLE_WITH_FISH, ITEM_FISH, OBJECT_GI_FISH, GID_FISH, 0x47, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 200); + itemTable[RG_BUY_RED_POTION_30] = Item(RG_BUY_RED_POTION_30, Text{ "Buy Red Potion [30]", "Acheter: Potion Rouge [30]", "Rotes Elixier kaufen [30]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 30); + itemTable[RG_BUY_GREEN_POTION] = Item(RG_BUY_GREEN_POTION, Text{ "Buy Green Potion", "Acheter: Potion Verte", "Grünes Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_GREEN, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 30); + itemTable[RG_BUY_BLUE_POTION] = Item(RG_BUY_BLUE_POTION, Text{ "Buy Blue Potion", "Acheter: Potion Bleue", "Blaues Elixier kaufen" }, ITEMTYPE_SHOP, GI_POTION_BLUE, true, LOGIC_BUY_MAGIC_POTION, RHT_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 100); + itemTable[RG_BUY_HYLIAN_SHIELD] = Item(RG_BUY_HYLIAN_SHIELD, Text{ "Buy Hylian Shield", "Acheter: Bouclier Hylien", "Hylia-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_HYLIAN, true, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {}, "%g", false, 80); + itemTable[RG_BUY_DEKU_SHIELD] = Item(RG_BUY_DEKU_SHIELD, Text{ "Buy Deku Shield", "Acheter: Bouclier Mojo", "Deku-Schild kaufen" }, ITEMTYPE_SHOP, GI_SHIELD_DEKU, true, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {}, "%g", false, 40); + itemTable[RG_BUY_GORON_TUNIC] = Item(RG_BUY_GORON_TUNIC, Text{ "Buy Goron Tunic", "Acheter: Tunique Goron", "Goronen-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {}, "%g", false, 200); + itemTable[RG_BUY_ZORA_TUNIC] = Item(RG_BUY_ZORA_TUNIC, Text{ "Buy Zora Tunic", "Acheter: Tunique Zora", "Zora-Tunika kaufen" }, ITEMTYPE_SHOP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {}, "%g", false, 300); + itemTable[RG_BUY_HEART] = Item(RG_BUY_HEART, Text{ "Buy Heart", "Acheter: Coeur de Vie", "Herz kaufen" }, ITEMTYPE_SHOP, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 10); + itemTable[RG_BUY_BOMBCHUS_10] = Item(RG_BUY_BOMBCHUS_10, Text{ "Buy Bombchu (10)", "Acheter: Missiles (10)", "Krabbelminen kaufen (10)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_10, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_10, ITEM_BOMBCHU, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 99); + itemTable[RG_BUY_BOMBCHUS_20] = Item(RG_BUY_BOMBCHUS_20, Text{ "Buy Bombchu (20)", "Acheter: Missiles (20)", "Krabbelminen kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBCHUS_20, true, LOGIC_BUY_BOMBCHUS, RHT_BOMBCHUS_20, ITEM_BOMBCHUS_20, OBJECT_GI_BOMB_2, GID_BOMBCHU, 0x33, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 180); + itemTable[RG_BUY_DEKU_SEEDS_30] = Item(RG_BUY_DEKU_SEEDS_30, Text{ "Buy Deku Seeds (30)", "Acheter: Graines Mojo (30)", "Deku-Samen kaufen (30)" }, ITEMTYPE_SHOP, GI_SEEDS_30, true, LOGIC_BUY_SEED, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 30); + itemTable[RG_SOLD_OUT] = Item(RG_SOLD_OUT, Text{ "Sold Out", "Rupture de stock", "Ausverkauft" }, ITEMTYPE_SHOP, RG_SOLD_OUT, false, LOGIC_NONE, RHT_NONE, {}, "%g", false, 0); + itemTable[RG_BUY_BLUE_FIRE] = Item(RG_BUY_BLUE_FIRE, Text{ "Buy Blue Fire", "Acheter: Flamme Bleue", "Blaues Feuer kaufen" }, ITEMTYPE_SHOP, GI_BLUE_FIRE, true, LOGIC_BLUE_FIRE_ACCESS, RHT_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, 0x5D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 300); + itemTable[RG_BUY_BOTTLE_BUG] = Item(RG_BUY_BOTTLE_BUG, Text{ "Buy Bottle Bug", "Acheter: Insecte en bouteille", "Flaschenkäfer kaufen" }, ITEMTYPE_SHOP, GI_BUGS, true, LOGIC_BUGS_ACCESS, RHT_BOTTLE_WITH_BUGS, ITEM_BUG, OBJECT_GI_INSECT, GID_BUG, 0x7A, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 50); + itemTable[RG_BUY_POE] = Item(RG_BUY_POE, Text{ "Buy Poe", "Acheter: Esprit", "Geist kaufen" }, ITEMTYPE_SHOP, RG_BUY_POE, false, LOGIC_NONE, RHT_BOTTLE_WITH_BIG_POE, ITEM_POE, OBJECT_GI_GHOST, GID_POE, 0x97, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 30); + itemTable[RG_BUY_FAIRYS_SPIRIT] = Item(RG_BUY_FAIRYS_SPIRIT, Text{ "Buy Fairy's Spirit", "Acheter: Esprit de Fée", "Feengeist kaufen" }, ITEMTYPE_SHOP, GI_FAIRY, true, LOGIC_FAIRY_ACCESS, RHT_BOTTLE_WITH_FAIRY, ITEM_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x46, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 50); + itemTable[RG_BUY_ARROWS_10] = Item(RG_BUY_ARROWS_10, Text{ "Buy Arrows (10)", "Acheter: Flèches (10)", "Pfeile kaufen (10)" }, ITEMTYPE_SHOP, GI_ARROWS_SMALL, true, LOGIC_BUY_ARROW, RHT_ARROWS_10, ITEM_ARROWS_SMALL, OBJECT_GI_ARROW, GID_ARROWS_SMALL, 0xE6, 0x48, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 20); + itemTable[RG_BUY_BOMBS_20] = Item(RG_BUY_BOMBS_20, Text{ "Buy Bombs (20)", "Acheter: Bombes (20)", "Bomben kaufen (20)" }, ITEMTYPE_SHOP, GI_BOMBS_20, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_20, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 80); + itemTable[RG_BUY_BOMBS_30] = Item(RG_BUY_BOMBS_30, Text{ "Buy Bombs (30)", "Acheter: Bombes (30)", "Bomben kaufen (30)" }, ITEMTYPE_SHOP, GI_BOMBS_30, true, LOGIC_BUY_BOMB, RHT_BOMBS_20, ITEM_BOMBS_30, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 120); + itemTable[RG_BUY_BOMBS_535] = Item(RG_BUY_BOMBS_535, Text{ "Buy Bombs (5) [35]", "Acheter: Bombes (5) [35]", "Bomben kaufen (5) [35]" }, ITEMTYPE_SHOP, GI_BOMBS_5, true, LOGIC_BUY_BOMB, RHT_BOMBS_5, ITEM_BOMBS_5, OBJECT_GI_BOMB_1, GID_BOMB, 0x32, 0x59, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 35); + itemTable[RG_BUY_RED_POTION_40] = Item(RG_BUY_RED_POTION_40, Text{ "Buy Red Potion [40]", "Acheter: Potion Rouge [40]", "Rotes Elixier kaufen [40]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 40); + itemTable[RG_BUY_RED_POTION_50] = Item(RG_BUY_RED_POTION_50, Text{ "Buy Red Potion [50]", "Acheter: Potion Rouge [50]", "Rotes Elixier kaufen [50]" }, ITEMTYPE_SHOP, GI_POTION_RED, false, LOGIC_NONE, RHT_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 50); // Misc. - itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "Âme de Gohma", "Gohmas Seele" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_CAN_SUMMON_GOHMA, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GOHMA_SOUL] = Item(RG_GOHMA_SOUL, Text{ "Gohma's Soul", "Âme de Gohma", "Gohmas Seele" }, ITEMTYPE_ITEM, 0xE0, true, LOGIC_CAN_SUMMON_GOHMA, RHT_GOHMA_SOUL, RG_GOHMA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%g"); itemTable[RG_GOHMA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_KING_DODONGO_SOUL] = Item(RG_KING_DODONGO_SOUL, Text{ "King Dodongo's Soul", "Âme du Roi Dodongo", "König Dodongos Seele" }, ITEMTYPE_ITEM, 0xE1, true, LOGIC_CAN_SUMMON_KINGDODONGO, RHT_KING_DODONGO_SOUL, RG_KING_DODONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_KING_DODONGO_SOUL] = Item(RG_KING_DODONGO_SOUL, Text{ "King Dodongo's Soul", "Âme du Roi Dodongo", "König Dodongos Seele" }, ITEMTYPE_ITEM, 0xE1, true, LOGIC_CAN_SUMMON_KINGDODONGO, RHT_KING_DODONGO_SOUL, RG_KING_DODONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%r"); itemTable[RG_KING_DODONGO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_BARINADE_SOUL] = Item(RG_BARINADE_SOUL, Text{ "Barinade's Soul", "Âme de Barinade", "Barinades Seele" }, ITEMTYPE_ITEM, 0xE2, true, LOGIC_CAN_SUMMON_BARINADE, RHT_BARINADE_SOUL, RG_BARINADE_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BARINADE_SOUL] = Item(RG_BARINADE_SOUL, Text{ "Barinade's Soul", "Âme de Barinade", "Barinades Seele" }, ITEMTYPE_ITEM, 0xE2, true, LOGIC_CAN_SUMMON_BARINADE, RHT_BARINADE_SOUL, RG_BARINADE_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%b"); itemTable[RG_BARINADE_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_PHANTOM_GANON_SOUL] = Item(RG_PHANTOM_GANON_SOUL, Text{ "Phantom Ganon's Soul", "Âme de Ganon Spectral", "Phantom-Ganons Seele" }, ITEMTYPE_ITEM, 0xE3, true, LOGIC_CAN_SUMMON_PHANTOMGANON, RHT_PHANTOM_GANON_SOUL, RG_PHANTOM_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_PHANTOM_GANON_SOUL] = Item(RG_PHANTOM_GANON_SOUL, Text{ "Phantom Ganon's Soul", "Âme de Ganon Spectral", "Phantom-Ganons Seele" }, ITEMTYPE_ITEM, 0xE3, true, LOGIC_CAN_SUMMON_PHANTOMGANON, RHT_PHANTOM_GANON_SOUL, RG_PHANTOM_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%g"); itemTable[RG_PHANTOM_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_VOLVAGIA_SOUL] = Item(RG_VOLVAGIA_SOUL, Text{ "Volvagia's Soul", "Âme de Vulcania", "Volvagias Seele" }, ITEMTYPE_ITEM, 0xE4, true, LOGIC_CAN_SUMMON_VOLVAGIA, RHT_VOLVAGIA_SOUL, RG_VOLVAGIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_VOLVAGIA_SOUL] = Item(RG_VOLVAGIA_SOUL, Text{ "Volvagia's Soul", "Âme de Vulcania", "Volvagias Seele" }, ITEMTYPE_ITEM, 0xE4, true, LOGIC_CAN_SUMMON_VOLVAGIA, RHT_VOLVAGIA_SOUL, RG_VOLVAGIA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%r"); itemTable[RG_VOLVAGIA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_MORPHA_SOUL] = Item(RG_MORPHA_SOUL, Text{ "Morpha's Soul", "Âme de Morpha", "Morphas Seele" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_MORPHA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_MORPHA_SOUL] = Item(RG_MORPHA_SOUL, Text{ "Morpha's Soul", "Âme de Morpha", "Morphas Seele" }, ITEMTYPE_ITEM, 0xE5, true, LOGIC_CAN_SUMMON_MORPHA, RHT_MORPHA_SOUL, RG_MORPHA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%b"); itemTable[RG_MORPHA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_BONGO_BONGO_SOUL] = Item(RG_BONGO_BONGO_SOUL, Text{ "Bongo Bongo's Soul", "Âme de Bongo Bongo", "Bongo Bongos Seele" }, ITEMTYPE_ITEM, 0xE6, true, LOGIC_CAN_SUMMON_BONGOBONGO, RHT_BONGO_BONGO_SOUL, RG_BONGO_BONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_BONGO_BONGO_SOUL] = Item(RG_BONGO_BONGO_SOUL, Text{ "Bongo Bongo's Soul", "Âme de Bongo Bongo", "Bongo Bongos Seele" }, ITEMTYPE_ITEM, 0xE6, true, LOGIC_CAN_SUMMON_BONGOBONGO, RHT_BONGO_BONGO_SOUL, RG_BONGO_BONGO_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%p"); itemTable[RG_BONGO_BONGO_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_TWINROVA_SOUL] = Item(RG_TWINROVA_SOUL, Text{ "Twinrova's Soul", "Âme du Duo Maléfique", "Twinrovas Seele" }, ITEMTYPE_ITEM, 0xE7, true, LOGIC_CAN_SUMMON_TWINROVA, RHT_TWINROVA_SOUL, RG_TWINROVA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_TWINROVA_SOUL] = Item(RG_TWINROVA_SOUL, Text{ "Twinrova's Soul", "Âme du Duo Maléfique", "Twinrovas Seele" }, ITEMTYPE_ITEM, 0xE7, true, LOGIC_CAN_SUMMON_TWINROVA, RHT_TWINROVA_SOUL, RG_TWINROVA_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%y"); itemTable[RG_TWINROVA_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); - itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "Âme de Ganon", "Ganons Seele" }, ITEMTYPE_ITEM, 0xE8, true, LOGIC_CAN_SUMMON_GANON, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); + itemTable[RG_GANON_SOUL] = Item(RG_GANON_SOUL, Text{ "Ganon's Soul", "Âme de Ganon", "Ganons Seele" }, ITEMTYPE_ITEM, 0xE8, true, LOGIC_CAN_SUMMON_GANON, RHT_GANON_SOUL, RG_GANON_SOUL, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {}, "%r"); itemTable[RG_GANON_SOUL].SetCustomDrawFunc(Randomizer_DrawBossSoul); itemTable[RG_FISHING_POLE] = Item(RG_FISHING_POLE, Text{ "Fishing Pole", "Canne à Pêche", "Angelrute" }, ITEMTYPE_ITEM, RG_FISHING_POLE, true, LOGIC_FISHING_POLE, RHT_FISHING_POLE, RG_FISHING_POLE, OBJECT_GI_FISH, GID_FISHING_POLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "das ", "le "}); itemTable[RG_FISHING_POLE].SetCustomDrawFunc(Randomizer_DrawFishingPoleGI); From 31f9b659afb37223193f3750b917438730f45f95 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 12 Mar 2025 20:52:47 -0400 Subject: [PATCH 051/103] Clean up now unused skulltula hint storage --- .../Enhancements/randomizer/3drando/hint_list.cpp | 5 ----- soh/soh/Enhancements/randomizer/randomizerTypes.h | 7 ------- soh/soh/Enhancements/randomizer/static_data.cpp | 12 ------------ 3 files changed, 24 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp index 3081d4863..ef4abede5 100644 --- a/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp +++ b/soh/soh/Enhancements/randomizer/3drando/hint_list.cpp @@ -2323,11 +2323,6 @@ void StaticData::HintTable_Init() { hintTextTable[RHT_OOT_HINT] = HintText(CustomMessage("Bring the #Spiritual Stones# to the past so you can receive #[[1]]# from Zelda and learn #[[2]]#!", {QM_BLUE, QM_GREEN, QM_GREEN})); - hintTextTable[RHT_SKULLS_HINT] = HintText(CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying #[[d]] Spiders of the Curse# and I will give you my #[[1]]#!", - /*german*/ "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du #[[d]] Skulltulas# zerstörst und ich werde Dir dafür #[[1]]# geben!", - /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore #[[d]] Araignées de la Malédiction# et j'aurai quelque chose à te donner! #([[1]])#", - {QM_YELLOW, QM_GREEN})); - hintTextTable[RHT_MASK_SHOP_HINT] = HintText(CustomMessage("Some young scrubs in the #Deku Theatre# love seeing Masks!^" "They'll give you #[[1]]# if you show them the #Skull Mask#, and #[[2]]# if you show them the #Mask of Truth#!", {QM_GREEN, QM_GREEN, QM_RED, QM_GREEN, QM_RED})); diff --git a/soh/soh/Enhancements/randomizer/randomizerTypes.h b/soh/soh/Enhancements/randomizer/randomizerTypes.h index 23cbb290f..c99458758 100644 --- a/soh/soh/Enhancements/randomizer/randomizerTypes.h +++ b/soh/soh/Enhancements/randomizer/randomizerTypes.h @@ -3467,12 +3467,6 @@ typedef enum { RH_BIGGORON_HINT, RH_FROGS_HINT, RH_OOT_HINT, - RH_KAK_10_SKULLS_HINT, - RH_KAK_20_SKULLS_HINT, - RH_KAK_30_SKULLS_HINT, - RH_KAK_40_SKULLS_HINT, - RH_KAK_50_SKULLS_HINT, - RH_KAK_100_SKULLS_HINT, RH_MASK_SHOP_HINT, RH_MAX, } RandomizerHint; @@ -4740,7 +4734,6 @@ typedef enum { RHT_BIGGORON_HINT, RHT_FROGS_HINT, RHT_OOT_HINT, - RHT_SKULLS_HINT, RHT_MASK_SHOP_HINT, // Shuffle Pots RHT_POT_KOKIRI_FOREST, diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index 84da0d3c1..c3c2e4aa0 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -85,12 +85,6 @@ std::unordered_map StaticData::hintNames = { {RH_BIGGORON_HINT, CustomMessage("Biggoron Claim Check Hint")}, {RH_FROGS_HINT, CustomMessage("Final Frogs in River Hint")}, {RH_OOT_HINT, CustomMessage("Sheik in Temple of Time Hint")}, - {RH_KAK_10_SKULLS_HINT, CustomMessage("10 Skulls Hint")}, - {RH_KAK_20_SKULLS_HINT, CustomMessage("20 Skulls Hint")}, - {RH_KAK_30_SKULLS_HINT, CustomMessage("30 Skulls Hint")}, - {RH_KAK_40_SKULLS_HINT, CustomMessage("40 Skulls Hint")}, - {RH_KAK_50_SKULLS_HINT, CustomMessage("50 Skulls Hint")}, - {RH_KAK_100_SKULLS_HINT, CustomMessage("100 Skulls Hint")}, {RH_MASK_SHOP_HINT, CustomMessage("Mask Shop Hint")}, }; @@ -204,12 +198,6 @@ std::unordered_map StaticData::staticHintInfoMap {RH_BIGGORON_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_BIGGORON_HINT}, RSK_BIGGORON_HINT, true, {RC_DMT_TRADE_CLAIM_CHECK})}, {RH_FROGS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_FROGS_HINT}, RSK_FROGS_HINT, true, {RC_ZR_FROGS_OCARINA_GAME})}, {RH_OOT_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_OOT_HINT}, RSK_OOT_HINT, true, {RC_HF_OCARINA_OF_TIME_ITEM, RC_SONG_FROM_OCARINA_OF_TIME}, {}, {RC_TOT_SHEIK_HINT})}, - {RH_KAK_10_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_10_SKULLS_HINT, true, {RC_KAK_10_GOLD_SKULLTULA_REWARD}, {}, {}, false, 10)}, - {RH_KAK_20_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_20_SKULLS_HINT, true, {RC_KAK_20_GOLD_SKULLTULA_REWARD}, {}, {}, false, 20)}, - {RH_KAK_30_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_30_SKULLS_HINT, true, {RC_KAK_30_GOLD_SKULLTULA_REWARD}, {}, {}, false, 30)}, - {RH_KAK_40_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_40_SKULLS_HINT, true, {RC_KAK_40_GOLD_SKULLTULA_REWARD}, {}, {}, false, 40)}, - {RH_KAK_50_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_50_SKULLS_HINT, true, {RC_KAK_50_GOLD_SKULLTULA_REWARD}, {}, {}, false, 50)}, - {RH_KAK_100_SKULLS_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_SKULLS_HINT}, RSK_KAK_100_SKULLS_HINT, true, {RC_KAK_100_GOLD_SKULLTULA_REWARD}, {}, {}, false, 100)}, {RH_MASK_SHOP_HINT, StaticHintInfo(HINT_TYPE_ITEM, {RHT_MASK_SHOP_HINT}, RSK_MASK_SHOP_HINT, true, {RC_DEKU_THEATER_SKULL_MASK, RC_DEKU_THEATER_MASK_OF_TRUTH}, {}, {RC_MASK_SHOP_HINT})} }; From 43b3c615a52c8591aad27de1bf78293535ee7bad Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Mon, 24 Mar 2025 21:20:26 -0400 Subject: [PATCH 052/103] Fix rebase conflicts and port Skulltula Freeze fix --- soh/soh/Enhancements/NoSkulltulaFreeze.cpp | 29 +++ .../randomizer/ColoredMapsAndCompasses.cpp | 1 + soh/soh/Enhancements/randomizer/item_list.cpp | 182 +++++++++--------- 3 files changed, 116 insertions(+), 96 deletions(-) create mode 100644 soh/soh/Enhancements/NoSkulltulaFreeze.cpp diff --git a/soh/soh/Enhancements/NoSkulltulaFreeze.cpp b/soh/soh/Enhancements/NoSkulltulaFreeze.cpp new file mode 100644 index 000000000..ee30cd674 --- /dev/null +++ b/soh/soh/Enhancements/NoSkulltulaFreeze.cpp @@ -0,0 +1,29 @@ +#include + +extern "C" { + #include "variables.h" +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) + +void AutoDismissSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_TOKENS).IsNot(RO_TOKENSANITY_OFF)) { + *loadFromMessageTable = true; + return; + } + *loadFromMessageTable = false; + CustomMessage msg = CustomMessage::LoadVanillaMessageTableEntry(TEXT_GS_FREEZE); + msg.Replace(CustomMessage::MESSAGE_END(), "\x0E\x3C"); + msg += CustomMessage::MESSAGE_END(); + msg.LoadIntoFont(); +} + +void NoSkulltulaFreeze_Register() { + COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) == 0, AutoDismissSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) == 0, AutoDismissSkulltulaMessage); +} + + +static RegisterShipInitFunc initFunc(NoSkulltulaFreeze_Register, { + CVAR_ENHANCEMENT("SkulltulaFreeze") +}); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/ColoredMapsAndCompasses.cpp b/soh/soh/Enhancements/randomizer/ColoredMapsAndCompasses.cpp index fcfa13d97..a6846b29b 100644 --- a/soh/soh/Enhancements/randomizer/ColoredMapsAndCompasses.cpp +++ b/soh/soh/Enhancements/randomizer/ColoredMapsAndCompasses.cpp @@ -5,6 +5,7 @@ #include "z64save.h" #include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_map/object_gi_map.h" +#include "soh/OTRGlobals.h" extern "C" { extern SaveContext gSaveContext; diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index ba1e71d65..5dd91356f 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -22,20 +22,20 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_SHIELD] = Item(RG_DEKU_SHIELD, Text{ "Deku Shield", "Bouclier Mojo", "Deku-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_DEKU, false, LOGIC_DEKU_SHIELD, RHT_DEKU_SHIELD, ITEM_SHIELD_DEKU, OBJECT_GI_SHIELD_1, GID_SHIELD_DEKU, 0x4C, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_HYLIAN_SHIELD] = Item(RG_HYLIAN_SHIELD, Text{ "Hylian Shield", "Bouclier Hylien", "Hylia-Schild" }, ITEMTYPE_EQUIP, GI_SHIELD_HYLIAN, false, LOGIC_HYLIAN_SHIELD, RHT_HYLIAN_SHIELD, ITEM_SHIELD_HYLIAN, OBJECT_GI_SHIELD_2, GID_SHIELD_HYLIAN, 0x4D, 0xA0, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_MIRROR_SHIELD] = Item(RG_MIRROR_SHIELD, Text{ "Mirror Shield", "Bouclier Miroir", "Spiegelschild" }, ITEMTYPE_EQUIP, GI_SHIELD_MIRROR, true, LOGIC_MIRROR_SHIELD, RHT_MIRROR_SHIELD, ITEM_SHIELD_MIRROR, OBJECT_GI_SHIELD_3, GID_SHIELD_MIRROR, 0x4E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); - itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}, "%r"); - itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}, "%b"); + itemTable[RG_GORON_TUNIC] = Item(RG_GORON_TUNIC, Text{ "Goron Tunic", "Tunique Goron", "Goronen-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_GORON, true, LOGIC_GORON_TUNIC, RHT_GORON_TUNIC, ITEM_TUNIC_GORON, OBJECT_GI_CLOTHES, GID_TUNIC_GORON, 0x50, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_ZORA_TUNIC] = Item(RG_ZORA_TUNIC, Text{ "Zora Tunic", "Tunique Zora", "Zora-Tunika" }, ITEMTYPE_EQUIP, GI_TUNIC_ZORA, true, LOGIC_ZORA_TUNIC, RHT_ZORA_TUNIC, ITEM_TUNIC_ZORA, OBJECT_GI_CLOTHES, GID_TUNIC_ZORA, 0x51, 0xA0, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); itemTable[RG_IRON_BOOTS] = Item(RG_IRON_BOOTS, Text{ "Iron Boots", "Bottes de plomb", "Eisenstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_IRON, true, LOGIC_IRON_BOOTS, RHT_IRON_BOOTS, ITEM_BOOTS_IRON, OBJECT_GI_BOOTS_2, GID_BOOTS_IRON, 0x53, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); itemTable[RG_HOVER_BOOTS] = Item(RG_HOVER_BOOTS, Text{ "Hover Boots", "Bottes de airs", "Gleitstiefel" }, ITEMTYPE_EQUIP, GI_BOOTS_HOVER, true, LOGIC_HOVER_BOOTS, RHT_HOVER_BOOTS, ITEM_BOOTS_HOVER, OBJECT_GI_HOVERBOOTS, GID_BOOTS_HOVER, 0x54, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "les "}); itemTable[RG_BOOMERANG] = Item(RG_BOOMERANG, Text{ "Boomerang", "Boomerang", "Bumerang" }, ITEMTYPE_ITEM, GI_BOOMERANG, true, LOGIC_BOOMERANG, RHT_BOOMERANG, ITEM_BOOMERANG, OBJECT_GI_BOOMERANG, GID_BOOMERANG, 0x35, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); itemTable[RG_LENS_OF_TRUTH] = Item(RG_LENS_OF_TRUTH, Text{ "Lens of Truth", "Monocle de Vérité", "Auge der Wahrheit" }, ITEMTYPE_ITEM, GI_LENS, true, LOGIC_LENS_OF_TRUTH, RHT_LENS_OF_TRUTH, ITEM_LENS, OBJECT_GI_GLASSES, GID_LENS, 0x39, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); itemTable[RG_MEGATON_HAMMER] = Item(RG_MEGATON_HAMMER, Text{ "Megaton Hammer", "Masse des Titans", "Stahlhammer" }, ITEMTYPE_ITEM, GI_HAMMER, true, LOGIC_HAMMER, RHT_MEGATON_HAMMER, ITEM_HAMMER, OBJECT_GI_HAMMER, GID_HAMMER, 0x38, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); itemTable[RG_STONE_OF_AGONY] = Item(RG_STONE_OF_AGONY, Text{ "Stone of Agony", "Pierre de Souffrance", "Stein des Wissens" }, ITEMTYPE_ITEM, GI_STONE_OF_AGONY, true, LOGIC_STONE_OF_AGONY, RHT_STONE_OF_AGONY, ITEM_STONE_OF_AGONY, OBJECT_GI_MAP, GID_STONE_OF_AGONY, 0x68, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "la "}); - itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%r"); - itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%g"); - itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%b"); - itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrows", "Flèches de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%r"); - itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrows", "Flèches de Glace", "Eispfeile" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%c"); - itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrows", "Flèches de Lumière", "Lichtpfeile" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%y"); + itemTable[RG_DINS_FIRE] = Item(RG_DINS_FIRE, Text{ "Din's Fire", "Feu de Din", "Dins Feuerinferno" }, ITEMTYPE_ITEM, GI_DINS_FIRE, true, LOGIC_DINS_FIRE, RHT_DINS_FIRE, ITEM_DINS_FIRE, OBJECT_GI_GODDESS, GID_DINS_FIRE, 0xAD, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FARORES_WIND] = Item(RG_FARORES_WIND, Text{ "Farore's Wind", "Vent de Farore", "Farores Donnersturm" }, ITEMTYPE_ITEM, GI_FARORES_WIND, true, LOGIC_FARORES_WIND, RHT_FARORES_WIND, ITEM_FARORES_WIND, OBJECT_GI_GODDESS, GID_FARORES_WIND, 0xAE, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_NAYRUS_LOVE] = Item(RG_NAYRUS_LOVE, Text{ "Nayru's Love", "Amour de Nayru", "Nayrus Umarmung" }, ITEMTYPE_ITEM, GI_NAYRUS_LOVE, true, LOGIC_NAYRUS_LOVE, RHT_NAYRUS_LOVE, ITEM_NAYRUS_LOVE, OBJECT_GI_GODDESS, GID_NAYRUS_LOVE, 0xAF, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_FIRE_ARROWS] = Item(RG_FIRE_ARROWS, Text{ "Fire Arrows", "Flèches de Feu", "Feuerpfeile" }, ITEMTYPE_ITEM, GI_ARROW_FIRE, true, LOGIC_FIRE_ARROWS, RHT_FIRE_ARROWS, ITEM_ARROW_FIRE, OBJECT_GI_M_ARROW, GID_ARROW_FIRE, 0x70, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_ICE_ARROWS] = Item(RG_ICE_ARROWS, Text{ "Ice Arrows", "Flèches de Glace", "Eispfeile" }, ITEMTYPE_ITEM, GI_ARROW_ICE, true, LOGIC_ICE_ARROWS, RHT_ICE_ARROWS, ITEM_ARROW_ICE, OBJECT_GI_M_ARROW, GID_ARROW_ICE, 0x71, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_LIGHT_ARROWS] = Item(RG_LIGHT_ARROWS, Text{ "Light Arrows", "Flèches de Lumière", "Lichtpfeile" }, ITEMTYPE_ITEM, GI_ARROW_LIGHT, true, LOGIC_LIGHT_ARROWS, RHT_LIGHT_ARROWS, ITEM_ARROW_LIGHT, OBJECT_GI_M_ARROW, GID_ARROW_LIGHT, 0x72, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); itemTable[RG_GERUDO_MEMBERSHIP_CARD] = Item(RG_GERUDO_MEMBERSHIP_CARD, Text{ "Gerudo Membership Card", "Carte Gerudo", "Gerudo-Pass" }, ITEMTYPE_ITEM, GI_GERUDO_CARD, true, LOGIC_GERUDO_CARD, RHT_GERUDO_MEMBERSHIP_CARD, ITEM_GERUDO_CARD, OBJECT_GI_GERUDO, GID_GERUDO_CARD, 0x7B, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); itemTable[RG_MAGIC_BEAN] = Item(RG_MAGIC_BEAN, Text{ "Magic Bean", "Haricots Magiques", "Wundererbse" }, ITEMTYPE_ITEM, GI_BEAN, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN, ITEM_BEAN, OBJECT_GI_BEAN, GID_BEAN, 0x48, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "eine ", "un "}); itemTable[RG_MAGIC_BEAN_PACK] = Item(RG_MAGIC_BEAN_PACK, Text{ "Magic Bean Pack", "Paquet de Haricots Magiques", "Wundererbsen-Packung" }, ITEMTYPE_ITEM, RG_MAGIC_BEAN_PACK, true, LOGIC_MAGIC_BEAN, RHT_MAGIC_BEAN_PACK, RG_MAGIC_BEAN_PACK, OBJECT_GI_BEAN, GID_BEAN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "das ", "le "}); @@ -57,7 +57,7 @@ void Rando::StaticData::InitItemTable() { // Skulltula Token itemTable[RG_GOLD_SKULLTULA_TOKEN] = Item(RG_GOLD_SKULLTULA_TOKEN, Text{ "Gold Skulltula Token", "Symbole de Skulltula d'Or", "Goldenes Skulltula-Symbol" }, ITEMTYPE_TOKEN, GI_SKULL_TOKEN, true, LOGIC_GOLD_SKULLTULA_TOKENS, RHT_GOLD_SKULLTULA_TOKEN, ITEM_SKULL_TOKEN, OBJECT_GI_SUTARU, GID_SKULL_TOKEN, 0xB4, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SKULLTULA_TOKEN, MOD_NONE, {"a ", "ein ", "un "}); // Progressive Items - itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, {"a ", "einen ", "un "}, "%g", true); + itemTable[RG_PROGRESSIVE_HOOKSHOT] = Item(RG_PROGRESSIVE_HOOKSHOT, Text{ "Progressive Hookshot", "Grappin (prog.)", "Progressiver Fanghaken" }, ITEMTYPE_ITEM, 0x80, true, LOGIC_PROGRESSIVE_HOOKSHOT, RHT_PROGRESSIVE_HOOKSHOT, {"a ", "einen ", " un"}, "%g", true); itemTable[RG_PROGRESSIVE_STRENGTH] = Item(RG_PROGRESSIVE_STRENGTH, Text{ "Strength Upgrade", "Amélioration de Force (prog.)", "Progressives Kraft-Upgrade" }, ITEMTYPE_ITEM, 0x81, true, LOGIC_PROGRESSIVE_STRENGTH, RHT_PROGRESSIVE_STRENGTH, {"a ", "ein ", "une "}, "%g", true); itemTable[RG_PROGRESSIVE_BOMB_BAG] = Item(RG_PROGRESSIVE_BOMB_BAG, Text{ "Progressive Bomb Bag", "Sac de Bombes (prog.)", "Progressive Bombentasche" }, ITEMTYPE_ITEM, 0x82, true, LOGIC_PROGRESSIVE_BOMB_BAG, RHT_PROGRESSIVE_BOMB_BAG, {"a ", "eine ", "un "}, "%g", true); itemTable[RG_PROGRESSIVE_BOW] = Item(RG_PROGRESSIVE_BOW, Text{ "Progressive Bow", "Arc (prog.)", "Progressiver Bogen" }, ITEMTYPE_ITEM, 0x83, true, LOGIC_PROGRESSIVE_BOW, RHT_PROGRESSIVE_BOW, {"a ", "einen ", "un "}, "%g", true); @@ -73,9 +73,9 @@ void Rando::StaticData::InitItemTable() { // Bottles itemTable[RG_EMPTY_BOTTLE] = Item(RG_EMPTY_BOTTLE, Text{ "Empty Bottle", "Bouteille Vide", "Leere Flasche" }, ITEMTYPE_ITEM, GI_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_BOTTLE, OBJECT_GI_BOTTLE, GID_BOTTLE, 0x42, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"an ", "eine ", "une "}); itemTable[RG_BOTTLE_WITH_MILK] = Item(RG_BOTTLE_WITH_MILK, Text{ "Bottle with Milk", "Bouteille avec du Lait", "Flasche mit Milch" }, ITEMTYPE_ITEM, GI_MILK_BOTTLE, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_MILK, ITEM_MILK_BOTTLE, OBJECT_GI_MILK, GID_MILK, 0x98, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "eine ", "une "}); - itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}, "%r"); - itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}, "%g"); - itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}, "%b"); + itemTable[RG_BOTTLE_WITH_RED_POTION] = Item(RG_BOTTLE_WITH_RED_POTION, Text{ "Bottle with Red Potion", "Bouteille avec une Potion Rouge", "Flasche mit rotem Elixier" }, ITEMTYPE_ITEM, 0x8C, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_RED_POTION, RG_BOTTLE_WITH_RED_POTION, OBJECT_GI_LIQUID, GID_POTION_RED, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_GREEN_POTION] = Item(RG_BOTTLE_WITH_GREEN_POTION, Text{ "Bottle with Green Potion", "Bouteille avec une Potion Verte", "Flasche mit grünem Elixier" }, ITEMTYPE_ITEM, 0x8D, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_GREEN_POTION, RG_BOTTLE_WITH_GREEN_POTION, OBJECT_GI_LIQUID, GID_POTION_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); + itemTable[RG_BOTTLE_WITH_BLUE_POTION] = Item(RG_BOTTLE_WITH_BLUE_POTION, Text{ "Bottle with Blue Potion", "Bouteille avec une Potion Bleue", "Flasche mit blauem Elixier" }, ITEMTYPE_ITEM, 0x8E, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_POTION, RG_BOTTLE_WITH_BLUE_POTION, OBJECT_GI_LIQUID, GID_POTION_BLUE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); itemTable[RG_BOTTLE_WITH_FAIRY] = Item(RG_BOTTLE_WITH_FAIRY, Text{ "Bottle with Fairy", "Bouteille avec une Fée", "Flasche mit Fee" }, ITEMTYPE_ITEM, 0x8F, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FAIRY, RG_BOTTLE_WITH_FAIRY, OBJECT_GI_BOTTLE, GID_BOTTLE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); itemTable[RG_BOTTLE_WITH_FISH] = Item(RG_BOTTLE_WITH_FISH, Text{ "Bottle with Fish", "Bouteille avec un Poisson", "Flasche mit Fisch" }, ITEMTYPE_ITEM, 0x90, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_FISH, RG_BOTTLE_WITH_FISH, OBJECT_GI_FISH, GID_FISH, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); itemTable[RG_BOTTLE_WITH_BLUE_FIRE] = Item(RG_BOTTLE_WITH_BLUE_FIRE, Text{ "Bottle with Blue Fire", "Bouteille avec une Flamme Bleue", "Flasche mit blauem Feuer" }, ITEMTYPE_ITEM, 0x91, true, LOGIC_BOTTLES, RHT_BOTTLE_WITH_BLUE_FIRE, RG_BOTTLE_WITH_BLUE_FIRE, OBJECT_GI_FIRE, GID_BLUE_FIRE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "une "}); @@ -84,89 +84,79 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_RUTOS_LETTER] = Item(RG_RUTOS_LETTER, Text{ "Bottle with Ruto's Letter", "Bouteille avec la Lettre de Ruto", "Flasche mit Rutos Brief" }, ITEMTYPE_ITEM, GI_LETTER_RUTO, true, LOGIC_RUTOS_LETTER, RHT_RUTOS_LETTER, ITEM_LETTER_RUTO, OBJECT_GI_BOTTLE_LETTER, GID_LETTER_RUTO, 0x99, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_BOTTLE_WITH_BIG_POE] = Item(RG_BOTTLE_WITH_BIG_POE, Text{ "Bottle with Big Poe", "Bouteille avec une Âme", "Flasche mit Seele" }, ITEMTYPE_ITEM, 0x93, true, LOGIC_BOTTLE_WITH_BIG_POE, RHT_BOTTLE_WITH_BIG_POE, RG_BOTTLE_WITH_BIG_POE, OBJECT_GI_GHOST, GID_BIG_POE, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "einen ", "un "}); // Songs - itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%p"); - itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%y"); - itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Salias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%g"); - itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Hymne der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%y"); - itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "la "}, "%c"); - itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%b"); - itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%g"); - itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}, "%r"); - itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}, "%b"); - itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}, "%p"); - itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); - itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); + itemTable[RG_ZELDAS_LULLABY] = Item(RG_ZELDAS_LULLABY, Text{ "Zelda's Lullaby", "Berceuse de Zelda", "Zeldas Wiegenlied" }, ITEMTYPE_SONG, 0xC1, true, LOGIC_ZELDAS_LULLABY, RHT_ZELDAS_LULLABY, ITEM_SONG_LULLABY, OBJECT_GI_MELODY, GID_SONG_ZELDA, 0xD4, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_EPONAS_SONG] = Item(RG_EPONAS_SONG, Text{ "Epona's Song", "Chant d'Epona", "Eponas Lied" }, ITEMTYPE_SONG, 0xC2, true, LOGIC_EPONAS_SONG, RHT_EPONAS_SONG, ITEM_SONG_EPONA, OBJECT_GI_MELODY, GID_SONG_EPONA, 0xD2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SARIAS_SONG] = Item(RG_SARIAS_SONG, Text{ "Saria's Song", "Chant de Saria", "Salias Lied" }, ITEMTYPE_SONG, 0xC3, true, LOGIC_SARIAS_SONG, RHT_SARIAS_SONG, ITEM_SONG_SARIA, OBJECT_GI_MELODY, GID_SONG_SARIA, 0xD1, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SUNS_SONG] = Item(RG_SUNS_SONG, Text{ "Sun's Song", "Chant du Soleil", "Hymne der Sonne" }, ITEMTYPE_SONG, 0xC4, true, LOGIC_SUNS_SONG, RHT_SUNS_SONG, ITEM_SONG_SUN, OBJECT_GI_MELODY, GID_SONG_SUN, 0xD3, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE); + itemTable[RG_SONG_OF_TIME] = Item(RG_SONG_OF_TIME, Text{ "Song of Time", "Chant du Temps", "Hymne der Zeit" }, ITEMTYPE_SONG, 0xC5, true, LOGIC_SONG_OF_TIME, RHT_SONG_OF_TIME, ITEM_SONG_TIME, OBJECT_GI_MELODY, GID_SONG_TIME, 0xD5, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "la "}); + itemTable[RG_SONG_OF_STORMS] = Item(RG_SONG_OF_STORMS, Text{ "Song of Storms", "Chant des Tempêtes", "Hymne des Sturms" }, ITEMTYPE_SONG, 0xC6, true, LOGIC_SONG_OF_STORMS, RHT_SONG_OF_STORMS, ITEM_SONG_STORMS, OBJECT_GI_MELODY, GID_SONG_STORM, 0xD6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_MINUET_OF_FOREST] = Item(RG_MINUET_OF_FOREST, Text{ "Minuet of Forest", "Menuet des Bois", "Menuett des Waldes" }, ITEMTYPE_SONG, 0xBB, true, LOGIC_MINUET_OF_FOREST, RHT_MINUET_OF_FOREST, ITEM_SONG_MINUET, OBJECT_GI_MELODY, GID_SONG_MINUET, 0x73, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_BOLERO_OF_FIRE] = Item(RG_BOLERO_OF_FIRE, Text{ "Bolero of Fire", "Boléro du Feu", "Bolero des Feuers" }, ITEMTYPE_SONG, 0xBC, true, LOGIC_BOLERO_OF_FIRE, RHT_BOLERO_OF_FIRE, ITEM_SONG_BOLERO, OBJECT_GI_MELODY, GID_SONG_BOLERO, 0x74, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_SERENADE_OF_WATER] = Item(RG_SERENADE_OF_WATER, Text{ "Serenade of Water", "Sérénade de l'Eau", "Serenade des Wassers" }, ITEMTYPE_SONG, 0xBD, true, LOGIC_SERENADE_OF_WATER, RHT_SERENADE_OF_WATER, ITEM_SONG_SERENADE, OBJECT_GI_MELODY, GID_SONG_SERENADE, 0x75, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "la "}); + itemTable[RG_NOCTURNE_OF_SHADOW] = Item(RG_NOCTURNE_OF_SHADOW, Text{ "Nocturne of Shadow", "Nocturne de l'Ombre", "Nocturne des Schattens" }, ITEMTYPE_SONG, 0xBF, true, LOGIC_NOCTURNE_OF_SHADOW, RHT_NOCTURNE_OF_SHADOW, ITEM_SONG_NOCTURNE, OBJECT_GI_MELODY, GID_SONG_NOCTURNE, 0x77, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "die ", "le "}); + itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); // Maps and Compasses - itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", " die ", "la "}, "%g"); - itemTable[RG_DEKU_TREE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%r"); - itemTable[RG_DODONGOS_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%b"); - itemTable[RG_JABU_JABUS_BELLY_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%g"); - itemTable[RG_FOREST_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%r"); - itemTable[RG_FIRE_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%b"); - itemTable[RG_WATER_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%y"); - itemTable[RG_SPIRIT_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%p"); - itemTable[RG_SHADOW_TEMPLE_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%p"); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%c"); - itemTable[RG_ICE_CAVERN_MAP].SetCustomDrawFunc(Randomizer_DrawMap); - itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); + itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", " die ", "la "}); + itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); + itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); + itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%b"); + itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); + itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); + itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%b"); + itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%y"); + itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); + itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%c"); + itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys - itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); + itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); + itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FIRE_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%b"); + itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_WATER_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%y"); + itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); + itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_SHADOW_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); + itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_GANONS_CASTLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%g"); + itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_FOREST_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%r"); + itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_FIRE_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%b"); + itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_WATER_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); + itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%p"); + itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%p"); + itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); + itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); + itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%r"); + itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE, {"a ", "einen ", "une "}); itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); @@ -218,44 +208,44 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FISHING_HOLE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); // Key Rings - itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%g"); + itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%r"); + itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_FIRE_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%b"); + itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_WATER_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); + itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%p"); + itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_SHADOW_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%p"); + itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); + itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); + itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%r"); + itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_TREASURE_GAME_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); // Dungeon Rewards - itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}, "%g"); - itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}, "%r"); - itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", " le"}, "%b"); - itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%g"); - itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%r"); - itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%b"); - itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); - itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%p"); - itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); + itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); + itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", " le"}); + itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); // Generic Items itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "ein ", "un "}); itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüner Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); itemTable[RG_GREG_RUPEE] = Item(RG_GREG_RUPEE, Text{ "Greg the Green Rupee", "Rubis Greg", "Greg Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, true, LOGIC_GREG, RHT_GREG_RUPEE, RG_GREG_RUPEE, OBJECT_GI_RUPY, GID_RUPEE_GREEN, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); - itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%b"); - itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%r"); - itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%p"); - itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}, "%y"); + itemTable[RG_BLUE_RUPEE] = Item(RG_BLUE_RUPEE, Text{ "Blue Rupee", "Rubis Bleu", "Blauer Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_BLUE, false, LOGIC_NONE, RHT_BLUE_RUPEE, ITEM_RUPEE_BLUE, OBJECT_GI_RUPY, GID_RUPEE_BLUE, 0xCC, 0x01, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_RED_RUPEE] = Item(RG_RED_RUPEE, Text{ "Red Rupee", "Rubis Rouge", "Roter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_RED, false, LOGIC_NONE, RHT_RED_RUPEE, ITEM_RUPEE_RED, OBJECT_GI_RUPY, GID_RUPEE_RED, 0xF0, 0x02, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_PURPLE_RUPEE] = Item(RG_PURPLE_RUPEE, Text{ "Purple Rupee", "Rubis Pourpre", "Violetter Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_PURPLE, false, LOGIC_NONE, RHT_PURPLE_RUPEE, ITEM_RUPEE_PURPLE, OBJECT_GI_RUPY, GID_RUPEE_PURPLE, 0xF1, 0x14, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_HUGE_RUPEE] = Item(RG_HUGE_RUPEE, Text{ "Huge Rupee", "Énorme Rubis", "Riesiger Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GOLD, false, LOGIC_NONE, RHT_HUGE_RUPEE, ITEM_RUPEE_GOLD, OBJECT_GI_RUPY, GID_RUPEE_GOLD, 0xF2, 0x13, CHEST_ANIM_SHORT, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "eine ", "une "}); itemTable[RG_PIECE_OF_HEART] = Item(RG_PIECE_OF_HEART, Text{ "Piece of Heart", "Quart de Coeur", "Herzstück" }, ITEMTYPE_ITEM, GI_HEART_PIECE, true, LOGIC_PIECE_OF_HEART, RHT_PIECE_OF_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xC2, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "ein ", "un "}); itemTable[RG_HEART_CONTAINER] = Item(RG_HEART_CONTAINER, Text{ "Heart Container", "Réceptacle de Coeur", "Herzcontainer" }, ITEMTYPE_ITEM, GI_HEART_CONTAINER_2, true, LOGIC_HEART_CONTAINER, RHT_HEART_CONTAINER, ITEM_HEART_CONTAINER, OBJECT_GI_HEARTS, GID_HEART_CONTAINER, 0xC6, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"a ", "einen ", "un "}); itemTable[RG_ICE_TRAP] = Item(RG_ICE_TRAP, Text{ "Ice Trap", "Piège de Glace", "Eisfalle" }, ITEMTYPE_ITEM, RG_ICE_TRAP, false, LOGIC_NONE, RHT_ICE_TRAP, RG_ICE_TRAP, OBJECT_GI_RUPY, GID_RUPEE_GOLD, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER); @@ -276,12 +266,12 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_DEKU_NUTS_10] = Item(RG_DEKU_NUTS_10, Text{ "Deku Nuts (10)", "Noix Mojo (10)", "Deku-Nüsse (10)" }, ITEMTYPE_REFILL, GI_NUTS_10, false, LOGIC_NONE, RHT_DEKU_NUTS_10, ITEM_NUTS_10, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_DEKU_SEEDS_30] = Item(RG_DEKU_SEEDS_30, Text{ "Deku Seeds (30)", "Graines Mojo (30)", "Deku-Samen (30)" }, ITEMTYPE_REFILL, GI_SEEDS_30, false, LOGIC_NONE, RHT_DEKU_SEEDS_30, ITEM_SEEDS_30, OBJECT_GI_SEED, GID_SEEDS, 0xDC, 0x50, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE); itemTable[RG_DEKU_STICK_1] = Item(RG_DEKU_STICK_1, Text{ "Deku Stick (1)", "Bâton Mojo (1)", "Deku-Stab (1)" }, ITEMTYPE_REFILL, GI_STICKS_1, false, LOGIC_NONE, RHT_DEKU_STICK_1, ITEM_STICK, OBJECT_GI_STICK, GID_STICK, 0x37, 0x0D, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "einen ", "un "}); - itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%r"); - itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%g"); - itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}, "%b"); + itemTable[RG_RED_POTION_REFILL] = Item(RG_RED_POTION_REFILL, Text{ "Red Potion Refill", "Recharge de Potion Rouge", "Nachfüllpackung des roten Elixiers" }, ITEMTYPE_REFILL, GI_POTION_RED, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_RED, OBJECT_GI_LIQUID, GID_POTION_RED, 0x43, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_GREEN_POTION_REFILL] = Item(RG_GREEN_POTION_REFILL, Text{ "Green Potion Refill", "Recharge de Potion Verte", "Nachfüllpackung des grünen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_GREEN, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_GREEN, OBJECT_GI_LIQUID, GID_POTION_GREEN, 0x44, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); + itemTable[RG_BLUE_POTION_REFILL] = Item(RG_BLUE_POTION_REFILL, Text{ "Blue Potion Refill", "Recharge de Potion Bleue", "Nachfüllpackung des blauen Elixiers" }, ITEMTYPE_REFILL, GI_POTION_BLUE, false, LOGIC_NONE, RHT_NONE, ITEM_POTION_BLUE, OBJECT_GI_LIQUID, GID_POTION_BLUE, 0x45, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); // Treasure Game itemTable[RG_TREASURE_GAME_HEART] = Item(RG_TREASURE_GAME_HEART, Text{ "Piece of Heart (WINNER)", "Quart de Coeur (Chasse-aux-Trésors)", "Herzstück (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_HEART_PIECE_WIN, true, LOGIC_PIECE_OF_HEART, RHT_TREASURE_GAME_HEART, ITEM_HEART_PIECE_2, OBJECT_GI_HEARTS, GID_HEART_PIECE, 0xFA, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüner Rubin (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE, {}, "%g"); + itemTable[RG_TREASURE_GAME_GREEN_RUPEE] = Item(RG_TREASURE_GAME_GREEN_RUPEE, Text{ "Green Rupee (LOSER)", "Rubis Vert (Chasse-aux-Trésors)", "Grüner Rubin (Schatztruhenminispiel)" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN_LOSE, false, LOGIC_NONE, RHT_TREASURE_GAME_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0xF4, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_MAJOR, MOD_NONE); // Shop itemTable[RG_BUY_DEKU_NUTS_5] = Item(RG_BUY_DEKU_NUTS_5, Text{ "Buy Deku Nut (5)", "Acheter: Noix Mojo (5)", "Deku-Nuß kaufen (5)" }, ITEMTYPE_SHOP, GI_NUTS_5_2, true, LOGIC_NUTS, RHT_DEKU_NUTS_5, ITEM_NUTS_5, OBJECT_GI_NUTS, GID_NUTS, 0x34, 0x0C, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 15); itemTable[RG_BUY_ARROWS_30] = Item(RG_BUY_ARROWS_30, Text{ "Buy Arrows (30)", "Acheter: Flèches (30)", "Pfeile kaufen (30)" }, ITEMTYPE_SHOP, GI_ARROWS_MEDIUM, true, LOGIC_BUY_ARROW, RHT_ARROWS_30, ITEM_ARROWS_MEDIUM, OBJECT_GI_ARROW, GID_ARROWS_MEDIUM, 0xE6, 0x49, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {}, "%g", false, 60); @@ -349,7 +339,7 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_BRONZE_SCALE] = Item(RG_BRONZE_SCALE, Text{ "Bronze Scale", "Écaille de Bronze", "Bronzene Schuppe" }, ITEMTYPE_ITEM, GI_SCALE_SILVER, true, LOGIC_PROGRESSIVE_WALLET, RHT_BRONZE_SCALE, RG_BRONZE_SCALE, OBJECT_GI_SCALE, GID_SCALE_SILVER, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"the ", "die ", "le "}); itemTable[RG_BRONZE_SCALE].SetCustomDrawFunc(Randomizer_DrawBronzeScale); - itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "Sac de Missiles Teigneux" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); + itemTable[RG_BOMBCHU_BAG] = Item(RG_BOMBCHU_BAG, Text{ "Bombchu Bag", "!!!", "!!!" }, ITEMTYPE_ITEM, RG_BOMBCHU_BAG, true, LOGIC_BOMBCHUS, RHT_BOMBCHU_BAG, RG_BOMBCHU_BAG, OBJECT_GI_BOMB_2, GID_BOMBCHU, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_RANDOMIZER, {"a ", "eine ", "un "}); itemTable[RG_BOMBCHU_BAG].SetCustomDrawFunc(Randomizer_DrawBombchuBag); itemTable[RG_QUIVER_INF] = Item(RG_QUIVER_INF, Text{ "Infinite Quiver", "Carquois Infini", "Unendlicher Köcher" }, ITEMTYPE_ITEM, RG_QUIVER_INF, true, LOGIC_PROGRESSIVE_BOW, RHT_QUIVER_INF, RG_QUIVER_INF, OBJECT_GI_ARROWCASE, GID_QUIVER_50, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "le "}); From 9c48d034d8936e1195d1dc101c4a6d6deceaefce Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 00:45:04 -0500 Subject: [PATCH 053/103] Defines the hook for OnTextLoad --- .../game-interactor/GameInteractor_HookTable.h | 1 + .../Enhancements/game-interactor/GameInteractor_Hooks.cpp | 8 ++++++++ .../Enhancements/game-interactor/GameInteractor_Hooks.h | 3 +++ 3 files changed, 12 insertions(+) diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h index 44d0e643a..1a40b0e8e 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h @@ -67,3 +67,4 @@ DEFINE_HOOK(OnSetGameLanguage, ()); DEFINE_HOOK(OnFileDropped, (std::string filePath)); DEFINE_HOOK(OnAssetAltChange, ()); DEFINE_HOOK(OnKaleidoUpdate, ()); +DEFINE_HOOK(OnOpenText, (uint16_t* textId, bool* loadFromMessageTable)); diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp index 9231da843..095eec0e7 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.cpp @@ -291,3 +291,11 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)) { void GameInteractor_ExecuteOnKaleidoUpdate() { GameInteractor::Instance->ExecuteHooks(); } + +// MARK: Messages +void GameInteractor_ExecuteOnOpenText(uint16_t* textId, bool* loadFromMessageTable) { + LUSLOG_DEBUG("OnOpenText: textId: {}", *textId); + GameInteractor::Instance->ExecuteHooks(textId, loadFromMessageTable); + GameInteractor::Instance->ExecuteHooksForID(*textId, textId, loadFromMessageTable); + GameInteractor::Instance->ExecuteHooksForFilter(textId, loadFromMessageTable); +} diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h index 33c8d2681..8cc0bb03e 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_Hooks.h @@ -79,6 +79,9 @@ void GameInteractor_RegisterOnAssetAltChange(void (*fn)(void)); // Mark: - Pause Menu void GameInteractor_ExecuteOnKaleidoUpdate(); +// MARK: - Messages +void GameInteractor_ExecuteOnOpenText(uint16_t* textId, bool* loadFromMessageTable); + #ifdef __cplusplus } #endif From c6b586e16bdbf0a37ed33e34d4e17b88fc1c1561 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 01:29:47 -0500 Subject: [PATCH 054/103] Intercepts message loading with hooks --- soh/src/code/z_message_PAL.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index fc63f96c8..c7ad0ec1f 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -2713,6 +2713,9 @@ void Message_OpenText(PlayState* play, u16 textId) { Font* font = &msgCtx->font; s16 textBoxType; + bool loadFromMessageTable = false; + GameInteractor_ExecuteOnOpenText(&textId, &loadFromMessageTable); + sDisplayNextMessageAsEnglish = false; if (msgCtx->msgMode == MSGMODE_NONE) { @@ -2783,7 +2786,7 @@ void Message_OpenText(PlayState* play, u16 textId) { } // RANDOTODO: Use this for ice trap messages - if (CustomMessage_RetrieveIfExists(play)) { + if (!loadFromMessageTable) { osSyncPrintf("Found custom message"); if (gSaveContext.language == LANGUAGE_JPN) { sDisplayNextMessageAsEnglish = true; From 2a291a817bb7c57d60bf7c6ef794099dd0b2c02e Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 13:54:27 -0500 Subject: [PATCH 055/103] Adds file to handle the CustomMessage creation for items. --- .../Enhancements/randomizer/ItemMessages.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 soh/soh/Enhancements/randomizer/ItemMessages.cpp diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/ItemMessages.cpp new file mode 100644 index 000000000..4bb0b242b --- /dev/null +++ b/soh/soh/Enhancements/randomizer/ItemMessages.cpp @@ -0,0 +1,17 @@ +#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include "soh/Enhancements/custom-message/CustomMessageTypes.h" +#include "soh/ShipInit.hpp" + +extern "C" { +#include "variables.h" +} + +void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { + +} + +void RegisterItemMessages () { + COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_CUSTOM_ITEM, IS_RANDO, BuildItemMessage); +} + +static RegisterShipInitFunc initFunc(RegisterItemMessages, { "IS_RANDO" }); \ No newline at end of file From 489d52f419b7c139b12c8a95f9dee9599b4097f8 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 18:19:35 -0500 Subject: [PATCH 056/103] Handles Ice Traps, Triforce Pieces, and Custom Items --- .../Enhancements/randomizer/ItemMessages.cpp | 372 +++++++++++++++++- 1 file changed, 370 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/ItemMessages.cpp index 4bb0b242b..39ed4bf8d 100644 --- a/soh/soh/Enhancements/randomizer/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/ItemMessages.cpp @@ -1,13 +1,381 @@ #include "soh/Enhancements/game-interactor/GameInteractor.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" #include "soh/ShipInit.hpp" +#include "randomizer.h" extern "C" { -#include "variables.h" +#include +#include +#include +#include +extern PlayState* gPlayState; +} + +static const char* const englishIceTrapMessages[169] = { + "You are a #FOOL#!", + "You are a #FOWL#!", + "#FOOL#!", + "You just got #PUNKED#!", + "Stay #frosty#, @.", + "Take a #chill pill#, @.", + "#Winter# is coming.", + "#ICE# to see you, @.", + "Feeling a little %rhot%w under the collar? #Let's fix that#.", + "It's a #cold day# in the Evil Realm.", + "Getting #cold feet#?", + "Say hello to the #Zoras# for me!", + "Can you keep a #cool head#?", + "Ganondorf used #Ice Trap#!&It's super effective!", + "Allow me to break the #ice#!", + "#Cold pun#.", + "The #Titanic# would be scared of you, @.", + "Oh no!", + "Uh oh!", + "What killed the dinosaurs?&The #ICE# age!", + "Knock knock. Who's there? Ice. Ice who? Ice see that you're a #FOOL#.", + "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", + "Thank you #@#! But your item is in another castle!", + "#FREEZE#! Don't move!", + "Wouldn't it be #ice# if we were colder?", + "Greetings from #Snowhead#! Wish you were here.", + "Too #cool# for you?", + "#Ice#, #ice#, baby...", + "Time to break the #ice#.", + "We wish that you would read this... We wish that you would read this... But we set our bar low.", + "#Freeze# and put your hands in the air!", + "#Ice# to meet you!", + "Do you want to #freeze# a snowman?", + "Isn't there a #mansion# around here?", + "Now you know how #King Zora# feels.", + "May the #Frost# be with you.", + "Carpe diem. #Freeze# the day.", + "There #snow# place like home.", + "That'll do, #ice#. That'll do.", + "All that is #cold# does not glitter. Not all those who wander are #frost#.", + "I Used To Be An Adventurer Like You. Then I Took An #Icetrap# To The Knee.", + "Would you like #ice# with that?", + "You have obtained the #Ice# Medallion!", + "Quick, do a #Zora# impression!", + "One item #on the rocks#!",//would be better if it could display the name of the item + "How much does a polar bear weigh?&Enough to break the #ice#.", + "You got Din's #Ice#!", + "You got Nayru's #Cold#!", + "You got Farore's #Freeze#!", + "KEKW", + "You just got #ICE TRAPPED#! Tag your friends to totally #ICE TRAP# them!", + "Are you okay, @? You're being #cold# today.", + "In a moment, your game might experience some #freezing#.", + "Breeze? Trees? Squeeze? No, it's a #freeze#!", + "After collecting this item, @ was assaulted in #cold# blood.", + "Only #chill# vibes around here!", + "Here's a #cool# gift for you!", + "Aha! You THOUGHT.", + "Stay hydrated and brush your teeth!", + "Isn't it too hot here? Let's turn the #AC# on.", + "One serving of #cold# @, coming right up!", + "Is it #cold# in here or is that just me?", + "Yahaha! You found me!", + "You'd make a great #ice#-tronaut!", + "That's just the tip of the #iceberg#!", + "It's the triforce!&No, just kidding, it's an #ice trap#.", + "WINNER!", + "LOSER!", + "Greetings from #Cold Miser#!", + "Pardon me while I turn up the #AC#.", + "If you can't stand the #cold#, get out of the #freezer#.", + "Oh, goodie! #Frozen @# for the main course!", + "You have #freeze# power!", + "You obtained the #Ice Beam#! No wait, wrong game.", + "Here's to another lousy millenium!", + "You've activated my #trap card#!", + "I love #refrigerators#!", + "You expected an item,&BUT IT WAS I, AN #ICE TRAP#!", + "It's dangerous to go alone! Take #this#!", + "soh.exe has #stopped responding#.", + "Enough! My #Ice Trap# thaws in the morning!", + "Nobody expects the span-#ice# inquisition!", + "This is one #cool# item!", + "Say hello to my #little friend#!", + "We made you an offer you #can't refuse#.", + "Hyrule? More like #Hycool#!", + "Ice puns are #snow# problem!", + "This #ice# is #snow# joke!", + "There's no business like #snow# business!", + "No, dude.", + "N#ice# trap ya got here!", + "Quick do your best impression of #Zoras Domain#!", + "Ganon used #ice beam#, it's super effective!", + "I was #frozen# today.", + "You're not in a #hurry#, right?", + "It's a #trap#!", + "At least it's not a VC crash and only Link is #frozen#!", + "Oh no! #BRAIN FREEZE#!", + "Looks like your game #froze#! Nope just you!", + "PK #FREEZE#!", + "May I interest you in some #iced# Tea?", + "Time for some Netflix and #chill#.", + "I know, I know... #FREEZE#!", + "#Ice# of you to drop by!", + "STOP!&You violated the #Thaw#!", + "I wanted to give you a treasure, but it looks like you got #cold feet#.", + "You told me you wanted to deliver #just ice# to Ganondorf!", + "You got the triforce!&This ancient artifact of divine power can grant any- wait, no, sorry, it's just an ice trap. My bad.", + "Time to #cool off#!", + "The #Ice Cavern# sends its regards.", + "Loading item, please #wait#...", + "Mash A+B to not #die#.", + "Sorry, your item is in another location.", //would be better if it could have the name of the item + "You only wish this was %gGreg%w.", + "Do you want to drink a hot chocolate?", + "The #cold# never bothered me anyway.", + "Hope you're too school for #cool#!", + "Be thankful this isn't #absolute zero#.", + "Did you know the F in ZFG stands for #Freeze#?", + "You got #Ice Age (2002)#!", + "Now you can cast a #spell# you don't know.", + "How's about a hero #on the rocks#?", + "Ain't no tunic for #this#!", + "I knew you were #part metroid#!", + "That's just the #icing on the cake#!", + "You're so #cool#, @!", + "You found #disappointment#!", + "You got #FOOLED#!", + "Start Mashing.", + "This item will #self-destruct# in 5 seconds...", + "Remember, there may be some momentary #discomfort#.", + "In a perfect world #ice traps# like me would not exist, but this is not a perfect world.", + "Gee, it sure is #cold# around here.", + "You tested the item with your #ice detector#, it beeped.", //would be better if it could have the name of the item + "You have found the way of the zero. The #sub-zero#.", + "Mweep... mweep... mweep...", + "Scum, #freezebag#! I mean #freeze#, scumbag!", + "Is it #chilly# in here or is it just #you#?", + "#Proceed#.", + "WHAT'S SHE GONNA DO, MAKE ME AN #[Ice Cream]#!?", + "You've met with a #terrible fate#, haven't you?", + "So I heard you like the Shining, here's how it #ends#.", + "Minor routing mistake. #I win#.", + "Hold this #L#, @.", + "#SKILL ISSUE#.", + "All your heat are belong to us.", + "Wait a second, don't you already have #this item#?", + "#Freeze#! We have you surrounded!", + "Error 404 - Item not #found#.", + "Hydration break! Hey, who #froze# my water?", + "Oops, wrong #item model#.", + "Whoops! You have to put the item #in your inventory#.", + "You dropped the item, shattering it into #shards of ice#!", //would be better if it could have the name of the item + "Is this... golden age Simpsons?&BECAUSE I'M ABOUT TO #CHOKE A CHILD#.", + "You are the weakest @, #goodbye#!", + "Ugh... Why did we even randomize #this item#?", + "The #Frost Moon# is rising...", + "According to all known laws of physics and biology, there is no way that @ should be able to survive #getting fully encased in ice#. The cells in @'s body would all die by the time they #unthaw#. Of course, this is a video game, so @ survives anyway... #Probably#.", + "Okay, so stop me if you've heard this one - a gamer and a bottle of #liquid nitrogen# walk into a milk bar...", + "Lástima, es una #trampa de hielo#...&&Nobody expects the Spanish #ice trap#!", + "Gee, it sure is #BURR#ing around here.", + "Navi? Oh! I thought she was called #Névé#!", + "It's fine, @ knew this was a #trap#, they're just using it to take damage intentionally to manipulate RNG.", + "Unfortunately, the item has #stopped#.", //would be better if it could have the name of the item + "This item is #not available# in your country.", //would be better if it could have the name of the item + "#Ice# try. #;)#", + "D'oh, I #missed#!", + "Where is my #super suit#?", + "#Titanic's revenge#.", +}; + +static const char* const germanIceTrapMessages[23] = { + "Du bist ein #DUMMKOPF#!", + "Du bist eine #Frostbeule#!", + "#DUMMKOPF#!", + "Du wurdest #eiskalt# erwischt!", + "Es läuft Dir #eiskalt# den Rücken hinunter, @.", + "Bleib #cool#, @.", + "Der #Winter# naht.", + "Alles #cool# im Pool?", + "#Abkühlung gefällig#?", + "Es ist ein %kalter%w Tag im Herzen von Hyrule.", + "Bekommst Du etwa #kalte# Füße?", + "Sag den #Zoras# viele Grüße von mir!", + "Bewahre einen #kühlen#! Kopf.", + "Ganondorf setzt #Eisstrahl# ein. Das ist sehr effektiv!", + "Ein Lächeln ist der beste Weg, um das #Eis# zu brechen!", + "#Eiskalt# lässt du meine Seele erfrier'n.", + "Die #Titanic# hätte Angst vor Dir, @.", + "Oh nein!", + "Was die Dinosaurier getötet hat?&Die #Eiszeit#!", + "Nachts ist es #kälter# als draußen.", + "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", + "Danke #@#! Aber der Gegenstand ist in einem anderem Schloß!", + "Kalt. Kalt. Kälter. #EISKALT#!", +}; + +static const char* const frenchIceTrapMessages[83] = { + "#Pauvre fou#...", + "Tu es un #glaçon#, Harry!", + "#Sot# que tu es.", + "Ça me #glace# le sang!", + "#Reste au frais#, @.", + "Et c'est la douche #froide#!", + "L'#hiver# vient.", + "#Glacier#!", + "Ça en jette un #froid#.", + "Est-ce que tu as déjà eu des sueurs #froides#?", + "La vengeance est un plat qui se mange #froid#!", + "Dit bonjour aux #Zoras# pour moi!", + "Il faut parfois savoir garder la tête #froide#!", + "Ganondorf utilise #Piège de Glace#! C'est super efficace!", + "Laisse moi briser la #glace#!", + "Balance man..., Cadence man..., Trace la #glace#..., c'est le Cooooolllll Rasta!", + "Le #Titanic# aurait peur de toi, @.", + "Oh non!", + "Qu'est-ce qui a tué les dinosaures?&L'ère #glacière#!", + "L'imbécile réfléchit uniquement quand il s'observe dans la #glace#.", + "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", + "Merci #@#! Mais ton objet est dans un autre château!", + "J'espère que ça ne te fait ni chaud, ni #froid#.", + "Je voulais t'offrir un trésor, mais il semble que tu aies eu #froid aux pieds#", + "Tu m'as dit que tu voulais livrer #de la glace# à Ganondorf!", + "Tu as obtenu la Triforce!&Cet ancien artefact divin peut exaucer n'importe quel... ah non, désolé, c'est juste un piège de glace.", + "Il est temps de #te rafraîchir#!", + "La #Caverne Polaire# te passe le bonjour.", + "Chargement de l'objet, veuillez #patienter#...", + "Martèle A+B pour ne pas #mourir#.", + "Désolé, ton objet est à un autre endroit.", //would be better if it could have the name of the item + "Tu espérais que ce soit %gGreg%w.", + "Tu veux boire un chocolat chaud?", + "Le #froid# ne m'a jamais dérangé, de toute façon.", + "J'espère que tu es trop cool pour être #cool#!", + "Sois reconnaissant que ce n'est pas le #zéro absolu#.", + "Tu savais que le G de ZFG signifie #Glace#?", + "Tu as obtenu #L'Âge de Glace (2002)#!", + "Maintenant, tu peux lancer un #sort# que tu ne connais pas.", + "Que dirais-tu d'un héros #sur glace# ?", + "Pas de tunique pour #ça#!", + "Je savais que tu étais #partiellement Metroid#!", + "Voilà juste la #cerise sur le gâteau#!", + "Tu es tellement #cool#, @!", + "Tu as trouvé de la #déception#!", + "Tu t'es fait #BERNER#!", + "Commence à marteler.", + "Cet objet va #s'autodétruire# dans 5 secondes...", + "Souviens-toi, il pourrait y avoir un léger #inconfort#.", + "Dans un monde parfait, les #pièges de glace# comme moi n'existeraient pas, mais ce n'est pas un monde parfait.", + "Mon dieu qu'il fait #froid# ici.", + "Tu as testé l'objet avec ton #détecteur de glace#, il a bipé.", //would be better if it could have the name of the item + "Tu as découvert le chemin du zéro. Le #sub-zéro#.", + "Mweep... mweep... mweep...", + "Gelé, #sac à glace#! Je veux dire #gèle-toi#, racaille!", + "Est-ce qu'il fait #frais# ici ou est-ce juste #toi#?", + "#Continue#", + "QU'EST-CE QU'ELLE VA FAIRE, ME FAIRE UNE #[Glace]#!?", + "Tu as rencontré un #terrible destin#, n'est-ce pas?", + "Alors comme ça, tu aimes Shining ? Voici comment ça #finit#.", + "Petite erreur de trajectoire. #Je gagne#.", + "Prends ce #L#, @.", + "#Problème de compétence#", + "Tout ton chauffage nous appartient.", + "Attends une seconde, tu as déjà #cet objet#, non?", + "#Gèle#! Tu es entouré !", + "Erreur 404 - Objet non #trouvé#.", + "Pause hydratation ! Hé, qui a #gelé# mon eau?", + "Oups, mauvais #modèle d'objet#.", + "Oups! Tu dois mettre l'objet #dans ton inventaire#.", + "Tu as fait tomber l'objet, le brisant en #éclats de glace#!", //would be better if it could have the name of the item + "Tu es le maillon faible @, #au revoir#!", + "Ugh... Pourquoi avons-nous même randomisé #cet objet#?", + "La #Lune de Givre# se lève...", + "Selon toutes les lois connues de la physique et de la biologie, @ ne devrait pas survivre à #être complètement enfermé dans la glace#. Les cellules de @ mourraient avant qu'elles ne #dégèlent#. Mais c'est un jeu vidéo, alors @ survit... #Probablement#.", + "OK, arrête-moi si tu l'as déjà entendue - un joueur et une bouteille de #nitrogène liquide# entrent dans un bar à lait...", + "Lástima, c'est un #piège de glace#...&&Personne ne s'attend à un #piège de glace espagnol#!", + "Mon dieu qu'il fait #GLAGLA# ici.", + "C'est bon, @ savait que c'était un #piège#, il l'utilise juste pour prendre des dégâts intentionnellement et manipuler la RNG.", + "Cet objet n'est #pas disponible# dans votre pays.", //would be better if it could have the name of the item + "#Bonne# tentative. #;)#", + "Où est mon #Super Costume#?", + "#La revanche du Titanic#.", +}; + +void BuildIceTrapMessage(CustomMessage& msg) { + if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { + msg = CustomMessage( + /*english*/ "This year for Christmas, all you get is #COAL#!", + /*german*/ "This year for Christmas, all you get is #COAL#!", + /*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", + { QM_BLUE } + ); + } else { + msg = CustomMessage( + RandomElement(englishIceTrapMessages), + RandomElement(germanIceTrapMessages), + RandomElement(frenchIceTrapMessages), + { QM_BLUE, QM_BLUE, QM_BLUE } + ); + } + + msg.AutoFormat(); +} + +void BuildTriforcePieceMessage(CustomMessage& msg) { + uint8_t current = gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected + 1; + uint8_t required = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) + 1; + uint8_t remaining = required - current; + float percentageCollected = (float)current / (float)required; + + if (percentageCollected <= 0.25) { + msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", + "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est un début!" }; + } else if (percentageCollected <= 0.5) { + msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", + "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Ça avance!" }; + } else if (percentageCollected <= 0.75) { + msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", + "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über die Hälfte!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" }; + } else if (percentageCollected < 1.0) { + msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", + "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est presque&terminé!" }; + } else if (current == required) { + msg = { "You completed the %yTriforce of&Courage%w! %gGG%w!", + "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", + "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }; + } else { + msg = { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", + "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", + "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, mais vous en avez %g[[current]]%w en&tout!" }; + } + msg.Replace("[[current]]", std::to_string(current)); + msg.Replace("[[remaining]]", std::to_string(remaining)); + msg.Replace("[[required]]", std::to_string(required)); + msg.Format(); +} + +void BuildCustomItemMessage(Player* player, CustomMessage& msg) { + int16_t rgid; + msg = CustomMessage("You found the %g[[name]]%w!", "Du erhältst das %g[[name]]%w!", "Vous ebtenez %g[[name]]%w!", TEXTBOX_TYPE_BLUE); + if (player->getItemEntry.objectId != OBJECT_INVALID) { + rgid = player->getItemEntry.getItemId; + } else { + rgid = player->getItemId; + } + CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); + name.Replace("[[name]]", name); + name.AutoFormat(); } void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { - + Player* player = GET_PLAYER(gPlayState); + CustomMessage messageEntry; + + if (player->getItemEntry.getItemId == RG_ICE_TRAP) { + BuildIceTrapMessage(messageEntry); + } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { + BuildTriforcePieceMessage(messageEntry); + } else { + BuildCustomItemMessage(player, messageEntry); + } } void RegisterItemMessages () { From 86564c0902ba2287889f02546a01cdedd605cf8f Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 19:25:24 -0500 Subject: [PATCH 057/103] Handle maps, compasses, and keys --- soh/include/macros.h | 10 +- .../Enhancements/randomizer/ItemMessages.cpp | 92 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 49 +--------- 3 files changed, 103 insertions(+), 48 deletions(-) diff --git a/soh/include/macros.h b/soh/include/macros.h index 325fb91b6..f9d787633 100644 --- a/soh/include/macros.h +++ b/soh/include/macros.h @@ -330,10 +330,12 @@ extern GraphicsContext* __gfxCtx; #define GANONS_CASTLE_SMALL_KEY_MAX (ResourceMgr_IsSceneMasterQuest(SCENE_INSIDE_GANONS_CASTLE) ? 3 : 2) #define TREASURE_GAME_SMALL_KEY_MAX 6 -#define DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(randomizerSettingsKey) \ - (Randomizer_GetSettingValue(randomizerSettingsKey) != RO_DUNGEON_ITEM_LOC_STARTWITH && \ - Randomizer_GetSettingValue(randomizerSettingsKey) != RO_DUNGEON_ITEM_LOC_VANILLA && \ - Randomizer_GetSettingValue(randomizerSettingsKey) != RO_DUNGEON_ITEM_LOC_OWN_DUNGEON) +#ifdef __cplusplus +#define DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(rsk) \ + (OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_STARTWITH) && \ + OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_VANILLA) && \ + OTRGlobals::Instance->gRandoContext->GetOption(rsk).IsNot(RO_DUNGEON_ITEM_LOC_OWN_DUNGEON)) +#endif // #endregion #endif diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/ItemMessages.cpp index 39ed4bf8d..a879f5d87 100644 --- a/soh/soh/Enhancements/randomizer/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/ItemMessages.cpp @@ -8,6 +8,7 @@ extern "C" { #include #include #include +#include extern PlayState* gPlayState; } @@ -376,10 +377,101 @@ void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { } else { BuildCustomItemMessage(player, messageEntry); } + *loadFromMessageTable = false; +} + +void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { + GetItemEntry itemEntry = GET_PLAYER(gPlayState)->getItemEntry; + auto ctx = OTRGlobals::Instance->gRandoContext; + CustomMessage msg = CustomMessage( + "You found the %g[[name]]%w! [[typeHint]]", + "Du erhältst das %g[[name]]%w! [[typeHint]]", + "Vous ebtenez %g[[name]]%w! [[typeHint]]", + TEXTBOX_TYPE_BLUE + ); + int sceneNum; + switch (itemEntry.getItemId) { + case RG_DEKU_TREE_MAP: + sceneNum = SCENE_DEKU_TREE; + break; + case RG_DODONGOS_CAVERN_MAP: + sceneNum = SCENE_DODONGOS_CAVERN; + break; + case RG_JABU_JABUS_BELLY_MAP: + sceneNum = SCENE_JABU_JABU; + break; + case RG_FOREST_TEMPLE_MAP: + sceneNum = SCENE_FOREST_TEMPLE; + break; + case RG_FIRE_TEMPLE_MAP: + sceneNum = SCENE_FIRE_TEMPLE; + break; + case RG_WATER_TEMPLE_MAP: + sceneNum = SCENE_WATER_TEMPLE; + break; + case RG_SPIRIT_TEMPLE_MAP: + sceneNum = SCENE_SPIRIT_TEMPLE; + break; + case RG_SHADOW_TEMPLE_MAP: + sceneNum = SCENE_SHADOW_TEMPLE; + break; + case RG_BOTTOM_OF_THE_WELL_MAP: + sceneNum = SCENE_BOTTOM_OF_THE_WELL; + break; + case RG_ICE_CAVERN_MAP: + sceneNum = SCENE_ICE_CAVERN; + break; + } + if ( + ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_NONE) || + (ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_SET_NUMBER) && + ctx->GetOption(RSK_MQ_DUNGEON_COUNT).Is(12)) + ) { + msg.Replace("[[typeHint]]", ""); + } else if (ResourceMgr_IsSceneMasterQuest(sceneNum)) { + msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_MASTERFUL].GetHintMessage()); + } else { + msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage()); + } + *loadFromMessageTable = false; +} + +void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { + Player* player = GET_PLAYER(gPlayState); + if (player->getItemEntry.getItemId == RG_GANONS_CASTLE_BOSS_KEY && !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)) { + return; + } + if (player->getItemEntry.getItemId != RG_GANONS_CASTLE_BOSS_KEY && !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY)) { + return; + } + CustomMessage msg; + BuildCustomItemMessage(player, msg); + *loadFromMessageTable = false; +} + +void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { + Player* player = GET_PLAYER(gPlayState); + if (player->getItemEntry.getItemId == RG_GERUDO_FORTRESS_SMALL_KEY && OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_VANILLA)) { + return; + } + if (player->getItemEntry.getItemId != RG_GERUDO_FORTRESS_SMALL_KEY && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)) { + return; + } + CustomMessage msg; + BuildCustomItemMessage(player, msg); + *loadFromMessageTable = false; } void RegisterItemMessages () { COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_CUSTOM_ITEM, IS_RANDO, BuildItemMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_DUNGEON_MAP, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), BuildMapMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_COMPASS, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), BuildItemMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_BOSS, + (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY) || + DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)), BuildBossKeyMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_SMALL, + (OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).IsNot(RO_GERUDO_KEYS_VANILLA) || + DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)), BuildSmallKeyMessage); } static RegisterShipInitFunc initFunc(RegisterItemMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0151773a9..8f6163b10 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2177,50 +2177,11 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); Player* player = GET_PLAYER(play); - if (textId == TEXT_RANDOMIZER_CUSTOM_ITEM) { - if (player->getItemEntry.getItemId == RG_ICE_TRAP) { - messageEntry = Randomizer::GetIceTrapMessage(); - } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { - messageEntry = Randomizer::GetTriforcePieceMessage(); - } else { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } else if (textId == TEXT_ITEM_DUNGEON_MAP || textId == TEXT_ITEM_COMPASS) { - if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS)) { - if (textId == TEXT_ITEM_DUNGEON_MAP) { - messageEntry = - OTRGlobals::Instance->gRandomizer->GetMapGetItemMessageWithHint(player->getItemEntry); - } else { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } - } else if (textId == TEXT_ITEM_KEY_BOSS) { - if (player->getItemEntry.getItemId == RG_GANONS_CASTLE_BOSS_KEY) { - if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)) { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } else { - if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY)) { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } - } else if (textId == TEXT_ITEM_KEY_SMALL) { - if (player->getItemEntry.getItemId == RG_GERUDO_FORTRESS_SMALL_KEY) { - if (Randomizer_GetSettingValue(RSK_GERUDO_KEYS) != RO_GERUDO_KEYS_VANILLA) { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } else { - if (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)) { - messageEntry = Randomizer_GetCustomGetItemMessage(player); - } - } - } else if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && - Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != RO_GOSSIP_STONES_NONE && - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_NOTHING || - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_TRUTH && - Player_GetMask(play) == PLAYER_MASK_TRUTH) || - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_STONE && - CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { + if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != RO_GOSSIP_STONES_NONE && + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_NOTHING || + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_TRUTH && + Player_GetMask(play) == PLAYER_MASK_TRUTH) || + (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_STONE && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { Actor* stone = GET_PLAYER(play)->talkActor; RandomizerHint stoneHint = RH_NONE; From eb7e481cc3aa2c2c73c4697ff5b557ad69b48326 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 20:20:04 -0500 Subject: [PATCH 058/103] Set up actual loading of messages into memory Only for the items, other things previously covered by CustomMessage_Retrieve if exists have not yet been covered as of this commit and will either load their vanilla text or crash. --- .../custom-message/CustomMessageManager.cpp | 34 +++++++++++++++++++ .../custom-message/CustomMessageManager.h | 2 ++ .../Enhancements/randomizer/ItemMessages.cpp | 24 +++++++------ soh/src/code/z_message_PAL.c | 2 +- 4 files changed, 50 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index d4c478657..61040ee72 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -6,6 +6,7 @@ #include #include #include +#include using namespace std::literals::string_literals; @@ -260,6 +261,39 @@ bool CustomMessage::operator!=(const CustomMessage& operand) const { return !operator==(operand); } +int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) { + if (!inputStr.empty()) { + // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents negatives. + memset(buffer, 0, std::max(0, maxBufferSize)); + // Gaurentee that this value will be greater than 0, regardless of passed variables. + const int copiedCharLen = std::min(std::max(0, maxBufferSize - 1), inputStr.length()); + memcpy(buffer, inputStr.c_str(), copiedCharLen); + return copiedCharLen; + } + + return 0; +} + +void CustomMessage::LoadIntoFont() { + MessageContext* msgCtx = &gPlayState->msgCtx; + Font* font = &msgCtx->font; + char* buffer = font->msgBuf; + const int maxBufferSize = sizeof(font->msgBuf); + font->charTexBuf[0] = (type << 4) | position; + switch (gSaveContext.language) { + case LANGUAGE_FRA: + msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetFrench(MF_RAW), buffer, maxBufferSize); + break; + case LANGUAGE_GER: + msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetGerman(MF_RAW), buffer, maxBufferSize); + break; + case LANGUAGE_ENG: + default: + msgCtx->msgLength = font->msgLength = CopyStringToCharBuffer(GetEnglish(MF_RAW), buffer, maxBufferSize); + break; + } +} + void CustomMessage::Replace(std::string&& oldStr, std::string&& newStr) { for (std::string& str : messages) { size_t position = str.find(oldStr); diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 71ae423b5..ffb8d8d8c 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -83,6 +83,8 @@ class CustomMessage { bool operator==(const std::string& operand) const; bool operator!=(const CustomMessage& right) const; + void LoadIntoFont(); + /** * @brief Finds an instance of oldStr in each language of the CustomMessage * and replaces it with newStr. Typically used for dynamic variable replacement diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/ItemMessages.cpp index a879f5d87..828958937 100644 --- a/soh/soh/Enhancements/randomizer/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/ItemMessages.cpp @@ -1,14 +1,12 @@ -#include "soh/Enhancements/game-interactor/GameInteractor.h" +#include +#include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" #include "soh/ShipInit.hpp" -#include "randomizer.h" +#include extern "C" { #include #include -#include -#include -#include extern PlayState* gPlayState; } @@ -362,22 +360,23 @@ void BuildCustomItemMessage(Player* player, CustomMessage& msg) { rgid = player->getItemId; } CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); - name.Replace("[[name]]", name); - name.AutoFormat(); + msg.Replace("[[name]]", name); + msg.AutoFormat(); } void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { Player* player = GET_PLAYER(gPlayState); - CustomMessage messageEntry; + CustomMessage msg; if (player->getItemEntry.getItemId == RG_ICE_TRAP) { - BuildIceTrapMessage(messageEntry); + BuildIceTrapMessage(msg); } else if (player->getItemEntry.getItemId == RG_TRIFORCE_PIECE) { - BuildTriforcePieceMessage(messageEntry); + BuildTriforcePieceMessage(msg); } else { - BuildCustomItemMessage(player, messageEntry); + BuildCustomItemMessage(player, msg); } *loadFromMessageTable = false; + msg.LoadIntoFont(); } void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { @@ -434,6 +433,7 @@ void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage()); } *loadFromMessageTable = false; + msg.LoadIntoFont(); } void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { @@ -447,6 +447,7 @@ void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; BuildCustomItemMessage(player, msg); *loadFromMessageTable = false; + msg.LoadIntoFont(); } void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { @@ -460,6 +461,7 @@ void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; BuildCustomItemMessage(player, msg); *loadFromMessageTable = false; + msg.LoadIntoFont(); } void RegisterItemMessages () { diff --git a/soh/src/code/z_message_PAL.c b/soh/src/code/z_message_PAL.c index c7ad0ec1f..054998af4 100644 --- a/soh/src/code/z_message_PAL.c +++ b/soh/src/code/z_message_PAL.c @@ -2713,7 +2713,7 @@ void Message_OpenText(PlayState* play, u16 textId) { Font* font = &msgCtx->font; s16 textBoxType; - bool loadFromMessageTable = false; + bool loadFromMessageTable = true; GameInteractor_ExecuteOnOpenText(&textId, &loadFromMessageTable); sDisplayNextMessageAsEnglish = false; From 136e13ded7398fc717259ce924953c2452a456d0 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 20:58:51 -0500 Subject: [PATCH 059/103] Remove now-unused code --- .../Enhancements/randomizer/randomizer.cpp | 818 ------------------ soh/soh/Enhancements/randomizer/randomizer.h | 3 - soh/soh/OTRGlobals.cpp | 30 +- 3 files changed, 1 insertion(+), 850 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index d567a3d8e..987a6d473 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4459,67 +4459,6 @@ CustomMessage Randomizer::GetMerchantMessage(RandomizerCheck rc, TextIDs textId, return messageEntry; } -CustomMessage Randomizer::GetMapGetItemMessageWithHint(GetItemEntry itemEntry) { - CustomMessage messageEntry = - CustomMessageManager::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, itemEntry.getItemId); - int sceneNum; - switch (itemEntry.getItemId) { - case RG_DEKU_TREE_MAP: - sceneNum = SCENE_DEKU_TREE; - break; - case RG_DODONGOS_CAVERN_MAP: - sceneNum = SCENE_DODONGOS_CAVERN; - break; - case RG_JABU_JABUS_BELLY_MAP: - sceneNum = SCENE_JABU_JABU; - break; - case RG_FOREST_TEMPLE_MAP: - sceneNum = SCENE_FOREST_TEMPLE; - break; - case RG_FIRE_TEMPLE_MAP: - sceneNum = SCENE_FIRE_TEMPLE; - break; - case RG_WATER_TEMPLE_MAP: - sceneNum = SCENE_WATER_TEMPLE; - break; - case RG_SPIRIT_TEMPLE_MAP: - sceneNum = SCENE_SPIRIT_TEMPLE; - break; - case RG_SHADOW_TEMPLE_MAP: - sceneNum = SCENE_SHADOW_TEMPLE; - break; - case RG_BOTTOM_OF_THE_WELL_MAP: - sceneNum = SCENE_BOTTOM_OF_THE_WELL; - break; - case RG_ICE_CAVERN_MAP: - sceneNum = SCENE_ICE_CAVERN; - break; - } - - if (GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_NONE || - (GetRandoSettingValue(RSK_MQ_DUNGEON_RANDOM) == RO_MQ_DUNGEONS_SET_NUMBER && - GetRandoSettingValue(RSK_MQ_DUNGEON_COUNT) == 12)) { - messageEntry.Replace("[[typeHint]]", ""); - } else if (ResourceMgr_IsSceneMasterQuest(sceneNum)) { - messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_MASTERFUL].GetHintMessage()); - } else { - messageEntry.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_ORDINARY].GetHintMessage()); - } - - return messageEntry; -} - -template void CreateGetItemMessages(const std::array& messageEntries) { - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(Randomizer::getItemMessageTableID); - for (const GetItemMessage& messageEntry : messageEntries) { - customMessageManager->CreateGetItemMessage( - Randomizer::getItemMessageTableID, messageEntry.giid, messageEntry.iid, - CustomMessage(messageEntry.english, messageEntry.german, messageEntry.french, TEXTBOX_TYPE_BLUE, - TEXTBOX_POS_BOTTOM)); - } -} - void CreateRupeeMessages() { CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); @@ -4555,77 +4494,6 @@ CustomMessage Randomizer::GetRupeeMessage(u16 rupeeTextId) { return messageEntry; } -void CreateTriforcePieceMessages() { - CustomMessage TriforcePieceMessages[NUM_TRIFORCE_PIECE_MESSAGES] = { - - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", - "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à " - "trouver. C'est un début!" }, - - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", - "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à " - "trouver. Ça avance!" }, - - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", - "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über die " - "Hälfte!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à " - "trouver. Il en reste un&peu moins que la moitié!" }, - - { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", - "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à " - "trouver. C'est presque&terminé!" }, - - { "You completed the %yTriforce of&Courage%w! %gGG%w!", - "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", - "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }, - - { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", - "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", - "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, mais " - "vous en avez %g[[current]]%w en&tout!" }, - }; - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(Randomizer::triforcePieceMessageTableID); - for (unsigned int i = 0; i <= (NUM_TRIFORCE_PIECE_MESSAGES - 1); i++) { - customMessageManager->CreateMessage(Randomizer::triforcePieceMessageTableID, i, TriforcePieceMessages[i]); - } -} - -CustomMessage Randomizer::GetTriforcePieceMessage() { - // Item is only given after the textbox, so reflect that inside the textbox. - uint8_t current = gSaveContext.ship.quest.data.randomizer.triforcePiecesCollected + 1; - uint8_t required = OTRGlobals::Instance->gRandomizer->GetRandoSettingValue(RSK_TRIFORCE_HUNT_PIECES_REQUIRED) + 1; - uint8_t remaining = required - current; - float percentageCollected = (float)current / (float)required; - uint8_t messageIndex; - - if (percentageCollected <= 0.25) { - messageIndex = TH_MESSAGE_START; - } else if (percentageCollected <= 0.5) { - messageIndex = TH_MESSAGE_PROGRESS; - } else if (percentageCollected <= 0.75) { - messageIndex = TH_MESSAGE_HALFWAY; - } else if (percentageCollected < 1) { - messageIndex = TH_MESSAGE_ALMOSTDONE; - } else if (current == required) { - messageIndex = TH_MESSAGE_FINISHED; - } else { - messageIndex = TH_MESSAGE_SURPLUS; - } - - CustomMessage messageEntry = - CustomMessageManager::Instance->RetrieveMessage(Randomizer::triforcePieceMessageTableID, messageIndex); - messageEntry.Replace("[[current]]", std::to_string(current)); - messageEntry.Replace("[[remaining]]", std::to_string(remaining)); - messageEntry.Replace("[[required]]", std::to_string(required)); - messageEntry.Format(); - return messageEntry; -} - void CreateNaviRandoMessages() { CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { @@ -4739,320 +4607,6 @@ void CreateNaviRandoMessages() { } } -CustomMessage Randomizer::GetIceTrapMessage() { - static const char* const englishIceTrapMessages[169] = { - "You are a #FOOL#!", - "You are a #FOWL#!", - "#FOOL#!", - "You just got #PUNKED#!", - "Stay #frosty#, @.", - "Take a #chill pill#, @.", - "#Winter# is coming.", - "#ICE# to see you, @.", - "Feeling a little %rhot%w under the collar? #Let's fix that#.", - "It's a #cold day# in the Evil Realm.", - "Getting #cold feet#?", - "Say hello to the #Zoras# for me!", - "Can you keep a #cool head#?", - "Ganondorf used #Ice Trap#!&It's super effective!", - "Allow me to break the #ice#!", - "#Cold pun#.", - "The #Titanic# would be scared of you, @.", - "Oh no!", - "Uh oh!", - "What killed the dinosaurs?&The #ICE# age!", - "Knock knock. Who's there? Ice. Ice who? Ice see that you're a #FOOL#.", - "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", - "Thank you #@#! But your item is in another castle!", - "#FREEZE#! Don't move!", - "Wouldn't it be #ice# if we were colder?", - "Greetings from #Snowhead#! Wish you were here.", - "Too #cool# for you?", - "#Ice#, #ice#, baby...", - "Time to break the #ice#.", - "We wish that you would read this... We wish that you would read this... But we set our bar low.", - "#Freeze# and put your hands in the air!", - "#Ice# to meet you!", - "Do you want to #freeze# a snowman?", - "Isn't there a #mansion# around here?", - "Now you know how #King Zora# feels.", - "May the #Frost# be with you.", - "Carpe diem. #Freeze# the day.", - "There #snow# place like home.", - "That'll do, #ice#. That'll do.", - "All that is #cold# does not glitter. Not all those who wander are #frost#.", - "I Used To Be An Adventurer Like You. Then I Took An #Icetrap# To The Knee.", - "Would you like #ice# with that?", - "You have obtained the #Ice# Medallion!", - "Quick, do a #Zora# impression!", - "One item #on the rocks#!", // would be better if it could display the name of the item - "How much does a polar bear weigh?&Enough to break the #ice#.", - "You got Din's #Ice#!", - "You got Nayru's #Cold#!", - "You got Farore's #Freeze#!", - "KEKW", - "You just got #ICE TRAPPED#! Tag your friends to totally #ICE TRAP# them!", - "Are you okay, @? You're being #cold# today.", - "In a moment, your game might experience some #freezing#.", - "Breeze? Trees? Squeeze? No, it's a #freeze#!", - "After collecting this item, @ was assaulted in #cold# blood.", - "Only #chill# vibes around here!", - "Here's a #cool# gift for you!", - "Aha! You THOUGHT.", - "Stay hydrated and brush your teeth!", - "Isn't it too hot here? Let's turn the #AC# on.", - "One serving of #cold# @, coming right up!", - "Is it #cold# in here or is that just me?", - "Yahaha! You found me!", - "You'd make a great #ice#-tronaut!", - "That's just the tip of the #iceberg#!", - "It's the triforce!&No, just kidding, it's an #ice trap#.", - "WINNER!", - "LOSER!", - "Greetings from #Cold Miser#!", - "Pardon me while I turn up the #AC#.", - "If you can't stand the #cold#, get out of the #freezer#.", - "Oh, goodie! #Frozen @# for the main course!", - "You have #freeze# power!", - "You obtained the #Ice Beam#! No wait, wrong game.", - "Here's to another lousy millenium!", - "You've activated my #trap card#!", - "I love #refrigerators#!", - "You expected an item,&BUT IT WAS I, AN #ICE TRAP#!", - "It's dangerous to go alone! Take #this#!", - "soh.exe has #stopped responding#.", - "Enough! My #Ice Trap# thaws in the morning!", - "Nobody expects the span-#ice# inquisition!", - "This is one #cool# item!", - "Say hello to my #little friend#!", - "We made you an offer you #can't refuse#.", - "Hyrule? More like #Hycool#!", - "Ice puns are #snow# problem!", - "This #ice# is #snow# joke!", - "There's no business like #snow# business!", - "No, dude.", - "N#ice# trap ya got here!", - "Quick do your best impression of #Zoras Domain#!", - "Ganon used #ice beam#, it's super effective!", - "I was #frozen# today.", - "You're not in a #hurry#, right?", - "It's a #trap#!", - "At least it's not a VC crash and only Link is #frozen#!", - "Oh no! #BRAIN FREEZE#!", - "Looks like your game #froze#! Nope just you!", - "PK #FREEZE#!", - "May I interest you in some #iced# Tea?", - "Time for some Netflix and #chill#.", - "I know, I know... #FREEZE#!", - "#Ice# of you to drop by!", - "STOP!&You violated the #Thaw#!", - "I wanted to give you a treasure, but it looks like you got #cold feet#.", - "You told me you wanted to deliver #just ice# to Ganondorf!", - "You got the triforce!&This ancient artifact of divine power can grant any- wait, no, sorry, it's just an ice " - "trap. My bad.", - "Time to #cool off#!", - "The #Ice Cavern# sends its regards.", - "Loading item, please #wait#...", - "Mash A+B to not #die#.", - "Sorry, your item is in another location.", // would be better if it could have the name of the item - "You only wish this was %gGreg%w.", - "Do you want to drink a hot chocolate?", - "The #cold# never bothered me anyway.", - "Hope you're too school for #cool#!", - "Be thankful this isn't #absolute zero#.", - "Did you know the F in ZFG stands for #Freeze#?", - "You got #Ice Age (2002)#!", - "Now you can cast a #spell# you don't know.", - "How's about a hero #on the rocks#?", - "Ain't no tunic for #this#!", - "I knew you were #part metroid#!", - "That's just the #icing on the cake#!", - "You're so #cool#, @!", - "You found #disappointment#!", - "You got #FOOLED#!", - "Start Mashing.", - "This item will #self-destruct# in 5 seconds...", - "Remember, there may be some momentary #discomfort#.", - "In a perfect world #ice traps# like me would not exist, but this is not a perfect world.", - "Gee, it sure is #cold# around here.", - "You tested the item with your #ice detector#, it beeped.", // would be better if it could have the name of the - // item - "You have found the way of the zero. The #sub-zero#.", - "Mweep... mweep... mweep...", - "Scum, #freezebag#! I mean #freeze#, scumbag!", - "Is it #chilly# in here or is it just #you#?", - "#Proceed#.", - "WHAT'S SHE GONNA DO, MAKE ME AN #[Ice Cream]#!?", - "You've met with a #terrible fate#, haven't you?", - "So I heard you like the Shining, here's how it #ends#.", - "Minor routing mistake. #I win#.", - "Hold this #L#, @.", - "#SKILL ISSUE#.", - "All your heat are belong to us.", - "Wait a second, don't you already have #this item#?", - "#Freeze#! We have you surrounded!", - "Error 404 - Item not #found#.", - "Hydration break! Hey, who #froze# my water?", - "Oops, wrong #item model#.", - "Whoops! You have to put the item #in your inventory#.", - "You dropped the item, shattering it into #shards of ice#!", // would be better if it could have the name of the - // item - "Is this... golden age Simpsons?&BECAUSE I'M ABOUT TO #CHOKE A CHILD#.", - "You are the weakest @, #goodbye#!", - "Ugh... Why did we even randomize #this item#?", - "The #Frost Moon# is rising...", - "According to all known laws of physics and biology, there is no way that @ should be able to survive #getting " - "fully encased in ice#. The cells in @'s body would all die by the time they #unthaw#. Of course, this is a " - "video game, so @ survives anyway... #Probably#.", - "Okay, so stop me if you've heard this one - a gamer and a bottle of #liquid nitrogen# walk into a milk bar...", - "Lástima, es una #trampa de hielo#...&&Nobody expects the Spanish #ice trap#!", - "Gee, it sure is #BURR#ing around here.", - "Navi? Oh! I thought she was called #Névé#!", - "It's fine, @ knew this was a #trap#, they're just using it to take damage intentionally to manipulate RNG.", - "Unfortunately, the item has #stopped#.", // would be better if it could have the name of the item - "This item is #not available# in your country.", // would be better if it could have the name of the item - "#Ice# try. #;)#", - "D'oh, I #missed#!", - "Where is my #super suit#?", - "#Titanic's revenge#.", - }; - - static const char* const germanIceTrapMessages[23] = { - "Du bist ein #DUMMKOPF#!", - "Du bist eine #Frostbeule#!", - "#DUMMKOPF#!", - "Du wurdest #eiskalt# erwischt!", - "Es läuft Dir #eiskalt# den Rücken hinunter, @.", - "Bleib #cool#, @.", - "Der #Winter# naht.", - "Alles #cool# im Pool?", - "#Abkühlung gefällig#?", - "Es ist ein %kalter%w Tag im Herzen von Hyrule.", - "Bekommst Du etwa #kalte# Füße?", - "Sag den #Zoras# viele Grüße von mir!", - "Bewahre einen #kühlen#! Kopf.", - "Ganondorf setzt #Eisstrahl# ein. Das ist sehr effektiv!", - "Ein Lächeln ist der beste Weg, um das #Eis# zu brechen!", - "#Eiskalt# lässt du meine Seele erfrier'n.", - "Die #Titanic# hätte Angst vor Dir, @.", - "Oh nein!", - "Was die Dinosaurier getötet hat?&Die #Eiszeit#!", - "Nachts ist es #kälter# als draußen.", - "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", - "Danke #@#! Aber der Gegenstand ist in einem anderem Schloß!", - "Kalt. Kalt. Kälter. #EISKALT#!", - }; - - static const char* const frenchIceTrapMessages[83] = { - "#Pauvre fou#...", - "Tu es un #glaçon#, Harry!", - "#Sot# que tu es.", - "Ça me #glace# le sang!", - "#Reste au frais#, @.", - "Et c'est la douche #froide#!", - "L'#hiver# vient.", - "#Glacier#!", - "Ça en jette un #froid#.", - "Est-ce que tu as déjà eu des sueurs #froides#?", - "La vengeance est un plat qui se mange #froid#!", - "Dit bonjour aux #Zoras# pour moi!", - "Il faut parfois savoir garder la tête #froide#!", - "Ganondorf utilise #Piège de Glace#! C'est super efficace!", - "Laisse moi briser la #glace#!", - "Balance man..., Cadence man..., Trace la #glace#..., c'est le Cooooolllll Rasta!", - "Le #Titanic# aurait peur de toi, @.", - "Oh non!", - "Qu'est-ce qui a tué les dinosaures?&L'ère #glacière#!", - "L'imbécile réfléchit uniquement quand il s'observe dans la #glace#.", - "Never gonna #give you up#. Never gonna #let you down#. Never gonna run around and #desert you#.", - "Merci #@#! Mais ton objet est dans un autre château!", - "J'espère que ça ne te fait ni chaud, ni #froid#.", - "Je voulais t'offrir un trésor, mais il semble que tu aies eu #froid aux pieds#", - "Tu m'as dit que tu voulais livrer #de la glace# à Ganondorf!", - "Tu as obtenu la Triforce!&Cet ancien artefact divin peut exaucer n'importe quel... ah non, désolé, c'est " - "juste un piège de glace.", - "Il est temps de #te rafraîchir#!", - "La #Caverne Polaire# te passe le bonjour.", - "Chargement de l'objet, veuillez #patienter#...", - "Martèle A+B pour ne pas #mourir#.", - "Désolé, ton objet est à un autre endroit.", // would be better if it could have the name of the item - "Tu espérais que ce soit %gGreg%w.", - "Tu veux boire un chocolat chaud?", - "Le #froid# ne m'a jamais dérangé, de toute façon.", - "J'espère que tu es trop cool pour être #cool#!", - "Sois reconnaissant que ce n'est pas le #zéro absolu#.", - "Tu savais que le G de ZFG signifie #Glace#?", - "Tu as obtenu #L'Âge de Glace (2002)#!", - "Maintenant, tu peux lancer un #sort# que tu ne connais pas.", - "Que dirais-tu d'un héros #sur glace# ?", - "Pas de tunique pour #ça#!", - "Je savais que tu étais #partiellement Metroid#!", - "Voilà juste la #cerise sur le gâteau#!", - "Tu es tellement #cool#, @!", - "Tu as trouvé de la #déception#!", - "Tu t'es fait #BERNER#!", - "Commence à marteler.", - "Cet objet va #s'autodétruire# dans 5 secondes...", - "Souviens-toi, il pourrait y avoir un léger #inconfort#.", - "Dans un monde parfait, les #pièges de glace# comme moi n'existeraient pas, mais ce n'est pas un monde " - "parfait.", - "Mon dieu qu'il fait #froid# ici.", - "Tu as testé l'objet avec ton #détecteur de glace#, il a bipé.", // would be better if it could have the name of - // the item - "Tu as découvert le chemin du zéro. Le #sub-zéro#.", - "Mweep... mweep... mweep...", - "Gelé, #sac à glace#! Je veux dire #gèle-toi#, racaille!", - "Est-ce qu'il fait #frais# ici ou est-ce juste #toi#?", - "#Continue#", - "QU'EST-CE QU'ELLE VA FAIRE, ME FAIRE UNE #[Glace]#!?", - "Tu as rencontré un #terrible destin#, n'est-ce pas?", - "Alors comme ça, tu aimes Shining ? Voici comment ça #finit#.", - "Petite erreur de trajectoire. #Je gagne#.", - "Prends ce #L#, @.", - "#Problème de compétence#", - "Tout ton chauffage nous appartient.", - "Attends une seconde, tu as déjà #cet objet#, non?", - "#Gèle#! Tu es entouré !", - "Erreur 404 - Objet non #trouvé#.", - "Pause hydratation ! Hé, qui a #gelé# mon eau?", - "Oups, mauvais #modèle d'objet#.", - "Oups! Tu dois mettre l'objet #dans ton inventaire#.", - "Tu as fait tomber l'objet, le brisant en #éclats de glace#!", // would be better if it could have the name of - // the item - "Tu es le maillon faible @, #au revoir#!", - "Ugh... Pourquoi avons-nous même randomisé #cet objet#?", - "La #Lune de Givre# se lève...", - "Selon toutes les lois connues de la physique et de la biologie, @ ne devrait pas survivre à #être " - "complètement enfermé dans la glace#. Les cellules de @ mourraient avant qu'elles ne #dégèlent#. Mais c'est un " - "jeu vidéo, alors @ survit... #Probablement#.", - "OK, arrête-moi si tu l'as déjà entendue - un joueur et une bouteille de #nitrogène liquide# entrent dans un " - "bar à lait...", - "Lástima, c'est un #piège de glace#...&&Personne ne s'attend à un #piège de glace espagnol#!", - "Mon dieu qu'il fait #GLAGLA# ici.", - "C'est bon, @ savait que c'était un #piège#, il l'utilise juste pour prendre des dégâts intentionnellement et " - "manipuler la RNG.", - "Cet objet n'est #pas disponible# dans votre pays.", // would be better if it could have the name of the item - "#Bonne# tentative. #;)#", - "Où est mon #Super Costume#?", - "#La revanche du Titanic#.", - }; - - CustomMessage msg; - - if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { - msg = CustomMessage( - /*english*/ "This year for Christmas, all you get is #COAL#!", - /*german*/ "This year for Christmas, all you get is #COAL#!", - /*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", { QM_BLUE }); - } else { - msg = CustomMessage(RandomElement(englishIceTrapMessages), RandomElement(germanIceTrapMessages), - RandomElement(frenchIceTrapMessages), { QM_BLUE, QM_BLUE, QM_BLUE }); - } - - msg.AutoFormat(); - return msg; -} - static int goronIDs[9] = { TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME, TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET, TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET, @@ -5154,379 +4708,7 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { } void Randomizer::CreateCustomMessages() { - // RANDTODO: Translate into french and german and replace GIMESSAGE_UNTRANSLATED - // with GIMESSAGE(getItemID, itemID, english, german, french). - const std::array getItemMessages = { { - GIMESSAGE(RG_GREG_RUPEE, ITEM_MASK_GORON, "You found %gGreg%w!", "%gGreg%w! Du hast ihn wirklich gefunden!", - "Félicitation! Vous avez trouvé %gGreg%w!"), - GIMESSAGE(RG_MASTER_SWORD, ITEM_SWORD_MASTER, "You found the %gMaster Sword%w!", - "Du erhältst das %gMaster-Schwert%w!", "Vous obtenez %gl'Épée de Légende%w!"), - GIMESSAGE( - RG_BOTTLE_WITH_BLUE_FIRE, ITEM_BLUE_FIRE, "You got a %rBottle with Blue &Fire%w! Use it to melt Red Ice!", - "Du erhältst eine %rFlasche mit&blauem Feuer%w! Nutze es um&%rRotes Eis%w zu schmelzen!", - "Vous obtenez une %rBouteille avec&une Flamme Bleue%w! Utilisez-la&pour faire fondre la %rGlace&Rouge%w!"), - GIMESSAGE(RG_BOTTLE_WITH_BIG_POE, ITEM_BIG_POE, "You got a %rBig Poe in a Bottle%w!&Sell it to the Ghost Shop!", - "Du hast einen %rNachtschwärmer%w&in einer Flasche gefangen!&Gehe zum %rGespenstermarkt%w&und " - "verkaufe ihn!", - "Vous obtenez une %rBouteille avec&une Âme%w! Vendez-la au Marchand&d'Âme"), - GIMESSAGE( - RG_BOTTLE_WITH_BLUE_POTION, ITEM_POTION_BLUE, - "You got a %rBottle of Blue Potion%w!&Drink it to replenish your&%ghealth%w and %bmagic%w!", - "Du erhältst ein %rBlaues Elixier%w!&Nutze es, um Deine %rMagie- und&Energieleiste%w komplett&aufzufüllen!", - "Vous obtenez une %rBouteille avec&une Potion Bleue%w! Buvez-la pour&restaurer votre %rénergie " - "vitale%w&ainsi que votre %gmagie%w!"), - GIMESSAGE(RG_BOTTLE_WITH_FISH, ITEM_FISH, - "You got a %rFish in a Bottle%w!&It looks fresh and delicious!&They say Jabu-Jabu loves them!", - "Du hast jetzt einen %rFisch in&einer Flasche%w! Er sieht richtig&frisch aus! Man sagt,&Lord " - "Jabu-Jabu liebt Fische!", - "Vous obtenez une %rBouteille avec&un Poisson%w! Il a l'air délicieux!&Il paraîtrait que %bJabu-Jabu " - "%wen&serait friand!"), - GIMESSAGE(RG_BOTTLE_WITH_BUGS, ITEM_BUG, "You got a %rBug in a Bottle%w!&They love to burrow in&dirt holes!", - "Du hast jetzt %rKäfer in einer&Flasche&%w!&Sie graben gerne&in Erdlöchern.", - "Vous obtenez une %rBouteille avec&des Insectes%w! Ils adorent creuser&dans la terre meuble!"), - GIMESSAGE(RG_BOTTLE_WITH_FAIRY, ITEM_FAIRY, "You got a %rFairy in a Bottle%w!&Use it wisely!", - "Du hast jetzt eine %rFee in einer&Flasche%w! Nutze sie weise!", - "Vous obtenez une %rBouteille avec&une Fée%w! Faites-en bon usage!"), - GIMESSAGE( - RG_BOTTLE_WITH_RED_POTION, ITEM_POTION_RED, - "You got a %rBottle of Red Potion%w!&Drink it to replenish your&%ghealth%w!", - "Du erhältst ein %rRotes Elixier%w!&Nutze es, um Deine %rEnergieleiste&%weinmalig komplett aufzufüllen!", - "Vous obtenez une %rBouteille avec&une Potion Rouge%w! Buvez-la pour&restaurer votre %rénergie vitale%w!"), - GIMESSAGE( - RG_BOTTLE_WITH_GREEN_POTION, ITEM_POTION_GREEN, - "You got a %rBottle of Green Potion%w!&Drink it to replenish your&%bmagic%w!", - "Du erhältst ein %rGrünes Elixier%w!&Nutze es, um Deine %bMagieleiste&%weinmalig komplett aufzufüllen!", - "Vous obtenez une %rBouteille avec&une Potion Verte%w! Buvez-la pour&restaurer votre %gmagie%w!"), - GIMESSAGE(RG_BOTTLE_WITH_POE, ITEM_POE, - "You got a %rPoe in a Bottle%w!&That creepy Ghost Shop might&be interested in this...", - "Du hast jetzt ein %rIrrlicht in einer&Flasche%w! Der %rGespenstermarkt%w&interessiert sich für " - "vielleicht&dafür...", - "Vous obtenez une %rBouteille avec&un Esprit%w! Ça intéresserait&peut-être le vendeur d'Âme "), - - GIMESSAGE(RG_GERUDO_FORTRESS_SMALL_KEY, ITEM_KEY_SMALL, "You found a %yThieves Hideout &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %yDiebesversteck%w!", - "Vous obtenez une %rPetite Clé %w&du %yRepaire des Voleurs%w!"), - GIMESSAGE(RG_FOREST_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %gForest Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gWaldtempel%w!", - "Vous obtenez une %rPetite Clé %w&du %gTemple de la Forêt%w!"), - GIMESSAGE(RG_FIRE_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rFire Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %rFeuertempel%w!", - "Vous obtenez une %rPetite Clé %w&du %rTemple du Feu%w!"), - GIMESSAGE(RG_WATER_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %bWater Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %bWassertempel%w!", - "Vous obtenez une %rPetite Clé %w&du %bTemple de l'Eau%w!"), - GIMESSAGE(RG_SPIRIT_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %ySpirit Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %yGeistertempel%w!", - "Vous obtenez une %rPetite Clé %w&du %yTemple de l'Esprit%w!"), - GIMESSAGE(RG_SHADOW_TEMPLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pShadow Temple &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %pSchattentempel%w!", - "Vous obtenez une %rPetite Clé %w&du %pTemple de l'Ombre%w!"), - GIMESSAGE(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, ITEM_KEY_SMALL, "You found a %pBottom of the &Well %wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %pGrund des Brunnens%w!", - "Vous obtenez une %rPetite Clé %w&du %pPuits%w!"), - GIMESSAGE(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, ITEM_KEY_SMALL, - "You found a %yGerudo Training &Ground %wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %yGerudo-Trainingsgelände%w!", - "Vous obtenez une %rPetite Clé %w&du %yGymnase Gerudo%w!"), - GIMESSAGE(RG_GANONS_CASTLE_SMALL_KEY, ITEM_KEY_SMALL, "You found a %rGanon's Castle &%wSmall Key!", - "Du erhältst einen %rkleinen&Schlüssel%w für %rGanons Schloß%w!", - "Vous obtenez une %rPetite Clé %w&du %rChâteau de Ganon%w!"), - GIMESSAGE(RG_GUARD_HOUSE_KEY, ITEM_KEY_SMALL, "You found the key to the&%gGuard House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus der Wachen%w!", - "Vous obtenez la %rClé %wde la&%gMaison des Gardes%w!"), - GIMESSAGE(RG_MARKET_BAZAAR_KEY, ITEM_KEY_SMALL, "You found the key to the&%gMarket Bazaar%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar des Marktes%w!", - "Vous obtenez la %rClé %wdu %gBazar&de la Place du Marché%w!"), - GIMESSAGE(RG_MARKET_POTION_SHOP_KEY, ITEM_KEY_SMALL, "You found the key to the&%gMarket Potion Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden des Marktes%w!", - "Vous obtenez la %rClé %wde la&%gPlace du Marché%w!"), - GIMESSAGE(RG_MASK_SHOP_KEY, ITEM_KEY_SMALL, "You found the key to the&%gMask Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gMaskenladen%w!", - "Vous obtenez la %rClé %wde la&%gFoire aux Masques%w!"), - GIMESSAGE(RG_MARKET_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gMarket Shooting Gallery%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude des Marktes%w!", - "Vous obtenez la %rClé %wdu %gStand de&Tir de la Place du Marché%w!"), - GIMESSAGE(RG_BOMBCHU_BOWLING_KEY, ITEM_KEY_SMALL, "You found the key to the&%gBombchu Bowling Alley%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gMinenbowlingbahn%w!", - "Vous obtenez la %rClé %wdu %gBowling&Teigneux%w!"), - GIMESSAGE(RG_TREASURE_CHEST_GAME_BUILDING_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gTreasure Chest Game Building%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Schatzkisten-Pokers%w!", - "Vous obtenez la %rClé %wdu %gJeu de la&Chasse au Trésor%w!"), - GIMESSAGE(RG_BOMBCHU_SHOP_KEY, ITEM_KEY_SMALL, "You found the key to the&%gBombchu Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gKrabbelminenladen%w!", - "Vous obtenez la %rClé %wdu %gMagasin&de Missiles%w!"), - GIMESSAGE(RG_RICHARDS_HOUSE_KEY, ITEM_KEY_SMALL, "You found the key to&%gRichard's House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Richard%w!", - "Vous obtenez la %rClé %wde la %gMaison&de Kiki%w!"), - GIMESSAGE(RG_ALLEY_HOUSE_KEY, ITEM_KEY_SMALL, "You found the key to&the %gAlley House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus in der Gasse%w!", - "Vous obtenez la %rClé %wde la %gMaison&de la Ruelle%w!"), - GIMESSAGE(RG_KAK_BAZAAR_KEY, ITEM_KEY_SMALL, "You found the key to the&%gKakariko Bazaar%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gBasar von Kakariko%w!", - "Vous obtenez la %rClé %wdu %gBazar&de Cocorico%w!"), - GIMESSAGE(RG_KAK_POTION_SHOP_KEY, ITEM_KEY_SMALL, "You found the key to the&%gKakariko Potion Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gMagie-Laden von Kakariko%w!", - "Vous obtenez la %rClé %wdu %gMagasin de&Potions de Cocorico%w!"), - GIMESSAGE(RG_BOSS_HOUSE_KEY, ITEM_KEY_SMALL, "You found the key to the&%gBoss's House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus des Chefs%w!", - "Vous obtenez la %rClé %wde la %gMaison&du chef des ouvriers%w!"), - GIMESSAGE(RG_GRANNYS_POTION_SHOP_KEY, ITEM_KEY_SMALL, "You found the key to&%gGranny's Potion Shop%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für %gAsas Hexenladen%w!", - "Vous obtenez la %rClé %wde&l'%gApothicaire%w!"), - GIMESSAGE(RG_SKULLTULA_HOUSE_KEY, ITEM_KEY_SMALL, "You found the key to the&%gSkulltula House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gSkulltula-Haus%w!", - "Vous obtenez la %rClé %wde la %gMaison&des Araignées%w!"), - GIMESSAGE(RG_IMPAS_HOUSE_KEY, ITEM_KEY_SMALL, "You found the key to&%gImpa's House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Impa%w!", - "Vous obtenez la %rClé %wde la %gMaison&d'Impa%w!"), - GIMESSAGE(RG_WINDMILL_KEY, ITEM_KEY_SMALL, "You found the key to the&%gWindmill%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gWindmühle%w!", - "Vous obtenez la %rClé %w du %gMoulin%w!"), - GIMESSAGE(RG_KAK_SHOOTING_GALLERY_KEY, ITEM_KEY_SMALL, - "You found the key to the&%gKakariko Shooting Gallery%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gSchießbude von Kakariko%w!", - "Vous obtenez la %rClé %w du %gStand de&Tir de Cocorico%w!"), - GIMESSAGE(RG_DAMPES_HUT_KEY, ITEM_KEY_SMALL, "You found the key to&%gDampe's Hut%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gHütte von Boris%w!", - "Vous obtenez la %rClé %wde la %gCabane&d'Igor%w!"), - GIMESSAGE(RG_TALONS_HOUSE_KEY, ITEM_KEY_SMALL, "You found the key to&%gTalon's House%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHaus von Talon%w!", - "Vous obtenez la %rClé %wde la %gMaison&de Talon%w!"), - GIMESSAGE(RG_STABLES_KEY, ITEM_KEY_SMALL, "You found the key to the&%gStables%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für die %gStälle%w!", - "Vous obtenez la %rClé %wdes %gÉcuries%w!"), - GIMESSAGE(RG_BACK_TOWER_KEY, ITEM_KEY_SMALL, "You found the key to the&%gBack Tower%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %ghinteren Turm%w!", - "Vous obtenez la %rClé %wdu %gSilo%w!"), - GIMESSAGE(RG_HYLIA_LAB_KEY, ITEM_KEY_SMALL, "You found the key to the&%gHylia Laboratory%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für das %gHylia-Labor%w!", - "Vous obtenez la %rClé %wdu %gLaboratoire&du Lac Hylia%w!"), - GIMESSAGE(RG_FISHING_HOLE_KEY, ITEM_KEY_SMALL, "You found the key to the&%gPond%w!", - "Du erhältst einen %rkleinen&Schlüssel%w für den %gFischweiher%w!", - "Vous obtenez la %rClé %wde l'%gÉtang%w!"), - - GIMESSAGE(RG_GERUDO_FORTRESS_KEY_RING, ITEM_KEY_SMALL, "You found a %yThieves Hideout&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für das %yDiebesversteck%w!", - "Vous obtenez le trousseau de&clés du %yRepaire des Voleurs%w!"), - GIMESSAGE(RG_FOREST_TEMPLE_KEY_RING, ITEM_KEY_SMALL, "You found a %gForest Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %gWaldtempel%w!", - "Vous obtenez le trousseau de&clés du %gTemple de la Forêt%w!"), - GIMESSAGE(RG_FIRE_TEMPLE_KEY_RING, ITEM_KEY_SMALL, "You found a %rFire Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %rFeuertempel%w!", - "Vous obtenez le trousseau de&clés du %rTemple du Feu%w!"), - GIMESSAGE(RG_WATER_TEMPLE_KEY_RING, ITEM_KEY_SMALL, "You found a %bWater Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %bWassertempel%w!", - "Vous obtenez le trousseau de&clés du %bTemple de l'Eau%w!"), - GIMESSAGE(RG_SPIRIT_TEMPLE_KEY_RING, ITEM_KEY_SMALL, "You found a %ySpirit Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %yGeistertempel%w!", - "Vous obtenez le trousseau de&clés du %yTemple de l'Esprit%w!"), - GIMESSAGE(RG_SHADOW_TEMPLE_KEY_RING, ITEM_KEY_SMALL, "You found a %pShadow Temple&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %pSchattentempel%w!", - "Vous obtenez le trousseau de&clés du %pTemple de l'Ombre%w!"), - GIMESSAGE(RG_BOTTOM_OF_THE_WELL_KEY_RING, ITEM_KEY_SMALL, "You found a %pBottom of the&Well %wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für den %pGrund des Brunnens%w!", - "Vous obtenez le trousseau de&clés du %pPuits%w!"), - GIMESSAGE(RG_GERUDO_TRAINING_GROUND_KEY_RING, ITEM_KEY_SMALL, "You found a %yGerudo Training&Ground %wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für das %yGerudo-Trainingsgelände%w!", - "Vous obtenez le trousseau de&clés du %yGymnase Gerudo%w!"), - GIMESSAGE(RG_GANONS_CASTLE_KEY_RING, ITEM_KEY_SMALL, "You found a %rGanon's Castle&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w&für %rGanons Schloß%w!", - "Vous obtenez le trousseau de&clés du %rChâteau de Ganon%w!"), - GIMESSAGE(RG_TREASURE_GAME_KEY_RING, ITEM_KEY_SMALL, "You found a %rTreasure Chest Game&%wKeyring!", - "Du erhältst ein %rSchlüsselbund%w& für das %rSchatztruhen-Poker&%w!", - "Vous obtenez le trousseau de&clés du %rJeu de la Chasse au Trésor%w!"), - - GIMESSAGE(RG_FOREST_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %gForest Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %gWaldtempel%w!", - "Vous obtenez la %rClé d'or %wdu&%gTemple de la Forêt%w!"), - GIMESSAGE(RG_FIRE_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rFire Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %rFeuertempel%w!", - "Vous obtenez la %rClé d'or %wdu&%rTemple du Feu%w!"), - GIMESSAGE(RG_WATER_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %bWater Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %bWassertempel%w!", - "Vous obtenez la %rClé d'or %wdu&%bTemple de l'Eau%w!"), - GIMESSAGE(RG_SPIRIT_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %ySpirit Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %yGeistertempel%w!", - "Vous obtenez la %rClé d'or %wdu&%yTemple de l'Esprit%w!"), - GIMESSAGE(RG_SHADOW_TEMPLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %pShadow Temple&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für den %pSchattentempel%w!", - "Vous obtenez la %rClé d'or %wdu&%pTemple de l'Ombre%w!"), - GIMESSAGE(RG_GANONS_CASTLE_BOSS_KEY, ITEM_KEY_BOSS, "You found the %rGanon's Castle&%wBoss Key!", - "Du erhältst den %rMaster-Schlüssel%w&für %rGanons Schloß%w!", - "Vous obtenez la %rClé d'or %wdu&%rChâteau de Ganon%w!"), - - GIMESSAGE(RG_DEKU_TREE_MAP, ITEM_DUNGEON_MAP, "You found the %gDeku Tree&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%gDeku-Baum%w![[typeHint]]", - "Vous obtenez la %rCarte %wde&l'%gArbre Mojo%w![[typeHint]]"), - GIMESSAGE(RG_DODONGOS_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %rDodongo's Cavern&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für&%rDodongos Höhle%w![[typeHint]]", - "Vous obtenez la %rCarte %wde la&%rCaverne Dodongo%w![[typeHint]]"), - GIMESSAGE(RG_JABU_JABUS_BELLY_MAP, ITEM_DUNGEON_MAP, "You found the %bJabu Jabu's Belly&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für&%bJabu-Jabus Bauch%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%bVentre de Jabu-Jabu%w![[typeHint]]"), - GIMESSAGE(RG_FOREST_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %gForest Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%gWaldtempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%gTemple de la Forêt%w![[typeHint]]"), - GIMESSAGE(RG_FIRE_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %rFire Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%rFeuertempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%rTemple du Feu%w![[typeHint]]"), - GIMESSAGE(RG_WATER_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %bWater Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%bWassertempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%bTemple de l'Eau%w![[typeHint]]"), - GIMESSAGE(RG_SPIRIT_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %ySpirit Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%yGeistertempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%yTemple de l'Esprit%w![[typeHint]]"), - GIMESSAGE(RG_SHADOW_TEMPLE_MAP, ITEM_DUNGEON_MAP, "You found the %pShadow Temple&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%pSchattentempel%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%pTemple de l'Ombre%w![[typeHint]]"), - GIMESSAGE(RG_BOTTOM_OF_THE_WELL_MAP, ITEM_DUNGEON_MAP, "You found the %pBottom of the&Well %wMap![[typeHint]]", - "Du erhältst die %rKarte%w für den&%pGrund des Brunnens%w![[typeHint]]", - "Vous obtenez la %rCarte %wdu&%pPuits%w![[typeHint]]"), - GIMESSAGE(RG_ICE_CAVERN_MAP, ITEM_DUNGEON_MAP, "You found the %cIce Cavern&%wMap![[typeHint]]", - "Du erhältst die %rKarte%w für die&%cEishöhle%w![[typeHint]]", - "Vous obtenez la %rCarte %wde&la %cCaverne Polaire%w![[typeHint]]"), - - GIMESSAGE(RG_DEKU_TREE_COMPASS, ITEM_COMPASS, "You found the %gDeku Tree&%wCompass!", - "Du erhältst den %rKompaß%w für den&%gDeku-Baum%w!", - "Vous obtenez la %rBoussole %wde&l'%gArbre Mojo%w!"), - GIMESSAGE(RG_DODONGOS_CAVERN_COMPASS, ITEM_COMPASS, "You found the %rDodongo's Cavern&%wCompass!", - "Du erhältst den %rKompaß%w für&%rDodongos Höhle%w!", - "Vous obtenez la %rBoussole %wde la&%rCaverne Dodongo%w!"), - GIMESSAGE(RG_JABU_JABUS_BELLY_COMPASS, ITEM_COMPASS, "You found the %bJabu Jabu's Belly&%wCompass!", - "Du erhältst den %rKompaß%w für den&%bJabu-Jabus Bauch%w!", - "Vous obtenez la %rBoussole %wdu&%bVentre de Jabu-Jabu%w!"), - GIMESSAGE(RG_FOREST_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %gForest Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%gWaldtempel%w!", - "Vous obtenez la %rBoussole %wdu&%gTemple de la Forêt%w!"), - GIMESSAGE(RG_FIRE_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %rFire Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%rFeuertempel%w!", - "Vous obtenez la %rBoussole %wdu&%rTemple du Feu%w!"), - GIMESSAGE(RG_WATER_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %bWater Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%bWassertempel%w!", - "Vous obtenez la %rBoussole %wdu&%bTemple de l'Eau%w!"), - GIMESSAGE(RG_SPIRIT_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %ySpirit Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%yGeistertempel%w!", - "Vous obtenez la %rBoussole %wdu&%yTemple de l'Esprit%w!"), - GIMESSAGE(RG_SHADOW_TEMPLE_COMPASS, ITEM_COMPASS, "You found the %pShadow Temple&%wCompass!", - "Du erhältst den %rKompaß%w für den&%pSchattentempel%w!", - "Vous obtenez la %rBoussole %wdu&%pTemple de l'Ombre%w!"), - GIMESSAGE(RG_BOTTOM_OF_THE_WELL_COMPASS, ITEM_COMPASS, "You found the %pBottom of the&Well %wCompass!", - "Du erhältst den %rKompaß%w für den&%pGrund des Brunnens%w!", - "Vous obtenez la %rBoussole %wdu&%pPuits%w!"), - GIMESSAGE(RG_ICE_CAVERN_COMPASS, ITEM_COMPASS, "You found the %cIce Cavern&%wCompass!", - "Du erhältst den %rKompaß%w für die&%cEishöhle%w!", - "Vous obtenez la %rBoussole %wde&la %cCaverne Polaire%w!"), - - GIMESSAGE(RG_MAGIC_BEAN_PACK, ITEM_BEAN, - "You got a %rPack of Magic Beans%w!&Find a suitable spot for a garden&and plant them. Then, wait " - "for&something fun to happen!", - "Du erhältst eine %rPackung&Wundererbsen%w! Suche nach einer&Stelle um sie einzupflanzen.&Warte ab, " - "was passiert!", - "Vous obtenez un %rPaquet de&Haricots Magiques%w! Trouvez&un endroit approprié pour un&jardin et " - "plantez-les.^Attendez ensuite que quelque&chose d'amusant se produise!"), - GIMESSAGE(RG_TYCOON_WALLET, ITEM_WALLET_GIANT, - "You got a %rTycoon's Wallet%w!&It's gigantic! Now you can carry&up to %y999 rupees%w!", - "Du erhältst die %rGoldene&Geldbörse%w! Die größte aller&Geldbörsen! Jetzt kannst Du bis&zu %y999 " - "Rubine%w mit Dir führen!", - "Vous obtenez la %rBourse de Magnat%w!&Elle peut contenir jusqu'à %y999 rubis%w!&C'est gigantesque!"), - GIMESSAGE(RG_CHILD_WALLET, ITEM_WALLET_ADULT, - "You got a %rChild's Wallet%w!&Now you can carry&up to %y99 rupees%w!", - "Du erhältst die %rKindergeldbörse%w!&Jetzt kannst Du bis&zu %y99 Rubine%w mit Dir führen!", - "Vous obtenez la %rPetite Bourse%w!&Elle peut contenir jusqu'à %y99 rubis%w!"), - - GIMESSAGE(RG_GOHMA_SOUL, ITEM_BIG_POE, "You found the soul for %gGohma%w!", - "Du hast die Seele von %gGohma%w gefunden!", "Vous obtenez l'âme de %gGohma%w!"), - GIMESSAGE(RG_KING_DODONGO_SOUL, ITEM_BIG_POE, "You found the soul for %rKing&Dodongo%w!", - "Du hast die Seele von %rKönig&Dodongo%w gefunden!", "Vous obtenez l'âme du %rRoi Dodongo%w!"), - GIMESSAGE(RG_BARINADE_SOUL, ITEM_BIG_POE, "You found the soul for %bBarinade%w!", - "Du hast die Seele von %bBarinade%w gefunden!", "Vous obtenez l'âme de %bBarinade%w!"), - GIMESSAGE(RG_PHANTOM_GANON_SOUL, ITEM_BIG_POE, "You found the soul for %gPhantom&Ganon%w!", - "Du hast die Seele von %gPhantom-&Ganon%w gefunden!", "Vous obtenez l'âme de %gGanon&Spectral%w!"), - GIMESSAGE(RG_VOLVAGIA_SOUL, ITEM_BIG_POE, "You found the soul for %rVolvagia%w!", - "Du hast die Seele von %rVolvagia%w gefunden!", "Vous obtenez l'âme de %rVolcania%w!"), - GIMESSAGE(RG_MORPHA_SOUL, ITEM_BIG_POE, "You found the soul for %bMorpha%w!", - "Du hast die Seele von %bMorpha%w gefunden!", "Vous obtenez l'âme de %bMorpha%w!"), - GIMESSAGE(RG_BONGO_BONGO_SOUL, ITEM_BIG_POE, "You found the soul for %pBongo&Bongo%w!", - "Du hast die Seele von %pBongo&Bongo%w gefunden!", "Vous obtenez l'âme de %pBongo&Bongo%w!"), - GIMESSAGE(RG_TWINROVA_SOUL, ITEM_BIG_POE, "You found the soul for %yTwinrova%w!", - "Du hast die Seele von %yTwinrova%w gefunden!", "Vous obtenez l'âme du %yDuo&Maléfique%w!"), - GIMESSAGE(RG_GANON_SOUL, ITEM_BIG_POE, "You found the soul for %cGanon%w!", - "Du hast die Seele von %cGanon%w gefunden!", "Vous obtenez l'âme de %cGanon%w!"), - - GIMESSAGE(RG_OCARINA_A_BUTTON, ITEM_OCARINA_TIME, - "You got the %b\x9f%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %b\x9f%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %b\x9f%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en " - "jouez!"), - GIMESSAGE(RG_OCARINA_C_LEFT_BUTTON, ITEM_OCARINA_TIME, - "You got the %y\xa7%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %y\xa7%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %y\xa7%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en " - "jouez!"), - GIMESSAGE(RG_OCARINA_C_RIGHT_BUTTON, ITEM_OCARINA_TIME, - "You got the %y\xa8%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %y\xa8%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %y\xa8%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en " - "jouez!"), - GIMESSAGE(RG_OCARINA_C_UP_BUTTON, ITEM_OCARINA_TIME, - "You got the %y\xa5%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %y\xa5%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %y\xa5%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en " - "jouez!"), - GIMESSAGE(RG_OCARINA_C_DOWN_BUTTON, ITEM_OCARINA_TIME, - "You got the %y\xa6%r button for the&Ocarina%w! You can now use it&while playing songs!", - "Der %y\xa6%r Knopf%w!&Du kannst ihn nun zum Spielen&von Liedern auf der %rOkarina%w&verwenden!", - "Vous obtenez la %rtouche %y\xa6%r de&l'Ocarina%w! Vous pouvez&maintenant l'utiliser lorsque&vous en " - "jouez!"), - - GIMESSAGE(RG_BRONZE_SCALE, ITEM_SCALE_SILVER, "You got the %rBronze Scale%w!&The power of buoyancy is yours!", - "Du hast die %rBronzene Schuppe%w erhalten!&Die Macht der Schwungkraft ist dein!", - "Vous obtenez l'%rÉcaille de Bronze%w!&Le pouvoir de la flottabilité est&à vous!"), - GIMESSAGE(RG_FISHING_POLE, ITEM_FISHING_POLE, "You found a lost %rFishing Pole%w!&Time to hit the pond!", - "Du hast eine verlorene %rAngelrute%w gefunden!&Zeit, im Teich zu angeln!", - "Vous obtenez une %rCanne à pêche%w&perdue!&Il est temps d'aller à %gl'étang%w!"), - GIMESSAGE(RG_BOMBCHU_BAG, ITEM_BOMBCHU, "You found the %rBombchu Bag%w!", - "Du hast die %rKrabbelminentasche%w&gefunden!", "Vous obtenez un %rSac de Missiles&Teigneux%w!"), - GIMESSAGE( - RG_BOMB_BAG_INF, ITEM_BOMB_BAG_40, "You got an %rInfinite Bomb Bag%w!&Now you have %yinfinite bombs%w!", - "Du hast eine %runendliche Bombentasche%w&gefunden! Nun hast Du &%yunendliche Bomben%w!", - "Vous obtenez un %rSac de Bombes&sans fond%w!&Vous avez maintenant des %ybombes&en quantité illimitée%w!"), - GIMESSAGE(RG_QUIVER_INF, ITEM_QUIVER_50, "You got an %rInfinite Quiver%w!&Now you have %yinfinite arrows%w!", - "Du hast einen %runendlichen Köcher%w&gefunden! Nun hast Du &%yunendliche Pfeile%w!", - "Vous obtenez un %rCarquois Infini%w!&Vous avez maintenant des %yflèches&de manière illimitée%w!"), - GIMESSAGE(RG_BULLET_BAG_INF, ITEM_BULLET_BAG_50, - "You got an %rInfinite Bullet Bag%w!&Now you have %yinfinite&slingshot seeds%w!", - "Du hast eine %runendliche Samentasche%w&gefunden! Nun hast Du &%yunendliche Samen%w!", - "Vous obtenez un %rSac de Graines&sans fond%w!&Vous avez maintenant des %ygraines&de lance-pierres à " - "l'infini%w!"), - GIMESSAGE(RG_STICK_UPGRADE_INF, ITEM_STICK, "You now have %yinfinite%w %rDeku Sticks%w!", - "Du hast nun %yrunendliche%w %rDeku-Stäbe%w!", - "Vous avez maintenant des %yBâtons&Mojo de manière illimitée%w!"), - GIMESSAGE(RG_NUT_UPGRADE_INF, ITEM_NUT, "You now have %yinfinite%w %rDeku Nuts%w!", - "Du hast nun %yunendliche%w %rDeku-Nüsse%w!", - "Vous avez maintenant des %yNoix&Mojo de manière illimitée%w!"), - GIMESSAGE(RG_MAGIC_INF, ITEM_MAGIC_LARGE, "You now have %yinfinite%w %rMagic%w!", - "Du hast nun %yunendliche%w %rMagiew!", "Vous avez maintenant une quantité&de %ymagie illimitée%w!"), - GIMESSAGE(RG_BOMBCHU_INF, ITEM_BOMBCHU, "You now have %yinfinite%w %rBombchus%w!", - "Du hast nun %yunendliche%w %rKrabbelminen%w!", - "Vous avez maintenant des %yMissiles&Teigneux en quantité illimités%w!"), - GIMESSAGE(RG_WALLET_INF, ITEM_WALLET_GIANT, "You now have %yinfinite%w %rmoney%w!", - "Du hast nun %yunendliche%w %rRubinew!", - "Vous avez maintenant des %yRubis en& quantité illimitée%w!"), - GIMESSAGE(RG_SKELETON_KEY, ITEM_KEY_SMALL, "You found the %rSkeleton Key%w!", - "Du hast den %rSkelettschlüssel%w gefunden!", "Vous avez trouvé la %rClé Squelette%w!"), - GIMESSAGE(RG_DEKU_STICK_BAG, ITEM_STICK, "You found the %rDeku Stick Bag%w!&You can now hold Deku Sticks!", - "Du hast eine %rDeku-Stab-Tasche%w&gefunden! Nun kannst Du &%yDeku-Stäbe%w halten!", - "Vous avez trouvé le %rSac de Bâtons&Mojo%w!&Vous pouvez maintenant porter des&Bâtons Mojo!"), - GIMESSAGE(RG_DEKU_NUT_BAG, ITEM_NUT, "You found the %rDeku Nut Bag%w!&You can now hold Deku Nuts!", - "Du hast eine %rDeku-Nuß-Tasche%w&gefunden! Nun kannst Du &%yDeku-Nüsse%w halten!", - "Vous avez trouvé le %rSac de Noix& Mojo%w!&Vous pouvez maintenant porter des&Noix Mojo!"), - } }; - CreateGetItemMessages(getItemMessages); CreateRupeeMessages(); - CreateTriforcePieceMessages(); CreateNaviRandoMessages(); CreateFireTempleGoronMessages(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 78f48b01c..13540b094 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -69,11 +69,8 @@ class Randomizer { bool mysterious = false); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); - CustomMessage GetMapGetItemMessageWithHint(GetItemEntry itemEntry); static void CreateCustomMessages(); static CustomMessage GetRupeeMessage(u16 rupeeTextId); - static CustomMessage GetIceTrapMessage(); - static CustomMessage GetTriforcePieceMessage(); }; #ifdef __cplusplus diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 8f6163b10..1119e664e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -1741,20 +1741,6 @@ std::wstring StringToU16(const std::string& s) { return utf16; } -int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) { - if (!inputStr.empty()) { - // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents - // negatives. - memset(buffer, 0, std::max(0, maxBufferSize)); - // Gaurentee that this value will be greater than 0, regardless of passed variables. - const int copiedCharLen = std::min(std::max(0, maxBufferSize - 1), inputStr.length()); - memcpy(buffer, inputStr.c_str(), copiedCharLen); - return copiedCharLen; - } - - return 0; -} - extern "C" void OTRGfxPrint(const char* str, void* printer, void (*printImpl)(void*, char)) { const std::vector hira1 = { u'を', u'ぁ', u'ぃ', u'ぅ', u'ぇ', u'ぉ', u'ゃ', u'ゅ', u'ょ', u'っ', u'-', u'あ', u'い', @@ -2434,21 +2420,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { MF_FORMATTED); } if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { - messageEntry = - CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE, MF_FORMATTED); - } - font->charTexBuf[0] = (messageEntry.GetTextBoxType() << 4) | messageEntry.GetTextBoxPosition(); - switch (gSaveContext.language) { - case LANGUAGE_FRA: - return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetFrench(MF_RAW), buffer, maxBufferSize); - case LANGUAGE_GER: - return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetGerman(MF_RAW), buffer, maxBufferSize); - case LANGUAGE_ENG: - default: - return msgCtx->msgLength = font->msgLength = - CopyStringToCharBuffer(messageEntry.GetEnglish(MF_RAW), buffer, maxBufferSize); + messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE, MF_FORMATTED); } return false; } From a7ef50d8f8c0558d4fd40e77bb59db33af4d3c86 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 25 Feb 2025 23:14:43 -0500 Subject: [PATCH 060/103] Converts gossip stone hints to hook --- .../randomizer/GossipStoneHints.cpp | 52 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 40 ++------------ 2 files changed, 55 insertions(+), 37 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/GossipStoneHints.cpp diff --git a/soh/soh/Enhancements/randomizer/GossipStoneHints.cpp b/soh/soh/Enhancements/randomizer/GossipStoneHints.cpp new file mode 100644 index 000000000..17960c313 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/GossipStoneHints.cpp @@ -0,0 +1,52 @@ +#include + +extern "C" { +extern PlayState* gPlayState; +#include +#include +#include +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) + +void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) { + if ( + (RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_TRUTH) && Player_GetMask(gPlayState) == PLAYER_MASK_TRUTH) || + (RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_STONE) && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY) == 0) + ) { + return; + } + CustomMessage msg; + Actor* stone = GET_PLAYER(gPlayState)->talkActor; + RandomizerHint stoneHint = RH_NONE; + int16_t hintParams = stone->params & 0xFF; + + if (Rando::StaticData::stoneParamsToHint.contains(hintParams)) { + stoneHint = Rando::StaticData::stoneParamsToHint[hintParams]; + } else if (hintParams == 0x18) { + int numOfActorLists = sizeof(gPlayState->actorCtx.actorLists) / sizeof(gPlayState->actorCtx.actorLists[0]); + for (int i = 0; i < numOfActorLists; i++) { + if (gPlayState->actorCtx.actorLists[i].length) { + if ( + gPlayState->actorCtx.actorLists[i].head->id == 10 && + Rando::StaticData::grottoChestParamsToHint.contains(gPlayState->actorCtx.actorLists[i].head->params) + ) { + stoneHint = Rando::StaticData::grottoChestParamsToHint[gPlayState->actorCtx.actorLists[i].head->params]; + } + } + } + } + if (stoneHint == RH_NONE) { + msg = CustomMessage("INVALID STONE. PARAMS: " + std::to_string(hintParams)); + } else { + msg = OTRGlobals::Instance->gRandoContext->GetHint(stoneHint)->GetHintMessage(MF_AUTO_FORMAT); + } + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterGossipStoneHints() { + COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_GOSSIP_STONE_HINTS, RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE), BuildHintStoneMessage); +} + +static RegisterShipInitFunc initFunc(RegisterGossipStoneHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 1119e664e..674e57dfa 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2160,43 +2160,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || - ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); - Player* player = GET_PLAYER(play); - if (textId == TEXT_RANDOMIZER_GOSSIP_STONE_HINTS && Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) != RO_GOSSIP_STONES_NONE && - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_NOTHING || - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_TRUTH && - Player_GetMask(play) == PLAYER_MASK_TRUTH) || - (Randomizer_GetSettingValue(RSK_GOSSIP_STONE_HINTS) == RO_GOSSIP_STONES_NEED_STONE && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY)))) { - - Actor* stone = GET_PLAYER(play)->talkActor; - RandomizerHint stoneHint = RH_NONE; - s16 hintParams = stone->params & 0xFF; - - if (Rando::StaticData::stoneParamsToHint.contains(hintParams)) { - stoneHint = Rando::StaticData::stoneParamsToHint[hintParams]; - } else if (hintParams == 0x18) { - // look for the chest in the actorlist to determine - // which grotto we're in - int numOfActorLists = sizeof(play->actorCtx.actorLists) / sizeof(play->actorCtx.actorLists[0]); - for (int i = 0; i < numOfActorLists; i++) { - if (play->actorCtx.actorLists[i].length) { - if (play->actorCtx.actorLists[i].head->id == 10 && - Rando::StaticData::grottoChestParamsToHint.contains( - play->actorCtx.actorLists[i].head->params)) { - // use the chest params to find the stone hint - stoneHint = - Rando::StaticData::grottoChestParamsToHint[play->actorCtx.actorLists[i].head->params]; - } - } - } - } - if (stoneHint == RH_NONE) { - messageEntry = CustomMessage("INVALID STONE. PARAMS: " + std::to_string(hintParams)); - } else { - messageEntry = ctx->GetHint(stoneHint)->GetHintMessage(MF_AUTO_FORMAT); - } - } else if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { + bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || + ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); + if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); From 63b20f8d51604a5c2c389ed4561c33299068496e Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 26 Feb 2025 19:28:59 -0500 Subject: [PATCH 061/103] Moved into "Messages" folder --- .../Enhancements/randomizer/{ => Messages}/GossipStoneHints.cpp | 0 soh/soh/Enhancements/randomizer/{ => Messages}/ItemMessages.cpp | 0 2 files changed, 0 insertions(+), 0 deletions(-) rename soh/soh/Enhancements/randomizer/{ => Messages}/GossipStoneHints.cpp (100%) rename soh/soh/Enhancements/randomizer/{ => Messages}/ItemMessages.cpp (100%) diff --git a/soh/soh/Enhancements/randomizer/GossipStoneHints.cpp b/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp similarity index 100% rename from soh/soh/Enhancements/randomizer/GossipStoneHints.cpp rename to soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp diff --git a/soh/soh/Enhancements/randomizer/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp similarity index 100% rename from soh/soh/Enhancements/randomizer/ItemMessages.cpp rename to soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp From fb9e95da389c76375a1552191981466861c190a5 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 26 Feb 2025 20:06:48 -0500 Subject: [PATCH 062/103] Handle one-off merchant messages --- .../randomizer/Messages/MerchantMessages.cpp | 114 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 96 ++------------- soh/soh/OTRGlobals.cpp | 39 +----- 3 files changed, 126 insertions(+), 123 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp new file mode 100644 index 000000000..4f03af228 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -0,0 +1,114 @@ +#include + +extern "C" { +extern PlayState* gPlayState; +#include +#include +#include +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) +#define RAND_GET_ITEM(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) +#define RAND_GET_OVERRIDE(rc) OTRGlobals::Instance->gRandoContext->overrides[rc] +#define NON_BEAN_MERCHANTS (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || \ + RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) + +void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) { + RandomizerGet rgid = RAND_GET_ITEM(rc)->GetPlacedRandomizerGet(); + uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); + CustomMessage itemName; + bool mysterious = RAND_GET_OPTION(RSK_MERCHANT_TEXT_HINT).Is(RO_GENERIC_OFF) || + CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); + if (mysterious) { + itemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage(); + } else if (rgid == RG_ICE_TRAP) { + rgid = RAND_GET_OVERRIDE(rc).LooksLike(); + itemName = CustomMessage(RAND_GET_OVERRIDE(rc).GetTrickName()); + } else { + itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName()); + } + msg.InsertNames({ itemName , CustomMessage(std::to_string(price))}); +} + +void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { + msg = CustomMessage( + "I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no less.\x1B%gYes&No%w", + "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 Rubine%w.\x1B&%gJa&Nein%w", + "Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w" + ); + msg.Format(); + } else if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) { + msg = CustomMessage( + "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + ); + BuildMerchantMessage(msg, RC_ZR_MAGIC_BEAN_SALESMAN); + msg.AutoFormat(); + } + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + ); + BuildMerchantMessage(msg, RC_GC_MEDIGORON); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildGrannyMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && + (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) || + INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { + CustomMessage msg = CustomMessage( + "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + ); + BuildMerchantMessage(msg, RC_KAK_GRANNYS_SHOP); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; + } +} + +void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (*textId == TEXT_CARPET_SALESMAN_ARMS_DEALER) { + msg = CustomMessage("Finally! Now I can go back to being an %rarms dealer%w!", + /*german*/"Endlich! Schon bald kann ich wieder %rKrabbelminen-Händler%w sein!", + /*french*/"Squalala! Je vais enfin pouvoir %rprendre des vacances%w!"); + } else if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { + msg = CustomMessage( + "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" + ); + BuildMerchantMessage(msg, RC_WASTELAND_BOMBCHU_SALESMAN); + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterMerchantMessages() { + COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_10, + (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || + RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)), + BuildBeanGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_100, IS_RANDO, BuildBeanGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_MEDIGORON, NON_BEAN_MERCHANTS, BuildMedigoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_GRANNYS_SHOP, NON_BEAN_MERCHANTS, BuildGrannyMessage); + COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_1, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_ARMS_DEALER, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); +} + +static RegisterShipInitFunc initFunc(RegisterMerchantMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 987a6d473..022180186 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -461,13 +461,6 @@ void Randomizer::LoadMerchantMessages() { "J'abandonne! Tu veux bien m'acheter un #[[1]]#? Ça fera #[[2]] Rubis#!\x07\x10\xA3", { QM_GREEN, QM_YELLOW })); - // Carpet Salesman - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_ARMS_DEALER, - CustomMessage("Finally! Now I can go back to being an #arms dealer#!", - /*german*/ "Endlich! Schon bald kann ich wieder #Krabbelminen-Händler# sein!", - /*french*/ "Squalala! Je vais enfin pouvoir #prendre des vacances#!", { QM_RED })); - // Each shop item has two messages, one for when the cursor is over it, and one for when you select it and are // prompted buy/don't buy CustomMessageManager::Instance->CreateMessage( @@ -481,87 +474,16 @@ void Randomizer::LoadMerchantMessages() { CustomMessageManager::Instance->CreateMessage( Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM_CONFIRM, CustomMessage("\x08#[[1]]# #[[2]]_Rupees#\x09\x1B#Buy&Don't buy#\x09\x02", - "\x08#[[1]]# #[[2]]_Rubine#\x09\x1B#Kaufen&Nicht kaufen#\x09\x02", - "\x08#[[1]]# #[[2]]_Rubis#\x09\x1B#Acheter&Ne pas acheter#\x09\x02", - { QM_GREEN, QM_YELLOW, QM_GREEN })); + "\x08#[[1]]# #[[2]]_Rubine#\x09\x1B#Kaufen&Nicht kaufen#\x09\x02", + "\x08#[[1]]# #[[2]]_Rubis#\x09\x1B#Acheter&Ne pas acheter#\x09\x02", + {QM_GREEN, QM_YELLOW, QM_GREEN})); - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_10, - CustomMessage( - "I tried to be a #magic bean# salesman, but it turns out my marketing skills weren't worth " - "beans!^Anyway, want to buy #[[1]]# for #[[2]] Rupees#?\x1B#Yes&No#", - /*german*/ "Möchten Sie #[[1]]# für #[[2]] Rubine# kaufen?\x1B#Ja&Nein#", - /*french*/ - "J'ai essayé d'être un vendeur de #haricots magiques#, mais j'étais mauvais au niveau du marketing et ça " - "me courait sur le haricot...^Enfin bref, ça te dirait de m'acheter #[[1]]# pour #[[2]] " - "Rubis#?\x1B#Oui&Non#", - { QM_RED, QM_GREEN, QM_YELLOW, QM_GREEN })); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100, - CustomMessage( - "I never thought I'd say this, but I'm selling the last #Magic Bean#.^#99 Rupees#, no less.\x1B#Yes&No#", - "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^#Wundererbse# für #99 " - "Rubine#.\x1B&#Ja&Nein#", - "Je te vends mon dernier #Haricot&magique# pour #99 Rubis#.\x1B&#AcheterNe pas acheter#", - { QM_RED, QM_YELLOW, QM_GREEN })); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_MEDIGORON, - CustomMessage("How about buying #[[1]]# for #[[2]] Rupees#?\x1B#Buy&Don't buy#", - /*german*/ "Möchtest Du #[[1]]# für #[[2]] Rubine# kaufen?\x1B#Klar!&Nie im Leben!#", - /*french*/ "Veux-tu acheter #[[1]]# pour #[[2]] rubis#?\x1B#Acheter&Ne pas acheter#", - { QM_GREEN, QM_YELLOW, QM_GREEN })); - /*spanish*/ // ¿Me compras #[[1]]# por #[[2]] rupias#?\x1B#Comprar&No comprar# - - CustomMessage firstCarpet = CustomMessage( - "Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special is...^", - /*german*/ - "Sei gegrüßt!^Ich verkaufe allerlei Kuriositäten. Stets sonderliche und seltene Ware aus " - "aller Welt für jedermann. Das heutige Angebot bleibt...^", - /*french*/ "Bienvenue!^Je vends des objets rares et merveilleux du monde entier. En spécial aujourd'hui...^"); - /*spanish*/ // ¡Acércate!^Vendo productos extraños y difíciles de encontrar... De todo el mundo a todo el mundo. La - // oferta de hoy es...^#¡ - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_MYSTERIOUS, - firstCarpet + - CustomMessage( - "Terrifying! I won't tell you what it is until I see the #money#...^How about #[[2]] Rupees#?&&" - "\x1B#Buy&Don't buy#", - /*german*/ - "Furchterregend, oder? Ich erzähle Euch mehr, wenn ich #Geld# sehe...^Wie wär's mit #[[2]] Rubinen#?&&" - "\x1B#Aber sicher!&Ich bin weg!#", - /*french*/ - "Terrible! Mais montre tes #rubis# avant que je te dise ce que c'est...^Disons #[[2]] " - "rubis#?&&\x1B#Acheter&Ne pas acheter#", - { QM_RED, QM_YELLOW, QM_GREEN })); - /*spanish*/ // ¡Terrorífico! No te revelaré su nombre hasta que vea el #dinero#...^#[[2]] rupias#, ¿qué te - // parece?&&" - // "\x1B#Comprar&No comprar# - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_CARPET_SALESMAN_1, - firstCarpet + - CustomMessage( - "#[[1]]!# It's real, I promise! A lonely man such as myself wouldn't #lie# to you, hmm?^" - "How about #[[2]] Rupees#?\x1B#Buy&Don't buy#", - /*german*/ - "#[[1]]#! Ich kann versichern, es ist ein aufrichtiges Angebot!^Ein einsamer Mann wie ich würde Dich " - "doch " - "nicht #anlügen#, oder?^Wie wär's mit #[[2]] Rubinen#?\x1B#Aber sicher!&Ich bin weg!#", - /*french*/ - "#[[1]]!# C'est vrai! J'te jure! Un gars comme moi ne te #mentirai# pas tu ne crois pas?^Disons #[[2]] " - "rubis#?\x1B#Acheter&Ne pas acheter#", - { QM_GREEN, QM_RED, QM_YELLOW })); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_GRANNYS_SHOP, - CustomMessage("#[[1]]#! How about #[[2]] Rupees#?\x1B#Buy&Don't buy#", - /*german*/ "#[[1]]#! Sagen wir #[[2]] Rubine#?\x1B#Gerne!&Auf keinen Fall!#", - /*french*/ "#[[1]]#! Que dis-tu de #[[2]] rubis#?\x1B#Acheter&Ne pas acheter#", - { QM_GREEN, QM_YELLOW, QM_GREEN }, { true })); - // /*spanish*/#[[1]]#. Vendo por #[[2]] rupias#.&\x1B#Comprar&No comprar# + CustomMessage firstCarpet = CustomMessage("Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special is...^", + /*german*/ "Sei gegrüßt!^Ich verkaufe allerlei Kuriositäten. Stets sonderliche und seltene Ware aus " + "aller Welt für jedermann. Das heutige Angebot bleibt...^", + /*french*/ "Bienvenue!^Je vends des objets rares et merveilleux du monde entier. En spécial aujourd'hui...^"); + /*spanish*/ // ¡Acércate!^Vendo productos extraños y difíciles de encontrar... De todo el mundo a todo el mundo. La oferta de hoy es...^#¡ + } std::map trialFlagToTrialKey = { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 674e57dfa..4e752961e 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2207,42 +2207,9 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, - naviTextId, MF_FORMATTED); - } else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_10 && - (ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || - ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL))) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage( - RC_ZR_MAGIC_BEAN_SALESMAN, TEXT_BEAN_SALESMAN_BUY_FOR_10, TEXT_NONE, - Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } else if (textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage( - Randomizer::merchantMessageTableID, TEXT_BEAN_SALESMAN_BUY_FOR_100, MF_AUTO_FORMAT); - } else if (textId == TEXT_GRANNYS_SHOP && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && - nonBeanMerchants && - (ctx->GetOption(RSK_SHUFFLE_ADULT_TRADE) || INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage( - RC_KAK_GRANNYS_SHOP, TEXT_GRANNYS_SHOP, TEXT_NONE, - Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } else if (textId == TEXT_MEDIGORON && nonBeanMerchants) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage( - RC_GC_MEDIGORON, TEXT_MEDIGORON, TEXT_NONE, - Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } else if (textId == TEXT_CARPET_SALESMAN_1 && !Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN) && - nonBeanMerchants) { - if (Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage( - RC_WASTELAND_BOMBCHU_SALESMAN, TEXT_CARPET_SALESMAN_1, TEXT_NONE, - Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } else { - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage( - RC_WASTELAND_BOMBCHU_SALESMAN, TEXT_CARPET_SALESMAN_MYSTERIOUS, TEXT_NONE, - Randomizer_GetSettingValue(RSK_MERCHANT_TEXT_HINT) == RO_GENERIC_OFF); - } - } else if (textId == TEXT_CARPET_SALESMAN_ARMS_DEALER) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId, - MF_AUTO_FORMAT); - } else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); + } + else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { actorParams = GET_PLAYER(play)->talkActor->params; if (actorParams == 1 && ctx->GetOption(RSK_KAK_10_SKULLS_HINT)) { messageEntry = ctx->GetHint(RH_KAK_10_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); From 787caf2c673e378c065dfc10d4487bf8d64a69c9 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 26 Feb 2025 22:30:16 -0500 Subject: [PATCH 063/103] Convert scrubs and shop text and remove now-unused code --- .../randomizer/Messages/MerchantMessages.cpp | 45 ++++++++++ .../Enhancements/randomizer/randomizer.cpp | 84 ------------------- soh/soh/Enhancements/randomizer/randomizer.h | 3 - soh/soh/OTRGlobals.cpp | 29 +------ soh/soh/OTRGlobals.h | 1 - .../ovl_file_choose/z_file_choose.c | 1 - 6 files changed, 49 insertions(+), 114 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 4f03af228..4248912d5 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -5,6 +5,7 @@ extern PlayState* gPlayState; #include #include #include +#include } #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) @@ -99,6 +100,48 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { + EnDns* enDns = reinterpret_cast(GET_PLAYER(gPlayState)->talkActor); + RandomizerCheck rc = enDns->sohScrubIdentity.randomizerCheck; + uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); + CustomMessage msg; + if (price == 0) { + msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will give you a %g[[1]]%w!&Please, take it!\x07\x10\xA3", + "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w geben!\x07\x10\xA3", + "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3"); + } else { + msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %g[[2]] Rupees%w it is!\x07\x10\xA3", + "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", + "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); + } + BuildMerchantMessage(msg, rc); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + RandomizerCheck rc; + if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { + rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); + msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", + "\x08%g[[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", + "\x08%g[[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); + } else if (*textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && *textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END) { + rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); + msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w\x09\x1B%gBuy&Don't buy%w\x09\x02", + "\x08%g[[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", + "\x08%g[[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); + } else { + return; + } + BuildMerchantMessage(msg, rc); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterMerchantMessages() { COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_10, (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || @@ -109,6 +152,8 @@ void RegisterMerchantMessages() { COND_ID_HOOK(OnOpenText, TEXT_GRANNYS_SHOP, NON_BEAN_MERCHANTS, BuildGrannyMessage); COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_1, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_ARMS_DEALER, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_SCRUB_RANDOM, IS_RANDO, BuildScrubMessage); + COND_HOOK(OnOpenText, RAND_GET_OPTION(RSK_SHOPSANITY).IsNot(RO_SHOPSANITY_OFF), BuildShopMessage); } static RegisterShipInitFunc initFunc(RegisterMerchantMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 022180186..8df45f572 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -432,60 +432,6 @@ std::unordered_map randomizerGetToEnGirlShopItem { RG_BUY_RED_POTION_50, SI_RED_POTION_R50 }, }; -void Randomizer::LoadMerchantMessages() { - auto ctx = Rando::Context::GetInstance(); - CustomMessageManager::Instance->ClearMessageTable(Randomizer::merchantMessageTableID); - CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::merchantMessageTableID); - - // Prices have a chance of being 0, and the "sell" message below doesn't really make sense for a free item, so - // adding a "free" variation here - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM_FREE, - CustomMessage( - "\x12\x38\x82" - "All right! You win! In return for sparing me, I will give you a #[[1]]#!&Please, take it!\x07\x10\xA3", - "\x12\x38\x82" - "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen #[[1]]# " - "geben!\x07\x10\xA3", - "\x12\x38\x82" - "J'me rends! Laisse-moi partir et en échange, je te donne un #[[1]]#! Vas-y prends le!\x07\x10\xA3", - { QM_GREEN })); - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_SCRUB_RANDOM, - CustomMessage("\x12\x38\x82" - "All right! You win! In return for sparing me, I will sell you a #[[1]]#! #[[2]] Rupees# it " - "is!\x07\x10\xA3", - "\x12\x38\x82" - "Ich gebe auf! Ich verkaufe Dir einen #[[1]]# für #[[2]] Rubine#!\x07\x10\xA3", - "\x12\x38\x82" - "J'abandonne! Tu veux bien m'acheter un #[[1]]#? Ça fera #[[2]] Rubis#!\x07\x10\xA3", - { QM_GREEN, QM_YELLOW })); - - // Each shop item has two messages, one for when the cursor is over it, and one for when you select it and are - // prompted buy/don't buy - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM, - CustomMessage( - "\x08#[[1]]# #[[2]]_Rupees#&Special deal! #ONE LEFT#!&Get it while it lasts!\x0A\x02", - "\x08#[[1]]# #[[2]]_Rubine#&Sonderangebot! #NUR NOCH EINES VERFÜGBAR#!&Beeilen Sie sich!\x0A\x02", - "\x08#[[1]]# #[[2]]_Rubis#&Offre spéciale! #DERNIER EN STOCK#!&Faites vite!\x0A\x02", - { QM_GREEN, QM_YELLOW, QM_RED })); - - CustomMessageManager::Instance->CreateMessage( - Randomizer::merchantMessageTableID, TEXT_SHOP_ITEM_RANDOM_CONFIRM, - CustomMessage("\x08#[[1]]# #[[2]]_Rupees#\x09\x1B#Buy&Don't buy#\x09\x02", - "\x08#[[1]]# #[[2]]_Rubine#\x09\x1B#Kaufen&Nicht kaufen#\x09\x02", - "\x08#[[1]]# #[[2]]_Rubis#\x09\x1B#Acheter&Ne pas acheter#\x09\x02", - {QM_GREEN, QM_YELLOW, QM_GREEN})); - - CustomMessage firstCarpet = CustomMessage("Welcome!^I am selling stuff, strange and rare, from all over the world to everybody. Today's special is...^", - /*german*/ "Sei gegrüßt!^Ich verkaufe allerlei Kuriositäten. Stets sonderliche und seltene Ware aus " - "aller Welt für jedermann. Das heutige Angebot bleibt...^", - /*french*/ "Bienvenue!^Je vends des objets rares et merveilleux du monde entier. En spécial aujourd'hui...^"); - /*spanish*/ // ¡Acércate!^Vendo productos extraños y difíciles de encontrar... De todo el mundo a todo el mundo. La oferta de hoy es...^#¡ - -} - std::map trialFlagToTrialKey = { { EVENTCHKINF_COMPLETED_LIGHT_TRIAL, TK_LIGHT_TRIAL }, { EVENTCHKINF_COMPLETED_FOREST_TRIAL, TK_FOREST_TRIAL }, { EVENTCHKINF_COMPLETED_FIRE_TRIAL, TK_FIRE_TRIAL }, { EVENTCHKINF_COMPLETED_WATER_TRIAL, TK_WATER_TRIAL }, @@ -4351,36 +4297,6 @@ CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { return messageEntry; } -CustomMessage Randomizer::GetMerchantMessage(RandomizerCheck rc, TextIDs textId, TextIDs freeTextId, bool mysterious) { - auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry; - RandomizerGet shopItemGet = ctx->GetItemLocation(rc)->GetPlacedRandomizerGet(); - CustomMessage shopItemName; - u16 shopItemPrice = ctx->GetItemLocation(rc)->GetPrice(); - - if (mysterious || CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0)) { - shopItemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage(); - } else if (shopItemGet == RG_ICE_TRAP) { - shopItemGet = ctx->overrides[rc].LooksLike(); - shopItemName = CustomMessage(ctx->overrides[rc].GetTrickName()); - } else { - auto shopItem = Rando::StaticData::RetrieveItem(shopItemGet); - shopItemName = { shopItem.GetName() }; - } - - if (freeTextId != TEXT_NONE && shopItemPrice == 0) { - messageEntry = - CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, freeTextId, MF_RAW); - } else { - messageEntry = - CustomMessageManager::Instance->RetrieveMessage(Randomizer::merchantMessageTableID, textId, MF_RAW); - } - - messageEntry.InsertNames({ shopItemName, { std::to_string(shopItemPrice) } }); - messageEntry.AutoFormat(); - return messageEntry; -} - void CreateRupeeMessages() { CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 13540b094..ce730759c 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -41,7 +41,6 @@ class Randomizer { static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); - void LoadMerchantMessages(); void LoadHintMessages(); bool IsTrialRequired(s32 trialFlag); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); @@ -65,8 +64,6 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); CustomMessage GetSheikMessage(s16 scene, u16 originalTextId); CustomMessage GetFishingPondOwnerMessage(u16 originalTextId); - CustomMessage GetMerchantMessage(RandomizerCheck rc, TextIDs textId, TextIDs freeTextId = TEXT_NONE, - bool mysterious = false); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); static void CreateCustomMessages(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 4e752961e..0b82f0f75 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2028,10 +2028,6 @@ extern "C" void Randomizer_LoadHintMessages() { OTRGlobals::Instance->gRandomizer->LoadHintMessages(); } -extern "C" void Randomizer_LoadMerchantMessages() { - OTRGlobals::Instance->gRandomizer->LoadMerchantMessages(); -} - extern "C" bool Randomizer_IsTrialRequired(s32 trialFlag) { return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag); } @@ -2160,8 +2156,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - bool nonBeanMerchants = ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || - ctx->GetOption(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL); if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() @@ -2180,25 +2174,10 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } } } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); - // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS - // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) - // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) - } else if (textId >= TEXT_SHOP_ITEM_RANDOM && textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { - RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf( - (RandomizerInf)((textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(rc, TEXT_SHOP_ITEM_RANDOM); - } else if (textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END) { - RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf( - (RandomizerInf)((textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage(rc, TEXT_SHOP_ITEM_RANDOM_CONFIRM); - } else if (textId == TEXT_SCRUB_RANDOM) { - EnDns* enDns = (EnDns*)GET_PLAYER(play)->talkActor; - RandomizerCheck rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf( - (RandomizerInf)enDns->sohScrubIdentity.randomizerInf); - messageEntry = OTRGlobals::Instance->gRandomizer->GetMerchantMessage( - rc, TEXT_SCRUB_RANDOM, TEXT_SCRUB_RANDOM_FREE, - Randomizer_GetSettingValue(RSK_SCRUB_TEXT_HINT) == RO_GENERIC_OFF); + messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); + // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS + // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index b14d322d2..08a60e723 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -134,7 +134,6 @@ CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ); FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams); void Randomizer_ParseSpoiler(const char* fileLoc); void Randomizer_LoadHintMessages(); -void Randomizer_LoadMerchantMessages(); bool Randomizer_IsTrialRequired(s32 trialFlag); GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index 546bb3230..eee849f7c 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -3336,7 +3336,6 @@ void FileChoose_LoadGame(GameState* thisx) { this->state.running = false; Randomizer_LoadHintMessages(); - Randomizer_LoadMerchantMessages(); gSaveContext.respawn[0].entranceIndex = ENTR_LOAD_OPENING; gSaveContext.respawnFlag = 0; From 4cc77bb48b6f49678402489a6c343cc151512235 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 10:01:01 -0500 Subject: [PATCH 064/103] Moves comment about shops --- soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp | 3 +++ soh/soh/OTRGlobals.cpp | 3 --- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 4248912d5..234fc1a79 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -123,6 +123,9 @@ void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; RandomizerCheck rc; + // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS + // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0b82f0f75..837b019e8 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2175,9 +2175,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { } } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); - // Shop items each have two message entries, second one offset by NUM_SHOP_ITEMS - // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) - // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { From ab0980a40c01d73f8140161c439b54c3a60fe1f1 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 10:01:33 -0500 Subject: [PATCH 065/103] Convert Sheik and Ganondorf hint text --- .../randomizer/Messages/StaticHints.cpp | 87 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 18 +--- 2 files changed, 88 insertions(+), 17 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp new file mode 100644 index 000000000..6f1044210 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -0,0 +1,87 @@ +#include + +extern "C" { +extern PlayState* gPlayState; +#include +#include +#include +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) +#define RAND_GET_HINT(rh) OTRGlobals::Instance->gRandoContext->GetHint(rh) +#define RAND_GET_ITEM_LOC(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) + +void BuildGanondorfHint(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (RAND_GET_OPTION(RSK_SHUFFLE_MASTER_SWORD) && !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { + if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) { + msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); + } else { + msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); + } + } else { + if (INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT) { + msg = RAND_GET_HINT(RH_GANONDORF_JOKE)->GetHintMessage(MF_AUTO_FORMAT); + } else { + msg = RAND_GET_HINT(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); + } + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildSheikMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + switch (gPlayState->sceneNum) { + case SCENE_TEMPLE_OF_TIME: + if (RAND_GET_OPTION(RSK_OOT_HINT) && !RAND_GET_ITEM_LOC(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()){ + msg = RAND_GET_HINT(RH_OOT_HINT)->GetHintMessage(MF_RAW); + } else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { + msg = CustomMessage( + "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", + "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.", + "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w."); + } else { + msg = CustomMessage( + "The time has come. Prepare yourself.", + "Die Zeit ist gekommen.&Mach Dich bereit.", + "Le moment est venu @.&Tu ferais bien de te préparer."); + } + break; + case SCENE_INSIDE_GANONS_CASTLE: + if (RAND_GET_OPTION(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) { + msg = RAND_GET_HINT(RH_SHEIK_HINT)->GetHintMessage(MF_RAW); + } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && + CUR_CAPACITY(UPG_QUIVER) >= 30 && gSaveContext.isMagicAcquired)) { + msg = CustomMessage("You are still ill-equipped to face %rGanondorf%w." + "^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the %ylight%w.", + "Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^" + "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", + "@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^" + "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour invoquer la %ylumière%w."); + } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && !RAND_GET_OPTION(RSK_TRIAL_COUNT).Is(0)){ + msg = CustomMessage( + "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still stands.^Complete the remaining %gtrials%w to destroy it.", + "Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.", + "@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours actives.^Termine les épreuves restantes pour les détruire."); + } else { + msg = CustomMessage( + "If you're ready, then proceed.^Good luck.", + "Wenn Du bereit bist, so schreite&voran.^Viel Glück.", + "Si tu es prêt, tu peux y aller.^Bonne chance."); + } + break; + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterStaticHints() { + COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); + COND_ID_HOOK(OnOpenText, TEXT_SHEIK_NEED_HOOK, IS_RANDO, BuildSheikMessage); + COND_ID_HOOK(OnOpenText, TEXT_SHEIK_HAVE_HOOK, IS_RANDO, BuildSheikMessage); +} + +RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 837b019e8..10cf55e4c 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2158,23 +2158,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { auto ctx = Rando::Context::GetInstance(); if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { // rando hints at altar - messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() - : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); - } else if (textId == TEXT_GANONDORF) { - if (ctx->GetOption(RSK_GANONDORF_HINT)) { - if (ctx->GetOption(RSK_SHUFFLE_MASTER_SWORD) && - !CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER)) { - messageEntry = INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT - ? ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1) - : ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); - } else { - messageEntry = INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT - ? ctx->GetHint(RH_GANONDORF_JOKE)->GetHintMessage(MF_AUTO_FORMAT) - : ctx->GetHint(RH_GANONDORF_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); - } - } - } else if (textId == TEXT_SHEIK_NEED_HOOK || textId == TEXT_SHEIK_HAVE_HOOK) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetSheikMessage(gPlayState->sceneNum, textId); + messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { From 2401bbe88a21565124a019c95af839d8ada18d1b Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 10:47:35 -0500 Subject: [PATCH 066/103] Convert skulltula people messages --- .../randomizer/Messages/StaticHints.cpp | 50 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 25 ++-------- 2 files changed, 54 insertions(+), 21 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 6f1044210..3656f3c28 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -10,6 +10,11 @@ extern PlayState* gPlayState; #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) #define RAND_GET_HINT(rh) OTRGlobals::Instance->gRandoContext->GetHint(rh) #define RAND_GET_ITEM_LOC(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) +#define ANY_SKULLTULA_HINTS RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT) void BuildGanondorfHint(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; @@ -78,10 +83,55 @@ void BuildSheikMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildChildAltarMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_ALTAR_CHILD)->GetHintMessage(); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildAdultAltarMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_ALTAR_ADULT)->GetHintMessage(); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + int16_t actorParams = GET_PLAYER(gPlayState)->talkActor->params; + if (actorParams == 1 && RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_10_SKULLS_HINT)->GetHintMessage(); + } else if (actorParams == 2 && RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_20_SKULLS_HINT)->GetHintMessage(); + } else if (actorParams == 3 && RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_30_SKULLS_HINT)->GetHintMessage(); + } else if (actorParams == 4 && RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_40_SKULLS_HINT)->GetHintMessage(); + } else if (actorParams == 5 && RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT)) { + msg = RAND_GET_HINT(RH_KAK_50_SKULLS_HINT)->GetHintMessage(); + } else { + return; + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_KAK_100_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); COND_ID_HOOK(OnOpenText, TEXT_SHEIK_NEED_HOOK, IS_RANDO, BuildSheikMessage); COND_ID_HOOK(OnOpenText, TEXT_SHEIK_HAVE_HOOK, IS_RANDO, BuildSheikMessage); + COND_ID_HOOK(OnOpenText, TEXT_ALTAR_CHILD, IS_RANDO, BuildChildAltarMessage); + COND_ID_HOOK(OnOpenText, TEXT_ALTAR_ADULT, IS_RANDO, BuildAdultAltarMessage); + COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_IM_CURSED, ANY_SKULLTULA_HINTS, BuildSkulltulaPeopleMessage); + COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT), Build100SkullsHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 10cf55e4c..9347618ce 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2156,10 +2156,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - if ((textId == TEXT_ALTAR_CHILD || textId == TEXT_ALTAR_ADULT)) { - // rando hints at altar - messageEntry = (LINK_IS_ADULT) ? ctx->GetHint(RH_ALTAR_ADULT)->GetHintMessage() : ctx->GetHint(RH_ALTAR_CHILD)->GetHintMessage(MF_AUTO_FORMAT); - } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || textId == TEXT_HUGE_RUPEE)) { messageEntry = Randomizer::GetRupeeMessage(textId); @@ -2169,20 +2166,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } - else if (textId == TEXT_SKULLTULA_PEOPLE_IM_CURSED) { - actorParams = GET_PLAYER(play)->talkActor->params; - if (actorParams == 1 && ctx->GetOption(RSK_KAK_10_SKULLS_HINT)) { - messageEntry = ctx->GetHint(RH_KAK_10_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (actorParams == 2 && ctx->GetOption(RSK_KAK_20_SKULLS_HINT)) { - messageEntry = ctx->GetHint(RH_KAK_20_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (actorParams == 3 && ctx->GetOption(RSK_KAK_30_SKULLS_HINT)) { - messageEntry = ctx->GetHint(RH_KAK_30_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (actorParams == 4 && ctx->GetOption(RSK_KAK_40_SKULLS_HINT)) { - messageEntry = ctx->GetHint(RH_KAK_40_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (ctx->GetOption(RSK_KAK_50_SKULLS_HINT)) { - messageEntry = ctx->GetHint(RH_KAK_50_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } - } else if (textId == TEXT_DAMPES_DIARY && ctx->GetOption(RSK_DAMPES_DIARY_HINT)) { + else if (textId == TEXT_DAMPES_DIARY && ctx->GetOption(RSK_DAMPES_DIARY_HINT)) { messageEntry = ctx->GetHint(RH_DAMPES_DIARY)->GetHintMessage(MF_AUTO_FORMAT); } else if ((textId == TEXT_CHEST_GAME_PROCEED || textId == TEXT_CHEST_GAME_REAL_GAMBLER || textId == TEXT_CHEST_GAME_THANKS_A_LOT) && @@ -2251,9 +2235,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); } else if (textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED && ctx->GetOption(RSK_MALON_HINT)) { messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); - } else if (ctx->GetOption(RSK_KAK_100_SKULLS_HINT) && textId == TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH) { - messageEntry = ctx->GetHint(RH_KAK_100_SKULLS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (textId == TEXT_GF_HBA_SIGN && ctx->GetOption(RSK_HBA_HINT)) { + } + else if (textId == TEXT_GF_HBA_SIGN && ctx->GetOption(RSK_HBA_HINT)) { messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); } else if (textId == TEXT_HBA_NOT_ON_HORSE && ctx->GetOption(RSK_HBA_HINT)) { messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); From 98a02e3a4e0dc03b8f680513b83beddfad3b826c Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 11:52:04 -0500 Subject: [PATCH 067/103] Convert more static hints Specifically Dampe, Greg, Warp Songs, Frogs, Loach, Fishing Pole, and Saria --- .../randomizer/Messages/StaticHints.cpp | 142 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 25 --- soh/soh/Enhancements/randomizer/randomizer.h | 1 - soh/soh/OTRGlobals.cpp | 67 ++------- 4 files changed, 155 insertions(+), 80 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 3656f3c28..cf4597921 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -124,14 +124,156 @@ void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildDampesDiaryMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_DAMPES_DIARY)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildGregHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildMinuetWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_MINUET_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildBoleroWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_BOLERO_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildSerenadeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_SERENADE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildRequiemWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_REQUIEM_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildNocturneWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_NOCTURNE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildPreludeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_PRELUDE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildFrogsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_FROGS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildLoachHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_LOACH_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildFishingPoleHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND)) { + return; + } + CustomMessage msg = CustomMessage( + "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!", + "Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht fischen!", + "Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!" + ); + if (RAND_GET_OPTION(RSK_FISHING_POLE_HINT)) { + msg = msg + RAND_GET_HINT(RH_FISHING_POLE)->GetHintMessage(); + } + if (*textId == TEXT_FISHING_POND_START_MET) { + msg = CustomMessage( + "Hey, mister! I remember you!&It's been a long time!^", + "Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!", + "Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!" + ) + msg; + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildSariaMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (*textId == TEXT_SARIA_SFM) { + msg = RAND_GET_HINT(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); + } else { + msg = RAND_GET_HINT(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); + } + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { + // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); + // Sheik COND_ID_HOOK(OnOpenText, TEXT_SHEIK_NEED_HOOK, IS_RANDO, BuildSheikMessage); COND_ID_HOOK(OnOpenText, TEXT_SHEIK_HAVE_HOOK, IS_RANDO, BuildSheikMessage); + // Altar COND_ID_HOOK(OnOpenText, TEXT_ALTAR_CHILD, IS_RANDO, BuildChildAltarMessage); COND_ID_HOOK(OnOpenText, TEXT_ALTAR_ADULT, IS_RANDO, BuildAdultAltarMessage); + //Skulltula COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_IM_CURSED, ANY_SKULLTULA_HINTS, BuildSkulltulaPeopleMessage); COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT), Build100SkullsHintMessage); + // Dampe's Diary + COND_ID_HOOK(OnOpenText, TEXT_DAMPES_DIARY, RAND_GET_OPTION(RSK_DAMPES_DIARY_HINT), BuildDampesDiaryMessage); + // Chest Game + COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_PROCEED, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_REAL_GAMBLER, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_CHEST_GAME_THANKS_A_LOT, RAND_GET_OPTION(RSK_GREG_HINT), BuildGregHintMessage); + // Warp + COND_ID_HOOK(OnOpenText, TEXT_WARP_MINUET_OF_FOREST, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildMinuetWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_BOLERO_OF_FIRE, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildBoleroWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_SERENADE_OF_WATER, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildSerenadeWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_REQUIEM_OF_SPIRIT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildRequiemWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_NOCTURNE_OF_SHADOW, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildNocturneWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_PRELUDE_OF_LIGHT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildPreludeWarpMessage); + // Frogs + COND_ID_HOOK(OnOpenText, TEXT_FROGS_UNDERWATER, RAND_GET_OPTION(RSK_FROGS_HINT), BuildFrogsHintMessage); + // Loach + COND_ID_HOOK(OnOpenText, TEXT_FISHING_CLOUDY, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_SECRETS, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_GOOD_FISHERMAN, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_DIFFERENT_POND, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_SCRATCHING, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + // Fishing Pole + COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), BuildFishingPoleHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START_MET, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), BuildFishingPoleHintMessage); + // Saria + COND_ID_HOOK(OnOpenText, TEXT_SARIA_SFM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FACE_TO_FACE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FOREST_SOUNDS, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_MR_DARUNIA, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_SPIRITUAL_WATER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_SPIRITUAL_FIRE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DREAD_CASTLE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DIFFERENT_OCARINA, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_EYES_DARKNESS_STORM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_DESERT_GODDESS, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_TEMPLES, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FOREST_TEMPLE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_GLAD_NOW, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); + } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 8df45f572..04ff6ba4e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4272,31 +4272,6 @@ CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { return messageEntry; } -CustomMessage Randomizer::GetFishingPondOwnerMessage(u16 originalTextId) { - auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry = CustomMessage( - "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!", - "Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht " - "fischen!", - "Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!"); - - if (Rando::Context::GetInstance()->GetOption(RSK_FISHING_POLE_HINT)) { - messageEntry = messageEntry + CustomMessage(ctx->GetHint(RH_FISHING_POLE)->GetHintMessage()); - } - - // if the fishing pond guy doesnt remember me i will cry :( - if (originalTextId == TEXT_FISHING_POND_START_MET) { - messageEntry = CustomMessage("Hey, mister! I remember you!&It's been a long time!^", - "Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!", - "Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!") + - messageEntry; - } - - messageEntry.Format(); // RANDOTODO why is this needed when it's not elsewhere.... - - return messageEntry; -} - void CreateRupeeMessages() { CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index ce730759c..1dc3bb4c4 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -63,7 +63,6 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); CustomMessage GetSheikMessage(s16 scene, u16 originalTextId); - CustomMessage GetFishingPondOwnerMessage(u16 originalTextId); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); static void CreateCustomMessages(); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 9347618ce..6c440dd16 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2166,62 +2166,21 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } - else if (textId == TEXT_DAMPES_DIARY && ctx->GetOption(RSK_DAMPES_DIARY_HINT)) { - messageEntry = ctx->GetHint(RH_DAMPES_DIARY)->GetHintMessage(MF_AUTO_FORMAT); - } else if ((textId == TEXT_CHEST_GAME_PROCEED || textId == TEXT_CHEST_GAME_REAL_GAMBLER || - textId == TEXT_CHEST_GAME_THANKS_A_LOT) && - play->sceneNum == SCENE_TREASURE_BOX_SHOP && ctx->GetOption(RSK_GREG_HINT)) { - messageEntry = ctx->GetHint(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); - } else if (textId == TEXT_WARP_MINUET_OF_FOREST && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_MINUET_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } else if (textId == TEXT_WARP_BOLERO_OF_FIRE && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_BOLERO_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } else if (textId == TEXT_WARP_SERENADE_OF_WATER && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_SERENADE_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } else if (textId == TEXT_WARP_REQUIEM_OF_SPIRIT && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_REQUIEM_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } else if (textId == TEXT_WARP_NOCTURNE_OF_SHADOW && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_NOCTURNE_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } else if (textId == TEXT_WARP_PRELUDE_OF_LIGHT && ctx->GetOption(RSK_WARP_SONG_HINTS)) { - messageEntry = ctx->GetHint(RH_PRELUDE_WARP_LOC)->GetHintMessage(MF_FORMATTED); - } else if (textId >= TEXT_WARP_MINUET_OF_FOREST && textId <= TEXT_WARP_PRELUDE_OF_LIGHT && - ctx->GetOption(RSK_SHUFFLE_WARP_SONGS)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, - TEXT_WARP_MINUET_OF_FOREST, MF_FORMATTED); - } else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { - messageEntry = - CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId, MF_AUTO_FORMAT); - } else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage( - Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, MF_AUTO_FORMAT); - } else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || - (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && - textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { + else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId, MF_AUTO_FORMAT); + } + else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, MF_AUTO_FORMAT); + } + else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); - } else if (textId == TEXT_FROGS_UNDERWATER && ctx->GetOption(RSK_FROGS_HINT)) { - messageEntry = ctx->GetHint(RH_FROGS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (Randomizer_GetSettingValue(RSK_LOACH_HINT) && - (textId == TEXT_FISHING_CLOUDY || textId == TEXT_FISHING_TRY_ANOTHER_LURE || - textId == TEXT_FISHING_SECRETS || textId == TEXT_FISHING_GOOD_FISHERMAN || - textId == TEXT_FISHING_DIFFERENT_POND || textId == TEXT_FISHING_SCRATCHING || - textId == TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE)) { - messageEntry = ctx->GetHint(RH_LOACH_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if ((textId == TEXT_FISHING_POND_START || textId == TEXT_FISHING_POND_START_MET) && - ctx->GetOption(RSK_SHUFFLE_FISHING_POLE) && !Flags_GetRandomizerInf(RAND_INF_FISHING_POLE_FOUND)) { - messageEntry = OTRGlobals::Instance->gRandomizer->GetFishingPondOwnerMessage(textId); - } else if (textId == TEXT_SARIA_SFM && gPlayState->sceneNum == SCENE_SACRED_FOREST_MEADOW && - ctx->GetOption(RSK_SARIA_HINT)) { - messageEntry = ctx->GetHint(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); - } else if ((textId >= TEXT_SARIAS_SONG_FACE_TO_FACE && textId <= TEXT_SARIAS_SONG_CHANNELING_POWER) && - ctx->GetOption(RSK_SARIA_HINT)) { - messageEntry = ctx->GetHint(RH_SARIA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); - } else if (ctx->GetOption(RSK_BIGGORON_HINT) && - (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || - textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS || textId == TEXT_BIGGORON_I_MAAAADE_THISSSS)) { - messageEntry = ctx->GetHint(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (ctx->GetOption(RSK_BIG_POES_HINT) && - (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { + } + else if (ctx->GetOption(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || + textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS || textId == TEXT_BIGGORON_I_MAAAADE_THISSSS)) { + messageEntry = ctx->GetHint(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); + } + else if (ctx->GetOption(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { messageEntry = ctx->GetHint(RH_BIG_POES_HINT)->GetHintMessage(MF_AUTO_FORMAT); } else if (ctx->GetOption(RSK_CHICKENS_HINT) && (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { From 1f4a832246e0f47c9700e0544e82fc52ac609283 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 11:53:32 -0500 Subject: [PATCH 068/103] Remove now-unused Sheik hint functions --- .../Enhancements/randomizer/randomizer.cpp | 54 ------------------- soh/soh/Enhancements/randomizer/randomizer.h | 1 - 2 files changed, 55 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 04ff6ba4e..b3a711905 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -4218,60 +4218,6 @@ void RandomizerSettingsWindow::UpdateElement() { } } -CustomMessage Randomizer::GetSheikMessage(s16 scene, u16 originalTextId) { - auto ctx = Rando::Context::GetInstance(); - CustomMessage messageEntry; - switch (scene) { - case SCENE_TEMPLE_OF_TIME: - if (ctx->GetOption(RSK_OOT_HINT) && !ctx->GetItemLocation(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()) { - messageEntry = ctx->GetHint(RH_OOT_HINT)->GetHintMessage(MF_RAW); - } else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { - messageEntry = CustomMessage( - "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", - "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.", - "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w."); - } else { - messageEntry = - CustomMessage("The time has come. Prepare yourself.", "Die Zeit ist gekommen.&Mach Dich bereit.", - "Le moment est venu @.&Tu ferais bien de te préparer."); - } - break; - case SCENE_INSIDE_GANONS_CASTLE: - if (ctx->GetOption(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) { - messageEntry = ctx->GetHint(RH_SHEIK_HINT)->GetHintMessage(MF_RAW); - } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && - INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && CUR_CAPACITY(UPG_QUIVER) >= 30 && - gSaveContext.isMagicAcquired)) { - messageEntry = CustomMessage( - "You are still ill-equipped to face %rGanondorf%w." - "^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the " - "%ylight%w.", - "Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^" - "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu " - "geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", - "@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^" - "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour " - "invoquer la %ylumière%w."); - } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && - !ctx->GetOption(RSK_TRIAL_COUNT).Is(0)) { - messageEntry = CustomMessage( - "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still " - "stands.^Complete the remaining %gtrials%w to destroy it.", - "Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w " - "steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.", - "@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours " - "actives.^Termine les épreuves restantes pour les détruire."); - } else { - messageEntry = CustomMessage("If you're ready, then proceed.^Good luck.", - "Wenn Du bereit bist, so schreite&voran.^Viel Glück.", - "Si tu es prêt, tu peux y aller.^Bonne chance."); - } - break; - } - messageEntry.AutoFormat(); - return messageEntry; -} - void CreateRupeeMessages() { CustomMessageManager* customMessageManager = CustomMessageManager::Instance; customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 1dc3bb4c4..b83c3d13b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -62,7 +62,6 @@ class Randomizer { bool checkObtainability = true); ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); - CustomMessage GetSheikMessage(s16 scene, u16 originalTextId); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); static void CreateCustomMessages(); From 25ea48532e018fbaa83fbb70bd1ebc3536ef4284 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 11:58:40 -0500 Subject: [PATCH 069/103] Convert Biggoron Hint --- .../Enhancements/randomizer/Messages/StaticHints.cpp | 12 +++++++++++- soh/soh/OTRGlobals.cpp | 4 ---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index cf4597921..ffad5d524 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -219,6 +219,12 @@ void BuildSariaMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildBiggoronHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -273,7 +279,11 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_GLAD_NOW, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); - + //Biggoron + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 6c440dd16..99f78868f 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2176,10 +2176,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (ctx->GetOption(RSK_BIGGORON_HINT) && (textId == TEXT_BIGGORON_BETTER_AT_SMITHING || textId == TEXT_BIGGORON_WAITING_FOR_YOU || - textId == TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS || textId == TEXT_BIGGORON_I_MAAAADE_THISSSS)) { - messageEntry = ctx->GetHint(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (ctx->GetOption(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { messageEntry = ctx->GetHint(RH_BIG_POES_HINT)->GetHintMessage(MF_AUTO_FORMAT); } else if (ctx->GetOption(RSK_CHICKENS_HINT) && From 7a95b3eb1f528cdbb0846c631bc29ed876e91ec8 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:01:57 -0500 Subject: [PATCH 070/103] Convert Big Poes hint --- .../Enhancements/randomizer/Messages/StaticHints.cpp | 11 ++++++++++- soh/soh/OTRGlobals.cpp | 5 +---- 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index ffad5d524..0d3eaa96b 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -225,6 +225,12 @@ void BuildBiggoronHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildBigPoesHintMessage(uint16_t * textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -279,11 +285,14 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_GLAD_NOW, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); - //Biggoron + // Biggoron COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + // Big Poes + COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_EXPLAINATION, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 99f78868f..1429823ff 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2176,10 +2176,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (ctx->GetOption(RSK_BIG_POES_HINT) && (textId == TEXT_GHOST_SHOP_EXPLAINATION || textId == TEXT_GHOST_SHOP_CARD_HAS_POINTS)) { - messageEntry = ctx->GetHint(RH_BIG_POES_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if (ctx->GetOption(RSK_CHICKENS_HINT) && - (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { + else if (ctx->GetOption(RSK_CHICKENS_HINT) && (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { messageEntry = ctx->GetHint(RH_CHICKENS_HINT)->GetHintMessage(MF_AUTO_FORMAT); } else if ((textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG) && ctx->GetOption(RSK_MALON_HINT)) { From 3eb3f6092521dce742f48c5b0962662199d3d2bf Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:06:37 -0500 Subject: [PATCH 071/103] Adds TODO comment about breaking these up later. --- soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp | 2 ++ soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 2 ++ 2 files changed, 4 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 234fc1a79..9f27e4a52 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -1,3 +1,5 @@ +// RANDOTODO: Consider breaking this up into the different actors +// That speak these hints, like 2Ship does with ActorBehavior #include extern "C" { diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 0d3eaa96b..98a3fde2d 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -1,3 +1,5 @@ +// RANDOTODO: Consider breaking this up into the different actors +// That speak these hints, like 2Ship does with ActorBehavior #include extern "C" { From a421f7b8f72e1ecc37455f326d1a2a8a6038f830 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:08:11 -0500 Subject: [PATCH 072/103] Convert Anju hint dialogue --- .../Enhancements/randomizer/Messages/StaticHints.cpp | 12 ++++++++++++ soh/soh/OTRGlobals.cpp | 5 +---- 2 files changed, 13 insertions(+), 4 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 98a3fde2d..cf4f36436 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -233,6 +233,12 @@ void BuildBigPoesHintMessage(uint16_t * textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildChickensHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_CHICKENS_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -295,6 +301,12 @@ void RegisterStaticHints() { // Big Poes COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_EXPLAINATION, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); + // Anju + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_4_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 1429823ff..35ec266f3 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2176,10 +2176,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (ctx->GetOption(RSK_CHICKENS_HINT) && (textId >= TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK && textId <= TEXT_ANJU_PLEASE_BRING_1_CUCCO)) { - messageEntry = ctx->GetHint(RH_CHICKENS_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } else if ((textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG) && - ctx->GetOption(RSK_MALON_HINT)) { + else if ((textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG)&& ctx->GetOption(RSK_MALON_HINT)){ messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); } else if (textId == TEXT_MALON_HOW_IS_EPONA_DOING && ctx->GetOption(RSK_MALON_HINT)) { messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); From 7be5d8676c84cf677ed72ab0980c6213896ea7a8 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:19:15 -0500 Subject: [PATCH 073/103] Convert Malon hint --- .../randomizer/Messages/StaticHints.cpp | 26 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 9 ------- 2 files changed, 26 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index cf4f36436..56dbd6743 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -239,6 +239,26 @@ void BuildChickensHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildMalonHintMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + int id; + if (*textId == TEXT_MALON_EVERYONE_TURNING_EVIL || *textId == TEXT_MALON_I_SING_THIS_SONG) { + id = 0; + } else if (*textId == TEXT_MALON_HOW_IS_EPONA_DOING) { + id = 1; + } else if (*textId == TEXT_MALON_OBSTICLE_COURSE) { + id = 2; + } else if (*textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED) { + id = 3; + } else { + assert(!"This should not be reachable"); + return; + } + msg = RAND_GET_HINT(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, id); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -307,6 +327,12 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + // Malon + COND_ID_HOOK(OnOpenText, TEXT_MALON_EVERYONE_TURNING_EVIL, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_I_SING_THIS_SONG, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_HOW_IS_EPONA_DOING, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_OBSTICLE_COURSE, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 35ec266f3..f9db72e06 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2176,15 +2176,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if ((textId == TEXT_MALON_EVERYONE_TURNING_EVIL || textId == TEXT_MALON_I_SING_THIS_SONG)&& ctx->GetOption(RSK_MALON_HINT)){ - messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); - } else if (textId == TEXT_MALON_HOW_IS_EPONA_DOING && ctx->GetOption(RSK_MALON_HINT)) { - messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); - } else if (textId == TEXT_MALON_OBSTICLE_COURSE && ctx->GetOption(RSK_MALON_HINT)) { - messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); - } else if (textId == TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED && ctx->GetOption(RSK_MALON_HINT)) { - messageEntry = ctx->GetHint(RH_MALON_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); - } else if (textId == TEXT_GF_HBA_SIGN && ctx->GetOption(RSK_HBA_HINT)) { messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); } else if (textId == TEXT_HBA_NOT_ON_HORSE && ctx->GetOption(RSK_HBA_HINT)) { From 0cb95d28293df3f0e3e29f5b5b76cda856afb5c9 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:25:17 -0500 Subject: [PATCH 074/103] Convert Horseback Archery hints --- .../randomizer/Messages/StaticHints.cpp | 25 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 16 +++--------- 2 files changed, 29 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 56dbd6743..65f591ba5 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -259,6 +259,26 @@ void BuildMalonHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildHorsebackArcheryMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + int id; + if (*textId == TEXT_GF_HBA_SIGN) { + id = 0; + } else if (*textId == TEXT_HBA_NOT_ON_HORSE) { + id = 1; + } else if (*textId == TEXT_HBA_INITIAL_EXPLAINATION) { + id = 2; + } else if (*textId == TEXT_HBA_ALREADY_HAVE_1000) { + id = 3; + } else { + assert(!"This should not be reachable"); + return; + } + msg = RAND_GET_HINT(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, id); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -333,6 +353,11 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_MALON_HOW_IS_EPONA_DOING, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_OBSTICLE_COURSE, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + // Horseback Archery + COND_ID_HOOK(OnOpenText, TEXT_GF_HBA_SIGN, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + COND_ID_HOOK(OnOpenText, TEXT_HBA_NOT_ON_HORSE, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + COND_ID_HOOK(OnOpenText, TEXT_HBA_ALREADY_HAVE_1000, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index f9db72e06..86c7547c9 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2176,18 +2176,10 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (textId == TEXT_GF_HBA_SIGN && ctx->GetOption(RSK_HBA_HINT)) { - messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 0); - } else if (textId == TEXT_HBA_NOT_ON_HORSE && ctx->GetOption(RSK_HBA_HINT)) { - messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 1); - } else if (textId == TEXT_HBA_INITIAL_EXPLAINATION && ctx->GetOption(RSK_HBA_HINT)) { - messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 2); - } else if (textId == TEXT_HBA_ALREADY_HAVE_1000 && ctx->GetOption(RSK_HBA_HINT)) { - messageEntry = ctx->GetHint(RH_HBA_HINT)->GetHintMessage(MF_AUTO_FORMAT, 3); - } else if (textId == TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY) { - messageEntry = - CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); - } else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) { + else if (textId == TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY){ + messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); + } + else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) { messageEntry = ctx->GetHint(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT); } } From 8675bff6308a40272f140885e661692c5b1816a4 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:29:31 -0500 Subject: [PATCH 075/103] Convert Mask Shop SIgn hint This is the last of the static hints --- soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 8 ++++++++ soh/soh/OTRGlobals.cpp | 3 --- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 65f591ba5..56544ee21 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -279,6 +279,12 @@ void BuildHorsebackArcheryMessage(uint16_t* textId, bool* loadFromMessageTable) *loadFromMessageTable = false; } +void BuildMaskShopSignMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = RAND_GET_HINT(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterStaticHints() { // Ganondorf COND_ID_HOOK(OnOpenText, TEXT_GANONDORF, RAND_GET_OPTION(RSK_GANONDORF_HINT), BuildGanondorfHint); @@ -358,6 +364,8 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_HBA_NOT_ON_HORSE, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_ALREADY_HAVE_1000, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + // Mask Shop Sign + COND_ID_HOOK(OnOpenText, TEXT_MASK_SHOP_SIGN, RAND_GET_OPTION(RSK_MASK_SHOP_HINT), BuildMaskShopSignMessage); } RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 86c7547c9..06044a016 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2179,9 +2179,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { else if (textId == TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY){ messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); } - else if (textId == TEXT_MASK_SHOP_SIGN && ctx->GetOption(RSK_MASK_SHOP_HINT)) { - messageEntry = ctx->GetHint(RH_MASK_SHOP_HINT)->GetHintMessage(MF_AUTO_FORMAT); - } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { From 2c252783b5c438d5ddd35eba0c2c0885b04c1095 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:37:24 -0500 Subject: [PATCH 076/103] Add some documentation comments --- .../Enhancements/randomizer/Messages/GossipStoneHints.cpp | 4 ++++ soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp | 7 +++++++ .../Enhancements/randomizer/Messages/MerchantMessages.cpp | 6 ++++++ soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 5 +++++ 4 files changed, 22 insertions(+) diff --git a/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp b/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp index 17960c313..ebad2bd3e 100644 --- a/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp @@ -1,3 +1,7 @@ +/** + * This file handles the custom messages for Gossip Stone + * hints. + */ #include extern "C" { diff --git a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp index 828958937..1ce898437 100644 --- a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp @@ -1,3 +1,10 @@ +// RANDOTODO: Consider putting Ice Traps in their own file. +/** + * This file handles custom messages relating to Items, + * such as Get Item messages for non-vanilla items, + * Vanilla/MQ hints when collecting Maps, Ice Trap messages, + * etc. + */ #include #include "soh/Enhancements/game-interactor/GameInteractor_Hooks.h" #include "soh/Enhancements/custom-message/CustomMessageTypes.h" diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 9f27e4a52..b9d716293 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -1,5 +1,11 @@ // RANDOTODO: Consider breaking this up into the different actors // That speak these hints, like 2Ship does with ActorBehavior + +/** + * This file handles the custom messages for merchants, + * including both shops and one-off merchants (i.e. Medigoron, Bean Guy, + * and Carpet Salesman) + */ #include extern "C" { diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 56544ee21..a12bda6e2 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -1,5 +1,10 @@ // RANDOTODO: Consider breaking this up into the different actors // That speak these hints, like 2Ship does with ActorBehavior + +/** + * File for registering hooks for "Static" hints, i.e. hints that + * are always given by a specific NPC and/or for a specific item. + */ #include extern "C" { From 510b17e551757932323cac498e8e670079b41b88 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:46:59 -0500 Subject: [PATCH 077/103] Handles previously missed Carpet Guy can't buy message. --- .../randomizer/Messages/MerchantMessages.cpp | 11 +++++++++++ soh/soh/OTRGlobals.cpp | 3 --- soh/soh/z_message_OTR.cpp | 11 ++--------- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index b9d716293..2c281d55b 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -108,6 +108,16 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildCarpetGuyFailToBuyMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "I'm sorry I can't sell you these fine specimens, they need an %rexperienced owner%w.^" + "Come back when you have had %gBombchus%w of your own." + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { EnDns* enDns = reinterpret_cast(GET_PLAYER(gPlayState)->talkActor); RandomizerCheck rc = enDns->sohScrubIdentity.randomizerCheck; @@ -165,6 +175,7 @@ void RegisterMerchantMessages() { COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_ARMS_DEALER, NON_BEAN_MERCHANTS, BuildCarpetGuyMessage); COND_ID_HOOK(OnOpenText, TEXT_SCRUB_RANDOM, IS_RANDO, BuildScrubMessage); COND_HOOK(OnOpenText, RAND_GET_OPTION(RSK_SHOPSANITY).IsNot(RO_SHOPSANITY_OFF), BuildShopMessage); + COND_ID_HOOK(OnOpenText, TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY, IS_RANDO, BuildCarpetGuyFailToBuyMessage); } static RegisterShipInitFunc initFunc(RegisterMerchantMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 06044a016..5aeb6197a 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2176,9 +2176,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } - else if (textId == TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY){ - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_AUTO_FORMAT); - } } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index bcd301627..7d3fe38e4 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -163,13 +163,6 @@ extern "C" void OTRMessage_Init() { CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_FISHERMAN_LEAVE, CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", - "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du " - "aufhören?&\x1B&%gJa&Nein%w", - "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous " - "arrêter?&\x1B&%gOui&Non%w")); // TODO Used AI translation as placeholder - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_CARPET_SALESMAN_CUSTOM_FAIL_TO_BUY, - CustomMessage("I'm sorry I can't sell you these fine specimens, they need an #experienced owner#.^" - "Come back when you have had #Bombchus# of your own.", - { QM_RED, QM_GREEN })); + "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", + "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w")); //TODO Used AI translation as placeholder } From 5c8e3ff3d5cf8fe329c557e7f9d78731c86c278c Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 12:55:30 -0500 Subject: [PATCH 078/103] Removes some more unused stuff --- soh/soh/Enhancements/randomizer/randomizer.cpp | 17 ----------------- soh/soh/Enhancements/randomizer/randomizer.h | 4 ---- soh/soh/OTRGlobals.cpp | 12 ------------ 3 files changed, 33 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index b3a711905..8f7eb6bd9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -56,14 +56,9 @@ std::set enabledGlitches; u8 generated; char* seedString; -const std::string Randomizer::getItemMessageTableID = "Randomizer"; const std::string Randomizer::hintMessageTableID = "RandomizerHints"; -const std::string Randomizer::merchantMessageTableID = "RandomizerMerchants"; const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; -const std::string Randomizer::triforcePieceMessageTableID = "RandomizerTriforcePiece"; const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; -const std::string Randomizer::IceTrapRandoMessageTableID = "RandomizerIceTrap"; -const std::string Randomizer::randoMiscHintsTableID = "RandomizerMiscHints"; static const char* englishRupeeNames[175] = { "[P]", @@ -365,10 +360,6 @@ void Randomizer::LoadHintMessages() { CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID); CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID); - // Extra Hints - CustomMessageManager::Instance->ClearMessageTable(Randomizer::randoMiscHintsTableID); - CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::randoMiscHintsTableID); - // Bow Shooting Gallery reminder CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, @@ -376,14 +367,6 @@ void Randomizer::LoadHintMessages() { "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen #speziellen Preis# zu erhalten!", "J'aurai #une autre récompense# pour toi lorsque tu auras ton propre arc.", { QM_RED })); - // Warp Song Mysterious text - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_WARP_MINUET_OF_FOREST, - CustomMessage("Warp to&#a mysterious place?#&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", - "Zu&#einem mysteriösen Ort#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK&No#", - "Se téléporter vers&#un endroit mystérieux#?&" + CustomMessages::TWO_WAY_CHOICE() + "#OK!&Non#", - { QM_RED, QM_GREEN })); - // Lake Hylia water level system CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index b83c3d13b..4887373cb 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -32,12 +32,8 @@ class Randomizer { static const std::string getItemMessageTableID; static const std::string hintMessageTableID; - static const std::string merchantMessageTableID; static const std::string rupeeMessageTableID; - static const std::string triforcePieceMessageTableID; static const std::string NaviRandoMessageTableID; - static const std::string IceTrapRandoMessageTableID; - static const std::string randoMiscHintsTableID; static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 5aeb6197a..b15e36b79 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2134,18 +2134,6 @@ extern "C" void Randomizer_ShowRandomizerMenu() { SohGui::ShowRandomizerSettingsMenu(); } -CustomMessage Randomizer_GetCustomGetItemMessage(Player* player) { - s16 giid; - if (player->getItemEntry.objectId != OBJECT_INVALID) { - giid = player->getItemEntry.getItemId; - } else { - giid = player->getItemId; - } - const CustomMessage getItemText = - CustomMessageManager::Instance->RetrieveMessage(Randomizer::getItemMessageTableID, giid); - return getItemText; -} - extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { MessageContext* msgCtx = &play->msgCtx; uint16_t textId = msgCtx->textId; From 34e6d60f7fde4317a3d98bdeb3b76e09e1945a9a Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 13:12:48 -0500 Subject: [PATCH 079/103] Convert Lake Hylia Switch related text --- .../randomizer/Messages/Miscellaneous.cpp | 37 +++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 19 ++-------- soh/soh/OTRGlobals.cpp | 3 -- 3 files changed, 40 insertions(+), 19 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp new file mode 100644 index 000000000..e97178f89 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp @@ -0,0 +1,37 @@ +// RANDOTODO: Consider breaking these up by actor similar +// to how 2Ship does ActorBehavior stuff. +/** + * This file is intended to handle some rando-specific + * text changes that don't really fit anywhere else. + */ + +#include + +extern "C" { +#include +} + +void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg; + if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI) { + msg = CustomMessage( + "%cThis switch is rustier than you think.^%cSomething must be wrong with the pipe system in the %bWater Temple%c.", + "%cDieser Schalter scheint rostiger zu sein als er aussieht.^%cEtwas muss mit dem Leitungssystem im %bWassertempel%c nicht stimmen.", + "%cCet interrupteur est très rouillé.^%cIl doit y avoir un problème avec la tuyauterie du %bTemple de l'Eau%c." + ); + } else if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { + msg = CustomMessage( + "Water level control system.&Keep away!", + "Wasserstand Kontrollsystem&Finger weg!", + "Système de contrôle du niveau&d'eau.&Ne pas toucher!" + ); + } + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterMiscellaneousMessages() { + COND_ID_HOOK(OnOpenText, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI, IS_RANDO, BuildWaterSwitchMessage); + COND_ID_HOOK(OnOpenText, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, IS_RANDO, BuildWaterSwitchMessage); +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 8f7eb6bd9..dfa012a1f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -364,22 +364,9 @@ void Randomizer::LoadHintMessages() { CustomMessageManager::Instance->CreateMessage( Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, CustomMessage("Come back when you have your own bow and you'll get a #different prize#!", - "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen #speziellen Preis# zu erhalten!", - "J'aurai #une autre récompense# pour toi lorsque tu auras ton propre arc.", { QM_RED })); - - // Lake Hylia water level system - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, - CustomMessage("Water level control system.&Keep away!", "Wasserstand Kontrollsystem&Finger weg!", - "Système de contrôle du niveau&d'eau.&Ne pas toucher!")); - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI, - CustomMessage("%cThis switch is rustier than you think.^%cSomething must be wrong with the pipe system in the " - "%bWater Temple%c.", - "%cDieser Schalter scheint rostiger zu sein als er aussieht.^%cEtwas muss mit dem Leitungssystem " - "im %bWassertempel%c nicht stimmen.", - "%cCet interrupteur est très rouillé.^%cIl doit y avoir un problème avec la tuyauterie du " - "%bTemple de l'Eau%c.")); + "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen #speziellen Preis# zu erhalten!", + "J'aurai #une autre récompense# pour toi lorsque tu auras ton propre arc.", + {QM_RED})); } // Reference soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.h diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index b15e36b79..bf57be7ee 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2154,9 +2154,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } - else if (textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI || textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, textId, MF_AUTO_FORMAT); - } else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, MF_AUTO_FORMAT); } From 1d56d74131f2c661a2bd0d8fd962665d3e1ac16e Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 13:13:05 -0500 Subject: [PATCH 080/103] Convert Shooting Gallery bow reminder message --- .../randomizer/Messages/Miscellaneous.cpp | 16 +++++++++++++++- soh/soh/Enhancements/randomizer/randomizer.cpp | 8 -------- soh/soh/OTRGlobals.cpp | 3 --- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp index e97178f89..f9264db1f 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp @@ -31,7 +31,21 @@ void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildShootingGalleryNoBowMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "Come back when you have your own bow and you'll get a %rdifferent prize%w!", + "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen %rspeziellen Preis%w zu erhalten!", + "J'aurai %rune autre récompense%w pour toi lorsque tu auras ton propre arc." + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void RegisterMiscellaneousMessages() { COND_ID_HOOK(OnOpenText, TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI, IS_RANDO, BuildWaterSwitchMessage); COND_ID_HOOK(OnOpenText, TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN, IS_RANDO, BuildWaterSwitchMessage); -} \ No newline at end of file + COND_ID_HOOK(OnOpenText, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, IS_RANDO, BuildShootingGalleryNoBowMessage); +} + +RegisterShipInitFunc initFunc(RegisterMiscellaneousMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index dfa012a1f..101b05e09 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -359,14 +359,6 @@ void Randomizer::LoadHintMessages() { CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID); CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID); - - // Bow Shooting Gallery reminder - CustomMessageManager::Instance->CreateMessage( - Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, - CustomMessage("Come back when you have your own bow and you'll get a #different prize#!", - "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen #speziellen Preis# zu erhalten!", - "J'aurai #une autre récompense# pour toi lorsque tu auras ton propre arc.", - {QM_RED})); } // Reference soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.h diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index bf57be7ee..0b4312127 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2154,9 +2154,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } - else if (textId == TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::hintMessageTableID, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, MF_AUTO_FORMAT); - } else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); From 2acb988e446d5bc528e37e398d9cf9db6340afaf Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 13:14:53 -0500 Subject: [PATCH 081/103] Removes now-unused stuff for hint messages --- soh/soh/Enhancements/randomizer/randomizer.cpp | 7 ------- soh/soh/Enhancements/randomizer/randomizer.h | 1 - soh/soh/OTRGlobals.cpp | 4 ---- soh/soh/OTRGlobals.h | 1 - .../overlays/gamestates/ovl_file_choose/z_file_choose.c | 2 -- 5 files changed, 15 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 101b05e09..882962f9b 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -354,13 +354,6 @@ bool Randomizer::SpoilerFileExists(const char* spoilerFileName) { #pragma GCC pop_options #pragma optimize("", on) -void Randomizer::LoadHintMessages() { - auto ctx = Rando::Context::GetInstance(); - - CustomMessageManager::Instance->ClearMessageTable(Randomizer::hintMessageTableID); - CustomMessageManager::Instance->AddCustomMessageTable(Randomizer::hintMessageTableID); -} - // Reference soh/src/overlays/actors/ovl_En_GirlA/z_en_girla.h std::unordered_map randomizerGetToEnGirlShopItem = { { RG_BUY_DEKU_NUTS_5, SI_DEKU_NUTS_5 }, diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 4887373cb..4df1d496f 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -37,7 +37,6 @@ class Randomizer { static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); - void LoadHintMessages(); bool IsTrialRequired(s32 trialFlag); u8 GetRandoSettingValue(RandomizerSettingKey randoSettingKey); RandomizerCheck GetCheckFromRandomizerInf(RandomizerInf randomizerInf); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0b4312127..7f0442759 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2024,10 +2024,6 @@ extern "C" void Randomizer_ParseSpoiler(const char* fileLoc) { OTRGlobals::Instance->gRandoContext->ParseSpoiler(fileLoc); } -extern "C" void Randomizer_LoadHintMessages() { - OTRGlobals::Instance->gRandomizer->LoadHintMessages(); -} - extern "C" bool Randomizer_IsTrialRequired(s32 trialFlag) { return OTRGlobals::Instance->gRandomizer->IsTrialRequired(trialFlag); } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 08a60e723..6b5b16b58 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -133,7 +133,6 @@ ShopItemIdentity Randomizer_IdentifyShopItem(s32 sceneNum, u8 slotIndex); CowIdentity Randomizer_IdentifyCow(s32 sceneNum, s32 posX, s32 posZ); FishIdentity Randomizer_IdentifyFish(s32 sceneNum, s32 actorParams); void Randomizer_ParseSpoiler(const char* fileLoc); -void Randomizer_LoadHintMessages(); bool Randomizer_IsTrialRequired(s32 trialFlag); GetItemEntry Randomizer_GetItemFromActor(s16 actorId, s16 sceneNum, s16 actorParams, GetItemID ogId); GetItemEntry Randomizer_GetItemFromActorWithoutObtainabilityCheck(s16 actorId, s16 sceneNum, s16 actorParams, diff --git a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c index eee849f7c..86930c06c 100644 --- a/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c +++ b/soh/src/overlays/gamestates/ovl_file_choose/z_file_choose.c @@ -3335,8 +3335,6 @@ void FileChoose_LoadGame(GameState* thisx) { this->state.running = false; - Randomizer_LoadHintMessages(); - gSaveContext.respawn[0].entranceIndex = ENTR_LOAD_OPENING; gSaveContext.respawnFlag = 0; gSaveContext.seqId = (u8)NA_BGM_DISABLED; From 1dbe1d842a6a8392c55486ec4dcd479ee12306c0 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 13:56:10 -0500 Subject: [PATCH 082/103] Convert random rupee names --- .../randomizer/Messages/Rupees.cpp | 124 ++++++++++ .../Enhancements/randomizer/randomizer.cpp | 234 ------------------ soh/soh/Enhancements/randomizer/randomizer.h | 1 - soh/soh/OTRGlobals.cpp | 8 +- 4 files changed, 125 insertions(+), 242 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/Rupees.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp new file mode 100644 index 000000000..e8b02a57b --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp @@ -0,0 +1,124 @@ +/** + * This file is for handling the Randomize Rupee Names + * enhancement + */ +#include + +extern "C" { +#include "variables.h" +} + +static const char* englishRupeeNames[175] = { + "[P]", "Bad RNG Rolls", "Bananas", "Beanbean Coins", "Beans", + "Beli", "Bells", "Berries", "Bison Dollars", "Bitcoin", + "Blue Essence", "Bolts", "Bones", "Boondollars", "Bottle Caps", + "Bratwürste", "Bucks", "BugFrags", "Canadian Dollars", "Cards", + "Chaos Orbs", "Clams", "Coal", "Cocoa Beans", "Coins", + "Cookies", "Copper", "Cor", "Cornflakes", "Credits", + "Crimebucks", "Crystal Shards", "Cubits", "Cucumbers", "Dalmations", + "Dampécoin", "Dark Elixir", "Darseks", "Dead Memes", "Diamonds", + "DNA", "Doge", "Dogecoin", "Doll Hairs", "Dollars", + "Dollarydoos", "Dosh", "Doubloons", "Dwarfbucks", "Elexit", + "Emeralds", "Energon", "Eris", "Ether", "Euro", + "Experience", "Extinction Points", "Floopies", "Flurbos", "FPS", + "Friends", "Frog Coins", "Gald", "Gekz", "Gems", + "Geo", "Gil", "Glimmer", "Glitches", "Gold", + "Gold Dragons", "Goober Dollars", "Green Herbs", "Greg Siblings", "Grouses", + "Gummybears", "Hell", "Hyrule Loaches", "Ice Traps", "ISK", + "Jiggies", "KF7 Ammo", "Kinstones", "Kremcoins", "Kroner", + "Leaves", "Lemmings", "Lien", "Lira", "Lumber", + "Lungmen Dollars", "Macca", "Mana", "Mann Co. Keys", "Meat", + "Meat Stacks", "Medaparts", "Meseta", "Mesetas", "Minerals", + "Monopoly Money", "Moons", "Mora", "Mumbo Tokens", "Munny", + "Mushrooms", "Mysteries", "Neopoints", "Notes", "Nuyen", + "Orbs", "Ore", "Pix", "Pixels", "Plastyks", + "Platinum", "Pokédollars", "Pokémon", "Poko", "Pokos", + "Potch", "Pounds", "Power Pellets", "Primogems", "Réals", + "Refined Metal", "Remote Mines", "Retweets", "Rhinu", "Rings", + "Riot Points", "Robux", "Rubies", "Rubles", "Runite Ore", + "Rupees", "Saint Quartz", "Septims", "Shekels", "Shillings", + "Silver", "Simoleons", "Smackaroos", "Social Credit", "Souls", + "Spent Casings", "Spice", "Spondulicks", "Spoons", "Star Bits", + "Star Chips", "Stars", "Stones of Jordan", "Store Credit", "Strawbs", + "Studs", "Super Sea Snails", "Talent", "Teef", "Telecrystals", + "Tiberium", "TokKul", "Toys", "Turnips", "Upvotes", + "V-Bucks", "Vespene Gas", "Watts", "Widgets", "Woolongs", + "World Dollars", "Wumpa Fruit", "Yen", "Zenny", "Zorkmids" +}; + +static const char* germanRupeeNames[65] = { + "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", + "Brötchen", "Cent", "Diamanten", "Diridari", "Dogecoin", + "ECU", "Elexit", "Erz", "Erzbrocken", "Euro", + "EXP", "Forint", "Franken", "Freunde", "Gil", + "Gold", "Groschen", "Gulden", "Gummibären", "Heller", + "Juwelen", "Karolin", "Kartoffeln", "Kies", "Knete", + "Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", + "Kronkorken", "Kröten", "Mark", "Mäuse", "Monde", + "Moorhühner", "Moos", "Münzen", "Penunze", "Pesa", + "Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks", + "Pokédollar", "Radieschen", "Rappen", "Rubine", "Saphire", + "Schilling", "Seelen", "Smaragde", "Steine", "Sterne", + "Sternis", "Tael", "Taler", "Wagenchips", "Zenny" +}; + +static const char* frenchRupeeNames[40] = { + "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", + "Blés", "Bling", "Capsules", "Centimes", "Champignons", + "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", + "Dollars", "Émeraudes", "Éthers", "Étoiles", "Euros", + "Florens", "Francs", "Galds", "Gils", "Grouses", + "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", + "Orbes", "Orens", "Pépètes", "Pièces", "Plastyks", + "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies" +}; + +void BuildRupeeMessage(uint16_t* textId, bool *loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You found [[color]][[amount]] [[rupee]]\x05\x00!", + "Du hast [[color]][[amount]] [[rupee]]\x05\x00 gefunden!", + "Vous obtenez [[color]][[amount]] [[rupee]]\x05\x00!", + TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM + ); + std::string color; + std::string amount; + CustomMessage rupee = CustomMessage(RandomElement(englishRupeeNames), + RandomElement(germanRupeeNames), + RandomElement(frenchRupeeNames)); + switch (*textId) { + case TEXT_BLUE_RUPEE: + color = "\x05\x03"; + amount = "5"; + break; + case TEXT_RED_RUPEE: + color = "\x05\x01"; + amount = "20"; + break; + case TEXT_PURPLE_RUPEE: + color = "\x05\x05"; + amount = "50"; + break; + case TEXT_HUGE_RUPEE: + color = "\x05\x06"; + amount = "200"; + break; + default: + assert(!"This should not be reachable"); + return; + } + msg.Replace("[[color]]", color); + msg.Replace("[[amount]]", amount); + msg.Replace("[[rupee]]", rupee); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterRandomRupeeNames() { + COND_ID_HOOK(OnOpenText, TEXT_BLUE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_RED_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_PURPLE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_HUGE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); +} + +RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 882962f9b..1392919ae 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -60,204 +60,6 @@ const std::string Randomizer::hintMessageTableID = "RandomizerHints"; const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; -static const char* englishRupeeNames[175] = { - "[P]", - "Bad RNG Rolls", - "Bananas", - "Beanbean Coins", - "Beans", - "Beli", - "Bells", - "Berries", - "Bison Dollars", - "Bitcoin", - "Blue Essence", - "Bolts", - "Bones", - "Boondollars", - "Bottle Caps", - "Bratwürste", - "Bucks", - "BugFrags", - "Canadian Dollars", - "Cards", - "Chaos Orbs", - "Clams", - "Coal", - "Cocoa Beans", - "Coins", - "Cookies", - "Copper", - "Cor", - "Cornflakes", - "Credits", - "Crimebucks", - "Crystal Shards", - "Cubits", - "Cucumbers", - "Dalmations", - "Dampécoin", - "Dark Elixir", - "Darseks", - "Dead Memes", - "Diamonds", - "DNA", - "Doge", - "Dogecoin", - "Doll Hairs", - "Dollars", - "Dollarydoos", - "Dosh", - "Doubloons", - "Dwarfbucks", - "Elexit", - "Emeralds", - "Energon", - "Eris", - "Ether", - "Euro", - "Experience", - "Extinction Points", - "Floopies", - "Flurbos", - "FPS", - "Friends", - "Frog Coins", - "Gald", - "Gekz", - "Gems", - "Geo", - "Gil", - "Glimmer", - "Glitches", - "Gold", - "Gold Dragons", - "Goober Dollars", - "Green Herbs", - "Greg Siblings", - "Grouses", - "Gummybears", - "Hell", - "Hyrule Loaches", - "Ice Traps", - "ISK", - "Jiggies", - "KF7 Ammo", - "Kinstones", - "Kremcoins", - "Kroner", - "Leaves", - "Lemmings", - "Lien", - "Lira", - "Lumber", - "Lungmen Dollars", - "Macca", - "Mana", - "Mann Co. Keys", - "Meat", - "Meat Stacks", - "Medaparts", - "Meseta", - "Mesetas", - "Minerals", - "Monopoly Money", - "Moons", - "Mora", - "Mumbo Tokens", - "Munny", - "Mushrooms", - "Mysteries", - "Neopoints", - "Notes", - "Nuyen", - "Orbs", - "Ore", - "Pix", - "Pixels", - "Plastyks", - "Platinum", - "Pokédollars", - "Pokémon", - "Poko", - "Pokos", - "Potch", - "Pounds", - "Power Pellets", - "Primogems", - "Réals", - "Refined Metal", - "Remote Mines", - "Retweets", - "Rhinu", - "Rings", - "Riot Points", - "Robux", - "Rubies", - "Rubles", - "Runite Ore", - "Rupees", - "Saint Quartz", - "Septims", - "Shekels", - "Shillings", - "Silver", - "Simoleons", - "Smackaroos", - "Social Credit", - "Souls", - "Spent Casings", - "Spice", - "Spondulicks", - "Spoons", - "Star Bits", - "Star Chips", - "Stars", - "Stones of Jordan", - "Store Credit", - "Strawbs", - "Studs", - "Super Sea Snails", - "Talent", - "Teef", - "Telecrystals", - "Tiberium", - "TokKul", - "Toys", - "Turnips", - "Upvotes", - "V-Bucks", - "Vespene Gas", - "Watts", - "Widgets", - "Woolongs", - "World Dollars", - "Wumpa Fruit", - "Yen", - "Zenny", - "Zorkmids", -}; - -static const char* germanRupeeNames[65] = { - "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", "Brötchen", "Cent", "Diamanten", - "Diridari", "Dogecoin", "ECU", "Elexit", "Erz", "Erzbrocken", "Euro", "EXP", - "Forint", "Franken", "Freunde", "Gil", "Gold", "Groschen", "Gulden", "Gummibären", - "Heller", "Juwelen", "Karolin", "Kartoffeln", "Kies", "Knete", "Knochen", "Kohle", - "Kraniche", "Kreuzer", "Kronen", "Kronkorken", "Kröten", "Mark", "Mäuse", "Monde", - "Moorhühner", "Moos", "Münzen", "Penunze", "Pesa", "Pfandflaschen", "Pfennig", "Pfund", - "Pilze", "Plastiks", "Pokédollar", "Radieschen", "Rappen", "Rubine", "Saphire", "Schilling", - "Seelen", "Smaragde", "Steine", "Sterne", "Sternis", "Tael", "Taler", "Wagenchips", - "Zenny" -}; - -static const char* frenchRupeeNames[40] = { - "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Blés", "Bling", "Capsules", - "Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", "Dollars", - "Émeraudes", "Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils", - "Grouses", "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", "Orbes", "Orens", - "Pépètes", "Pièces", "Plastyks", "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies" -}; - Randomizer::Randomizer() { Rando::StaticData::InitItemTable(); Rando::StaticData::InitLocationTable(); @@ -4173,41 +3975,6 @@ void RandomizerSettingsWindow::UpdateElement() { } } -void CreateRupeeMessages() { - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(Randomizer::rupeeMessageTableID); - const std::vector rupees = { TEXT_BLUE_RUPEE, TEXT_RED_RUPEE, TEXT_PURPLE_RUPEE, TEXT_HUGE_RUPEE }; - std::string rupeeText = " "; - for (u8 rupee : rupees) { - switch (rupee) { - case TEXT_BLUE_RUPEE: - rupeeText = "\x05\x03 5 [[rupee]]\x05\x00"; - break; - case TEXT_RED_RUPEE: - rupeeText = "\x05\x01 20 [[rupee]]\x05\x00"; - break; - case TEXT_PURPLE_RUPEE: - rupeeText = "\x05\x05 50 [[rupee]]\x05\x00"; - break; - case TEXT_HUGE_RUPEE: - rupeeText = "\x05\x06 200 [[rupee]]\x05\x00"; - break; - } - customMessageManager->CreateMessage( - Randomizer::rupeeMessageTableID, rupee, - CustomMessage("You found" + rupeeText + " !", "Du hast" + rupeeText + " gefunden!", - "Vous obtenez" + rupeeText + " !", TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM)); - } -} - -CustomMessage Randomizer::GetRupeeMessage(u16 rupeeTextId) { - CustomMessage messageEntry = - CustomMessageManager::Instance->RetrieveMessage(Randomizer::rupeeMessageTableID, rupeeTextId, MF_AUTO_FORMAT); - messageEntry.Replace("[[rupee]]", CustomMessage(RandomElement(englishRupeeNames), RandomElement(germanRupeeNames), - RandomElement(frenchRupeeNames))); - return messageEntry; -} - void CreateNaviRandoMessages() { CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { @@ -4422,7 +4189,6 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { } void Randomizer::CreateCustomMessages() { - CreateRupeeMessages(); CreateNaviRandoMessages(); CreateFireTempleGoronMessages(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 4df1d496f..ce0570272 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -60,7 +60,6 @@ class Randomizer { RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); CustomMessage GetGoronMessage(u16 index); static void CreateCustomMessages(); - static CustomMessage GetRupeeMessage(u16 rupeeTextId); }; #ifdef __cplusplus diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 7f0442759..6a88095e8 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2140,13 +2140,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1) && - (textId == TEXT_BLUE_RUPEE || textId == TEXT_RED_RUPEE || textId == TEXT_PURPLE_RUPEE || - textId == TEXT_HUGE_RUPEE)) { - messageEntry = Randomizer::GetRupeeMessage(textId); - // In rando, replace Navi's general overworld hints with rando-related gameplay tips - } else if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && - textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { + if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); } From ae1ecb8647c28399f85bc3bc0036c981afdfdf00 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 14:14:01 -0500 Subject: [PATCH 083/103] Convert Rando-Relevant Navi Enhancement --- .../Enhancements/randomizer/Messages/Navi.cpp | 153 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 114 ------------- soh/soh/Enhancements/randomizer/randomizer.h | 1 - soh/soh/OTRGlobals.cpp | 6 +- 4 files changed, 154 insertions(+), 120 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/Navi.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/Navi.cpp b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp new file mode 100644 index 000000000..0daf51f94 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp @@ -0,0 +1,153 @@ +/** + * This file is responsible for the messages + * for the Rando-Relevant Navi Hints enhancement. + */ +#include + +extern "C" { +#include +} + +#define NUM_NAVI_MESSAGES 18 +CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { + + { "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!", + "%cFehlt Dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!", + "%cIl te manque une %wPetite Clé %cdans&un donjon? C'est peut-être le %rboss&%cqui l'a!" }, + + { "%cSometimes you can use the %rMegaton&Hammer %cinstead of bombs!", + "%cManchmal kannst Du den %rStahlhammer&%cstatt Bomben verwenden!", + "%cParfois, tu peux utiliser la %rMasse&des Titans %cau lieu de tes bombes!" }, + + { "%cStuck on this seed? You could &throw in the towel and check the&%wspoiler log%c...", + "%cHängst Du bei diesem Seed fest?&Du könntest die Flinte ins Korn&werfen und ins %wSpoiler Log %cschauen...", + "%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." }, + + { "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?", + "%cWußtest Du, daß Du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", + "%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables " + "mouvants%c?" }, + + { "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!", + "%cDu kannst den Balkon von %wImpas&Haus %cerreichen indem Du von&der Baustelle aus mit einem " + "%rHuhn&%cspringst!", + "%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec " + "une&%rcocotte%c!" }, + + { "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?", + "%cDie %yGeister-Prüfung %cin %pGanons&Schloß %chat irgendwo eine&%wversteckte Kiste%c. Weißt Du schon&wo?", + "%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu " + "le savais&déjà?" }, + + { "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is " + "junk!", + "%cKennst Du die %wMinenbowlingbahn%c?&Ich habe gehört, daß sich nur &%wzwei der Preise%c lohnen. Der " + "Rest&ist Krimskrams!", + "%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont " + "intéréssant?" }, + + { "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!", + "%cBenutzt Du auch genügend %wDeku-Nüsse%c?&Ich habe mal gesehen, daß&man damit %rKrabbelminen " + "%cdetonieren&lassen kann!", + "%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" }, + + { "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your " + "safety!", + "%cVielleicht verbleibt Dir im&%bWassertempel %coder %rFeuertempel %cein&%wzusätzlicher Schlüssel%c. " + "Dies&ist zu Deiner Sicherheit!", + "%cIl se peut que tu aies une %wPetite&Clé %cen trop dans le %bTemple de l'Eau&%cou le %rTemple du Feu%c. " + "C'est pour ta&propre sécurité!" }, + + { "%cIf you can't pick up a %rbomb&flower %cwith your hands, you can&still detonate it with %rfire %cor&with " + "%warrows%c!", + "%cNur weil Du eine %rDonnerblume&%cnicht hochheben kannst, so kannst&Du sie noch immer mit %rFeuer " + "%coder&%wPfeilen %cdetonieren lassen!", + "%cSi tu ne peux pas ramasser&un %rChoux-Péteur %cavec tes mains, tu&peux toujours le faire exploser&avec du " + "%rFeu %cou avec des %wflèches%c!" }, + + { "%cEven an adult can't push large&blocks without some %wextra&strength%c!", + "%cSelbst ein Erwachsener kann ohne&etwas %wzusätzliche Kraft %ckeine&großen Blöcke verschieben!", + "%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" }, + + { "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?", + "%cIch habe gehört, daß der&%rFlammenderwisch %ceine Schwäche für&das %wMaster-Schwert %caufweist. Hast Du&es " + "schon einmal versucht einzusetzen?", + "%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as " + "essayé?" }, + + { "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!", + "%cFehlt Dir die Waffe um gegen&eine %rSkulltula %czu kämpfen? Versuche&sie mit einem %wKrug %cabzuwerfen!", + "%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une " + "%wjarre&%cà la figure?" }, + + { "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!", + "%cIch habe gehört, daß die Stelle&%wfeuchten Bodens %cim %bZora-Fluß %cals&einzige keine %rSkulltula " + "%cbeherbergt.", + "%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne " + "contienne pas&d'%raraignée%c." }, + + { "%cThe people of Hyrule sometimes&have %witems %cfor you, but they won't&like it if you're %wwearing a " + "mask%c!", + "%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür Dich, aber sie mögen&es nicht, wenn Du %wMasken " + "trägst%c!", + "%cIl se peut que les habitants d'Hyrule&aient des %wobjets %cpour toi. Par contre,&ils risquent de ne pas " + "trop apprécier&le fait que tu %wportes un masque%c!" }, + + { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&%wreset%c!", + "%cSolltest Du irgendwo eingeschlossen&sein, mußt Du vielleicht Dein %wSpiel&speichern %cund %wneu starten%c!", + "%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" }, + + { "%cSheik will meet you in a %rburning&village %conce you have %gForest%c,&%rFire%c, and %bWater " + "%cMedallions!", + "%cShiek wird Dich in einem %rbrennenden&Dorf %ctreffen, sobald Du das Amulett&des %gWaldes%c, %rFeuers %cund " + "%bWassers&%cbesitzt.", + "%cSheik t'attendra dans un %rvillage&en feu %clorsque tu auras récupéré&les médaillons de la %gForêt%c, du " + "%rFeu&%cet de l'%bEau%c!" }, + + { "%cIf you don't have a %wsword %cas a&child, try buying %wDeku Sticks%c!&They're effective against your " + "foes!", + "%cSolltest Du als Kind kein %wSchwert&%cbesitzen, empfehle ich %wDeku-Stäbe&%czu kaufen! Diese sind " + "effektiv gegen&Widersacher!", + "%cSi tu n'as pas d'%wépée %cen tant&qu'enfant, pourquoi n'irais-tu pas&acheter quelques %wBâtons Mojo%c? " + "Ils&sont efficaces contre tes ennemis!" } +}; + +void BuildNaviMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = NaviMessages[Random(0, NUM_NAVI_MESSAGES)]; + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterNaviMessages() { + COND_ID_HOOK(OnOpenText, TEXT_NAVI_DEKU_TREE_SUMMONS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CMON_BE_BRAVE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_VISIT_THE_PRINCESS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_MALONS_FATHER, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_THE_PRINCESS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHAT_WOULD_SARIA_SAY, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IMPA_SAID_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_USE_BOMB_FLOWER, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FAIRY_LIVES_ON_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SARIA_KNOWS_ABOUT_STONES, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_RUTO_INSIDE_JABUS_BELLY, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_COLLECTED_THREE_STONES, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_THREW_SOMETHING_IN_MOAT, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CHECK_TEMPLE_OF_TIME, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SHOULD_WE_BELIEVE_SHEIK, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHATS_GOING_ON_IN_FOREST, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CLOUD_OVER_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_ARTIC_WIND_IS_BLOWING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IRON_BOOTS_WEIGH_A_TON, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_LOOK_FOR_SOMONE_WHO_KNOWS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IT_CAME_OUT_OF_THE_WELL, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_BUILT_THE_SPIRIT_TEMPLE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_HAVE_YOU_EVER_PLAYED_NOCTURNE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHERE_GANONDORF_WAS_BORN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_EQUIP_THE_SILVER_GAUNTLETS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_IS_WAITING_FOR_US, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SAVE_PRINCESS_ZELDA, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_TRY_TO_KEEP_MOVING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); +} + +RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 1392919ae..837c118f3 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3975,119 +3975,6 @@ void RandomizerSettingsWindow::UpdateElement() { } } -void CreateNaviRandoMessages() { - CustomMessage NaviMessages[NUM_NAVI_MESSAGES] = { - - { "%cMissing a small key in a dungeon?&Maybe the %rboss %chas it!", - "%cFehlt Dir ein kleiner Schlüssel in &einem Labyrinth? Vielleicht hat ihn&ja der %rEndgegner%c!", - "%cIl te manque une %wPetite Clé %cdans&un donjon? C'est peut-être le %rboss&%cqui l'a!" }, - - { "%cSometimes you can use the %rMegaton&Hammer %cinstead of bombs!", - "%cManchmal kannst Du den %rStahlhammer&%cstatt Bomben verwenden!", - "%cParfois, tu peux utiliser la %rMasse&des Titans %cau lieu de tes bombes!" }, - - { "%cStuck on this seed? You could &throw in the towel and check the&%wspoiler log%c...", - "%cHängst Du bei diesem Seed fest?&Du könntest die Flinte ins Korn&werfen und ins %wSpoiler Log %cschauen...", - "%cSi tu es coincé sur cette seed,&tu peux toujours jeter l'éponge&et regader le %wSpoiler log%c..." }, - - { "%cDid you know that the %yHover&Boots %ccan be used to cross&%wquicksand%c?", - "%cWußtest Du, daß Du mit den&%yGleitstiefeln %cTreibsand %wüberqueren&kannst%c?", - "%cEst-ce que tu savais que les %rBottes&des airs %cpouvaient être utilisées&pour traverser les %wsables " - "mouvants%c?" }, - - { "%cYou can reach the back of %wImpa's&House %cby jumping from the&unfinished house with a %rcucco%c!", - "%cDu kannst den Balkon von %wImpas&Haus %cerreichen indem Du von&der Baustelle aus mit einem " - "%rHuhn&%cspringst!", - "%cTu peux atteindre l'arrière de la&%wMaison d'Impa %cen sautant depuis la&maison en construction avec " - "une&%rcocotte%c!" }, - - { "%cThe %ySpirit Trial %cin %pGanon's Castle&%chas a %whidden chest %csomewhere.&Did you already know that?", - "%cDie %yGeister-Prüfung %cin %pGanons&Schloß %chat irgendwo eine&%wversteckte Kiste%c. Weißt Du schon&wo?", - "%cL'%yÉpreuve de l'Esprit%c dans le %pChâteau&de Ganon %ca un coffre caché quelque&part. Je suppose que tu " - "le savais&déjà?" }, - - { "%cYou know the %wBombchu Bowling&Alley%c? I heard %wonly two of the &prizes %care worthwhile. The rest &is " - "junk!", - "%cKennst Du die %wMinenbowlingbahn%c?&Ich habe gehört, daß sich nur &%wzwei der Preise%c lohnen. Der " - "Rest&ist Krimskrams!", - "%cEst-ce que tu savais qu'au %wBowling&Teigneux%c, il n'y a que les %wdeux&premiers prix %cqui sont " - "intéréssant?" }, - - { "%cHave you been using %wDeku Nuts&%cenough? I've seen them blow up&a %rBombchu%c!", - "%cBenutzt Du auch genügend %wDeku-Nüsse%c?&Ich habe mal gesehen, daß&man damit %rKrabbelminen " - "%cdetonieren&lassen kann!", - "%cTu es sûr d'utiliser tes %wNoix Mojo &%ccorrectement? J'en ai déjà vu&exploser des %rChoux-Péteurs%c!" }, - - { "%cYou might end up with an %wextra&key %cfor the %bWater Temple %cor the&%rFire Temple%c. It's for your " - "safety!", - "%cVielleicht verbleibt Dir im&%bWassertempel %coder %rFeuertempel %cein&%wzusätzlicher Schlüssel%c. " - "Dies&ist zu Deiner Sicherheit!", - "%cIl se peut que tu aies une %wPetite&Clé %cen trop dans le %bTemple de l'Eau&%cou le %rTemple du Feu%c. " - "C'est pour ta&propre sécurité!" }, - - { "%cIf you can't pick up a %rbomb&flower %cwith your hands, you can&still detonate it with %rfire %cor&with " - "%warrows%c!", - "%cNur weil Du eine %rDonnerblume&%cnicht hochheben kannst, so kannst&Du sie noch immer mit %rFeuer " - "%coder&%wPfeilen %cdetonieren lassen!", - "%cSi tu ne peux pas ramasser&un %rChoux-Péteur %cavec tes mains, tu&peux toujours le faire exploser&avec du " - "%rFeu %cou avec des %wflèches%c!" }, - - { "%cEven an adult can't push large&blocks without some %wextra&strength%c!", - "%cSelbst ein Erwachsener kann ohne&etwas %wzusätzliche Kraft %ckeine&großen Blöcke verschieben!", - "%cMême un adulte ne peut pas pousser&de grands blocs sans un petit %wgain&de force%c!" }, - - { "%cI've heard that %rFlare Dancer&%cis weak to the %wMaster Sword%c!&Have you tried it?", - "%cIch habe gehört, daß der&%rFlammenderwisch %ceine Schwäche für&das %wMaster-Schwert %caufweist. Hast " - "Du&es " - "schon einmal versucht einzusetzen?", - "%cJ'ai entendu dire que les %rDanse-&Flammes %csont faîbles face à l'%wÉpée de&Légende%c! Est-ce que tu as " - "essayé?" }, - - { "%cDon't have a weapon to kill a&%rspider%c? Try throwing a %wpot&%cat it!", - "%cFehlt Dir die Waffe um gegen&eine %rSkulltula %czu kämpfen? Versuche&sie mit einem %wKrug %cabzuwerfen!", - "%cSi tu n'as pas d'arme pour tuer&une %raraignée%c, pourquoi n'essayerais&-tu pas de lui jetter une " - "%wjarre&%cà la figure?" }, - - { "%cI hear the patch of %wsoft soil&%cin %bZora's River %cis the only one&that isn't home to a %rspider%c!", - "%cIch habe gehört, daß die Stelle&%wfeuchten Bodens %cim %bZora-Fluß %cals&einzige keine %rSkulltula " - "%cbeherbergt.", - "%cJ'ai entendu dire que la %wterre meuble&%cqui se trouve à la %bRivière Zora %cest&la seule qui ne " - "contienne pas&d'%raraignée%c." }, - - { "%cThe people of Hyrule sometimes&have %witems %cfor you, but they won't&like it if you're %wwearing a " - "mask%c!", - "%cDie Bewohner Hyrules haben manchmal&%wGegenstände %cfür Dich, aber sie mögen&es nicht, wenn Du %wMasken " - "trägst%c!", - "%cIl se peut que les habitants d'Hyrule&aient des %wobjets %cpour toi. Par contre,&ils risquent de ne pas " - "trop apprécier&le fait que tu %wportes un masque%c!" }, - - { "%cIf you get trapped somewhere, you&might have to %wsave your game %cand&%wreset%c!", - "%cSolltest Du irgendwo eingeschlossen&sein, mußt Du vielleicht Dein %wSpiel&speichern %cund %wneu " - "starten%c!", - "%cSi tu es coincé quelque part, tu&devrais %wsauvegarder ta partie %cet&faire un %wreset%c!" }, - - { "%cSheik will meet you in a %rburning&village %conce you have %gForest%c,&%rFire%c, and %bWater " - "%cMedallions!", - "%cShiek wird Dich in einem %rbrennenden&Dorf %ctreffen, sobald Du das Amulett&des %gWaldes%c, %rFeuers " - "%cund " - "%bWassers&%cbesitzt.", - "%cSheik t'attendra dans un %rvillage&en feu %clorsque tu auras récupéré&les médaillons de la %gForêt%c, du " - "%rFeu&%cet de l'%bEau%c!" }, - - { "%cIf you don't have a %wsword %cas a&child, try buying %wDeku Sticks%c!&They're effective against your " - "foes!", - "%cSolltest Du als Kind kein %wSchwert&%cbesitzen, empfehle ich %wDeku-Stäbe&%czu kaufen! Diese sind " - "effektiv gegen&Widersacher!", - "%cSi tu n'as pas d'%wépée %cen tant&qu'enfant, pourquoi n'irais-tu pas&acheter quelques %wBâtons Mojo%c? " - "Ils&sont efficaces contre tes ennemis!" } - }; - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(Randomizer::NaviRandoMessageTableID); - for (unsigned int i = 0; i <= (NUM_NAVI_MESSAGES - 1); i++) { - customMessageManager->CreateMessage(Randomizer::NaviRandoMessageTableID, i, NaviMessages[i]); - } -} - static int goronIDs[9] = { TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME, TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET, TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET, @@ -4189,7 +4076,6 @@ CustomMessage Randomizer::GetGoronMessage(u16 index) { } void Randomizer::CreateCustomMessages() { - CreateNaviRandoMessages(); CreateFireTempleGoronMessages(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index ce0570272..d173da629 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -19,7 +19,6 @@ #define MAX_SEED_STRING_SIZE 1024 #define NUM_TRIFORCE_PIECE_MESSAGES 6 -#define NUM_NAVI_MESSAGES 18 #define NUM_GORON_MESSAGES 9 class Randomizer { diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 6a88095e8..33de0920f 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2140,11 +2140,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { s16 actorParams = 0; if (IS_RANDO) { auto ctx = Rando::Context::GetInstance(); - if (CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1) && textId >= TEXT_NAVI_DEKU_TREE_SUMMONS && textId <= TEXT_NAVI_TRY_TO_KEEP_MOVING) { - u16 naviTextId = Random(0, NUM_NAVI_MESSAGES); - messageEntry = CustomMessageManager::Instance->RetrieveMessage(Randomizer::NaviRandoMessageTableID, naviTextId, MF_FORMATTED); - } - else if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { + if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { u16 choice = Random(0, NUM_GORON_MESSAGES); messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); } From cfb56950e8a03eeaa820d8cb765a7544dea3f9ed Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 14:34:27 -0500 Subject: [PATCH 084/103] Convert Random Goron messages --- .../randomizer/Messages/Goron.cpp | 110 ++++++++++++++++++ .../Enhancements/randomizer/randomizer.cpp | 109 +---------------- soh/soh/Enhancements/randomizer/randomizer.h | 3 - 3 files changed, 112 insertions(+), 110 deletions(-) create mode 100644 soh/soh/Enhancements/randomizer/Messages/Goron.cpp diff --git a/soh/soh/Enhancements/randomizer/Messages/Goron.cpp b/soh/soh/Enhancements/randomizer/Messages/Goron.cpp new file mode 100644 index 000000000..e0791ade3 --- /dev/null +++ b/soh/soh/Enhancements/randomizer/Messages/Goron.cpp @@ -0,0 +1,110 @@ +/** + * Handles the randomized silly messages that the Fire Temple + * trapped Gorons have when you free them. + */ +#include + +extern "C" { +#include +} + +#define NUM_GORON_MESSAGES 9 +static CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = { + { + "Are you the one they call %g@%w?^You look really weird for %rDarunia's kid.%w&Are you adopted?", + "Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst Du&%rDarunias Kind.%w Bist Du " + "adoptiert?", + "C'est toi qu'on appelle %g@%w?^Tu es vraiment bizarre pour être&le %rfils du Chef%w. Tu as été adopté?", + }, + { + "Thank Hylia! I was so worried about&when my teacher would let me get&out of detention.^I gotta go home " + "and see my parents.", + "Ich wollte nur dieses Ding hier wieder&in seine Truhe zurücklegen, weil...^...gehört mir ja eigentlich " + "nicht,&weißt Du?^Doch dann ging plötzlich dieses&Tor hinter mir zu.&Danke für die Rettung.", + "Par les déesses!&Mon Frère?!&C'est bien toi?&Comment ça on ne se connaît pas?^Tu trouves vraiment que " + "je&ressemble à n'importe quel Goron?", + }, + { + "How long has it been, do you know?^%r[[days]]%w days!?^Oh no, and it's %r\x1F%w?&I have to check on my " + "cake!!", + "Weißt Du zufällig, wie viele Tage&vergangen sind?^%r[[days]]%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? " + "Ich&muss dringend nach meinem Kuchen&sehen!!!", + "Cela fait combien de temps que&je suis enfermé ici?&Non mais je ne vais pas crier.^COMBIEN?! %r[[days]]%w " + "JOURS!?^En plus il est %r\x1F%w...&Il faut vraiment que je rentre...", + }, + { + // 0x39C7 - ganon laugh + "\x12\x39\xC7You fell into my %rtrap!%w&Foolish boy, it was me, Ganondorf!!!^...whoa, where am I?&What " + "happened?^Weird.", + "\x12\x39\xC7" + "Du bist mir in die %rFalle%w gegangen!&Du Narr, ich bin es, %rGanondorf%w!!!^...Huch? Wo bin ich? Was ist " + "passiert?^Seltsam...", + "\x12\x39\xC7Tu es tombé dans mon %rpiège%w!&Tu croyais que j'étais un Goron mais,&c'était moi! " + "%rGanondorf%w!^...Hein? Où suis-je?&Que s'est-il passé?", + }, + { + "Thanks, but I don't know if I wanna go&just yet...^Hmm...^...^...^...^...^...maybe I can come back " + "later.&Bye bye.", + "Danke für die Rettung, aber&eigentlich finde ich es hier ganz&nett...^Hmm...^...^...^...^...^...Naja, ich " + "kann ja jederzeit&wiederkommen. Man sieht sich.", + "Merci, mais je me sens plus en&sécurité ici...^...^...^...^...^Hmm...^...Tout compte fait, je vais y " + "aller.&A plus tard.", + }, + { + "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " + "pressed it %b[[a_btn]]%w times.^Wow.", + "Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " + "erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", + "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " + "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." + }, + { + "\x13\x1A" + "Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w " + "rupees!", + "\x13\x1A" + "Hey, ist Dir nicht zu warm?&Besorge Dir doch eine Flasche&%rLon Lon-Milch%w, um Dich&abzukühlen.^Kostet " + "Dich auch nur %g30%w Rubine!", + "\x13\x1A" + "Woah! Tu dois avoir chaud!&Tu savais que tu pouvais acheter&du %rLait de Lon Lon%w pour&seulement %g30 " + "rubis%w?^Il n'y a rien de mieux pour s'hydrater!", + }, + { + "In that case, I'll help you out!^They say that %rthe thing you're&looking for%w can only be found%g " + "when&you're not looking for it.%w^Hope that helps!", + "Pass auf, ich gebe Dir einen Tipp!^Man sagt, man findet %rdas was&man sucht%w nur, und wirklich nur&dann, " + "%gwenn man gerade nicht danach&sucht%w.^Du kannst mich jederzeit wieder für&mehr hilfreiche Tipps " + "aufsuchen!", + "Dans ce cas, je vais t'aider!&On dit que l'objet que tu cherches&ne peut être trouvé que lorsque&tu ne le " + "cherches pas.", + }, + { + "I dunno why I was thrown in here,&truth be told.&I'm just a %g\"PR\"%w person.", + "Wat weiß'n ich, wieso ich hier&eingepfercht wurd. Ich mach&doch nur %g\"Pull&Requests\"%w.", + "Je ne sais pas comment on m'a jeté&ici. Il faut croire que je dors comme&une pierre.", + }, +}; + +void BuildGoronMessage(uint16_t* textId, bool* loadFromMessageTable) { + uint16_t choice = Random(0, NUM_GORON_MESSAGES); + CustomMessage msg = FireTempleGoronMessages[choice]; + msg.Replace("[[days]]", std::to_string(gSaveContext.totalDays)); + msg.Replace("[[a_btn]]", std::to_string(gSaveContext.ship.stats.count[COUNT_BUTTON_PRESSES_A])); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void RegisterGoronMessages() { + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_FLAME_DANCER_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_SWITCH_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_FLAME_DANCER_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_SWITCH_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_OCARINA_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_PILLAR_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_HIDDEN_DOOR_SECRET, IS_RANDO, BuildGoronMessage); + COND_ID_HOOK(OnOpenText, TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET, IS_RANDO, BuildGoronMessage); +} \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 837c118f3..927936784 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3975,112 +3975,8 @@ void RandomizerSettingsWindow::UpdateElement() { } } -static int goronIDs[9] = { TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME, - TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET, - TEXT_FIRE_TEMPLE_GORON_FIRE_SECRET, - TEXT_FIRE_TEMPLE_GORON_FLAME_DANCER_SECRET, - TEXT_FIRE_TEMPLE_GORON_SWITCH_SECRET, - TEXT_FIRE_TEMPLE_GORON_OCARINA_SECRET, - TEXT_FIRE_TEMPLE_GORON_PILLAR_SECRET, - TEXT_FIRE_TEMPLE_GORON_HIDDEN_DOOR_SECRET, - TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET }; - -void CreateFireTempleGoronMessages() { - CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = { - { - "Are you the one they call %g@%w?^You look really weird for %rDarunia's kid.%w&Are you adopted?", - "Du bist also der, den sie @ nennen?^Du siehst nicht aus als wärst Du&%rDarunias Kind.%w Bist Du " - "adoptiert?", - "C'est toi qu'on appelle %g@%w?^Tu es vraiment bizarre pour être&le %rfils du Chef%w. Tu as été adopté?", - }, - { - "Thank Hylia! I was so worried about&when my teacher would let me get&out of detention.^I gotta go home " - "and see my parents.", - "Ich wollte nur dieses Ding hier wieder&in seine Truhe zurücklegen, weil...^...gehört mir ja eigentlich " - "nicht,&weißt Du?^Doch dann ging plötzlich dieses&Tor hinter mir zu.&Danke für die Rettung.", - "Par les déesses!&Mon Frère?!&C'est bien toi?&Comment ça on ne se connaît pas?^Tu trouves vraiment que " - "je&ressemble à n'importe quel Goron?", - }, - { - "How long has it been, do you know?^%r[[days]]%w days!?^Oh no, and it's %r\x1F%w?&I have to check on my " - "cake!!", - "Weißt Du zufällig, wie viele Tage&vergangen sind?^%r[[days]]%w Tage!?^Oh je, und es ist %r\x1F%w Uhr? " - "Ich&muss dringend nach meinem Kuchen&sehen!!!", - "Cela fait combien de temps que&je suis enfermé ici?&Non mais je ne vais pas crier.^COMBIEN?! %r[[days]]%w " - "JOURS!?^En plus il est %r\x1F%w...&Il faut vraiment que je rentre...", - }, - { - // 0x39C7 - ganon laugh - "\x12\x39\xC7You fell into my %rtrap!%w&Foolish boy, it was me, Ganondorf!!!^...whoa, where am I?&What " - "happened?^Weird.", - "\x12\x39\xC7" - "Du bist mir in die %rFalle%w gegangen!&Du Narr, ich bin es, %rGanondorf%w!!!^...Huch? Wo bin ich? Was ist " - "passiert?^Seltsam...", - "\x12\x39\xC7Tu es tombé dans mon %rpiège%w!&Tu croyais que j'étais un Goron mais,&c'était moi! " - "%rGanondorf%w!^...Hein? Où suis-je?&Que s'est-il passé?", - }, - { - "Thanks, but I don't know if I wanna go&just yet...^Hmm...^...^...^...^...^...maybe I can come back " - "later.&Bye bye.", - "Danke für die Rettung, aber&eigentlich finde ich es hier ganz&nett...^Hmm...^...^...^...^...^...Naja, ich " - "kann ja jederzeit&wiederkommen. Man sieht sich.", - "Merci, mais je me sens plus en&sécurité ici...^...^...^...^...^Hmm...^...Tout compte fait, je vais y " - "aller.&A plus tard.", - }, - { "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " - "pressed it %b[[a_btn]]%w times.^Wow.", - "Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " - "erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", - "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " - "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." }, - { - "\x13\x1A" - "Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w " - "rupees!", - "\x13\x1A" - "Hey, ist Dir nicht zu warm?&Besorge Dir doch eine Flasche&%rLon Lon-Milch%w, um Dich&abzukühlen.^Kostet " - "Dich auch nur %g30%w Rubine!", - "\x13\x1A" - "Woah! Tu dois avoir chaud!&Tu savais que tu pouvais acheter&du %rLait de Lon Lon%w pour&seulement %g30 " - "rubis%w?^Il n'y a rien de mieux pour s'hydrater!", - }, - { - "In that case, I'll help you out!^They say that %rthe thing you're&looking for%w can only be found%g " - "when&you're not looking for it.%w^Hope that helps!", - "Pass auf, ich gebe Dir einen Tipp!^Man sagt, man findet %rdas was&man sucht%w nur, und wirklich nur&dann, " - "%gwenn man gerade nicht danach&sucht%w.^Du kannst mich jederzeit wieder für&mehr hilfreiche Tipps " - "aufsuchen!", - "Dans ce cas, je vais t'aider!&On dit que l'objet que tu cherches&ne peut être trouvé que lorsque&tu ne le " - "cherches pas.", - }, - { - "I dunno why I was thrown in here,&truth be told.&I'm just a %g\"PR\"%w person.", - "Wat weiß'n ich, wieso ich hier&eingepfercht wurd. Ich mach&doch nur %g\"Pull&Requests\"%w.", - "Je ne sais pas comment on m'a jeté&ici. Il faut croire que je dors comme&une pierre.", - }, - }; - - CustomMessageManager* customMessageManager = CustomMessageManager::Instance; - customMessageManager->AddCustomMessageTable(customMessageTableID); - for (u8 i = 0; i <= NUM_GORON_MESSAGES - 1; i++) { - customMessageManager->CreateMessage(customMessageTableID, goronIDs[i], FireTempleGoronMessages[i]); - } -} - -CustomMessage Randomizer::GetGoronMessage(u16 index) { - CustomMessage messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, goronIDs[index]); - messageEntry.Replace("[[days]]", std::to_string(gSaveContext.totalDays)); - messageEntry.Replace("[[a_btn]]", std::to_string(gSaveContext.ship.stats.count[COUNT_BUTTON_PRESSES_A])); - messageEntry.Format(); - return messageEntry; -} - -void Randomizer::CreateCustomMessages() { - CreateFireTempleGoronMessages(); -} - -class ExtendedVanillaTableInvalidItemIdException : public std::exception { - private: +class ExtendedVanillaTableInvalidItemIdException: public std::exception { + private: s16 itemID; public: @@ -4094,7 +3990,6 @@ class ExtendedVanillaTableInvalidItemIdException : public std::exception { void RandomizerSettingsWindow::InitElement() { mSettings = Rando::Settings::GetInstance(); - Randomizer::CreateCustomMessages(); seedString = (char*)calloc(MAX_SEED_STRING_SIZE, sizeof(char)); mSettings->UpdateOptionProperties(); } diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index d173da629..dc45d037a 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -19,7 +19,6 @@ #define MAX_SEED_STRING_SIZE 1024 #define NUM_TRIFORCE_PIECE_MESSAGES 6 -#define NUM_GORON_MESSAGES 9 class Randomizer { private: @@ -57,8 +56,6 @@ class Randomizer { ItemObtainability GetItemObtainabilityFromRandomizerCheck(RandomizerCheck randomizerCheck); ItemObtainability GetItemObtainabilityFromRandomizerGet(RandomizerGet randomizerCheck); RandomizerCheck GetCheckFromActor(s16 actorId, s16 sceneNum, s16 actorParams); - CustomMessage GetGoronMessage(u16 index); - static void CreateCustomMessages(); }; #ifdef __cplusplus From 55fbd45c1058cb38b53d7185a216404c4152d160 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 14:36:23 -0500 Subject: [PATCH 085/103] Removes final randomizer message unused stuff --- soh/soh/Enhancements/randomizer/randomizer.cpp | 4 ---- soh/soh/Enhancements/randomizer/randomizer.h | 8 +------- soh/soh/OTRGlobals.cpp | 7 ------- 3 files changed, 1 insertion(+), 18 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index 927936784..f91b704f6 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -56,10 +56,6 @@ std::set enabledGlitches; u8 generated; char* seedString; -const std::string Randomizer::hintMessageTableID = "RandomizerHints"; -const std::string Randomizer::rupeeMessageTableID = "RandomizerRupees"; -const std::string Randomizer::NaviRandoMessageTableID = "RandomizerNavi"; - Randomizer::Randomizer() { Rando::StaticData::InitItemTable(); Rando::StaticData::InitLocationTable(); diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index dc45d037a..5522609e9 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -18,7 +18,6 @@ #include "soh/Enhancements/randomizer/fishsanity.h" #define MAX_SEED_STRING_SIZE 1024 -#define NUM_TRIFORCE_PIECE_MESSAGES 6 class Randomizer { private: @@ -27,12 +26,7 @@ class Randomizer { public: Randomizer(); ~Randomizer(); - - static const std::string getItemMessageTableID; - static const std::string hintMessageTableID; - static const std::string rupeeMessageTableID; - static const std::string NaviRandoMessageTableID; - + static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); bool IsTrialRequired(s32 trialFlag); diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 33de0920f..ad84013a9 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2138,13 +2138,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { const int maxBufferSize = sizeof(font->msgBuf); CustomMessage messageEntry; s16 actorParams = 0; - if (IS_RANDO) { - auto ctx = Rando::Context::GetInstance(); - if (textId == TEXT_FIRE_TEMPLE_GORON_OWE_YOU_BIG_TIME || (textId >= TEXT_FIRE_TEMPLE_GORON_FALLING_DOORS_SECRET && textId <= TEXT_FIRE_TEMPLE_GORON_SOUNDS_DIFFERENT_SECRET)) { - u16 choice = Random(0, NUM_GORON_MESSAGES); - messageEntry = OTRGlobals::Instance->gRandomizer->GetGoronMessage(choice); - } - } if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { // The freeze text cannot be manually dismissed and must be auto-dismissed. From 257c3b80997a3314f1083959c9224c436c61ac87 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:04:13 -0500 Subject: [PATCH 086/103] Convert Injecting Skull token counts --- soh/soh/Enhancements/InjectItemCounts.cpp | 43 +++++++++++++++++++++++ soh/soh/OTRGlobals.cpp | 36 +++---------------- soh/soh/z_message_OTR.cpp | 16 --------- 3 files changed, 47 insertions(+), 48 deletions(-) create mode 100644 soh/soh/Enhancements/InjectItemCounts.cpp diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp new file mode 100644 index 000000000..e5888b6f3 --- /dev/null +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -0,0 +1,43 @@ +#include + +extern "C" { +#include "variables.h" +} + +#define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) + +void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!", + "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " + "Skulltula-Symbole&gesammelt!", + "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en " + "tout!", + TEXTBOX_TYPE_BLUE); + // The freeze text cannot be manually dismissed and must be auto-dismissed. + // This is fine and even wanted when skull tokens are not shuffled, but when + // when they are shuffled we don't want to be able to manually dismiss the box. + // Otherwise if we get a token from a chest or an NPC we get stuck in the ItemGet + // animation until the text box auto-dismisses. + // RANDOTODO: Implement a way to determine if an item came from a skulltula and + // inject the auto-dismiss control code if it did. + if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && + !(IS_RANDO && RAND_GET_OPTION(RSK_SHUFFLE_TOKENS).IsNot(RO_TOKENSANITY_OFF))) { + // Auto dismiss textbox after 0x3C (60) frames (about 3 seconds for OoT) + msg = msg + "\x0E\x3C"; + } + int16_t gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); + msg.Replace("[[gscount]]", std::to_string(gsCount)); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void InjectItemCounts_Register() { + COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), BuildSkulltulaMessage); +} + +RegisterShipInitFunc initFunc(InjectItemCounts_Register, { + CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), +}); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index ad84013a9..1a5ab18db 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2138,39 +2138,11 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { const int maxBufferSize = sizeof(font->msgBuf); CustomMessage messageEntry; s16 actorParams = 0; - if (textId == TEXT_GS_NO_FREEZE || textId == TEXT_GS_FREEZE) { - if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { - // The freeze text cannot be manually dismissed and must be auto-dismissed. - // This is fine and even wanted when skull tokens are not shuffled, but when - // when they are shuffled we want to be able to manually dismiss the box. - // Otherwise if we get a token from a chest or an NPC we get stuck in the ItemGet - // animation until the text box auto-dismisses. - // RANDOTODO: Implement a way to determine if an item came from a skulltula and - // inject the auto-dismiss control code if it did. - if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && - !(IS_RANDO && Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) != RO_TOKENSANITY_OFF)) { - textId = TEXT_GS_NO_FREEZE; - } else { - textId = TEXT_GS_FREEZE; - } - // In vanilla, GS token count is incremented prior to the text box displaying - // In rando we need to bump the token count by one to show the correct count - s16 gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); + if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && + (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - messageEntry.Replace("[[gsCount]]", std::to_string(gsCount)); - } else if (CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) != 0 && - (!IS_RANDO || Randomizer_GetSettingValue(RSK_SHUFFLE_TOKENS) == RO_TOKENSANITY_OFF)) { - messageEntry = CustomMessage::LoadVanillaMessageTableEntry(TEXT_GS_FREEZE); - messageEntry.Replace(CustomMessage::MESSAGE_END(), "\x0E\x3C"); - messageEntry += CustomMessage::MESSAGE_END(); - } - } else if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && - (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - } else if (textId == TEXT_HEART_CONTAINER && - CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0)) { - messageEntry = - CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_CONTAINER, MF_FORMATTED); + } else if (textId == TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0)) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_CONTAINER, MF_FORMATTED); messageEntry.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.ship.stats.heartContainers + 1)); } else if (textId >= TEXT_HEART_PIECE && textId < TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0)) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 7d3fe38e4..68ebd3488 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -113,22 +113,6 @@ extern "C" void OTRMessage_Init() { } CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); - CustomMessageManager::Instance->CreateGetItemMessage( - customMessageTableID, (GetItemID)TEXT_GS_NO_FREEZE, ITEM_SKULL_TOKEN, - CustomMessage("You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!\x0E\x3C", - "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " - "Skulltula-Symbole&gesammelt!\x0E\x3C", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en " - "tout!\x0E\x3C", - TEXTBOX_TYPE_BLUE)); - CustomMessageManager::Instance->CreateGetItemMessage( - customMessageTableID, (GetItemID)TEXT_GS_FREEZE, ITEM_SKULL_TOKEN, - CustomMessage( - "You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!", - "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " - "Skulltula-Symbole&gesammelt!", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en tout!", - TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_BUY_BOMBCHUS_10_DESC, CustomMessage("\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " From 0084a0f7b7cb3dbcc9e06e0d8bd46999b185aa75 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:36:06 -0500 Subject: [PATCH 087/103] Add in a way to AutoFormat with an item icon. --- .../custom-message/CustomMessageManager.cpp | 89 +++++++++---------- .../custom-message/CustomMessageManager.h | 1 + 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 61040ee72..6b04d5ade 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -343,6 +343,14 @@ void CustomMessage::AutoFormat() { } } +void CustomMessage::AutoFormat(ItemID iid) { + for (std::string &str : messages) { + str.insert(0, ITEM_OBTAINED(iid)); + } + AutoFormat(); + Replace(WAIT_FOR_INPUT(), WAIT_FOR_INPUT() + ITEM_OBTAINED(iid)); +} + void CustomMessage::Clean() { for (std::string& str : messages) { CleanString(str); @@ -391,51 +399,42 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin size_t totalPixelWidth = 0; size_t currentPos = lastNewline; - // Looping through the string from the lastNewline until the total - // width of counted characters exceeds the maximum pixels in a line. - size_t nextPosJump = 0; - while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) { - // Skip over control codes - if (textStr->at(currentPos) == '%') { - nextPosJump = 2; - } else if (textStr->at(currentPos) == '$') { - nextPosJump = 2; - } else if (textStr->at(currentPos) == '@') { - nextPosJump = 1; - // Assume worst case for player name 12 * 8 (widest character * longest name length) - totalPixelWidth += 96; - } else if (textStr->at(currentPos) == '\x05') { - // Skip colour control characters. - nextPosJump = 2; - } else if (textStr->at(currentPos) == '\x1E') { - // For the high score char, we have to take the next Char, then use that to get a worst case scenario. - if (textStr->at(currentPos + 1) == '\x01') { - totalPixelWidth += 28; - } - nextPosJump = 2; - } else { - // Some characters only one byte while others are two bytes - // So check both possibilities when checking for a character - if (pixelWidthTable.count(textStr->substr(currentPos, 1))) { - totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)]; - nextPosJump = 1; - } else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) { - totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)]; - nextPosJump = 2; - } else { - SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + - textStr->substr(currentPos, 2)); - SPDLOG_DEBUG("Full string: " + *textStr); - nextPosJump = 1; - } - } - currentPos += nextPosJump; - } - // return the total number of characters we looped through - if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') { - return currentPos - lastNewline - nextPosJump; + // Looping through the string from the lastNewline until the total + // width of counted characters exceeds the maximum pixels in a line. + size_t nextPosJump = 0; + while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) { + // Skip over control codes + if (textStr->at(currentPos) == '%') { + nextPosJump = 2; + } else if (textStr->at(currentPos) == '\x13') { + nextPosJump = 2; + } else if (textStr->at(currentPos) == '@') { + nextPosJump = 1; + // Assume worst case for player name 12 * 8 (widest character * longest name length) + totalPixelWidth += 96; + } else if (textStr->at(currentPos) == '\x05') { + // Skip colour control characters. + nextPosJump = 2; + } else if (textStr->at(currentPos) == '\x1E') { + //For the high score char, we have to take the next Char, then use that to get a worst case scenario. + if (textStr->at(currentPos+1) == '\x01'){ + totalPixelWidth += 28; + } + nextPosJump = 2; } else { - return currentPos - lastNewline; + // Some characters only one byte while others are two bytes + // So check both possibilities when checking for a character + if (pixelWidthTable.count(textStr->substr(currentPos, 1))) { + totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)]; + nextPosJump = 1; + } else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) { + totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)]; + nextPosJump = 2; + } else { + SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2)); + SPDLOG_DEBUG("Full string: " + *textStr); + nextPosJump = 1; + } } } @@ -503,7 +502,7 @@ void CustomMessage::AutoFormatString(std::string& str) const { ReplaceColors(str); // insert newlines either manually or when encountering a '&' size_t lastNewline = 0; - const bool hasIcon = str.find('$', 0) != std::string::npos; + const bool hasIcon = str.find('\x13') != std::string::npos; size_t lineLength = NextLineLength(&str, lastNewline, hasIcon); size_t lineCount = 1; size_t yesNo = str.find("\x1B"s[0], lastNewline); diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index ffb8d8d8c..cd778579e 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -166,6 +166,7 @@ class CustomMessage { * textboxes, and use it's formatting. */ void AutoFormat(); + void AutoFormat(ItemID iid); /** * @brief Removes all OoT formatting from the message, From 40896f4c97fcfb5cfeea481e450986bf85e68347 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:38:23 -0500 Subject: [PATCH 088/103] Fix some errors with skull tokens and apply icon --- soh/soh/Enhancements/InjectItemCounts.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index e5888b6f3..6ae327e0c 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -28,14 +28,15 @@ void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { } int16_t gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); msg.Replace("[[gscount]]", std::to_string(gsCount)); + msg.AutoFormat(ITEM_SKULL_TOKEN); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } void InjectItemCounts_Register() { - COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), BuildSkulltulaMessage); - COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); } RegisterShipInitFunc initFunc(InjectItemCounts_Register, { From ca5eec0c406fc4d87903887132bba810b3e79a7f Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:38:45 -0500 Subject: [PATCH 089/103] Convert heart container item counts --- soh/soh/Enhancements/InjectItemCounts.cpp | 15 ++++++++++++++- soh/soh/OTRGlobals.cpp | 9 ++------- soh/soh/z_message_OTR.cpp | 6 ------ 3 files changed, 16 insertions(+), 14 deletions(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index 6ae327e0c..ee5131ada 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -29,7 +29,18 @@ void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { int16_t gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); msg.Replace("[[gscount]]", std::to_string(gsCount)); msg.AutoFormat(ITEM_SKULL_TOKEN); - msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildHeartContainerMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You got a %rHeart Container%w!&You've collected %r[[heartContainerCount]]%w containers&in total!", + "Ein %rHerzcontainer%w!&Du hast nun insgesamt %r[[heartContainerCount]]%w&Herzcontainer gesammelt!", + "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!" + ); + msg.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.ship.stats.heartContainers + 1)); + msg.AutoFormat(ITEM_HEART_CONTAINER); msg.LoadIntoFont(); *loadFromMessageTable = false; } @@ -37,8 +48,10 @@ void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { void InjectItemCounts_Register() { COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_CONTAINER, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0), BuildHeartContainerMessage); } RegisterShipInitFunc initFunc(InjectItemCounts_Register, { CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), + CVAR_ENHANCEMENT("InjectItemCounts.HeartContainers"), }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 1a5ab18db..bfd8a6405 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2141,13 +2141,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - } else if (textId == TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_CONTAINER, MF_FORMATTED); - messageEntry.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.ship.stats.heartContainers + 1)); - } else if (textId >= TEXT_HEART_PIECE && textId < TEXT_HEART_CONTAINER && - CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0)) { - messageEntry = - CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_PIECE, MF_FORMATTED); + } else if (textId >= TEXT_HEART_PIECE && textId < TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0)) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_PIECE, MF_FORMATTED); messageEntry.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1)); } else if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 68ebd3488..6b4ed89ea 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -127,12 +127,6 @@ extern "C" void OTRMessage_Init() { "Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w")); - CustomMessageManager::Instance->CreateGetItemMessage( - customMessageTableID, (GetItemID)TEXT_HEART_CONTAINER, ITEM_HEART_CONTAINER, - CustomMessage( - "You got a %rHeart Container%w!&You've collected %r[[heartContainerCount]]%w containers&in total!", - "Ein %rHerzcontainer%w!&Du hast nun insgesamt %r[[heartContainerCount]]%w&Herzcontainer gesammelt!", - "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!")); CustomMessageManager::Instance->CreateGetItemMessage( customMessageTableID, (GetItemID)TEXT_HEART_PIECE, ITEM_HEART_PIECE, CustomMessage("You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", From d6d54334f0ddca0286994fb79f6786895e1febfd Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 16:49:00 -0500 Subject: [PATCH 090/103] Convert Inject Item Count for Heart Pieces. --- soh/soh/Enhancements/InjectItemCounts.cpp | 22 +++++++++++++++++++++- soh/soh/OTRGlobals.cpp | 9 ++------- soh/soh/z_message_OTR.cpp | 6 ------ 3 files changed, 23 insertions(+), 14 deletions(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index ee5131ada..0b6670668 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -45,13 +45,33 @@ void BuildHeartContainerMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } +void BuildHeartPieceMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", + "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!", + "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", + TEXTBOX_TYPE_BLUE + ); + msg.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1)); + msg.AutoFormat(ITEM_HEART_PIECE); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + void InjectItemCounts_Register() { COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); COND_ID_HOOK(OnOpenText, TEXT_HEART_CONTAINER, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0), BuildHeartContainerMessage); + // Heart Pieces don't have documented text IDs after the first one, but + // there are 3 more in between TEXT_HEART_PIECE and TEXT_HEART_CONTAINER. + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 1, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 2, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 3, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); } RegisterShipInitFunc initFunc(InjectItemCounts_Register, { CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), - CVAR_ENHANCEMENT("InjectItemCounts.HeartContainers"), + CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), + CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece") }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index bfd8a6405..014d675a7 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2141,13 +2141,8 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - } else if (textId >= TEXT_HEART_PIECE && textId < TEXT_HEART_CONTAINER && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_HEART_PIECE, MF_FORMATTED); - messageEntry.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1)); - } else if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && - play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT, - MF_FORMATTED); + } else if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { + messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT, MF_FORMATTED); } if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE, MF_FORMATTED); diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index 6b4ed89ea..b8d211ac4 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -127,12 +127,6 @@ extern "C" void OTRMessage_Init() { "Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w")); - CustomMessageManager::Instance->CreateGetItemMessage( - customMessageTableID, (GetItemID)TEXT_HEART_PIECE, ITEM_HEART_PIECE, - CustomMessage("You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", - "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!", - "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", - TEXTBOX_TYPE_BLUE)); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_MARKET_GUARD_NIGHT, CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", From 6399eb2d8997c2b85e09e505237a3fe88e4e8976 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 17:06:07 -0500 Subject: [PATCH 091/103] Port Better Bombchu Shopping --- .../Items/BetterBombchuShopping.cpp | 39 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 5 +-- soh/soh/z_message_OTR.cpp | 14 ------- 3 files changed, 40 insertions(+), 18 deletions(-) create mode 100644 soh/soh/Enhancements/Items/BetterBombchuShopping.cpp diff --git a/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp new file mode 100644 index 000000000..918b5bba2 --- /dev/null +++ b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp @@ -0,0 +1,39 @@ +#include + +extern "C" { +#include +} + +//RANDOTODO: Port the rest of the behavior associated with this option here. + +void BuildShopDescMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " + "self-propelled time&bomb!\x09\x0A", + "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als " + "Distanzwaffe&einsetzen kannst!\x09\x0A", + "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est " + "&destructrice!!!\x09\x0A" + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BuildShopPromptMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "\x08Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", + "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", + "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w" + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void BetterBombchuShopping_Register() { + COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_DESC, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopDescMessage); + COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_PROMPT, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopPromptMessage); +} + +RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 014d675a7..784291c26 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2138,10 +2138,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { const int maxBufferSize = sizeof(font->msgBuf); CustomMessage messageEntry; s16 actorParams = 0; - if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) && - (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); - } else if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { + if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT, MF_FORMATTED); } if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index b8d211ac4..b674ed86f 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -113,20 +113,6 @@ extern "C" void OTRMessage_Init() { } CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_BUY_BOMBCHUS_10_DESC, - CustomMessage("\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " - "self-propelled time&bomb!\x09\x0A", - "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als " - "Distanzwaffe&einsetzen kannst!\x09\x0A", - "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est " - "&destructrice!!!\x09\x0A")); - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_BUY_BOMBCHUS_10_PROMPT, - CustomMessage("\x08" - "Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", - "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", - "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w")); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_MARKET_GUARD_NIGHT, CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", From 23d66101390628a19162443d4b9191c444741ba6 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 17:15:28 -0500 Subject: [PATCH 092/103] Convert Market Sneak --- .../Enhancements/TimeSavers/MarketSneak.cpp | 24 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 3 --- soh/soh/z_message_OTR.cpp | 5 ---- 3 files changed, 24 insertions(+), 8 deletions(-) create mode 100644 soh/soh/Enhancements/TimeSavers/MarketSneak.cpp diff --git a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp new file mode 100644 index 000000000..c22d7b9b5 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp @@ -0,0 +1,24 @@ +#include + +extern "C" { +#include +} + +// RANDOTODO: Port the rest of the behavior for this enhancement here. + +void BuildNightGuardMessage(uint16_t* textId, bool* loadFromMessageTable) { + CustomMessage msg = CustomMessage( + "You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", + "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", + "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w" + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void MarketSneak_Register() { + COND_ID_HOOK(OnOpenText, TEXT_MARKET_GUARD_NIGHT, CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0), BuildNightGuardMessage); +} + +RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 784291c26..0f0fd6571 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2138,9 +2138,6 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { const int maxBufferSize = sizeof(font->msgBuf); CustomMessage messageEntry; s16 actorParams = 0; - if (textId == TEXT_MARKET_GUARD_NIGHT && CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0) && play->sceneNum == SCENE_MARKET_ENTRANCE_NIGHT) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_MARKET_GUARD_NIGHT, MF_FORMATTED); - } if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE, MF_FORMATTED); } diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index b674ed86f..a09157696 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -113,11 +113,6 @@ extern "C" void OTRMessage_Init() { } CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_MARKET_GUARD_NIGHT, - CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", - "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", - "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w")); CustomMessageManager::Instance->CreateMessage( customMessageTableID, TEXT_FISHERMAN_LEAVE, CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", From d28cb70984296f1c100ff02cb1d0d8baa8d8d25b Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 17:25:08 -0500 Subject: [PATCH 093/103] Port Quit Fishing At Door and clean up unused stuff --- .../TimeSavers/QuitFishingAtDoor.cpp | 26 +++++++++++++++++++ soh/soh/OTRGlobals.cpp | 14 ---------- soh/soh/OTRGlobals.h | 2 -- soh/soh/z_message_OTR.cpp | 7 ----- 4 files changed, 26 insertions(+), 23 deletions(-) create mode 100644 soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp diff --git a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp new file mode 100644 index 000000000..4da206159 --- /dev/null +++ b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp @@ -0,0 +1,26 @@ +#include + +extern "C" { +#include +} + +// TODO: Port the rest of the behavior for this enhancement here. + +void BuildQuitFishingMessage(uint16_t* textId, bool* loadFromMessageTable) { + // TODO: See about loading the vanilla message and manipulating that instead of + // a brand new one. Might not be worth it. + CustomMessage msg = CustomMessage( + "Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", + "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", + "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w" + ); + msg.AutoFormat(); + msg.LoadIntoFont(); + *loadFromMessageTable = false; +} + +void QuitFishingAtDoor_Register() { + COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0), BuildQuitFishingMessage); +} + +RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") }); \ No newline at end of file diff --git a/soh/soh/OTRGlobals.cpp b/soh/soh/OTRGlobals.cpp index 0f0fd6571..3e723e1fc 100644 --- a/soh/soh/OTRGlobals.cpp +++ b/soh/soh/OTRGlobals.cpp @@ -2130,20 +2130,6 @@ extern "C" void Randomizer_ShowRandomizerMenu() { SohGui::ShowRandomizerSettingsMenu(); } -extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) { - MessageContext* msgCtx = &play->msgCtx; - uint16_t textId = msgCtx->textId; - Font* font = &msgCtx->font; - char* buffer = font->msgBuf; - const int maxBufferSize = sizeof(font->msgBuf); - CustomMessage messageEntry; - s16 actorParams = 0; - if (textId == TEXT_FISHERMAN_LEAVE && CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0)) { - messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, TEXT_FISHERMAN_LEAVE, MF_FORMATTED); - } - return false; -} - extern "C" void Overlay_DisplayText(float duration, const char* text) { Ship::Context::GetInstance()->GetWindow()->GetGui()->GetGameOverlay()->TextDrawNotification(duration, true, text); } diff --git a/soh/soh/OTRGlobals.h b/soh/soh/OTRGlobals.h index 6b5b16b58..ba8a41ece 100644 --- a/soh/soh/OTRGlobals.h +++ b/soh/soh/OTRGlobals.h @@ -30,7 +30,6 @@ struct ExtensionEntry { extern std::unordered_map ExtensionCache; #include "Enhancements/randomizer/settings.h" -const std::string customMessageTableID = "BaseGameOverrides"; const std::string appShortName = "soh"; #ifdef __WIIU__ @@ -149,7 +148,6 @@ uint8_t Randomizer_IsSpoilerLoaded(); void Randomizer_SetSpoilerLoaded(bool spoilerLoaded); uint8_t Randomizer_GenerateRandomizer(); void Randomizer_ShowRandomizerMenu(); -int CustomMessage_RetrieveIfExists(PlayState* play); void Overlay_DisplayText(float duration, const char* text); void Overlay_DisplayText_Seconds(int seconds, const char* text); GetItemEntry ItemTable_Retrieve(int16_t getItemID); diff --git a/soh/soh/z_message_OTR.cpp b/soh/soh/z_message_OTR.cpp index a09157696..20c0f4762 100644 --- a/soh/soh/z_message_OTR.cpp +++ b/soh/soh/z_message_OTR.cpp @@ -111,11 +111,4 @@ extern "C" void OTRMessage_Init() { // Assert staff credits start at the first credits ID assert(sStaffMessageEntryTablePtr[0].textId == 0x0500); } - - CustomMessageManager::Instance->AddCustomMessageTable(customMessageTableID); - CustomMessageManager::Instance->CreateMessage( - customMessageTableID, TEXT_FISHERMAN_LEAVE, - CustomMessage("Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", - "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", - "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w")); //TODO Used AI translation as placeholder } From f0585d6bb82a52682089db5bdd5ae3c30fc013d1 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 18:26:39 -0500 Subject: [PATCH 094/103] Fix an overlap on Greg with Potion shop guy --- soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index a12bda6e2..b0a47f0ea 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -138,9 +138,11 @@ void BuildDampesDiaryMessage(uint16_t* textId, bool* loadFromMessageTable) { } void BuildGregHintMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = RAND_GET_HINT(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); - msg.LoadIntoFont(); - *loadFromMessageTable = false; + if (gPlayState->sceneNum == SCENE_TREASURE_BOX_SHOP) { + CustomMessage msg = RAND_GET_HINT(RH_GREG_RUPEE)->GetHintMessage(MF_AUTO_FORMAT); + msg.LoadIntoFont(); + *loadFromMessageTable = false; + } } void BuildMinuetWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { From 1c0504cc5abd47ec7c052ed7cc8b70c98e6fc4fc Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 18:29:25 -0500 Subject: [PATCH 095/103] Fixes an incorrect color for the Scrub text --- soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 2c281d55b..016b9060c 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -128,7 +128,7 @@ void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w geben!\x07\x10\xA3", "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3"); } else { - msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %g[[2]] Rupees%w it is!\x07\x10\xA3", + msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %y[[2]] Rupees%w it is!\x07\x10\xA3", "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); } From 97d7c6042735636f9be816b4005b9a974f053bb1 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 18:44:41 -0500 Subject: [PATCH 096/103] Reintroduce missing Mysterious warp song hint --- .../custom-message/CustomMessageManager.cpp | 4 ++ .../custom-message/CustomMessageManager.h | 17 ++++---- .../randomizer/Messages/StaticHints.cpp | 39 +++++++++++++++++++ 3 files changed, 51 insertions(+), 9 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 6b04d5ade..823d60cb8 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -725,6 +725,10 @@ std::string CustomMessage::PLAYER_NAME() { return "\x0F"s; } +std::string CustomMessage::TWO_WAY_CHOICE() { + return "\x1B"s; +} + bool CustomMessageManager::InsertCustomMessage(std::string tableID, uint16_t textID, CustomMessage messages) { auto foundMessageTable = messageTables.find(tableID); if (foundMessageTable == messageTables.end()) { diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index cd778579e..6849ae306 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -50,15 +50,14 @@ class CustomMessage { TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); - static CustomMessage LoadVanillaMessageTableEntry(uint16_t textId); - - static std::string MESSAGE_END(); - static std::string ITEM_OBTAINED(uint8_t x); - static std::string NEWLINE(); - static std::string COLOR(std::string x); - static std::string POINTS(std::string x); // HIGH_SCORE is also a macro - static std::string WAIT_FOR_INPUT(); - static std::string PLAYER_NAME(); + static std::string MESSAGE_END() ; + static std::string ITEM_OBTAINED(uint8_t x) ; + static std::string NEWLINE() ; + static std::string COLOR(std::string x) ; + static std::string POINTS(std::string x) ;//HIGH_SCORE is also a macro + static std::string WAIT_FOR_INPUT() ; + static std::string PLAYER_NAME() ; + static std::string TWO_WAY_CHOICE(); const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const; const std::string GetFrench(MessageFormat format = MF_FORMATTED) const; diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index b0a47f0ea..6aa9dbb08 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -145,37 +145,76 @@ void BuildGregHintMessage(uint16_t* textId, bool* loadFromMessageTable) { } } +void BuildMysteriousWarpMessage() { + CustomMessage msg = CustomMessage( + "Warp to&%ra mysterious place?%w&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w", + "Zu&%reinem mysteriösen Ort%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w", + "Se téléporter vers&%run endroit mystérieux%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%rOK!&Non%w" + ); + msg.LoadIntoFont(); +} + void BuildMinuetWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_MINUET_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildBoleroWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_BOLERO_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildSerenadeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_SERENADE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildRequiemWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_REQUIEM_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildNocturneWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_NOCTURNE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildPreludeWarpMessage(uint16_t* textId, bool* loadFromMessageTable) { + if (RAND_GET_OPTION(RSK_WARP_SONG_HINTS).Is(RO_GENERIC_OFF)) { + BuildMysteriousWarpMessage(); + *loadFromMessageTable = false; + return; + } CustomMessage msg = RAND_GET_HINT(RH_PRELUDE_WARP_LOC)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; From fb99088f875b81c1562cd869765bbb084458bebf Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 22:17:15 -0500 Subject: [PATCH 097/103] Make the the ShipInitFuncs static --- soh/soh/Enhancements/Items/BetterBombchuShopping.cpp | 2 +- soh/soh/Enhancements/TimeSavers/MarketSneak.cpp | 2 +- soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp | 2 +- soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp | 2 +- soh/soh/Enhancements/randomizer/Messages/Navi.cpp | 2 +- soh/soh/Enhancements/randomizer/Messages/Rupees.cpp | 2 +- soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp | 2 +- 7 files changed, 7 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp index 918b5bba2..67445741e 100644 --- a/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp +++ b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp @@ -36,4 +36,4 @@ void BetterBombchuShopping_Register() { COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_PROMPT, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopPromptMessage); } -RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp index c22d7b9b5..16a0099a8 100644 --- a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp +++ b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp @@ -21,4 +21,4 @@ void MarketSneak_Register() { COND_ID_HOOK(OnOpenText, TEXT_MARKET_GUARD_NIGHT, CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0), BuildNightGuardMessage); } -RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp index 4da206159..ab0ffd807 100644 --- a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp +++ b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp @@ -23,4 +23,4 @@ void QuitFishingAtDoor_Register() { COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0), BuildQuitFishingMessage); } -RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp index f9264db1f..7c512af63 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp @@ -48,4 +48,4 @@ void RegisterMiscellaneousMessages() { COND_ID_HOOK(OnOpenText, TEXT_SHOOTING_GALLERY_MAN_COME_BACK_WITH_BOW, IS_RANDO, BuildShootingGalleryNoBowMessage); } -RegisterShipInitFunc initFunc(RegisterMiscellaneousMessages, { "IS_RANDO" }); \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterMiscellaneousMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/Navi.cpp b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp index 0daf51f94..1863a64dd 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Navi.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp @@ -150,4 +150,4 @@ void RegisterNaviMessages() { COND_ID_HOOK(OnOpenText, TEXT_NAVI_TRY_TO_KEEP_MOVING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); } -RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp index e8b02a57b..3cb3d9e98 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp @@ -121,4 +121,4 @@ void RegisterRandomRupeeNames() { COND_ID_HOOK(OnOpenText, TEXT_HUGE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); } -RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 6aa9dbb08..fdedbac47 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -414,4 +414,4 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_MASK_SHOP_SIGN, RAND_GET_OPTION(RSK_MASK_SHOP_HINT), BuildMaskShopSignMessage); } -RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file +static RegisterShipInitFunc initFunc(RegisterStaticHints, { "IS_RANDO" }); \ No newline at end of file From c09d995a8e4c3485edfb3eb5eef00b5fd4a5dba9 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Thu, 27 Feb 2025 22:30:39 -0500 Subject: [PATCH 098/103] One more missed static initFunc --- soh/soh/Enhancements/InjectItemCounts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index 0b6670668..8be115362 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -70,7 +70,7 @@ void InjectItemCounts_Register() { COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 3, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); } -RegisterShipInitFunc initFunc(InjectItemCounts_Register, { +static RegisterShipInitFunc initFunc(InjectItemCounts_Register, { CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece") From ba7ffc9166c1600ece9719d7a4b9b3b3259a73f5 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Wed, 2 Apr 2025 11:45:22 -0400 Subject: [PATCH 099/103] Formatting and fixing bad merge conflict resolutions --- soh/soh/Enhancements/InjectItemCounts.cpp | 57 ++-- .../Items/BetterBombchuShopping.cpp | 34 +-- .../Enhancements/TimeSavers/MarketSneak.cpp | 11 +- .../TimeSavers/QuitFishingAtDoor.cpp | 9 +- .../custom-message/CustomMessageManager.cpp | 79 ++--- .../custom-message/CustomMessageManager.h | 15 +- .../GameInteractor_HookTable.h | 2 +- .../randomizer/ColoredMapsAndCompasses.cpp | 1 + .../randomizer/Messages/Goron.cpp | 14 +- .../randomizer/Messages/GossipStoneHints.cpp | 23 +- .../randomizer/Messages/ItemMessages.cpp | 142 +++++---- .../randomizer/Messages/MerchantMessages.cpp | 108 +++---- .../randomizer/Messages/Miscellaneous.cpp | 27 +- .../Enhancements/randomizer/Messages/Navi.cpp | 84 ++++-- .../randomizer/Messages/Rupees.cpp | 271 +++++++++++++----- .../randomizer/Messages/StaticHints.cpp | 138 +++++---- .../Enhancements/randomizer/randomizer.cpp | 4 +- soh/soh/Enhancements/randomizer/randomizer.h | 2 +- 18 files changed, 614 insertions(+), 407 deletions(-) diff --git a/soh/soh/Enhancements/InjectItemCounts.cpp b/soh/soh/Enhancements/InjectItemCounts.cpp index 8be115362..46b713d85 100644 --- a/soh/soh/Enhancements/InjectItemCounts.cpp +++ b/soh/soh/Enhancements/InjectItemCounts.cpp @@ -7,13 +7,13 @@ extern "C" { #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) void BuildSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!", - "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " - "Skulltula-Symbole&gesammelt!", - "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en " - "tout!", - TEXTBOX_TYPE_BLUE); + CustomMessage msg = + CustomMessage("You got a %rGold Skulltula Token%w!&You've collected %r[[gsCount]]%w tokens&in total!", + "Ein %rGoldenes Skulltula-Symbol%w!&Du hast nun insgesamt %r[[gsCount]]&%wGoldene " + "Skulltula-Symbole&gesammelt!", + "Vous obtenez un %rSymbole de&Skulltula d'or%w! Vous avez&collecté %r[[gsCount]]%w symboles en " + "tout!", + TEXTBOX_TYPE_BLUE); // The freeze text cannot be manually dismissed and must be auto-dismissed. // This is fine and even wanted when skull tokens are not shuffled, but when // when they are shuffled we don't want to be able to manually dismiss the box. @@ -37,8 +37,7 @@ void BuildHeartContainerMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg = CustomMessage( "You got a %rHeart Container%w!&You've collected %r[[heartContainerCount]]%w containers&in total!", "Ein %rHerzcontainer%w!&Du hast nun insgesamt %r[[heartContainerCount]]%w&Herzcontainer gesammelt!", - "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!" - ); + "Vous obtenez un %rCoeur&d'Energie%w! Vous en avez&collecté %r[[heartContainerCount]]%w en tout!"); msg.Replace("[[heartContainerCount]]", std::to_string(gSaveContext.ship.stats.heartContainers + 1)); msg.AutoFormat(ITEM_HEART_CONTAINER); msg.LoadIntoFont(); @@ -46,12 +45,11 @@ void BuildHeartContainerMessage(uint16_t* textId, bool* loadFromMessageTable) { } void BuildHeartPieceMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", - "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!", - "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", - TEXTBOX_TYPE_BLUE - ); + CustomMessage msg = + CustomMessage("You got a %rHeart Piece%w!&You've collected %r[[heartPieceCount]]%w pieces&in total!", + "Ein %rHerzteil%w!&Du hast nun insgesamt %r[[heartPieceCount]]%w&Herzteile gesammelt!", + "Vous obtenez un %rQuart de&Coeur%w! Vous en avez collecté&%r[[heartPieceCount]]%w en tout!", + TEXTBOX_TYPE_BLUE); msg.Replace("[[heartPieceCount]]", std::to_string(gSaveContext.ship.stats.heartPieces + 1)); msg.AutoFormat(ITEM_HEART_PIECE); msg.LoadIntoFont(); @@ -59,19 +57,24 @@ void BuildHeartPieceMessage(uint16_t* textId, bool* loadFromMessageTable) { } void InjectItemCounts_Register() { - COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); - COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), BuildSkulltulaMessage); - COND_ID_HOOK(OnOpenText, TEXT_HEART_CONTAINER, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0), BuildHeartContainerMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), + BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0), + BuildSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_CONTAINER, + CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), 0), BuildHeartContainerMessage); // Heart Pieces don't have documented text IDs after the first one, but // there are 3 more in between TEXT_HEART_PIECE and TEXT_HEART_CONTAINER. - COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); - COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 1, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); - COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 2, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); - COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 3, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), + BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 1, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), + BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 2, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), + BuildHeartPieceMessage); + COND_ID_HOOK(OnOpenText, TEXT_HEART_PIECE + 3, CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece"), 0), + BuildHeartPieceMessage); } -static RegisterShipInitFunc initFunc(InjectItemCounts_Register, { - CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), - CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), - CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece") -}); \ No newline at end of file +static RegisterShipInitFunc initFunc(InjectItemCounts_Register, { CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), + CVAR_ENHANCEMENT("InjectItemCounts.HeartContainer"), + CVAR_ENHANCEMENT("InjectItemCounts.HeartPiece") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp index 67445741e..f9cab726a 100644 --- a/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp +++ b/soh/soh/Enhancements/Items/BetterBombchuShopping.cpp @@ -4,36 +4,36 @@ extern "C" { #include } -//RANDOTODO: Port the rest of the behavior associated with this option here. +// RANDOTODO: Port the rest of the behavior associated with this option here. void BuildShopDescMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " - "self-propelled time&bomb!\x09\x0A", - "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als " - "Distanzwaffe&einsetzen kannst!\x09\x0A", - "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est " - "&destructrice!!!\x09\x0A" - ); + CustomMessage msg = + CustomMessage("\x08%rBombchu 10 pieces 99 Rupees&%wThis looks like a toy mouse, but&it's actually a " + "self-propelled time&bomb!\x09\x0A", + "\x08%rKrabbelmine 10 Stück 99 Rubine&%wDas ist eine praktische Zeitbombe,&die Du als " + "Distanzwaffe&einsetzen kannst!\x09\x0A", + "\x08%rMissile 10 unités 99 Rubis&%wProfilée comme une souris&mécanique, cette arme est " + "&destructrice!!!\x09\x0A"); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BuildShopPromptMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "\x08Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", - "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", - "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w" - ); + CustomMessage msg = CustomMessage("\x08Bombchu 10 pieces 99 Rupees\x09&&\x1B%gBuy&Don't buy%w", + "\x08Krabbelmine 10 Stück 99 Rubine\x09&&\x1B%gKaufen!&Nicht kaufen!%w", + "\x08Missiles 10 unités 99 Rubis\x09&&\x1B%gAcheter&Ne pas acheter%w"); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } void BetterBombchuShopping_Register() { - COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_DESC, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopDescMessage); - COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_PROMPT, IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopPromptMessage); + COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_DESC, + IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopDescMessage); + COND_ID_HOOK(OnOpenText, TEXT_BUY_BOMBCHUS_10_PROMPT, + IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0), BuildShopPromptMessage); } -static RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); \ No newline at end of file +static RegisterShipInitFunc initFunc(BetterBombchuShopping_Register, + { "IS_RANDO", CVAR_ENHANCEMENT("BetterBombchuShopping") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp index 16a0099a8..232f00f0a 100644 --- a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp +++ b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp @@ -7,18 +7,17 @@ extern "C" { // RANDOTODO: Port the rest of the behavior for this enhancement here. void BuildNightGuardMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", - "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", - "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w" - ); + CustomMessage msg = CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", + "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", + "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w"); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } void MarketSneak_Register() { - COND_ID_HOOK(OnOpenText, TEXT_MARKET_GUARD_NIGHT, CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0), BuildNightGuardMessage); + COND_ID_HOOK(OnOpenText, TEXT_MARKET_GUARD_NIGHT, CVarGetInteger(CVAR_ENHANCEMENT("MarketSneak"), 0), + BuildNightGuardMessage); } static RegisterShipInitFunc initFunc(MarketSneak_Register, { CVAR_ENHANCEMENT("MarketSneak") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp index ab0ffd807..9bfb61711 100644 --- a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp +++ b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp @@ -11,16 +11,17 @@ void BuildQuitFishingMessage(uint16_t* textId, bool* loadFromMessageTable) { // a brand new one. Might not be worth it. CustomMessage msg = CustomMessage( "Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", - "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du aufhören?&\x1B&%gJa&Nein%w", - "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w" - ); + "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du " + "aufhören?&\x1B&%gJa&Nein%w", + "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w"); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; } void QuitFishingAtDoor_Register() { - COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0), BuildQuitFishingMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHERMAN_LEAVE, CVarGetInteger(CVAR_ENHANCEMENT("QuitFishingAtDoor"), 0), + BuildQuitFishingMessage); } static RegisterShipInitFunc initFunc(QuitFishingAtDoor_Register, { CVAR_ENHANCEMENT("QuitFishingAtDoor") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 823d60cb8..f270dcaff 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -263,7 +263,8 @@ bool CustomMessage::operator!=(const CustomMessage& operand) const { int CopyStringToCharBuffer(const std::string& inputStr, char* buffer, const int maxBufferSize) { if (!inputStr.empty()) { - // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents negatives. + // Prevent potential horrible overflow due to implicit conversion of maxBufferSize to an unsigned. Prevents + // negatives. memset(buffer, 0, std::max(0, maxBufferSize)); // Gaurentee that this value will be greater than 0, regardless of passed variables. const int copiedCharLen = std::min(std::max(0, maxBufferSize - 1), inputStr.length()); @@ -344,7 +345,7 @@ void CustomMessage::AutoFormat() { } void CustomMessage::AutoFormat(ItemID iid) { - for (std::string &str : messages) { + for (std::string& str : messages) { str.insert(0, ITEM_OBTAINED(iid)); } AutoFormat(); @@ -399,42 +400,44 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin size_t totalPixelWidth = 0; size_t currentPos = lastNewline; - // Looping through the string from the lastNewline until the total - // width of counted characters exceeds the maximum pixels in a line. - size_t nextPosJump = 0; - while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) { - // Skip over control codes - if (textStr->at(currentPos) == '%') { - nextPosJump = 2; - } else if (textStr->at(currentPos) == '\x13') { - nextPosJump = 2; - } else if (textStr->at(currentPos) == '@') { - nextPosJump = 1; - // Assume worst case for player name 12 * 8 (widest character * longest name length) - totalPixelWidth += 96; - } else if (textStr->at(currentPos) == '\x05') { - // Skip colour control characters. - nextPosJump = 2; - } else if (textStr->at(currentPos) == '\x1E') { - //For the high score char, we have to take the next Char, then use that to get a worst case scenario. - if (textStr->at(currentPos+1) == '\x01'){ - totalPixelWidth += 28; - } - nextPosJump = 2; - } else { - // Some characters only one byte while others are two bytes - // So check both possibilities when checking for a character - if (pixelWidthTable.count(textStr->substr(currentPos, 1))) { - totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)]; - nextPosJump = 1; - } else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) { - totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)]; - nextPosJump = 2; - } else { - SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + textStr->substr(currentPos, 2)); - SPDLOG_DEBUG("Full string: " + *textStr); - nextPosJump = 1; - } + // Looping through the string from the lastNewline until the total + // width of counted characters exceeds the maximum pixels in a line. + size_t nextPosJump = 0; + while (totalPixelWidth < maxLinePixelWidth && currentPos < textStr->length()) { + // Skip over control codes + if (textStr->at(currentPos) == '%') { + nextPosJump = 2; + } else if (textStr->at(currentPos) == '\x13') { + nextPosJump = 2; + } else if (textStr->at(currentPos) == '@') { + nextPosJump = 1; + // Assume worst case for player name 12 * 8 (widest character * longest name length) + totalPixelWidth += 96; + } else if (textStr->at(currentPos) == '\x05') { + // Skip colour control characters. + nextPosJump = 2; + } else if (textStr->at(currentPos) == '\x1E') { + // For the high score char, we have to take the next Char, then use that to get a worst case scenario. + if (textStr->at(currentPos + 1) == '\x01') { + totalPixelWidth += 28; + } + nextPosJump = 2; + } else { + // Some characters only one byte while others are two bytes + // So check both possibilities when checking for a character + if (pixelWidthTable.count(textStr->substr(currentPos, 1))) { + totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 1)]; + nextPosJump = 1; + } else if (pixelWidthTable.count(textStr->substr(currentPos, 2))) { + totalPixelWidth += pixelWidthTable[textStr->substr(currentPos, 2)]; + nextPosJump = 2; + } else { + SPDLOG_DEBUG("Table does not contain " + textStr->substr(currentPos, 1) + "/" + + textStr->substr(currentPos, 2)); + SPDLOG_DEBUG("Full string: " + *textStr); + nextPosJump = 1; + } + } } } diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index 6849ae306..13bd538e1 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -50,15 +50,16 @@ class CustomMessage { TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(Text text, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); - static std::string MESSAGE_END() ; - static std::string ITEM_OBTAINED(uint8_t x) ; - static std::string NEWLINE() ; - static std::string COLOR(std::string x) ; - static std::string POINTS(std::string x) ;//HIGH_SCORE is also a macro - static std::string WAIT_FOR_INPUT() ; - static std::string PLAYER_NAME() ; + static std::string MESSAGE_END(); + static std::string ITEM_OBTAINED(uint8_t x); + static std::string NEWLINE(); + static std::string COLOR(std::string x); + static std::string POINTS(std::string x); // HIGH_SCORE is also a macro + static std::string WAIT_FOR_INPUT(); + static std::string PLAYER_NAME(); static std::string TWO_WAY_CHOICE(); + CustomMessage LoadVanillaMessageTableEntry(uint16_t textId); const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const; const std::string GetFrench(MessageFormat format = MF_FORMATTED) const; const std::string GetGerman(MessageFormat format = MF_FORMATTED) const; diff --git a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h index 1a40b0e8e..13e18e174 100644 --- a/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h +++ b/soh/soh/Enhancements/game-interactor/GameInteractor_HookTable.h @@ -67,4 +67,4 @@ DEFINE_HOOK(OnSetGameLanguage, ()); DEFINE_HOOK(OnFileDropped, (std::string filePath)); DEFINE_HOOK(OnAssetAltChange, ()); DEFINE_HOOK(OnKaleidoUpdate, ()); -DEFINE_HOOK(OnOpenText, (uint16_t* textId, bool* loadFromMessageTable)); +DEFINE_HOOK(OnOpenText, (uint16_t * textId, bool* loadFromMessageTable)); diff --git a/soh/soh/Enhancements/randomizer/ColoredMapsAndCompasses.cpp b/soh/soh/Enhancements/randomizer/ColoredMapsAndCompasses.cpp index 6c1db52f7..84c12291c 100644 --- a/soh/soh/Enhancements/randomizer/ColoredMapsAndCompasses.cpp +++ b/soh/soh/Enhancements/randomizer/ColoredMapsAndCompasses.cpp @@ -5,6 +5,7 @@ #include "z64save.h" #include "objects/object_gi_compass/object_gi_compass.h" #include "objects/object_gi_map/object_gi_map.h" +#include "soh/OTRGlobals.h" extern "C" { extern SaveContext gSaveContext; diff --git a/soh/soh/Enhancements/randomizer/Messages/Goron.cpp b/soh/soh/Enhancements/randomizer/Messages/Goron.cpp index e0791ade3..0f9d62a64 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Goron.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Goron.cpp @@ -50,14 +50,12 @@ static CustomMessage FireTempleGoronMessages[NUM_GORON_MESSAGES] = { "Merci, mais je me sens plus en&sécurité ici...^...^...^...^...^Hmm...^...Tout compte fait, je vais y " "aller.&A plus tard.", }, - { - "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " - "pressed it %b[[a_btn]]%w times.^Wow.", - "Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " - "erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", - "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " - "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." - }, + { "Do you know about %b\x9f%w?&It's this weird symbol that's been&in my dreams lately...^Apparently, you " + "pressed it %b[[a_btn]]%w times.^Wow.", + "Weißt Du über %b\x9f%w Bescheid?&Es sind Symbole, die mir&in letzter Zeit öfter in&meinen Träumen " + "erschienen sind...^Es scheint, dass Du sie schon&%b[[a_btn]]%w mal betätigt hast.^Faszinierend...", + "Tu as déjà entendu parler du&symbole %b\x9f%w?&C'est un symbole bizarre qui est&apparu dans mes rêves " + "dernièrement...^Apparemment, tu as appuyé dessus&%b[[a_btn]]%w fois.^Wow..." }, { "\x13\x1A" "Boy, you must be hot!&Get yourself a bottle of&%rLon Lon Milk%w right away and cool&down, for only %g30%w " diff --git a/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp b/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp index ebad2bd3e..55eb36eac 100644 --- a/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/GossipStoneHints.cpp @@ -14,11 +14,11 @@ extern PlayState* gPlayState; #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) { - if ( - (RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_TRUTH) && Player_GetMask(gPlayState) == PLAYER_MASK_TRUTH) || - (RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_STONE) && CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY) == 0) - ) { - return; + if ((RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_TRUTH) && + Player_GetMask(gPlayState) == PLAYER_MASK_TRUTH) || + (RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).Is(RO_GOSSIP_STONES_NEED_STONE) && + CHECK_QUEST_ITEM(QUEST_STONE_OF_AGONY) == 0)) { + return; } CustomMessage msg; Actor* stone = GET_PLAYER(gPlayState)->talkActor; @@ -31,11 +31,11 @@ void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) { int numOfActorLists = sizeof(gPlayState->actorCtx.actorLists) / sizeof(gPlayState->actorCtx.actorLists[0]); for (int i = 0; i < numOfActorLists; i++) { if (gPlayState->actorCtx.actorLists[i].length) { - if ( - gPlayState->actorCtx.actorLists[i].head->id == 10 && - Rando::StaticData::grottoChestParamsToHint.contains(gPlayState->actorCtx.actorLists[i].head->params) - ) { - stoneHint = Rando::StaticData::grottoChestParamsToHint[gPlayState->actorCtx.actorLists[i].head->params]; + if (gPlayState->actorCtx.actorLists[i].head->id == 10 && + Rando::StaticData::grottoChestParamsToHint.contains( + gPlayState->actorCtx.actorLists[i].head->params)) { + stoneHint = + Rando::StaticData::grottoChestParamsToHint[gPlayState->actorCtx.actorLists[i].head->params]; } } } @@ -50,7 +50,8 @@ void BuildHintStoneMessage(uint16_t* textId, bool* loadFromMessageTable) { } void RegisterGossipStoneHints() { - COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_GOSSIP_STONE_HINTS, RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE), BuildHintStoneMessage); + COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_GOSSIP_STONE_HINTS, + RAND_GET_OPTION(RSK_GOSSIP_STONE_HINTS).IsNot(RO_GOSSIP_STONES_NONE), BuildHintStoneMessage); } static RegisterShipInitFunc initFunc(RegisterGossipStoneHints, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp index 1ce898437..0c3155fdf 100644 --- a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp @@ -62,7 +62,7 @@ static const char* const englishIceTrapMessages[169] = { "Would you like #ice# with that?", "You have obtained the #Ice# Medallion!", "Quick, do a #Zora# impression!", - "One item #on the rocks#!",//would be better if it could display the name of the item + "One item #on the rocks#!", // would be better if it could display the name of the item "How much does a polar bear weigh?&Enough to break the #ice#.", "You got Din's #Ice#!", "You got Nayru's #Cold#!", @@ -125,12 +125,13 @@ static const char* const englishIceTrapMessages[169] = { "STOP!&You violated the #Thaw#!", "I wanted to give you a treasure, but it looks like you got #cold feet#.", "You told me you wanted to deliver #just ice# to Ganondorf!", - "You got the triforce!&This ancient artifact of divine power can grant any- wait, no, sorry, it's just an ice trap. My bad.", + "You got the triforce!&This ancient artifact of divine power can grant any- wait, no, sorry, it's just an ice " + "trap. My bad.", "Time to #cool off#!", "The #Ice Cavern# sends its regards.", "Loading item, please #wait#...", "Mash A+B to not #die#.", - "Sorry, your item is in another location.", //would be better if it could have the name of the item + "Sorry, your item is in another location.", // would be better if it could have the name of the item "You only wish this was %gGreg%w.", "Do you want to drink a hot chocolate?", "The #cold# never bothered me anyway.", @@ -151,7 +152,7 @@ static const char* const englishIceTrapMessages[169] = { "Remember, there may be some momentary #discomfort#.", "In a perfect world #ice traps# like me would not exist, but this is not a perfect world.", "Gee, it sure is #cold# around here.", - "You tested the item with your #ice detector#, it beeped.", //would be better if it could have the name of the item + "You tested the item with your #ice detector#, it beeped.", // would be better if it could have the name of the item "You have found the way of the zero. The #sub-zero#.", "Mweep... mweep... mweep...", "Scum, #freezebag#! I mean #freeze#, scumbag!", @@ -170,19 +171,22 @@ static const char* const englishIceTrapMessages[169] = { "Hydration break! Hey, who #froze# my water?", "Oops, wrong #item model#.", "Whoops! You have to put the item #in your inventory#.", - "You dropped the item, shattering it into #shards of ice#!", //would be better if it could have the name of the item + "You dropped the item, shattering it into #shards of ice#!", // would be better if it could have the name of the + // item "Is this... golden age Simpsons?&BECAUSE I'M ABOUT TO #CHOKE A CHILD#.", "You are the weakest @, #goodbye#!", "Ugh... Why did we even randomize #this item#?", "The #Frost Moon# is rising...", - "According to all known laws of physics and biology, there is no way that @ should be able to survive #getting fully encased in ice#. The cells in @'s body would all die by the time they #unthaw#. Of course, this is a video game, so @ survives anyway... #Probably#.", + "According to all known laws of physics and biology, there is no way that @ should be able to survive #getting " + "fully encased in ice#. The cells in @'s body would all die by the time they #unthaw#. Of course, this is a video " + "game, so @ survives anyway... #Probably#.", "Okay, so stop me if you've heard this one - a gamer and a bottle of #liquid nitrogen# walk into a milk bar...", "Lástima, es una #trampa de hielo#...&&Nobody expects the Spanish #ice trap#!", "Gee, it sure is #BURR#ing around here.", "Navi? Oh! I thought she was called #Névé#!", "It's fine, @ knew this was a #trap#, they're just using it to take damage intentionally to manipulate RNG.", - "Unfortunately, the item has #stopped#.", //would be better if it could have the name of the item - "This item is #not available# in your country.", //would be better if it could have the name of the item + "Unfortunately, the item has #stopped#.", // would be better if it could have the name of the item + "This item is #not available# in your country.", // would be better if it could have the name of the item "#Ice# try. #;)#", "D'oh, I #missed#!", "Where is my #super suit#?", @@ -241,12 +245,13 @@ static const char* const frenchIceTrapMessages[83] = { "J'espère que ça ne te fait ni chaud, ni #froid#.", "Je voulais t'offrir un trésor, mais il semble que tu aies eu #froid aux pieds#", "Tu m'as dit que tu voulais livrer #de la glace# à Ganondorf!", - "Tu as obtenu la Triforce!&Cet ancien artefact divin peut exaucer n'importe quel... ah non, désolé, c'est juste un piège de glace.", + "Tu as obtenu la Triforce!&Cet ancien artefact divin peut exaucer n'importe quel... ah non, désolé, c'est juste un " + "piège de glace.", "Il est temps de #te rafraîchir#!", "La #Caverne Polaire# te passe le bonjour.", "Chargement de l'objet, veuillez #patienter#...", "Martèle A+B pour ne pas #mourir#.", - "Désolé, ton objet est à un autre endroit.", //would be better if it could have the name of the item + "Désolé, ton objet est à un autre endroit.", // would be better if it could have the name of the item "Tu espérais que ce soit %gGreg%w.", "Tu veux boire un chocolat chaud?", "Le #froid# ne m'a jamais dérangé, de toute façon.", @@ -267,7 +272,8 @@ static const char* const frenchIceTrapMessages[83] = { "Souviens-toi, il pourrait y avoir un léger #inconfort#.", "Dans un monde parfait, les #pièges de glace# comme moi n'existeraient pas, mais ce n'est pas un monde parfait.", "Mon dieu qu'il fait #froid# ici.", - "Tu as testé l'objet avec ton #détecteur de glace#, il a bipé.", //would be better if it could have the name of the item + "Tu as testé l'objet avec ton #détecteur de glace#, il a bipé.", // would be better if it could have the name of the + // item "Tu as découvert le chemin du zéro. Le #sub-zéro#.", "Mweep... mweep... mweep...", "Gelé, #sac à glace#! Je veux dire #gèle-toi#, racaille!", @@ -286,16 +292,21 @@ static const char* const frenchIceTrapMessages[83] = { "Pause hydratation ! Hé, qui a #gelé# mon eau?", "Oups, mauvais #modèle d'objet#.", "Oups! Tu dois mettre l'objet #dans ton inventaire#.", - "Tu as fait tomber l'objet, le brisant en #éclats de glace#!", //would be better if it could have the name of the item + "Tu as fait tomber l'objet, le brisant en #éclats de glace#!", // would be better if it could have the name of the + // item "Tu es le maillon faible @, #au revoir#!", "Ugh... Pourquoi avons-nous même randomisé #cet objet#?", "La #Lune de Givre# se lève...", - "Selon toutes les lois connues de la physique et de la biologie, @ ne devrait pas survivre à #être complètement enfermé dans la glace#. Les cellules de @ mourraient avant qu'elles ne #dégèlent#. Mais c'est un jeu vidéo, alors @ survit... #Probablement#.", - "OK, arrête-moi si tu l'as déjà entendue - un joueur et une bouteille de #nitrogène liquide# entrent dans un bar à lait...", + "Selon toutes les lois connues de la physique et de la biologie, @ ne devrait pas survivre à #être complètement " + "enfermé dans la glace#. Les cellules de @ mourraient avant qu'elles ne #dégèlent#. Mais c'est un jeu vidéo, alors " + "@ survit... #Probablement#.", + "OK, arrête-moi si tu l'as déjà entendue - un joueur et une bouteille de #nitrogène liquide# entrent dans un bar à " + "lait...", "Lástima, c'est un #piège de glace#...&&Personne ne s'attend à un #piège de glace espagnol#!", "Mon dieu qu'il fait #GLAGLA# ici.", - "C'est bon, @ savait que c'était un #piège#, il l'utilise juste pour prendre des dégâts intentionnellement et manipuler la RNG.", - "Cet objet n'est #pas disponible# dans votre pays.", //would be better if it could have the name of the item + "C'est bon, @ savait que c'était un #piège#, il l'utilise juste pour prendre des dégâts intentionnellement et " + "manipuler la RNG.", + "Cet objet n'est #pas disponible# dans votre pays.", // would be better if it could have the name of the item "#Bonne# tentative. #;)#", "Où est mon #Super Costume#?", "#La revanche du Titanic#.", @@ -305,17 +316,11 @@ void BuildIceTrapMessage(CustomMessage& msg) { if (CVarGetInteger(CVAR_GENERAL("LetItSnow"), 0)) { msg = CustomMessage( /*english*/ "This year for Christmas, all you get is #COAL#!", - /*german*/ "This year for Christmas, all you get is #COAL#!", - /*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", - { QM_BLUE } - ); + /*german*/ "This year for Christmas, all you get is #COAL#!", + /*french*/ "Pour Noël, cette année, tu n'auras que du #CHARBON#! %rJoyeux Noël%w!", { QM_BLUE }); } else { - msg = CustomMessage( - RandomElement(englishIceTrapMessages), - RandomElement(germanIceTrapMessages), - RandomElement(frenchIceTrapMessages), - { QM_BLUE, QM_BLUE, QM_BLUE } - ); + msg = CustomMessage(RandomElement(englishIceTrapMessages), RandomElement(germanIceTrapMessages), + RandomElement(frenchIceTrapMessages), { QM_BLUE, QM_BLUE, QM_BLUE }); } msg.AutoFormat(); @@ -329,28 +334,36 @@ void BuildTriforcePieceMessage(CustomMessage& msg) { if (percentageCollected <= 0.25) { msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. It's a start!", - "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est un début!" }; + "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es ist ein&Anfang!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste " + "%c[[remaining]]%w à trouver. C'est un début!" }; } else if (percentageCollected <= 0.5) { msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Progress!", - "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Ça avance!" }; + "Ein %yTriforce-Splitter%w! Du hast&%g[[current]]%w von %c[[required]]%w gefunden. Es geht voran!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste " + "%c[[remaining]]%w à trouver. Ça avance!" }; } else if (percentageCollected <= 0.75) { msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Over half-way&there!", - "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über die Hälfte!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" }; + "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Schon&über " + "die Hälfte!", + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste " + "%c[[remaining]]%w à trouver. Il en reste un&peu moins que la moitié!" }; } else if (percentageCollected < 1.0) { - msg = { "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", + msg = { + "You found a %yTriforce Piece%w!&%g[[current]]%w down, %c[[remaining]]%w to go. Almost done!", "Ein %yTriforce-Splitter%w! Du hast&schon %g[[current]]%w von %c[[required]]%w gefunden. Fast&geschafft!", - "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w à trouver. C'est presque&terminé!" }; + "Vous trouvez un %yFragment de la&Triforce%w! Vous en avez %g[[current]]%w, il en&reste %c[[remaining]]%w " + "à trouver. C'est presque&terminé!" + }; } else if (current == required) { msg = { "You completed the %yTriforce of&Courage%w! %gGG%w!", - "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", - "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }; + "Das %yTriforce des Mutes%w! Du hast&alle Splitter gefunden. %gGut gemacht%w!", + "Vous avez complété la %yTriforce&du Courage%w! %gFélicitations%w!" }; } else { msg = { "You found a spare %yTriforce Piece%w!&You only needed %c[[required]]%w, but you have %g[[current]]%w!", - "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", - "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, mais vous en avez %g[[current]]%w en&tout!" }; + "Ein übriger %yTriforce-Splitter%w! Du&hast nun %g[[current]]%w von %c[[required]]%w nötigen gefunden.", + "Vous avez trouvé un %yFragment de&Triforce%w en plus! Vous n'aviez besoin&que de %c[[required]]%w, " + "mais vous en avez %g[[current]]%w en&tout!" }; } msg.Replace("[[current]]", std::to_string(current)); msg.Replace("[[remaining]]", std::to_string(remaining)); @@ -360,13 +373,15 @@ void BuildTriforcePieceMessage(CustomMessage& msg) { void BuildCustomItemMessage(Player* player, CustomMessage& msg) { int16_t rgid; - msg = CustomMessage("You found the %g[[name]]%w!", "Du erhältst das %g[[name]]%w!", "Vous ebtenez %g[[name]]%w!", TEXTBOX_TYPE_BLUE); + msg = CustomMessage("You found the %g[[name]]%w!", "Du erhältst das %g[[name]]%w!", "Vous ebtenez %g[[name]]%w!", + TEXTBOX_TYPE_BLUE); if (player->getItemEntry.objectId != OBJECT_INVALID) { rgid = player->getItemEntry.getItemId; } else { rgid = player->getItemId; } - CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); + CustomMessage name = + CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); msg.Replace("[[name]]", name); msg.AutoFormat(); } @@ -389,12 +404,9 @@ void BuildItemMessage(u16* textId, bool* loadFromMessageTable) { void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { GetItemEntry itemEntry = GET_PLAYER(gPlayState)->getItemEntry; auto ctx = OTRGlobals::Instance->gRandoContext; - CustomMessage msg = CustomMessage( - "You found the %g[[name]]%w! [[typeHint]]", - "Du erhältst das %g[[name]]%w! [[typeHint]]", - "Vous ebtenez %g[[name]]%w! [[typeHint]]", - TEXTBOX_TYPE_BLUE - ); + CustomMessage msg = + CustomMessage("You found the %g[[name]]%w! [[typeHint]]", "Du erhältst das %g[[name]]%w! [[typeHint]]", + "Vous ebtenez %g[[name]]%w! [[typeHint]]", TEXTBOX_TYPE_BLUE); int sceneNum; switch (itemEntry.getItemId) { case RG_DEKU_TREE_MAP: @@ -428,11 +440,9 @@ void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { sceneNum = SCENE_ICE_CAVERN; break; } - if ( - ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_NONE) || + if (ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_NONE) || (ctx->GetOption(RSK_MQ_DUNGEON_RANDOM).Is(RO_MQ_DUNGEONS_SET_NUMBER) && - ctx->GetOption(RSK_MQ_DUNGEON_COUNT).Is(12)) - ) { + ctx->GetOption(RSK_MQ_DUNGEON_COUNT).Is(12))) { msg.Replace("[[typeHint]]", ""); } else if (ResourceMgr_IsSceneMasterQuest(sceneNum)) { msg.Replace("[[typeHint]]", Rando::StaticData::hintTextTable[RHT_DUNGEON_MASTERFUL].GetHintMessage()); @@ -445,10 +455,12 @@ void BuildMapMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { Player* player = GET_PLAYER(gPlayState); - if (player->getItemEntry.getItemId == RG_GANONS_CASTLE_BOSS_KEY && !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)) { + if (player->getItemEntry.getItemId == RG_GANONS_CASTLE_BOSS_KEY && + !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)) { return; } - if (player->getItemEntry.getItemId != RG_GANONS_CASTLE_BOSS_KEY && !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY)) { + if (player->getItemEntry.getItemId != RG_GANONS_CASTLE_BOSS_KEY && + !DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY)) { return; } CustomMessage msg; @@ -459,10 +471,12 @@ void BuildBossKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { Player* player = GET_PLAYER(gPlayState); - if (player->getItemEntry.getItemId == RG_GERUDO_FORTRESS_SMALL_KEY && OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_VANILLA)) { + if (player->getItemEntry.getItemId == RG_GERUDO_FORTRESS_SMALL_KEY && + OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).Is(RO_GERUDO_KEYS_VANILLA)) { return; } - if (player->getItemEntry.getItemId != RG_GERUDO_FORTRESS_SMALL_KEY && DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)) { + if (player->getItemEntry.getItemId != RG_GERUDO_FORTRESS_SMALL_KEY && + DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)) { return; } CustomMessage msg; @@ -471,16 +485,20 @@ void BuildSmallKeyMessage(uint16_t* textId, bool* loadFromMessageTable) { msg.LoadIntoFont(); } -void RegisterItemMessages () { +void RegisterItemMessages() { COND_ID_HOOK(OnOpenText, TEXT_RANDOMIZER_CUSTOM_ITEM, IS_RANDO, BuildItemMessage); - COND_ID_HOOK(OnOpenText, TEXT_ITEM_DUNGEON_MAP, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), BuildMapMessage); - COND_ID_HOOK(OnOpenText, TEXT_ITEM_COMPASS, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), BuildItemMessage); - COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_BOSS, - (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY) || - DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)), BuildBossKeyMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_DUNGEON_MAP, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), + BuildMapMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_COMPASS, DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_SHUFFLE_MAPANDCOMPASS), + BuildItemMessage); + COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_BOSS, + (DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_BOSS_KEYSANITY) || + DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_GANONS_BOSS_KEY)), + BuildBossKeyMessage); COND_ID_HOOK(OnOpenText, TEXT_ITEM_KEY_SMALL, - (OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).IsNot(RO_GERUDO_KEYS_VANILLA) || - DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)), BuildSmallKeyMessage); + (OTRGlobals::Instance->gRandoContext->GetOption(RSK_GERUDO_KEYS).IsNot(RO_GERUDO_KEYS_VANILLA) || + DUNGEON_ITEMS_CAN_BE_OUTSIDE_DUNGEON(RSK_KEYSANITY)), + BuildSmallKeyMessage); } static RegisterShipInitFunc initFunc(RegisterItemMessages, { "IS_RANDO" }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 016b9060c..ee92d8cff 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -19,15 +19,16 @@ extern PlayState* gPlayState; #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) #define RAND_GET_ITEM(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) #define RAND_GET_OVERRIDE(rc) OTRGlobals::Instance->gRandoContext->overrides[rc] -#define NON_BEAN_MERCHANTS (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || \ - RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) +#define NON_BEAN_MERCHANTS \ + (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL_BUT_BEANS) || \ + RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)) void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) { RandomizerGet rgid = RAND_GET_ITEM(rc)->GetPlacedRandomizerGet(); uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); CustomMessage itemName; bool mysterious = RAND_GET_OPTION(RSK_MERCHANT_TEXT_HINT).Is(RO_GENERIC_OFF) || - CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); + CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); if (mysterious) { itemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage(); } else if (rgid == RG_ICE_TRAP) { @@ -36,24 +37,23 @@ void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) { } else { itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName()); } - msg.InsertNames({ itemName , CustomMessage(std::to_string(price))}); + msg.InsertNames({ itemName, CustomMessage(std::to_string(price)) }); } void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { msg = CustomMessage( - "I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no less.\x1B%gYes&No%w", - "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 Rubine%w.\x1B&%gJa&Nein%w", - "Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w" - ); + "I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no " + "less.\x1B%gYes&No%w", + "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 " + "Rubine%w.\x1B&%gJa&Nein%w", + "Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w"); msg.Format(); } else if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) { - msg = CustomMessage( - "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" - ); + msg = CustomMessage("Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"); BuildMerchantMessage(msg, RC_ZR_MAGIC_BEAN_SALESMAN); msg.AutoFormat(); } @@ -62,11 +62,9 @@ void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { } void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" - ); + CustomMessage msg = CustomMessage("Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"); BuildMerchantMessage(msg, RC_GC_MEDIGORON); msg.AutoFormat(); msg.LoadIntoFont(); @@ -75,13 +73,11 @@ void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildGrannyMessage(uint16_t* textId, bool* loadFromMessageTable) { if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && - (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) || - INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { - CustomMessage msg = CustomMessage( - "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" - ); + (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) || + INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { + CustomMessage msg = CustomMessage("Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"); BuildMerchantMessage(msg, RC_KAK_GRANNYS_SHOP); msg.AutoFormat(); msg.LoadIntoFont(); @@ -93,14 +89,12 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; if (*textId == TEXT_CARPET_SALESMAN_ARMS_DEALER) { msg = CustomMessage("Finally! Now I can go back to being an %rarms dealer%w!", - /*german*/"Endlich! Schon bald kann ich wieder %rKrabbelminen-Händler%w sein!", - /*french*/"Squalala! Je vais enfin pouvoir %rprendre des vacances%w!"); + /*german*/ "Endlich! Schon bald kann ich wieder %rKrabbelminen-Händler%w sein!", + /*french*/ "Squalala! Je vais enfin pouvoir %rprendre des vacances%w!"); } else if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { - msg = CustomMessage( - "Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" - ); + msg = CustomMessage("Want to buy %g[[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie %g[[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter %g[[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"); BuildMerchantMessage(msg, RC_WASTELAND_BOMBCHU_SALESMAN); } msg.AutoFormat(); @@ -109,10 +103,9 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { } void BuildCarpetGuyFailToBuyMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "I'm sorry I can't sell you these fine specimens, they need an %rexperienced owner%w.^" - "Come back when you have had %gBombchus%w of your own." - ); + CustomMessage msg = + CustomMessage("I'm sorry I can't sell you these fine specimens, they need an %rexperienced owner%w.^" + "Come back when you have had %gBombchus%w of your own."); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; @@ -124,13 +117,22 @@ void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); CustomMessage msg; if (price == 0) { - msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will give you a %g[[1]]%w!&Please, take it!\x07\x10\xA3", - "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w geben!\x07\x10\xA3", - "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3"); + msg = CustomMessage( + "\x12\x38\x82" + "All right! You win! In return for sparing me, I will give you a %g[[1]]%w!&Please, take it!\x07\x10\xA3", + "\x12\x38\x82" + "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen %g[[1]]%w " + "geben!\x07\x10\xA3", + "\x12\x38\x82" + "J'me rends! Laisse-moi partir et en échange, je te donne un %g[[1]]%w! Vas-y prends le!\x07\x10\xA3"); } else { - msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %y[[2]] Rupees%w it is!\x07\x10\xA3", - "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", - "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); + msg = CustomMessage("\x12\x38\x82" + "All right! You win! In return for sparing me, I will sell you a %g[[1]]%w! %y[[2]] " + "Rupees%w it is!\x07\x10\xA3", + "\x12\x38\x82" + "Ich gebe auf! Ich verkaufe Dir einen %g[[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", + "\x12\x38\x82" + "J'abandonne! Tu veux bien m'acheter un %g[[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); } BuildMerchantMessage(msg, rc); msg.AutoFormat(); @@ -145,15 +147,17 @@ void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) { // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { - rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); + rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf( + static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", - "\x08%g[[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", - "\x08%g[[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); + "\x08%g[[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", + "\x08%g[[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); } else if (*textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && *textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END) { - rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); + rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf( + static_cast((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); msg = CustomMessage("\x08%g[[1]]%w %y[[2]]_Rupees%w\x09\x1B%gBuy&Don't buy%w\x09\x02", - "\x08%g[[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", - "\x08%g[[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); + "\x08%g[[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", + "\x08%g[[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); } else { return; } @@ -164,10 +168,10 @@ void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) { } void RegisterMerchantMessages() { - COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_10, - (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || - RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)), - BuildBeanGuyMessage); + COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_10, + (RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_BEANS_ONLY) || + RAND_GET_OPTION(RSK_SHUFFLE_MERCHANTS).Is(RO_SHUFFLE_MERCHANTS_ALL)), + BuildBeanGuyMessage); COND_ID_HOOK(OnOpenText, TEXT_BEAN_SALESMAN_BUY_FOR_100, IS_RANDO, BuildBeanGuyMessage); COND_ID_HOOK(OnOpenText, TEXT_MEDIGORON, NON_BEAN_MERCHANTS, BuildMedigoronMessage); COND_ID_HOOK(OnOpenText, TEXT_GRANNYS_SHOP, NON_BEAN_MERCHANTS, BuildGrannyMessage); diff --git a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp index 7c512af63..aeb726531 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Miscellaneous.cpp @@ -14,17 +14,15 @@ extern "C" { void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_NAVI) { - msg = CustomMessage( - "%cThis switch is rustier than you think.^%cSomething must be wrong with the pipe system in the %bWater Temple%c.", - "%cDieser Schalter scheint rostiger zu sein als er aussieht.^%cEtwas muss mit dem Leitungssystem im %bWassertempel%c nicht stimmen.", - "%cCet interrupteur est très rouillé.^%cIl doit y avoir un problème avec la tuyauterie du %bTemple de l'Eau%c." - ); + msg = CustomMessage("%cThis switch is rustier than you think.^%cSomething must be wrong with the pipe system " + "in the %bWater Temple%c.", + "%cDieser Schalter scheint rostiger zu sein als er aussieht.^%cEtwas muss mit dem " + "Leitungssystem im %bWassertempel%c nicht stimmen.", + "%cCet interrupteur est très rouillé.^%cIl doit y avoir un problème avec la tuyauterie du " + "%bTemple de l'Eau%c."); } else if (*textId == TEXT_LAKE_HYLIA_WATER_SWITCH_SIGN) { - msg = CustomMessage( - "Water level control system.&Keep away!", - "Wasserstand Kontrollsystem&Finger weg!", - "Système de contrôle du niveau&d'eau.&Ne pas toucher!" - ); + msg = CustomMessage("Water level control system.&Keep away!", "Wasserstand Kontrollsystem&Finger weg!", + "Système de contrôle du niveau&d'eau.&Ne pas toucher!"); } msg.AutoFormat(); msg.LoadIntoFont(); @@ -32,11 +30,10 @@ void BuildWaterSwitchMessage(uint16_t* textId, bool* loadFromMessageTable) { } void BuildShootingGalleryNoBowMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "Come back when you have your own bow and you'll get a %rdifferent prize%w!", - "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen %rspeziellen Preis%w zu erhalten!", - "J'aurai %rune autre récompense%w pour toi lorsque tu auras ton propre arc." - ); + CustomMessage msg = + CustomMessage("Come back when you have your own bow and you'll get a %rdifferent prize%w!", + "Komm wieder sobald Du Deinen eigenen Bogen hast, um einen %rspeziellen Preis%w zu erhalten!", + "J'aurai %rune autre récompense%w pour toi lorsque tu auras ton propre arc."); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; diff --git a/soh/soh/Enhancements/randomizer/Messages/Navi.cpp b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp index 1863a64dd..012ac1f10 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Navi.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Navi.cpp @@ -120,34 +120,62 @@ void BuildNaviMessage(uint16_t* textId, bool* loadFromMessageTable) { } void RegisterNaviMessages() { - COND_ID_HOOK(OnOpenText, TEXT_NAVI_DEKU_TREE_SUMMONS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_CMON_BE_BRAVE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_VISIT_THE_PRINCESS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_MALONS_FATHER, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_THE_PRINCESS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHAT_WOULD_SARIA_SAY, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_IMPA_SAID_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_USE_BOMB_FLOWER, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_FAIRY_LIVES_ON_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_SARIA_KNOWS_ABOUT_STONES, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_RUTO_INSIDE_JABUS_BELLY, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_COLLECTED_THREE_STONES, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_THREW_SOMETHING_IN_MOAT, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_CHECK_TEMPLE_OF_TIME, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_SHOULD_WE_BELIEVE_SHEIK, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHATS_GOING_ON_IN_FOREST, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_CLOUD_OVER_DEATH_MOUNTAIN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_ARTIC_WIND_IS_BLOWING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_IRON_BOOTS_WEIGH_A_TON, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_LOOK_FOR_SOMONE_WHO_KNOWS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_IT_CAME_OUT_OF_THE_WELL, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_BUILT_THE_SPIRIT_TEMPLE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_HAVE_YOU_EVER_PLAYED_NOCTURNE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHERE_GANONDORF_WAS_BORN, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_EQUIP_THE_SILVER_GAUNTLETS, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_IS_WAITING_FOR_US, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_SAVE_PRINCESS_ZELDA, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); - COND_ID_HOOK(OnOpenText, TEXT_NAVI_TRY_TO_KEEP_MOVING, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_DEKU_TREE_SUMMONS, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CMON_BE_BRAVE, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_VISIT_THE_PRINCESS, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_MALONS_FATHER, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FIND_THE_PRINCESS, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHAT_WOULD_SARIA_SAY, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IMPA_SAID_DEATH_MOUNTAIN, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_USE_BOMB_FLOWER, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_FAIRY_LIVES_ON_DEATH_MOUNTAIN, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SARIA_KNOWS_ABOUT_STONES, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_RUTO_INSIDE_JABUS_BELLY, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_COLLECTED_THREE_STONES, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_THREW_SOMETHING_IN_MOAT, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CHECK_TEMPLE_OF_TIME, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SHOULD_WE_BELIEVE_SHEIK, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHATS_GOING_ON_IN_FOREST, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_CLOUD_OVER_DEATH_MOUNTAIN, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_ARTIC_WIND_IS_BLOWING, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IRON_BOOTS_WEIGH_A_TON, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_LOOK_FOR_SOMONE_WHO_KNOWS, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_IT_CAME_OUT_OF_THE_WELL, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_BUILT_THE_SPIRIT_TEMPLE, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_HAVE_YOU_EVER_PLAYED_NOCTURNE, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHERE_GANONDORF_WAS_BORN, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_EQUIP_THE_SILVER_GAUNTLETS, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_WHO_IS_WAITING_FOR_US, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_SAVE_PRINCESS_ZELDA, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); + COND_ID_HOOK(OnOpenText, TEXT_NAVI_TRY_TO_KEEP_MOVING, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi"), 1), BuildNaviMessage); } static RegisterShipInitFunc initFunc(RegisterNaviMessages, { CVAR_RANDOMIZER_ENHANCEMENT("RandoRelevantNavi") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp index 3cb3d9e98..bb4e0c3c9 100644 --- a/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/Rupees.cpp @@ -8,82 +8,209 @@ extern "C" { #include "variables.h" } -static const char* englishRupeeNames[175] = { - "[P]", "Bad RNG Rolls", "Bananas", "Beanbean Coins", "Beans", - "Beli", "Bells", "Berries", "Bison Dollars", "Bitcoin", - "Blue Essence", "Bolts", "Bones", "Boondollars", "Bottle Caps", - "Bratwürste", "Bucks", "BugFrags", "Canadian Dollars", "Cards", - "Chaos Orbs", "Clams", "Coal", "Cocoa Beans", "Coins", - "Cookies", "Copper", "Cor", "Cornflakes", "Credits", - "Crimebucks", "Crystal Shards", "Cubits", "Cucumbers", "Dalmations", - "Dampécoin", "Dark Elixir", "Darseks", "Dead Memes", "Diamonds", - "DNA", "Doge", "Dogecoin", "Doll Hairs", "Dollars", - "Dollarydoos", "Dosh", "Doubloons", "Dwarfbucks", "Elexit", - "Emeralds", "Energon", "Eris", "Ether", "Euro", - "Experience", "Extinction Points", "Floopies", "Flurbos", "FPS", - "Friends", "Frog Coins", "Gald", "Gekz", "Gems", - "Geo", "Gil", "Glimmer", "Glitches", "Gold", - "Gold Dragons", "Goober Dollars", "Green Herbs", "Greg Siblings", "Grouses", - "Gummybears", "Hell", "Hyrule Loaches", "Ice Traps", "ISK", - "Jiggies", "KF7 Ammo", "Kinstones", "Kremcoins", "Kroner", - "Leaves", "Lemmings", "Lien", "Lira", "Lumber", - "Lungmen Dollars", "Macca", "Mana", "Mann Co. Keys", "Meat", - "Meat Stacks", "Medaparts", "Meseta", "Mesetas", "Minerals", - "Monopoly Money", "Moons", "Mora", "Mumbo Tokens", "Munny", - "Mushrooms", "Mysteries", "Neopoints", "Notes", "Nuyen", - "Orbs", "Ore", "Pix", "Pixels", "Plastyks", - "Platinum", "Pokédollars", "Pokémon", "Poko", "Pokos", - "Potch", "Pounds", "Power Pellets", "Primogems", "Réals", - "Refined Metal", "Remote Mines", "Retweets", "Rhinu", "Rings", - "Riot Points", "Robux", "Rubies", "Rubles", "Runite Ore", - "Rupees", "Saint Quartz", "Septims", "Shekels", "Shillings", - "Silver", "Simoleons", "Smackaroos", "Social Credit", "Souls", - "Spent Casings", "Spice", "Spondulicks", "Spoons", "Star Bits", - "Star Chips", "Stars", "Stones of Jordan", "Store Credit", "Strawbs", - "Studs", "Super Sea Snails", "Talent", "Teef", "Telecrystals", - "Tiberium", "TokKul", "Toys", "Turnips", "Upvotes", - "V-Bucks", "Vespene Gas", "Watts", "Widgets", "Woolongs", - "World Dollars", "Wumpa Fruit", "Yen", "Zenny", "Zorkmids" -}; +static const char* englishRupeeNames[175] = { "[P]", + "Bad RNG Rolls", + "Bananas", + "Beanbean Coins", + "Beans", + "Beli", + "Bells", + "Berries", + "Bison Dollars", + "Bitcoin", + "Blue Essence", + "Bolts", + "Bones", + "Boondollars", + "Bottle Caps", + "Bratwürste", + "Bucks", + "BugFrags", + "Canadian Dollars", + "Cards", + "Chaos Orbs", + "Clams", + "Coal", + "Cocoa Beans", + "Coins", + "Cookies", + "Copper", + "Cor", + "Cornflakes", + "Credits", + "Crimebucks", + "Crystal Shards", + "Cubits", + "Cucumbers", + "Dalmations", + "Dampécoin", + "Dark Elixir", + "Darseks", + "Dead Memes", + "Diamonds", + "DNA", + "Doge", + "Dogecoin", + "Doll Hairs", + "Dollars", + "Dollarydoos", + "Dosh", + "Doubloons", + "Dwarfbucks", + "Elexit", + "Emeralds", + "Energon", + "Eris", + "Ether", + "Euro", + "Experience", + "Extinction Points", + "Floopies", + "Flurbos", + "FPS", + "Friends", + "Frog Coins", + "Gald", + "Gekz", + "Gems", + "Geo", + "Gil", + "Glimmer", + "Glitches", + "Gold", + "Gold Dragons", + "Goober Dollars", + "Green Herbs", + "Greg Siblings", + "Grouses", + "Gummybears", + "Hell", + "Hyrule Loaches", + "Ice Traps", + "ISK", + "Jiggies", + "KF7 Ammo", + "Kinstones", + "Kremcoins", + "Kroner", + "Leaves", + "Lemmings", + "Lien", + "Lira", + "Lumber", + "Lungmen Dollars", + "Macca", + "Mana", + "Mann Co. Keys", + "Meat", + "Meat Stacks", + "Medaparts", + "Meseta", + "Mesetas", + "Minerals", + "Monopoly Money", + "Moons", + "Mora", + "Mumbo Tokens", + "Munny", + "Mushrooms", + "Mysteries", + "Neopoints", + "Notes", + "Nuyen", + "Orbs", + "Ore", + "Pix", + "Pixels", + "Plastyks", + "Platinum", + "Pokédollars", + "Pokémon", + "Poko", + "Pokos", + "Potch", + "Pounds", + "Power Pellets", + "Primogems", + "Réals", + "Refined Metal", + "Remote Mines", + "Retweets", + "Rhinu", + "Rings", + "Riot Points", + "Robux", + "Rubies", + "Rubles", + "Runite Ore", + "Rupees", + "Saint Quartz", + "Septims", + "Shekels", + "Shillings", + "Silver", + "Simoleons", + "Smackaroos", + "Social Credit", + "Souls", + "Spent Casings", + "Spice", + "Spondulicks", + "Spoons", + "Star Bits", + "Star Chips", + "Stars", + "Stones of Jordan", + "Store Credit", + "Strawbs", + "Studs", + "Super Sea Snails", + "Talent", + "Teef", + "Telecrystals", + "Tiberium", + "TokKul", + "Toys", + "Turnips", + "Upvotes", + "V-Bucks", + "Vespene Gas", + "Watts", + "Widgets", + "Woolongs", + "World Dollars", + "Wumpa Fruit", + "Yen", + "Zenny", + "Zorkmids" }; static const char* germanRupeeNames[65] = { - "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", - "Brötchen", "Cent", "Diamanten", "Diridari", "Dogecoin", - "ECU", "Elexit", "Erz", "Erzbrocken", "Euro", - "EXP", "Forint", "Franken", "Freunde", "Gil", - "Gold", "Groschen", "Gulden", "Gummibären", "Heller", - "Juwelen", "Karolin", "Kartoffeln", "Kies", "Knete", - "Knochen", "Kohle", "Kraniche", "Kreuzer", "Kronen", - "Kronkorken", "Kröten", "Mark", "Mäuse", "Monde", - "Moorhühner", "Moos", "Münzen", "Penunze", "Pesa", - "Pfandflaschen", "Pfennig", "Pfund", "Pilze", "Plastiks", - "Pokédollar", "Radieschen", "Rappen", "Rubine", "Saphire", - "Schilling", "Seelen", "Smaragde", "Steine", "Sterne", - "Sternis", "Tael", "Taler", "Wagenchips", "Zenny" + "Bananen", "Bitcoin", "Bonbons", "Bratwürste", "Brause UFOs", "Brötchen", "Cent", "Diamanten", + "Diridari", "Dogecoin", "ECU", "Elexit", "Erz", "Erzbrocken", "Euro", "EXP", + "Forint", "Franken", "Freunde", "Gil", "Gold", "Groschen", "Gulden", "Gummibären", + "Heller", "Juwelen", "Karolin", "Kartoffeln", "Kies", "Knete", "Knochen", "Kohle", + "Kraniche", "Kreuzer", "Kronen", "Kronkorken", "Kröten", "Mark", "Mäuse", "Monde", + "Moorhühner", "Moos", "Münzen", "Penunze", "Pesa", "Pfandflaschen", "Pfennig", "Pfund", + "Pilze", "Plastiks", "Pokédollar", "Radieschen", "Rappen", "Rubine", "Saphire", "Schilling", + "Seelen", "Smaragde", "Steine", "Sterne", "Sternis", "Tael", "Taler", "Wagenchips", + "Zenny" }; static const char* frenchRupeeNames[40] = { - "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", - "Blés", "Bling", "Capsules", "Centimes", "Champignons", - "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", - "Dollars", "Émeraudes", "Éthers", "Étoiles", "Euros", - "Florens", "Francs", "Galds", "Gils", "Grouses", - "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", - "Orbes", "Orens", "Pépètes", "Pièces", "Plastyks", - "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies" + "Anneaux", "Baguettes", "Balles", "Bananes", "Bitcoin", "Blés", "Bling", "Capsules", + "Centimes", "Champignons", "Clochettes", "Crédits", "Croissants", "Diamants", "Dogecoin", "Dollars", + "Émeraudes", "Éthers", "Étoiles", "Euros", "Florens", "Francs", "Galds", "Gils", + "Grouses", "Halos", "Joyaux", "Lunes", "Mailles", "Munnies", "Orbes", "Orens", + "Pépètes", "Pièces", "Plastyks", "Pokédollars", "Pokémon", "Radis", "Rubis", "Zennies" }; -void BuildRupeeMessage(uint16_t* textId, bool *loadFromMessageTable) { +void BuildRupeeMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg = CustomMessage( - "You found [[color]][[amount]] [[rupee]]\x05\x00!", - "Du hast [[color]][[amount]] [[rupee]]\x05\x00 gefunden!", - "Vous obtenez [[color]][[amount]] [[rupee]]\x05\x00!", - TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM - ); + "You found [[color]][[amount]] [[rupee]]\x05\x00!", "Du hast [[color]][[amount]] [[rupee]]\x05\x00 gefunden!", + "Vous obtenez [[color]][[amount]] [[rupee]]\x05\x00!", TEXTBOX_TYPE_BLACK, TEXTBOX_POS_BOTTOM); std::string color; std::string amount; - CustomMessage rupee = CustomMessage(RandomElement(englishRupeeNames), - RandomElement(germanRupeeNames), + CustomMessage rupee = CustomMessage(RandomElement(englishRupeeNames), RandomElement(germanRupeeNames), RandomElement(frenchRupeeNames)); switch (*textId) { case TEXT_BLUE_RUPEE: @@ -115,10 +242,14 @@ void BuildRupeeMessage(uint16_t* textId, bool *loadFromMessageTable) { } void RegisterRandomRupeeNames() { - COND_ID_HOOK(OnOpenText, TEXT_BLUE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); - COND_ID_HOOK(OnOpenText, TEXT_RED_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); - COND_ID_HOOK(OnOpenText, TEXT_PURPLE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); - COND_ID_HOOK(OnOpenText, TEXT_HUGE_RUPEE, IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_BLUE_RUPEE, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_RED_RUPEE, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_PURPLE_RUPEE, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); + COND_ID_HOOK(OnOpenText, TEXT_HUGE_RUPEE, + IS_RANDO && CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames"), 1), BuildRupeeMessage); } static RegisterShipInitFunc initFunc(RegisterRandomRupeeNames, { CVAR_RANDOMIZER_ENHANCEMENT("RandomizeRupeeNames") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index fdedbac47..1a0258c59 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -17,11 +17,10 @@ extern PlayState* gPlayState; #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) #define RAND_GET_HINT(rh) OTRGlobals::Instance->gRandoContext->GetHint(rh) #define RAND_GET_ITEM_LOC(rc) OTRGlobals::Instance->gRandoContext->GetItemLocation(rc) -#define ANY_SKULLTULA_HINTS RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT) || \ - RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT) || \ - RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT) || \ - RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT) || \ - RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT) +#define ANY_SKULLTULA_HINTS \ + RAND_GET_OPTION(RSK_KAK_10_SKULLS_HINT) || RAND_GET_OPTION(RSK_KAK_20_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_30_SKULLS_HINT) || RAND_GET_OPTION(RSK_KAK_40_SKULLS_HINT) || \ + RAND_GET_OPTION(RSK_KAK_50_SKULLS_HINT) void BuildGanondorfHint(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; @@ -47,41 +46,47 @@ void BuildSheikMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; switch (gPlayState->sceneNum) { case SCENE_TEMPLE_OF_TIME: - if (RAND_GET_OPTION(RSK_OOT_HINT) && !RAND_GET_ITEM_LOC(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()){ + if (RAND_GET_OPTION(RSK_OOT_HINT) && !RAND_GET_ITEM_LOC(RC_SONG_FROM_OCARINA_OF_TIME)->HasObtained()) { msg = RAND_GET_HINT(RH_OOT_HINT)->GetHintMessage(MF_RAW); } else if (!CHECK_DUNGEON_ITEM(DUNGEON_KEY_BOSS, SCENE_GANONS_TOWER)) { msg = CustomMessage( - "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", - "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.", - "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w."); + "@, meet me at %gGanon's Castle%w once you obtain the %rkey to his lair%w.", + "@, wir treffen uns bei %gGanons Schloß%w, sobald Du den %rSchlüssel zu seinem Verlies%w hast.", + "Retrouve-moi au %gChâteau de Ganon%w une fois que tu auras obtenu la %rclé de son repaire%w."); } else { - msg = CustomMessage( - "The time has come. Prepare yourself.", - "Die Zeit ist gekommen.&Mach Dich bereit.", - "Le moment est venu @.&Tu ferais bien de te préparer."); + msg = CustomMessage("The time has come. Prepare yourself.", "Die Zeit ist gekommen.&Mach Dich bereit.", + "Le moment est venu @.&Tu ferais bien de te préparer."); } break; case SCENE_INSIDE_GANONS_CASTLE: if (RAND_GET_OPTION(RSK_SHEIK_LA_HINT) && INV_CONTENT(ITEM_ARROW_LIGHT) != ITEM_ARROW_LIGHT) { msg = RAND_GET_HINT(RH_SHEIK_HINT)->GetHintMessage(MF_RAW); - } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && - CUR_CAPACITY(UPG_QUIVER) >= 30 && gSaveContext.isMagicAcquired)) { - msg = CustomMessage("You are still ill-equipped to face %rGanondorf%w." - "^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the %ylight%w.", + } else if (!(CHECK_OWNED_EQUIP(EQUIP_TYPE_SWORD, EQUIP_INV_SWORD_MASTER) && + INV_CONTENT(ITEM_ARROW_LIGHT) == ITEM_ARROW_LIGHT && CUR_CAPACITY(UPG_QUIVER) >= 30 && + gSaveContext.isMagicAcquired)) { + msg = CustomMessage( + "You are still ill-equipped to face %rGanondorf%w." + "^Seek out the %cMaster Sword%w, %rsomething to hold your arrows%w, and %gmagic%w to summon the " + "%ylight%w.", "Du bist noch nicht gewappnet um Dich %rGanondorf%w stellen zu können.^" - "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", + "Begib Dich auf die Suche nach dem %cMaster-Schwert%w, %retwas um Deinen Pfeilen einen Sinn zu " + "geben%w,^sowie %gdie Magie%w, um das %yLicht%w herauf beschwören zu können.", "@, tu n'es toujours pas prêt à affronter %rGanondorf%w.^" - "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour invoquer la %ylumière%w."); - } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && !RAND_GET_OPTION(RSK_TRIAL_COUNT).Is(0)){ + "Cherche l'%cÉpée de Légende%w, %rquelque chose pour ranger tes flèches%w et de la %gmagie%w pour " + "invoquer la %ylumière%w."); + } else if (!Flags_GetEventChkInf(EVENTCHKINF_DISPELLED_GANONS_TOWER_BARRIER) && + !RAND_GET_OPTION(RSK_TRIAL_COUNT).Is(0)) { msg = CustomMessage( - "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still stands.^Complete the remaining %gtrials%w to destroy it.", - "Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.", - "@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours actives.^Termine les épreuves restantes pour les détruire."); + "You may have what you need to defeat %rthe Evil King%w, but the %cbarrier%w still " + "stands.^Complete the remaining %gtrials%w to destroy it.", + "Du magst das haben, was Du brauchst um %rden bösen König%w zu besiegen, aber die %cBarriere%w " + "steht noch.^Absolviere die verbleibenden %gPrüfungen%w um sie zu zerstören.", + "@, tu as peut-être ce qu'il te faut pour vaincre %rle Malin%w, mais les barrières sont toujours " + "actives.^Termine les épreuves restantes pour les détruire."); } else { - msg = CustomMessage( - "If you're ready, then proceed.^Good luck.", - "Wenn Du bereit bist, so schreite&voran.^Viel Glück.", - "Si tu es prêt, tu peux y aller.^Bonne chance."); + msg = CustomMessage("If you're ready, then proceed.^Good luck.", + "Wenn Du bereit bist, so schreite&voran.^Viel Glück.", + "Si tu es prêt, tu peux y aller.^Bonne chance."); } break; } @@ -149,8 +154,7 @@ void BuildMysteriousWarpMessage() { CustomMessage msg = CustomMessage( "Warp to&%ra mysterious place?%w&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w", "Zu&%reinem mysteriösen Ort%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%gOK&No%w", - "Se téléporter vers&%run endroit mystérieux%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%rOK!&Non%w" - ); + "Se téléporter vers&%run endroit mystérieux%w?&" + CustomMessage::TWO_WAY_CHOICE() + "%rOK!&Non%w"); msg.LoadIntoFont(); } @@ -238,18 +242,17 @@ void BuildFishingPoleHintMessage(uint16_t* textId, bool* loadFromMessageTable) { } CustomMessage msg = CustomMessage( "Sorry, but the pond is closed.&I've lost my good %rfishing pole%w...&Can't go fishing without it!", - "Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht fischen!", - "Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!" - ); + "Entschuldigung, aber der Teich ist zu.&Ich habe meine gute %rAngelrute%w verloren.&Ohne kann ich nicht " + "fischen!", + "Désolé, mais l'étang est fermé.&J'ai perdu ma bonne %rCanne à Pêche%w...&Impossible de pêcher sans elle!"); if (RAND_GET_OPTION(RSK_FISHING_POLE_HINT)) { msg = msg + RAND_GET_HINT(RH_FISHING_POLE)->GetHintMessage(); } if (*textId == TEXT_FISHING_POND_START_MET) { - msg = CustomMessage( - "Hey, mister! I remember you!&It's been a long time!^", - "Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!", - "Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!" - ) + msg; + msg = CustomMessage("Hey, mister! I remember you!&It's been a long time!^", + "Hallo, mein Herr! Ich erinnere mich an Sie!&Lang ist's her!", + "Hé, monsieur! Je me souviens de toi!&Ça fait longtemps!") + + msg; } msg.AutoFormat(); msg.LoadIntoFont(); @@ -273,7 +276,7 @@ void BuildBiggoronHintMessage(uint16_t* textId, bool* loadFromMessageTable) { *loadFromMessageTable = false; } -void BuildBigPoesHintMessage(uint16_t * textId, bool* loadFromMessageTable) { +void BuildBigPoesHintMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg = RAND_GET_HINT(RH_BIGGORON_HINT)->GetHintMessage(MF_AUTO_FORMAT); msg.LoadIntoFont(); *loadFromMessageTable = false; @@ -340,9 +343,10 @@ void RegisterStaticHints() { // Altar COND_ID_HOOK(OnOpenText, TEXT_ALTAR_CHILD, IS_RANDO, BuildChildAltarMessage); COND_ID_HOOK(OnOpenText, TEXT_ALTAR_ADULT, IS_RANDO, BuildAdultAltarMessage); - //Skulltula + // Skulltula COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_IM_CURSED, ANY_SKULLTULA_HINTS, BuildSkulltulaPeopleMessage); - COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT), Build100SkullsHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_SKULLTULA_PEOPLE_MAKE_YOU_VERY_RICH, RAND_GET_OPTION(RSK_KAK_100_SKULLS_HINT), + Build100SkullsHintMessage); // Dampe's Diary COND_ID_HOOK(OnOpenText, TEXT_DAMPES_DIARY, RAND_GET_OPTION(RSK_DAMPES_DIARY_HINT), BuildDampesDiaryMessage); // Chest Game @@ -352,9 +356,12 @@ void RegisterStaticHints() { // Warp COND_ID_HOOK(OnOpenText, TEXT_WARP_MINUET_OF_FOREST, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildMinuetWarpMessage); COND_ID_HOOK(OnOpenText, TEXT_WARP_BOLERO_OF_FIRE, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildBoleroWarpMessage); - COND_ID_HOOK(OnOpenText, TEXT_WARP_SERENADE_OF_WATER, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildSerenadeWarpMessage); - COND_ID_HOOK(OnOpenText, TEXT_WARP_REQUIEM_OF_SPIRIT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildRequiemWarpMessage); - COND_ID_HOOK(OnOpenText, TEXT_WARP_NOCTURNE_OF_SHADOW, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildNocturneWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_SERENADE_OF_WATER, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), + BuildSerenadeWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_REQUIEM_OF_SPIRIT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), + BuildRequiemWarpMessage); + COND_ID_HOOK(OnOpenText, TEXT_WARP_NOCTURNE_OF_SHADOW, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), + BuildNocturneWarpMessage); COND_ID_HOOK(OnOpenText, TEXT_WARP_PRELUDE_OF_LIGHT, RAND_GET_OPTION(RSK_WARP_SONG_HINTS), BuildPreludeWarpMessage); // Frogs COND_ID_HOOK(OnOpenText, TEXT_FROGS_UNDERWATER, RAND_GET_OPTION(RSK_FROGS_HINT), BuildFrogsHintMessage); @@ -365,10 +372,13 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_FISHING_GOOD_FISHERMAN, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); COND_ID_HOOK(OnOpenText, TEXT_FISHING_DIFFERENT_POND, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); COND_ID_HOOK(OnOpenText, TEXT_FISHING_SCRATCHING, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE, RAND_GET_OPTION(RSK_LOACH_HINT), BuildLoachHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_TRY_ANOTHER_LURE_WITH_SINKING_LURE, RAND_GET_OPTION(RSK_LOACH_HINT), + BuildLoachHintMessage); // Fishing Pole - COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), BuildFishingPoleHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START_MET, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), BuildFishingPoleHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), + BuildFishingPoleHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_FISHING_POND_START_MET, RAND_GET_OPTION(RSK_SHUFFLE_FISHING_POLE), + BuildFishingPoleHintMessage); // Saria COND_ID_HOOK(OnOpenText, TEXT_SARIA_SFM, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_FACE_TO_FACE, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); @@ -386,29 +396,41 @@ void RegisterStaticHints() { COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_IMPRISON_GANONDORF, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); COND_ID_HOOK(OnOpenText, TEXT_SARIAS_SONG_CHANNELING_POWER, RAND_GET_OPTION(RSK_SARIA_HINT), BuildSariaMessage); // Biggoron - COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT), BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_BETTER_AT_SMITHING, RAND_GET_OPTION(RSK_BIGGORON_HINT), + BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_WAITING_FOR_YOU, RAND_GET_OPTION(RSK_BIGGORON_HINT), + BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_RETURN_AFTER_A_FEW_DAYS, RAND_GET_OPTION(RSK_BIGGORON_HINT), + BuildBiggoronHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_BIGGORON_I_MAAAADE_THISSSS, RAND_GET_OPTION(RSK_BIGGORON_HINT), + BuildBiggoronHintMessage); // Big Poes COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_EXPLAINATION, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT), BuildBigPoesHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_GHOST_SHOP_CARD_HAS_POINTS, RAND_GET_OPTION(RSK_BIG_POES_HINT), + BuildBigPoesHintMessage); // Anju - COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_4_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT), BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_MY_CUCCOS_BACK, RAND_GET_OPTION(RSK_CHICKENS_HINT), + BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_4_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), + BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_3_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), + BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_2_CUCCOS, RAND_GET_OPTION(RSK_CHICKENS_HINT), + BuildChickensHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_ANJU_PLEASE_BRING_1_CUCCO, RAND_GET_OPTION(RSK_CHICKENS_HINT), + BuildChickensHintMessage); // Malon COND_ID_HOOK(OnOpenText, TEXT_MALON_EVERYONE_TURNING_EVIL, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_I_SING_THIS_SONG, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_HOW_IS_EPONA_DOING, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); COND_ID_HOOK(OnOpenText, TEXT_MALON_OBSTICLE_COURSE, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); - COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT), BuildMalonHintMessage); + COND_ID_HOOK(OnOpenText, TEXT_MALON_INGO_MUST_HAVE_BEEN_TEMPTED, RAND_GET_OPTION(RSK_MALON_HINT), + BuildMalonHintMessage); // Horseback Archery COND_ID_HOOK(OnOpenText, TEXT_GF_HBA_SIGN, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_NOT_ON_HORSE, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); - COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); + COND_ID_HOOK(OnOpenText, TEXT_HBA_INITIAL_EXPLAINATION, RAND_GET_OPTION(RSK_HBA_HINT), + BuildHorsebackArcheryMessage); COND_ID_HOOK(OnOpenText, TEXT_HBA_ALREADY_HAVE_1000, RAND_GET_OPTION(RSK_HBA_HINT), BuildHorsebackArcheryMessage); // Mask Shop Sign COND_ID_HOOK(OnOpenText, TEXT_MASK_SHOP_SIGN, RAND_GET_OPTION(RSK_MASK_SHOP_HINT), BuildMaskShopSignMessage); diff --git a/soh/soh/Enhancements/randomizer/randomizer.cpp b/soh/soh/Enhancements/randomizer/randomizer.cpp index f91b704f6..3d97e6459 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.cpp +++ b/soh/soh/Enhancements/randomizer/randomizer.cpp @@ -3971,8 +3971,8 @@ void RandomizerSettingsWindow::UpdateElement() { } } -class ExtendedVanillaTableInvalidItemIdException: public std::exception { - private: +class ExtendedVanillaTableInvalidItemIdException : public std::exception { + private: s16 itemID; public: diff --git a/soh/soh/Enhancements/randomizer/randomizer.h b/soh/soh/Enhancements/randomizer/randomizer.h index 5522609e9..5c825020e 100644 --- a/soh/soh/Enhancements/randomizer/randomizer.h +++ b/soh/soh/Enhancements/randomizer/randomizer.h @@ -26,7 +26,7 @@ class Randomizer { public: Randomizer(); ~Randomizer(); - + static Sprite* GetSeedTexture(uint8_t index); bool SpoilerFileExists(const char* spoilerFileName); bool IsTrialRequired(s32 trialFlag); From 5c7a23e87fe1c34785886d96a4db8f871e9f8cdd Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 29 Apr 2025 18:28:15 -0400 Subject: [PATCH 100/103] post-merge format run --- soh/soh/Enhancements/NoSkulltulaFreeze.cpp | 17 ++-- .../randomizer/Messages/ItemMessages.cpp | 10 +- .../randomizer/Messages/MerchantMessages.cpp | 93 ++++++++++--------- .../randomizer/Messages/StaticHints.cpp | 32 +++++-- soh/soh/Enhancements/randomizer/item.cpp | 20 ++-- soh/soh/Enhancements/randomizer/item.h | 10 +- 6 files changed, 104 insertions(+), 78 deletions(-) diff --git a/soh/soh/Enhancements/NoSkulltulaFreeze.cpp b/soh/soh/Enhancements/NoSkulltulaFreeze.cpp index ee30cd674..3b3051417 100644 --- a/soh/soh/Enhancements/NoSkulltulaFreeze.cpp +++ b/soh/soh/Enhancements/NoSkulltulaFreeze.cpp @@ -1,7 +1,7 @@ #include extern "C" { - #include "variables.h" +#include "variables.h" } #define RAND_GET_OPTION(rsk) OTRGlobals::Instance->gRandoContext->GetOption(rsk) @@ -19,11 +19,14 @@ void AutoDismissSkulltulaMessage(uint16_t* textId, bool* loadFromMessageTable) { } void NoSkulltulaFreeze_Register() { - COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) == 0, AutoDismissSkulltulaMessage); - COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) && CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) == 0, AutoDismissSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_FREEZE, + CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) && + CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) == 0, + AutoDismissSkulltulaMessage); + COND_ID_HOOK(OnOpenText, TEXT_GS_NO_FREEZE, + CVarGetInteger(CVAR_ENHANCEMENT("SkulltulaFreeze"), 0) && + CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) == 0, + AutoDismissSkulltulaMessage); } - -static RegisterShipInitFunc initFunc(NoSkulltulaFreeze_Register, { - CVAR_ENHANCEMENT("SkulltulaFreeze") -}); \ No newline at end of file +static RegisterShipInitFunc initFunc(NoSkulltulaFreeze_Register, { CVAR_ENHANCEMENT("SkulltulaFreeze") }); \ No newline at end of file diff --git a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp index fd35f6624..3308f6a25 100644 --- a/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/ItemMessages.cpp @@ -373,14 +373,18 @@ void BuildTriforcePieceMessage(CustomMessage& msg) { void BuildCustomItemMessage(Player* player, CustomMessage& msg) { int16_t rgid; - msg = CustomMessage("You found [[article]][[color]][[name]]%w!", "Du erhältst [[article]][[color]][[name]]%w gefunden!", "Vous avez trouvé [[article]][[color]][[name]]%w!", TEXTBOX_TYPE_BLUE); + msg = CustomMessage("You found [[article]][[color]][[name]]%w!", + "Du erhältst [[article]][[color]][[name]]%w gefunden!", + "Vous avez trouvé [[article]][[color]][[name]]%w!", TEXTBOX_TYPE_BLUE); if (player->getItemEntry.objectId != OBJECT_INVALID) { rgid = player->getItemEntry.getItemId; } else { rgid = player->getItemId; } - CustomMessage name = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); - CustomMessage article = CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetArticle(), TEXTBOX_TYPE_BLUE); + CustomMessage name = + CustomMessage(Rando::StaticData::RetrieveItem(static_cast(rgid)).GetName(), TEXTBOX_TYPE_BLUE); + CustomMessage article = CustomMessage( + Rando::StaticData::RetrieveItem(static_cast(rgid)).GetArticle(), TEXTBOX_TYPE_BLUE); msg.Replace("[[article]]", article); msg.Replace("[[color]]", Rando::StaticData::RetrieveItem(static_cast(rgid)).GetColor()); msg.Replace("[[name]]", name); diff --git a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp index 0adcfb010..2c94920de 100644 --- a/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/MerchantMessages.cpp @@ -29,7 +29,7 @@ void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) { CustomMessage itemName; std::string color = Rando::StaticData::RetrieveItem(static_cast(rgid)).GetColor(); bool mysterious = RAND_GET_OPTION(RSK_MERCHANT_TEXT_HINT).Is(RO_GENERIC_OFF) || - CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); + CVarGetInteger(CVAR_RANDOMIZER_ENHANCEMENT("MysteriousShuffle"), 0); if (mysterious) { itemName = Rando::StaticData::hintTextTable[RHT_MYSTERIOUS_ITEM_CAPITAL].GetHintMessage(); color = "%g"; @@ -41,24 +41,23 @@ void BuildMerchantMessage(CustomMessage& msg, RandomizerCheck rc) { itemName = CustomMessage(Rando::StaticData::RetrieveItem(rgid).GetName()); } msg.Replace("[[color]]", color); - msg.InsertNames({ itemName , CustomMessage(std::to_string(price))}); + msg.InsertNames({ itemName, CustomMessage(std::to_string(price)) }); } void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_100) { msg = CustomMessage( - "I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no less.\x1B%gYes&No%w", - "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 Rubine%w.\x1B&%gJa&Nein%w", - "Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w" - ); + "I never thought I'd say this, but I'm selling the last %rMagic Bean%w.^%y99 Rupees%w, no " + "less.\x1B%gYes&No%w", + "Ich hätte nie gedacht, daß ich das sage, aber ich verkaufe die letzte^%rWundererbse%w für %y99 " + "Rubine%w.\x1B&%gJa&Nein%w", + "Je te vends mon dernier %rHaricot&magique%g pour %y99 Rubis%w.\x1B&%gAcheterNe pas acheter%w"); msg.Format(); } else if (*textId == TEXT_BEAN_SALESMAN_BUY_FOR_10) { - msg = CustomMessage( - "Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" - ); + msg = CustomMessage("Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"); BuildMerchantMessage(msg, RC_ZR_MAGIC_BEAN_SALESMAN); msg.AutoFormat(); } @@ -67,11 +66,9 @@ void BuildBeanGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { } void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" - ); + CustomMessage msg = CustomMessage("Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"); BuildMerchantMessage(msg, RC_GC_MEDIGORON); msg.AutoFormat(); msg.LoadIntoFont(); @@ -80,13 +77,11 @@ void BuildMedigoronMessage(uint16_t* textId, bool* loadFromMessageTable) { void BuildGrannyMessage(uint16_t* textId, bool* loadFromMessageTable) { if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_GRANNYS_SHOP) && - (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) || - INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { - CustomMessage msg = CustomMessage( - "Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" - ); + (RAND_GET_OPTION(RSK_SHUFFLE_ADULT_TRADE).Is(RO_GENERIC_ON) || + INV_CONTENT(ITEM_CLAIM_CHECK) == ITEM_CLAIM_CHECK)) { + CustomMessage msg = CustomMessage("Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"); BuildMerchantMessage(msg, RC_KAK_GRANNYS_SHOP); msg.AutoFormat(); msg.LoadIntoFont(); @@ -98,14 +93,12 @@ void BuildCarpetGuyMessage(uint16_t* textId, bool* loadFromMessageTable) { CustomMessage msg; if (*textId == TEXT_CARPET_SALESMAN_ARMS_DEALER) { msg = CustomMessage("Finally! Now I can go back to being an %rarms dealer%w!", - /*german*/"Endlich! Schon bald kann ich wieder %rKrabbelminen-Händler%w sein!", - /*french*/"Squalala! Je vais enfin pouvoir %rprendre des vacances%w!"); + /*german*/ "Endlich! Schon bald kann ich wieder %rKrabbelminen-Händler%w sein!", + /*french*/ "Squalala! Je vais enfin pouvoir %rprendre des vacances%w!"); } else if (!Flags_GetRandomizerInf(RAND_INF_MERCHANTS_CARPET_SALESMAN)) { - msg = CustomMessage( - "Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", - "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", - "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w" - ); + msg = CustomMessage("Want to buy [[color]][[1]]%w for %y[[2]] Rupees%w?\x1B%gYes&No%w", + "Möchten Sie [[color]][[1]]%w für %y[[2]] Rubin%w kaufen?\x1B%gJa&Nein%w", + "Voulez-vous acheter [[color]][[1]]%w pour %y[[2]] Rubis%w?\x1B%gOui&Non%w"); BuildMerchantMessage(msg, RC_WASTELAND_BOMBCHU_SALESMAN); } msg.AutoFormat(); @@ -128,13 +121,24 @@ void BuildScrubMessage(uint16_t* textId, bool* loadFromMessageTable) { uint16_t price = RAND_GET_ITEM(rc)->GetPrice(); CustomMessage msg; if (price == 0) { - msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will give you a [[color]][[1]]%w!&Please, take it!\x07\x10\xA3", - "\x12\x38\x82" "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir einen [[color]][[1]]%w geben!\x07\x10\xA3", - "\x12\x38\x82" "J'me rends! Laisse-moi partir et en échange, je te donne un [[color]][[1]]%w! Vas-y prends le!\x07\x10\xA3"); + msg = CustomMessage("\x12\x38\x82" + "All right! You win! In return for sparing me, I will give you a [[color]][[1]]%w!&Please, " + "take it!\x07\x10\xA3", + "\x12\x38\x82" + "In Ordnung! Du gewinnst! Im Austausch dafür, dass Du mich verschont hast, werde ich Dir " + "einen [[color]][[1]]%w geben!\x07\x10\xA3", + "\x12\x38\x82" + "J'me rends! Laisse-moi partir et en échange, je te donne un [[color]][[1]]%w! Vas-y " + "prends le!\x07\x10\xA3"); } else { - msg = CustomMessage("\x12\x38\x82" "All right! You win! In return for sparing me, I will sell you a [[color]][[1]]%w! %y[[2]] Rupees%w it is!\x07\x10\xA3", - "\x12\x38\x82" "Ich gebe auf! Ich verkaufe Dir einen [[color]][[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", - "\x12\x38\x82" "J'abandonne! Tu veux bien m'acheter un [[color]][[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); + msg = CustomMessage( + "\x12\x38\x82" + "All right! You win! In return for sparing me, I will sell you a [[color]][[1]]%w! %y[[2]] Rupees%w it " + "is!\x07\x10\xA3", + "\x12\x38\x82" + "Ich gebe auf! Ich verkaufe Dir einen [[color]][[1]]%w für %y[[2]] Rubine%w!\x07\x10\xA3", + "\x12\x38\x82" + "J'abandonne! Tu veux bien m'acheter un [[color]][[1]]%w? Ça fera %y[[2]] Rubis%w!\x07\x10\xA3"); } BuildMerchantMessage(msg, rc); msg.AutoFormat(); @@ -149,15 +153,18 @@ void BuildShopMessage(uint16_t* textId, bool* loadFromMessageTable) { // textId: TEXT_SHOP_ITEM_RANDOM + (randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) // textId: TEXT_SHOP_ITEM_RANDOM + ((randomizerInf - RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1) + NUM_SHOP_ITEMS) if (*textId >= TEXT_SHOP_ITEM_RANDOM && *textId < TEXT_SHOP_ITEM_RANDOM_CONFIRM) { - rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); - msg = CustomMessage("\x08[[color]][[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", - "\x08[[color]][[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", - "\x08[[color]][[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); + rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf( + static_cast((*textId - TEXT_SHOP_ITEM_RANDOM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); + msg = + CustomMessage("\x08[[color]][[1]]%w %y[[2]]_Rupees%w&Special deal! %rONE LEFT%w!\x0A\x02", + "\x08[[color]][[1]]%w %y[[2]]_Rubine%w&Sonderangebot! %rNUR NOCH EINES VERFÜGBAR%w!\x0A\x02", + "\x08[[color]][[1]]%w %y[[2]]_Rubis%w&Offre spéciale! %rDERNIER EN STOCK%w!\x0A\x02"); } else if (*textId >= TEXT_SHOP_ITEM_RANDOM_CONFIRM && *textId <= TEXT_SHOP_ITEM_RANDOM_CONFIRM_END) { - rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf(static_cast((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); + rc = OTRGlobals::Instance->gRandomizer->GetCheckFromRandomizerInf( + static_cast((*textId - TEXT_SHOP_ITEM_RANDOM_CONFIRM) + RAND_INF_SHOP_ITEMS_KF_SHOP_ITEM_1)); msg = CustomMessage("\x08[[color]][[1]]%w %y[[2]]_Rupees%w\x09\x1B%gBuy&Don't buy%w\x09\x02", - "\x08[[color]][[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", - "\x08[[color]][[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); + "\x08[[color]][[1]]%w %y[[2]]_Rubine%w\x09\x1B%gKaufen&Nicht kaufen%w\x09\x02", + "\x08[[color]][[1]]%w %y[[2]]_Rubis%w\x09\x1B%gAcheter&Ne pas acheter%w\x09\x02"); } else { return; } diff --git a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp index 9670bc03f..70dc08ad1 100644 --- a/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp +++ b/soh/soh/Enhancements/randomizer/Messages/StaticHints.cpp @@ -132,10 +132,14 @@ void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) { return; } Rando::Item& item = Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(rc)->GetPlacedRandomizerGet()); - CustomMessage msg = CustomMessage( - "Yeaaarrgh! I'm cursed!!^Please save me by destroying %y[[d]] Spiders of the Curse%w and I will give you my [[color]][[1]]%w!", - /*german*/ "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du %y[[d]] Skulltulas%w zerstörst und ich werde Dir dafür [[color]][[1]]%w geben!", - /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore %y[[d]] Araignées de la Malédiction%w et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); + CustomMessage msg = CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying %y[[d]] Spiders of the " + "Curse%w and I will give you my [[color]][[1]]%w!", + /*german*/ + "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du %y[[d]] Skulltulas%w " + "zerstörst und ich werde Dir dafür [[color]][[1]]%w geben!", + /*french*/ + "Yeaaarrgh! Je suis maudit!^Détruit encore %y[[d]] Araignées de la Malédiction%w " + "et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); msg.InsertNumber(count); msg.Replace("[[color]]", item.GetColor()); msg.InsertNames({ item.GetName() }); @@ -145,12 +149,20 @@ void BuildSkulltulaPeopleMessage(uint16_t* textId, bool* loadFromMessageTable) { } void Build100SkullsHintMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage( - "Yeaaarrgh! I'm cursed!!^Please save me by destroying %y100 Spiders of the Curse%w and I will give you my [[color]][[1]]%w!", - /*german*/ "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du %y100 Skulltulas%w zerstörst und ich werde Dir dafür [[color]][[1]]%w geben!", - /*french*/ "Yeaaarrgh! Je suis maudit!^Détruit encore %y100 Araignées de la Malédiction%w et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); - msg.Replace("[[color]]", Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()).GetColor()); - msg.InsertNames({ Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()).GetName() }); + CustomMessage msg = CustomMessage("Yeaaarrgh! I'm cursed!!^Please save me by destroying %y100 Spiders of the " + "Curse%w and I will give you my [[color]][[1]]%w!", + /*german*/ + "Yeaaarrgh! Ich bin verflucht!^Bitte rette mich, indem Du %y100 Skulltulas%w " + "zerstörst und ich werde Dir dafür [[color]][[1]]%w geben!", + /*french*/ + "Yeaaarrgh! Je suis maudit!^Détruit encore %y100 Araignées de la Malédiction%w " + "et j'aurai quelque chose à te donner! [[color]]([[1]])%w"); + msg.Replace("[[color]]", Rando::StaticData::RetrieveItem( + RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()) + .GetColor()); + msg.InsertNames( + { Rando::StaticData::RetrieveItem(RAND_GET_ITEM_LOC(RC_KAK_100_GOLD_SKULLTULA_REWARD)->GetPlacedRandomizerGet()) + .GetName() }); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; diff --git a/soh/soh/Enhancements/randomizer/item.cpp b/soh/soh/Enhancements/randomizer/item.cpp index 7e0db1dde..0b6f08991 100644 --- a/soh/soh/Enhancements/randomizer/item.cpp +++ b/soh/soh/Enhancements/randomizer/item.cpp @@ -16,13 +16,13 @@ Item::Item() progressive(false), price(0) { } Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const uint16_t itemId_, - const uint16_t objectId_, const uint16_t gid_, const uint16_t textId_, const uint16_t field_, - const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_, - Text article_, const std::string color_, const bool progressive_, const uint16_t price_) + const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, const uint16_t itemId_, + const uint16_t objectId_, const uint16_t gid_, const uint16_t textId_, const uint16_t field_, + const int16_t chestAnimation_, const GetItemCategory category_, const uint16_t modIndex_, Text article_, + const std::string color_, const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), article(std::move(article_)), - color(std::move(color_)), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), article(std::move(article_)), + color(std::move(color_)), progressive(progressive_), price(price_) { if (modIndex_ == MOD_RANDOMIZER || getItemId > 0x7D) { giEntry = std::make_shared(GetItemEntry{ itemId_, field_, static_cast((chestAnimation_ != CHEST_ANIM_SHORT ? 1 : -1) * (gid_ + 1)), textId_, @@ -37,11 +37,11 @@ Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, } Item::Item(const RandomizerGet randomizerGet_, Text name_, const ItemType type_, const int16_t getItemId_, - const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, Text article_, - const std::string color_, const bool progressive_, const uint16_t price_) + const bool advancement_, LogicVal logicVal_, const RandomizerHintTextKey hintKey_, Text article_, + const std::string color_, const bool progressive_, const uint16_t price_) : randomizerGet(randomizerGet_), name(std::move(name_)), type(type_), getItemId(getItemId_), - advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), article(std::move(article_)), - color(std::move(color_)), progressive(progressive_), price(price_) { + advancement(advancement_), logicVal(logicVal_), hintKey(hintKey_), article(std::move(article_)), + color(std::move(color_)), progressive(progressive_), price(price_) { } Item::~Item() = default; diff --git a/soh/soh/Enhancements/randomizer/item.h b/soh/soh/Enhancements/randomizer/item.h index 39e558c40..71f67293d 100644 --- a/soh/soh/Enhancements/randomizer/item.h +++ b/soh/soh/Enhancements/randomizer/item.h @@ -31,12 +31,12 @@ class Item { public: Item(); Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - LogicVal logicVal_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_, - uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, - Text article_ = {}, std::string color_ = "%g", bool progressive_ = false, uint16_t price_ = 0); + LogicVal logicVal_, RandomizerHintTextKey hintKey_, uint16_t itemId_, uint16_t objectId_, uint16_t gid_, + uint16_t textId_, uint16_t field_, int16_t chestAnimation_, GetItemCategory category_, uint16_t modIndex_, + Text article_ = {}, std::string color_ = "%g", bool progressive_ = false, uint16_t price_ = 0); Item(RandomizerGet randomizerGet_, Text name_, ItemType type_, int16_t getItemId_, bool advancement_, - LogicVal logicVal_, RandomizerHintTextKey hintKey_, Text article_ = {}, std::string color_ = "%g", - bool progressive_ = false, uint16_t price_ = 0); + LogicVal logicVal_, RandomizerHintTextKey hintKey_, Text article_ = {}, std::string color_ = "%g", + bool progressive_ = false, uint16_t price_ = 0); ~Item(); void ApplyEffect() const; From adaf245dc3cfe7725bc9ebda8ae8939055fde3b1 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 29 Apr 2025 19:34:03 -0400 Subject: [PATCH 101/103] Fix post-merge build errros --- .../Enhancements/custom-message/CustomMessageManager.cpp | 7 +++++++ soh/soh/Enhancements/custom-message/CustomMessageManager.h | 1 - soh/soh/Enhancements/randomizer/static_data.cpp | 6 ------ 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp index 91083d6ae..dc520209f 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.cpp @@ -443,6 +443,13 @@ static size_t NextLineLength(const std::string* textStr, const size_t lastNewlin nextPosJump = 1; } } + currentPos += nextPosJump; + } + // return the total number of characters we looped through + if (totalPixelWidth > maxLinePixelWidth && textStr->at(currentPos - nextPosJump) != ' ') { + return currentPos - lastNewline - nextPosJump; + } else { + return currentPos - lastNewline; } } diff --git a/soh/soh/Enhancements/custom-message/CustomMessageManager.h b/soh/soh/Enhancements/custom-message/CustomMessageManager.h index bf1657aec..baaf5ac40 100644 --- a/soh/soh/Enhancements/custom-message/CustomMessageManager.h +++ b/soh/soh/Enhancements/custom-message/CustomMessageManager.h @@ -62,7 +62,6 @@ class CustomMessage { static std::string PLAYER_NAME(); static std::string TWO_WAY_CHOICE(); - CustomMessage LoadVanillaMessageTableEntry(uint16_t textId); const std::string GetEnglish(MessageFormat format = MF_FORMATTED) const; const std::string GetFrench(MessageFormat format = MF_FORMATTED) const; const std::string GetGerman(MessageFormat format = MF_FORMATTED) const; diff --git a/soh/soh/Enhancements/randomizer/static_data.cpp b/soh/soh/Enhancements/randomizer/static_data.cpp index 473f7edcd..68b1b3e7e 100644 --- a/soh/soh/Enhancements/randomizer/static_data.cpp +++ b/soh/soh/Enhancements/randomizer/static_data.cpp @@ -86,12 +86,6 @@ std::unordered_map StaticData::hintNames = { { RH_BIGGORON_HINT, CustomMessage("Biggoron Claim Check Hint") }, { RH_FROGS_HINT, CustomMessage("Final Frogs in River Hint") }, { RH_OOT_HINT, CustomMessage("Sheik in Temple of Time Hint") }, - { RH_KAK_10_SKULLS_HINT, CustomMessage("10 Skulls Hint") }, - { RH_KAK_20_SKULLS_HINT, CustomMessage("20 Skulls Hint") }, - { RH_KAK_30_SKULLS_HINT, CustomMessage("30 Skulls Hint") }, - { RH_KAK_40_SKULLS_HINT, CustomMessage("40 Skulls Hint") }, - { RH_KAK_50_SKULLS_HINT, CustomMessage("50 Skulls Hint") }, - { RH_KAK_100_SKULLS_HINT, CustomMessage("100 Skulls Hint") }, { RH_MASK_SHOP_HINT, CustomMessage("Mask Shop Hint") }, }; From 2da36ed29c2e530952beaf5a9ad15b6ff8958317 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 29 Apr 2025 21:19:59 -0400 Subject: [PATCH 102/103] Adds colors to more items. Not sure if I forgot these or if they got lost in a merge, but this adds colors to things like the dungeon keys, maps, and compasses. --- soh/soh/Enhancements/randomizer/item_list.cpp | 106 +++++++++--------- 1 file changed, 53 insertions(+), 53 deletions(-) diff --git a/soh/soh/Enhancements/randomizer/item_list.cpp b/soh/soh/Enhancements/randomizer/item_list.cpp index 889c4272b..46add0d64 100644 --- a/soh/soh/Enhancements/randomizer/item_list.cpp +++ b/soh/soh/Enhancements/randomizer/item_list.cpp @@ -99,66 +99,66 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_REQUIEM_OF_SPIRIT] = Item(RG_REQUIEM_OF_SPIRIT, Text{ "Requiem of Spirit", "Requiem des Esprits", "Requiem der Geister" }, ITEMTYPE_SONG, 0xBE, true, LOGIC_REQUIEM_OF_SPIRIT, RHT_REQUIEM_OF_SPIRIT, ITEM_SONG_REQUIEM, OBJECT_GI_MELODY, GID_SONG_REQUIEM, 0x76, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); itemTable[RG_PRELUDE_OF_LIGHT] = Item(RG_PRELUDE_OF_LIGHT, Text{ "Prelude of Light", "Prélude de la Lumière", "Kantate des Lichts" }, ITEMTYPE_SONG, 0xC0, true, LOGIC_PRELUDE_OF_LIGHT, RHT_PRELUDE_OF_LIGHT, ITEM_SONG_PRELUDE, OBJECT_GI_MELODY, GID_SONG_PRELUDE, 0x78, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); // Maps and Compasses - itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", " die ", "la "}); - itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}); - itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_DEKU_TREE_MAP] = Item(RG_DEKU_TREE_MAP, Text{ "Great Deku Tree Map", "Carte de l'Arbre Mojo", "Karte des Deku-Baums" }, ITEMTYPE_MAP, 0xA5, false, LOGIC_MAP_DEKU_TREE, RHT_DEKU_TREE_MAP, RG_DEKU_TREE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the", " die ", "la "}, "%g"); + itemTable[RG_DODONGOS_CAVERN_MAP] = Item(RG_DODONGOS_CAVERN_MAP, Text{ "Dodongo's Cavern Map", "Carte de la Caverne Dodongo", "Karte der Dodongo-Höhle" }, ITEMTYPE_MAP, 0xA6, false, LOGIC_MAP_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_MAP, RG_DODONGOS_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%r"); + itemTable[RG_JABU_JABUS_BELLY_MAP] = Item(RG_JABU_JABUS_BELLY_MAP, Text{ "Jabu-Jabu's Belly Map", "Carte du Ventre de Jabu-Jabu", "Karte des Jabu-Jabu-Bauchs" }, ITEMTYPE_MAP, 0xA7, false, LOGIC_MAP_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_MAP, RG_JABU_JABUS_BELLY_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%b"); + itemTable[RG_FOREST_TEMPLE_MAP] = Item(RG_FOREST_TEMPLE_MAP, Text{ "Forest Temple Map", "Carte du Temple de la Forêt", "Karte des Waldtempels" }, ITEMTYPE_MAP, 0xA8, false, LOGIC_MAP_FOREST_TEMPLE, RHT_FOREST_TEMPLE_MAP, RG_FOREST_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%g"); + itemTable[RG_FIRE_TEMPLE_MAP] = Item(RG_FIRE_TEMPLE_MAP, Text{ "Fire Temple Map", "Carte due Temple de Feu", "Karte des Feuertempels" }, ITEMTYPE_MAP, 0xA9, false, LOGIC_MAP_FIRE_TEMPLE, RHT_FIRE_TEMPLE_MAP, RG_FIRE_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%r"); + itemTable[RG_WATER_TEMPLE_MAP] = Item(RG_WATER_TEMPLE_MAP, Text{ "Water Temple Map", "Carte du Temple de l'Eau", "Karte des Wassertempels" }, ITEMTYPE_MAP, 0xAA, false, LOGIC_MAP_WATER_TEMPLE, RHT_WATER_TEMPLE_MAP, RG_WATER_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%b"); + itemTable[RG_SPIRIT_TEMPLE_MAP] = Item(RG_SPIRIT_TEMPLE_MAP, Text{ "Spirit Temple Map", "Carte due Temple de l'Esprit", "Karte des Geistertempels" }, ITEMTYPE_MAP, 0xAB, false, LOGIC_MAP_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_MAP, RG_SPIRIT_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%y"); + itemTable[RG_SHADOW_TEMPLE_MAP] = Item(RG_SHADOW_TEMPLE_MAP, Text{ "Shadow Temple Map", "Carte du Temple de l'Ombre", "Karte des Schattentempels" }, ITEMTYPE_MAP, 0xAC, false, LOGIC_MAP_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_MAP, RG_SHADOW_TEMPLE_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%p"); + itemTable[RG_BOTTOM_OF_THE_WELL_MAP] = Item(RG_BOTTOM_OF_THE_WELL_MAP, Text{ "Bottom of the Well Map", "Carte du Puits", "Karte des Grund des Brunnens" }, ITEMTYPE_MAP, 0xAD, false, LOGIC_MAP_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_MAP, RG_BOTTOM_OF_THE_WELL_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%p"); + itemTable[RG_ICE_CAVERN_MAP] = Item(RG_ICE_CAVERN_MAP, Text{ "Ice Cavern Map", "Carte de la Caverne Polaire", "Karte der Eishöhle" }, ITEMTYPE_MAP, 0xAE, false, LOGIC_MAP_ICE_CAVERN, RHT_ICE_CAVERN_MAP, RG_ICE_CAVERN_MAP, OBJECT_GI_MAP, GID_DUNGEON_MAP, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "die ", "la "}, "%c"); + itemTable[RG_DEKU_TREE_COMPASS] = Item(RG_DEKU_TREE_COMPASS, Text{ "Great Deku Tree Compass", "Boussole de l'Arbre Mojo", "Kompaß des Deku-Baums" }, ITEMTYPE_COMPASS, 0x9B, false, LOGIC_COMPASS_DEKU_TREE, RHT_DEKU_TREE_COMPASS, RG_DEKU_TREE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_DUNGEON_MAP, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); itemTable[RG_DEKU_TREE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_DODONGOS_CAVERN_COMPASS] = Item(RG_DODONGOS_CAVERN_COMPASS, Text{ "Dodongo's Cavern Compass", "Boussole de la Caverne Dodongo", "Kompaß der Dodongo-Höhle" }, ITEMTYPE_COMPASS, 0x9C, false, LOGIC_COMPASS_DODONGOS_CAVERN, RHT_DODONGOS_CAVERN_COMPASS, RG_DODONGOS_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); itemTable[RG_DODONGOS_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_JABU_JABUS_BELLY_COMPASS] = Item(RG_JABU_JABUS_BELLY_COMPASS, Text{ "Jabu-Jabu's Belly Compass", "Boussole du Ventre de Jabu-Jabu", "Kompaß des Jabu-Jabu-Bauchs" }, ITEMTYPE_COMPASS, 0x9D, false, LOGIC_COMPASS_JABU_JABUS_BELLY, RHT_JABU_JABUS_BELLY_COMPASS, RG_JABU_JABUS_BELLY_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%b"); itemTable[RG_JABU_JABUS_BELLY_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_FOREST_TEMPLE_COMPASS] = Item(RG_FOREST_TEMPLE_COMPASS, Text{ "Forest Temple Compass", "Boussole du Temple de la Forêt", "Kompaß des Waldtempels" }, ITEMTYPE_COMPASS, 0x9E, false, LOGIC_COMPASS_FOREST_TEMPLE, RHT_FOREST_TEMPLE_COMPASS, RG_FOREST_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); itemTable[RG_FOREST_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_FIRE_TEMPLE_COMPASS] = Item(RG_FIRE_TEMPLE_COMPASS, Text{ "Fire Temple Compass", "Boussole du Temple du Feu", "Kompaß des Feuertempels" }, ITEMTYPE_COMPASS, 0x9F, false, LOGIC_COMPASS_FIRE_TEMPLE, RHT_FIRE_TEMPLE_COMPASS, RG_FIRE_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); itemTable[RG_FIRE_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_WATER_TEMPLE_COMPASS] = Item(RG_WATER_TEMPLE_COMPASS, Text{ "Water Temple Compass", "Boussole du Temple de l'Eau", "Kompaß des Wassertempels" }, ITEMTYPE_COMPASS, 0xA0, false, LOGIC_COMPASS_WATER_TEMPLE, RHT_WATER_TEMPLE_COMPASS, RG_WATER_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%b"); itemTable[RG_WATER_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_SPIRIT_TEMPLE_COMPASS] = Item(RG_SPIRIT_TEMPLE_COMPASS, Text{ "Spirit Temple Compass", "Boussole due Temple de l'Esprit", "Kompaß des Geistertempels" }, ITEMTYPE_COMPASS, 0xA1, false, LOGIC_COMPASS_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_COMPASS, RG_SPIRIT_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_SHADOW_TEMPLE_COMPASS] = Item(RG_SHADOW_TEMPLE_COMPASS, Text{ "Shadow Temple Compass", "Boussole du Temple de l'Ombre", "Kompaß des Schattentempels" }, ITEMTYPE_COMPASS, 0xA2, false, LOGIC_COMPASS_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_COMPASS, RG_SHADOW_TEMPLE_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); itemTable[RG_SHADOW_TEMPLE_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS] = Item(RG_BOTTOM_OF_THE_WELL_COMPASS, Text{ "Bottom of the Well Compass", "Boussole du Puits", "Kompaß des Grund des Brunnens" }, ITEMTYPE_COMPASS, 0xA3, false, LOGIC_COMPASS_BOTTOM_OF_THE_WELL, RHT_BOTTOM_OF_THE_WELL_COMPASS, RG_BOTTOM_OF_THE_WELL_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); itemTable[RG_BOTTOM_OF_THE_WELL_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); - itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_ICE_CAVERN_COMPASS] = Item(RG_ICE_CAVERN_COMPASS, Text{ "Ice Cavern Compass", "Boussole de la Caverne Polaire", "Kompaß der Eishöhle" }, ITEMTYPE_COMPASS, 0xA4, false, LOGIC_COMPASS_ICE_CAVERN, RHT_ICE_CAVERN_COMPASS, RG_ICE_CAVERN_COMPASS, OBJECT_GI_COMPASS, GID_COMPASS, TEXT_ITEM_COMPASS, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_LESSER, MOD_RANDOMIZER, {"the ", "den ", "la "}, "%c"); itemTable[RG_ICE_CAVERN_COMPASS].SetCustomDrawFunc(Randomizer_DrawCompass); // Boss Keys - itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_FOREST_TEMPLE_BOSS_KEY] = Item(RG_FOREST_TEMPLE_BOSS_KEY, Text{ "Forest Temple Boss Key", "Clé d'Or du Temple de la Forêt", "Master-Schlüssel des Waldtempels" }, ITEMTYPE_BOSSKEY, 0x95, true, LOGIC_BOSS_KEY_FOREST_TEMPLE, RHT_FOREST_TEMPLE_BOSS_KEY, RG_FOREST_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%g"); itemTable[RG_FOREST_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_FIRE_TEMPLE_BOSS_KEY] = Item(RG_FIRE_TEMPLE_BOSS_KEY, Text{ "Fire Temple Boss Key", "Clé d'Or du Temple du Feu", "Master-Schlüssel des Feuertempels" }, ITEMTYPE_BOSSKEY, 0x96, true, LOGIC_BOSS_KEY_FIRE_TEMPLE, RHT_FIRE_TEMPLE_BOSS_KEY, RG_FIRE_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); itemTable[RG_FIRE_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_WATER_TEMPLE_BOSS_KEY] = Item(RG_WATER_TEMPLE_BOSS_KEY, Text{ "Water Temple Boss Key", "Clé d'Or du Temple de l'Eau", "Master-Schlüssel des Wassertempels" }, ITEMTYPE_BOSSKEY, 0x97, true, LOGIC_BOSS_KEY_WATER_TEMPLE, RHT_WATER_TEMPLE_BOSS_KEY, RG_WATER_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "b"); itemTable[RG_WATER_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY] = Item(RG_SPIRIT_TEMPLE_BOSS_KEY, Text{ "Spirit Temple Boss Key", "Clé d'Or du Temple de l'Esprit", "Master-Schlüssel des Geistertempels" }, ITEMTYPE_BOSSKEY, 0x98, true, LOGIC_BOSS_KEY_SPIRIT_TEMPLE, RHT_SPIRIT_TEMPLE_BOSS_KEY, RG_SPIRIT_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_SHADOW_TEMPLE_BOSS_KEY] = Item( RG_SHADOW_TEMPLE_BOSS_KEY, Text{ "Shadow Temple Boss Key", "Clé d'Or du Temple de l'Ombre", "Master-Schlüssel des Schattentempels" }, ITEMTYPE_BOSSKEY, 0x99, true, LOGIC_BOSS_KEY_SHADOW_TEMPLE, RHT_SHADOW_TEMPLE_BOSS_KEY, RG_SHADOW_TEMPLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%p"); itemTable[RG_SHADOW_TEMPLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); + itemTable[RG_GANONS_CASTLE_BOSS_KEY] = Item(RG_GANONS_CASTLE_BOSS_KEY, Text{ "Ganon's Castle Boss Key", "Clé d'Or du Château de Ganon", "Master-Schlüssel von Ganons Schloß" }, ITEMTYPE_BOSSKEY, 0x9A, true, LOGIC_BOSS_KEY_GANONS_CASTLE, RHT_GANONS_CASTLE_BOSS_KEY, RG_GANONS_CASTLE_BOSS_KEY, OBJECT_GI_BOSSKEY, GID_KEY_BOSS, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_BOSS_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}, "%r"); itemTable[RG_GANONS_CASTLE_BOSS_KEY].SetCustomDrawFunc(Randomizer_DrawBossKey); - itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_FOREST_TEMPLE_SMALL_KEY] = Item(RG_FOREST_TEMPLE_SMALL_KEY, Text{ "Forest Temple Small Key", "Petite Clé du Temple de la Forêt", "Kleiner Schlüssel für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xAF, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_SMALL_KEY, RG_FOREST_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%g"); itemTable[RG_FOREST_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_FIRE_TEMPLE_SMALL_KEY] = Item(RG_FIRE_TEMPLE_SMALL_KEY, Text{ "Fire Temple Small Key", "Petite Clé du Temple du Feu", "Kleiner Schlüssel für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xB0, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_SMALL_KEY, RG_FIRE_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%r"); itemTable[RG_FIRE_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_WATER_TEMPLE_SMALL_KEY] = Item(RG_WATER_TEMPLE_SMALL_KEY, Text{ "Water Temple Small Key", "Petite Clé du Temple de l'Eau", "Kleiner Schlüssel für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xB1, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_SMALL_KEY, RG_WATER_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%b"); itemTable[RG_WATER_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY] = Item(RG_SPIRIT_TEMPLE_SMALL_KEY, Text{ "Spirit Temple Small Key", "Petite Clé du Temple de l'Esprit", "Kleiner Schlüssel für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xB2, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_SMALL_KEY, RG_SPIRIT_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_SHADOW_TEMPLE_SMALL_KEY] = Item(RG_SHADOW_TEMPLE_SMALL_KEY, Text{ "Shadow Temple Small Key", "Petite Clé du Temple de l'Ombre", "Kleiner Schlüssel für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xB3, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_SMALL_KEY, RG_SHADOW_TEMPLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%p"); itemTable[RG_SHADOW_TEMPLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY] = Item(RG_BOTTOM_OF_THE_WELL_SMALL_KEY, Text{ "Bottom of the Well Small Key", "Petite Clé du Puits", "Kleiner Schlüssel für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xB4, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_SMALL_KEY, RG_BOTTOM_OF_THE_WELL_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%p"); itemTable[RG_BOTTOM_OF_THE_WELL_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY] = Item(RG_GERUDO_TRAINING_GROUND_SMALL_KEY, Text{ "Training Ground Small Key", "Petite Clé du Gymnase Gerudo", "Kleiner Schlüssel für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xB5, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_SMALL_KEY, RG_GERUDO_TRAINING_GROUND_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); itemTable[RG_GERUDO_TRAINING_GROUND_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_GERUDO_FORTRESS_SMALL_KEY] = Item(RG_GERUDO_FORTRESS_SMALL_KEY, Text{ "Gerudo Fortress Small Key", "Petite Clé du Repaire des Voleurs", "Kleiner Schlüssel für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xB6, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_SMALL_KEY, RG_GERUDO_FORTRESS_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%y"); itemTable[RG_GERUDO_FORTRESS_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); - itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}); + itemTable[RG_GANONS_CASTLE_SMALL_KEY] = Item(RG_GANONS_CASTLE_SMALL_KEY, Text{ "Ganon's Castle Small Key", "Petite Clé du Château de Ganon", "Kleiner Schlüssel für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xB7, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_SMALL_KEY, RG_GANONS_CASTLE_SMALL_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"a ", "einen ", "une "}, "%r"); itemTable[RG_GANONS_CASTLE_SMALL_KEY].SetCustomDrawFunc(Randomizer_DrawSmallKey); itemTable[RG_TREASURE_GAME_SMALL_KEY] = Item(RG_TREASURE_GAME_SMALL_KEY, Text{ "Chest Game Small Key", "Petite Clé du jeu la Chasse-aux-Trésors", "Kleiner Schlüssel für das Truhenspiel" }, ITEMTYPE_SMALLKEY, GI_DOOR_KEY, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_SMALL_KEY, ITEM_KEY_SMALL, OBJECT_GI_KEY, GID_KEY_SMALL, 0xF3, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_NONE, {"a ", "einen ", "une "}); itemTable[RG_GUARD_HOUSE_KEY] = Item(RG_GUARD_HOUSE_KEY, Text{ "Guard House Key", "Clé de la Maison des Gardes", "Schlüssel für das Haus der Wachen" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_GUARD_HOUSE_KEY, RHT_OVERWORLD_KEY, RG_GUARD_HOUSE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); @@ -210,36 +210,36 @@ void Rando::StaticData::InitItemTable() { itemTable[RG_FISHING_HOLE_KEY] = Item(RG_FISHING_HOLE_KEY, Text{ "Fishing Hole Key", "Clé de l'Étang", "Schlüssel für den Fischweiher" }, ITEMTYPE_ITEM, GI_DOOR_KEY, true, LOGIC_FISHING_HOLE_KEY, RHT_OVERWORLD_KEY, RG_FISHING_HOLE_KEY, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "la "}); itemTable[RG_FISHING_HOLE_KEY].SetCustomDrawFunc(Randomizer_DrawOverworldKey); // Key Rings - itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_FOREST_TEMPLE_KEY_RING] = Item(RG_FOREST_TEMPLE_KEY_RING, Text{ "Forest Temple Key Ring", "Trousseau du Temple de la Forêt", "Schlüsselbund für den Waldtempel" }, ITEMTYPE_SMALLKEY, 0xD5, true, LOGIC_FOREST_TEMPLE_KEYS, RHT_FOREST_TEMPLE_KEY_RING, RG_FOREST_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%g"); itemTable[RG_FOREST_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_FIRE_TEMPLE_KEY_RING] = Item(RG_FIRE_TEMPLE_KEY_RING, Text{ "Fire Temple Key Ring", "Trousseau du Temple du Feu", "Schlüsselbund für den Feuertempel" }, ITEMTYPE_SMALLKEY, 0xD6, true, LOGIC_FIRE_TEMPLE_KEYS, RHT_FIRE_TEMPLE_KEY_RING, RG_FIRE_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%r"); itemTable[RG_FIRE_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_WATER_TEMPLE_KEY_RING] = Item(RG_WATER_TEMPLE_KEY_RING, Text{ "Water Temple Key Ring", "Trousseau du Temple de l'Eau", "Schlüsselbund für den Wassertempel" }, ITEMTYPE_SMALLKEY, 0xD7, true, LOGIC_WATER_TEMPLE_KEYS, RHT_WATER_TEMPLE_KEY_RING, RG_WATER_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%b"); itemTable[RG_WATER_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_SPIRIT_TEMPLE_KEY_RING] = Item(RG_SPIRIT_TEMPLE_KEY_RING, Text{ "Spirit Temple Key Ring", "Trousseau du Temple de l'Esprit", "Schlüsselbund für den Geistertempel" }, ITEMTYPE_SMALLKEY, 0xD8, true, LOGIC_SPIRIT_TEMPLE_KEYS, RHT_SPIRIT_TEMPLE_KEY_RING, RG_SPIRIT_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); itemTable[RG_SPIRIT_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_SHADOW_TEMPLE_KEY_RING] = Item(RG_SHADOW_TEMPLE_KEY_RING, Text{ "Shadow Temple Key Ring", "Trousseau du Temple de l'Ombre", "Schlüsselbund für den Schattentempel" }, ITEMTYPE_SMALLKEY, 0xD9, true, LOGIC_SHADOW_TEMPLE_KEYS, RHT_SHADOW_TEMPLE_KEY_RING, RG_SHADOW_TEMPLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%p"); itemTable[RG_SHADOW_TEMPLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING] = Item(RG_BOTTOM_OF_THE_WELL_KEY_RING, Text{ "Bottom of the Well Key Ring", "Trousseau du Puits", "Schlüsselbund für den Grund des Brunnens" }, ITEMTYPE_SMALLKEY, 0xDA, true, LOGIC_BOTTOM_OF_THE_WELL_KEYS, RHT_BOTTOM_OF_THE_WELL_KEY_RING, RG_BOTTOM_OF_THE_WELL_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%p"); itemTable[RG_BOTTOM_OF_THE_WELL_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING] = Item(RG_GERUDO_TRAINING_GROUND_KEY_RING, Text{ "Training Ground Key Ring", "Trousseau du Gymnase Gerudo", "Schlüsselbund für das Gerudo-Trainingsgelände" }, ITEMTYPE_SMALLKEY, 0xDB, true, LOGIC_GERUDO_TRAINING_GROUND_KEYS, RHT_GERUDO_TRAINING_GROUND_KEY_RING, RG_GERUDO_TRAINING_GROUND_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); itemTable[RG_GERUDO_TRAINING_GROUND_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_GERUDO_FORTRESS_KEY_RING] = Item(RG_GERUDO_FORTRESS_KEY_RING, Text{ "Gerudo Fortress Key Ring", "Trousseau du Repaire des Voleurs", "Schlüsselbund für die Gerudo-Festung" }, ITEMTYPE_FORTRESS_SMALLKEY, 0xDC, true, LOGIC_GERUDO_FORTRESS_KEYS, RHT_GERUDO_FORTRESS_KEY_RING, RG_GERUDO_FORTRESS_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%y"); itemTable[RG_GERUDO_FORTRESS_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); - itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); + itemTable[RG_GANONS_CASTLE_KEY_RING] = Item(RG_GANONS_CASTLE_KEY_RING, Text{ "Ganon's Castle Key Ring", "Trousseau du Château de Ganon", "Schlüsselbund für Ganons Schloß" }, ITEMTYPE_SMALLKEY, 0xDD, true, LOGIC_GANONS_CASTLE_KEYS, RHT_GANONS_CASTLE_KEY_RING, RG_GANONS_CASTLE_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}, "%r"); itemTable[RG_GANONS_CASTLE_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); itemTable[RG_TREASURE_GAME_KEY_RING] = Item(RG_TREASURE_GAME_KEY_RING, Text{ "Chest Game Key Ring", "Trousseau du jeu la Chasse-aux-Trésors", "Schlüsselbund für das Truhenspiel" }, ITEMTYPE_SMALLKEY, 0xDE, true, LOGIC_TREASURE_GAME_KEYS, RHT_TREASURE_GAME_KEY_RING, RG_TREASURE_GAME_KEY_RING, OBJECT_GI_KEY, GID_KEY_SMALL, TEXT_RANDOMIZER_CUSTOM_ITEM, 0x80, CHEST_ANIM_SHORT, ITEM_CATEGORY_SMALL_KEY,MOD_RANDOMIZER, {"the ", "den ", "le "}); itemTable[RG_TREASURE_GAME_KEY_RING].SetCustomDrawFunc(Randomizer_DrawKeyRing); // Dungeon Rewards - itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); - itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}); - itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", " le"}); - itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); - itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}); + itemTable[RG_KOKIRI_EMERALD] = Item(RG_KOKIRI_EMERALD, Text{ "Kokiri's Emerald", "Émeraude Kokiri", "Kokiri-Smaragd" }, ITEMTYPE_DUNGEONREWARD, 0xCB, true, LOGIC_KOKIRI_EMERALD, RHT_KOKIRI_EMERALD, ITEM_KOKIRI_EMERALD, OBJECT_GI_JEWEL, GID_KOKIRI_EMERALD, 0x80, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}, "%g"); + itemTable[RG_GORON_RUBY] = Item(RG_GORON_RUBY, Text{ "Goron's Ruby", "Rubis Goron", "Goronen-Rubin" }, ITEMTYPE_DUNGEONREWARD, 0xCC, true, LOGIC_GORON_RUBY, RHT_GORON_RUBY, ITEM_GORON_RUBY, OBJECT_GI_JEWEL, GID_GORON_RUBY, 0x81, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", "le "}, "%r"); + itemTable[RG_ZORA_SAPPHIRE] = Item(RG_ZORA_SAPPHIRE, Text{ "Zora's Sapphire", "Saphir Zora", "Zora-Saphir" }, ITEMTYPE_DUNGEONREWARD, 0xCD, true, LOGIC_ZORA_SAPPHIRE, RHT_ZORA_SAPPHIRE, ITEM_ZORA_SAPPHIRE, OBJECT_GI_JEWEL, GID_ZORA_SAPPHIRE, 0x82, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "den ", " le"}, "%b"); + itemTable[RG_FOREST_MEDALLION] = Item(RG_FOREST_MEDALLION, Text{ "Forest Medallion", "Médaillon de la Forêt", "Amulett des Waldes" }, ITEMTYPE_DUNGEONREWARD, 0xCE, true, LOGIC_FOREST_MEDALLION, RHT_FOREST_MEDALLION, ITEM_MEDALLION_FOREST, OBJECT_GI_MEDAL, GID_MEDALLION_FOREST, 0x3E, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%g"); + itemTable[RG_FIRE_MEDALLION] = Item(RG_FIRE_MEDALLION, Text{ "Fire Medallion", "Médaillon du Feu", "Amulett des Feuers" }, ITEMTYPE_DUNGEONREWARD, 0xCF, true, LOGIC_FIRE_MEDALLION, RHT_FIRE_MEDALLION, ITEM_MEDALLION_FIRE, OBJECT_GI_MEDAL, GID_MEDALLION_FIRE, 0x3C, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%r"); + itemTable[RG_WATER_MEDALLION] = Item(RG_WATER_MEDALLION, Text{ "Water Medallion", "Médaillon de l'Eau", "Amulett des Wassers" }, ITEMTYPE_DUNGEONREWARD, 0xD0, true, LOGIC_WATER_MEDALLION, RHT_WATER_MEDALLION, ITEM_MEDALLION_WATER, OBJECT_GI_MEDAL, GID_MEDALLION_WATER, 0x3D, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%b"); + itemTable[RG_SPIRIT_MEDALLION] = Item(RG_SPIRIT_MEDALLION, Text{ "Spirit Medallion", "Médaillon de l'Esprit", "Amulett der Geister" }, ITEMTYPE_DUNGEONREWARD, 0xD1, true, LOGIC_SPIRIT_MEDALLION, RHT_SPIRIT_MEDALLION, ITEM_MEDALLION_SPIRIT, OBJECT_GI_MEDAL, GID_MEDALLION_SPIRIT, 0x3F, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); + itemTable[RG_SHADOW_MEDALLION] = Item(RG_SHADOW_MEDALLION, Text{ "Shadow Medallion", "Médaillon de l'Ombre", "Amulett des Schattens" }, ITEMTYPE_DUNGEONREWARD, 0xD2, true, LOGIC_SHADOW_MEDALLION, RHT_SHADOW_MEDALLION, ITEM_MEDALLION_SHADOW, OBJECT_GI_MEDAL, GID_MEDALLION_SHADOW, 0x41, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%p"); + itemTable[RG_LIGHT_MEDALLION] = Item(RG_LIGHT_MEDALLION, Text{ "Light Medallion", "Médaillon de la Lumière", "Amulett des Lichts" }, ITEMTYPE_DUNGEONREWARD, 0xD3, true, LOGIC_LIGHT_MEDALLION, RHT_LIGHT_MEDALLION, ITEM_MEDALLION_LIGHT, OBJECT_GI_MEDAL, GID_MEDALLION_LIGHT, 0x40, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_MAJOR, MOD_NONE, {"the ", "das ", "le "}, "%y"); // Generic Items itemTable[RG_RECOVERY_HEART] = Item(RG_RECOVERY_HEART, Text{ "Recovery Heart", "Coeur de Vie", "Herz" }, ITEMTYPE_ITEM, GI_HEART, false, LOGIC_NONE, RHT_RECOVERY_HEART, ITEM_HEART, OBJECT_GI_HEART, GID_HEART, 0x55, 0x80, CHEST_ANIM_LONG, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "ein ", "un "}); itemTable[RG_GREEN_RUPEE] = Item(RG_GREEN_RUPEE, Text{ "Green Rupee", "Rubis Vert", "Grüner Rubin" }, ITEMTYPE_ITEM, GI_RUPEE_GREEN, false, LOGIC_NONE, RHT_GREEN_RUPEE, ITEM_RUPEE_GREEN, OBJECT_GI_RUPY, GID_RUPEE_GREEN, 0x6F, 0x00, CHEST_ANIM_SHORT, ITEM_CATEGORY_JUNK, MOD_NONE, {"a ", "eine ", "une "}); From e585b76d51175f05bc667c4f95ea8b322fb95bd5 Mon Sep 17 00:00:00 2001 From: Christopher Leggett Date: Tue, 29 Apr 2025 22:00:41 -0400 Subject: [PATCH 103/103] Fix the Yes/No spacing on a couple of messages. --- soh/soh/Enhancements/TimeSavers/MarketSneak.cpp | 6 +++--- soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp index 232f00f0a..2b688bc9e 100644 --- a/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp +++ b/soh/soh/Enhancements/TimeSavers/MarketSneak.cpp @@ -7,9 +7,9 @@ extern "C" { // RANDOTODO: Port the rest of the behavior for this enhancement here. void BuildNightGuardMessage(uint16_t* textId, bool* loadFromMessageTable) { - CustomMessage msg = CustomMessage("You look bored. Wanna go out for a&walk?\x1B&%gYes&No%w", - "Du siehst gelangweilt aus.&Willst Du einen Spaziergang machen?\x1B&%gJa&Nein%w", - "Tu as l'air de t'ennuyer. Tu veux&aller faire un tour?\x1B&%gOui&Non%w"); + CustomMessage msg = CustomMessage("You look bored. Wanna go out for a walk?\x1B%gYes&No%w", + "Du siehst gelangweilt aus. Willst Du einen Spaziergang machen?\x1B%gJa&Nein%w", + "Tu as l'air de t'ennuyer. Tu veux aller faire un tour?\x1B%gOui&Non%w"); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false; diff --git a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp index 9bfb61711..3d408a056 100644 --- a/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp +++ b/soh/soh/Enhancements/TimeSavers/QuitFishingAtDoor.cpp @@ -10,10 +10,10 @@ void BuildQuitFishingMessage(uint16_t* textId, bool* loadFromMessageTable) { // TODO: See about loading the vanilla message and manipulating that instead of // a brand new one. Might not be worth it. CustomMessage msg = CustomMessage( - "Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?&\x1B&%gYes&No%w", + "Hey! Hey!&You can't take the rod out of here!&I'm serious!^Do you want to quit?\x1B%gYes&No%w", "Hey! Hey!&Du kannst die Angel doch nicht&einfach mitnehmen!&Ganz im Ernst!^Möchtest Du " - "aufhören?&\x1B&%gJa&Nein%w", - "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?&\x1B&%gOui&Non%w"); + "aufhören?\x1B%gJa&Nein%w", + "Holà! Holà!&Les cannes ne sortent pas d'ici!&Je suis sérieux!^Voulez-vous arrêter?\x1B%gOui&Non%w"); msg.AutoFormat(); msg.LoadIntoFont(); *loadFromMessageTable = false;