mirror of
https://github.com/HarbourMasters/Shipwright.git
synced 2024-11-11 03:55:07 -05:00
2b78bea475
* Revert changes to GetItemFromGet
* Fixes Ganon's Boss Key shuffled while regular boss Keys aren't.
* Enum + combo box
* Add obtainability checks correctly
* combobox title rename + no number tracking
* Fix repeatable purchases and bottles rendering incorrectly
* Move shopsanity option in GUI
* Struct instead of ImVec + basic comportment for all case
* Attempt to fix odd build issue
* Cast randoGet for ganons boss key
* Remove redundancy in KD room
* Update logic Cvar names
* Fix Ganons Trials coming from old save files. Fixes #1365
* Fixes crash when entering Ganon's Castle lobby on linux.
* Makes `Item_Give` safe to use with a NULL globalCtx.
This should allow it's use for giving items to Link's Pocket
during rando save initialization.
* Converts Song from Impa to use `Item_Give`
* Adds more options for Link's starting item.
* Removes unneeded `GiveLinkItem` functions.
* and make it build
* bring back new rando dropdown
* gSaveContext access in GameMenuBar.cpp
* Implement Skip Scarecrow's Song
* Reimplement progressive Bombchus
* Rando-next: Deku Nut and Seed ammo gives a blue rupee
Fixes #1390
* Fixes Link starting with BGS
* Persist item tracker notes
* Adjust Hooks include
* Use SohImGui::RequestCvarSaveOnNextTick
* Fix issues from LUS refactor
* Fix for overriding deku scrub messages
* Fix mistake from merge
oops
* Restore checkboxes to enhancements menu
These got lost in the merge
* Update location access logic
Including MQ locations in Spirit and GC now
* Implement rando bombchu drops
* Missing break
* Simplify mudwall collision check
There was no need to have a second collider specifically for Ice Arrow hits
* Update settings.cpp
* Simplify mudwall collision check
* Restore checkboxes in menu
Accidentally lost these during merge
* Clean up bool
* Update logic Cvar name
* Fixed capacity on ammmo tracking
* Fix for beans obtainability
* Hook into file delete and clear notes
* Incorporate magic arrows in rando settings
* Update tooltip
To inform the player that they might have to reload the room if they're enabling this for the first time.
* Update tooltip
* Add line break in tooltip
* Tooltip wording + line break
* tweak on main logic
* All color logic for all types
* Fix: changes to please new LUS
* Ensure itemTrackerNotes vector is not fully empty
* Implement's Tycoon Wallet.
* Refactor DrawItemCount and Use EnhancementCombobox for tracker capacity options
* small tweaks and rename
* always display XX/YY when in ammo/capacity mode
* Move all merchant messages to be generated on file load
* added hovertext for the number display
* Swap german and french translations for shop messages
* Set key colors to be on by default
* Add another flag to skip mask shop
* Fix Sold Out bug
* Fix gerudo keys, add disabled checkbox
* tooltip line break
* Add trials required and merchant prices to save file instead of loading from active spoiler log
* Remove trialsRequired persisting in save manager
* Adds slotIndex to girla (shop item actor) and uses that for IdentifyShopItem.
* Fix issue when merchantPrices is empty
* Fix for a single zeroed merchantPrice entry
* Fix #1417
* Implements items selling out and fixes issues with purchasing some items.
* Fixes order of operations so Rupees will be spent.
* Fixes sold out items not getting overwritten by the randomized info.
* Clarify var names and comments
Also preserve chain platform cutscene in spirit based on Link's position
* Remove !=0 from cvar check
* Clarify var names and comments
* Rename randomizerMerchantPrices to merchantPrices
* Handle shop items in SaveManager
* Fix merge mistake
* Base whats in the bazaar shop on entranceIndex instead of age
* Tidy up chain platform cutscene check
* Fix merge error
Didn't mean to have Zhora changes in here yet
* Use 3drando item table for parsing spoiler names
* Use another nested method instead of one at the top level to fetch the table
* Add missing newline
* Remove log
* Respect custom draw functions
* Fix issues with rendering songs
* Fix localized item names for shopsanity
* Implements a larger array of Sprites for the Icon Hash.
* Uses the hash instead of seed for spoilerfile name and icons.
* Removes some unused functions and variables in `spoiler_log.cpp`
* Prevents leading 0s added to hash from being in file name
* Changes filename format to icon indexes separated by dashes
* Hopefully makes Jenkins happy
* Hopefully makes Jenkins happy
* [Rando] Child Gerudo Fortress 37th Heartpiece randomized
Fixes #1071
* Add descriptions to save editor flags editor, and added randomizer flags (#1386)
* Add descriptions to save editor flags editor, and added randomizer flags
* Hide randomizer flags when not on a randomizer save
* Move flag descriptions to header file
* Update soh/soh/Enhancements/debugger/debugSaveEditor.h
* Update soh/soh/Enhancements/debugger/debugSaveEditor.h
* Fix merge error
* crash on pause menu on linux (only in appimage)
Fixes #1437
* Applies fix to Song from Impa as well.
* Allow buying tunics as child when shopsanity is on
* Fix for custom draw methods overriding sold out sign
* Simplify logic around shopsanity and fix some issues
* Fix dungeon reward stone rotation and add particles
* Fix some issues with ice traps
* Fix adult wallet having its own max capacity
* Fix amount of keys given for BotW
* format
* Use EnGirlAShopItem enum instead of raw hex values
* [#1434] Renders non-warp songs more consistently with warp songs
* A few changes around merchant messages
* Various changes from PR feedback
* Rando: Junk Hint missing french translation
* Typo
* Fix free scrub being at 0 instead of TEXT_SCRUB_RANDOM
* Replace magic numbers in message handler
* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
* Update soh/src/overlays/actors/ovl_En_Ossan/z_en_ossan.c
Co-authored-by: briaguya <70942617+briaguya-ai@users.noreply.github.com>
* Fix BGS softlock for shopsanity
* Support tycoon wallet on tracker
* Revert "Fix BGS softlock for shopsanity"
This reverts commit 5fdb961ea4
.
* [#1053] Resolves an issue with shop items and bombchu bowling where BGS would display two message boxes
* Implements some necessary plumbing and resolves several Ice Trap Softlocks.
Adds a way for an item entry to tell what type of check it came from (NPC vs Chest vs Freestanding, etc.)
Sets this value from chests and item00 actors.
Relocates pendingIceTraps to save context so it can persist through cutscenes and get stored on save init for Link's Pocket and Song from Impa.
Restructures pendingIceTraps into a counter rather than a true or false, so that we can be frozen multiple times in a row if applicable (atm that should only be at the start of a run if Link's Pocket and Song from Impa were both Ice Traps).
Adds a textbox for Ice Traps and a special case of holding up nothing in the get item process. This fixes all the cases where Ice Traps would softlock due to the actor giving the item expecting a closing textbox. After holding the item above his head Link increments the pendingIceTraps counter by one and sets whatever flag he has pending.
None of the above plumbing applies to Ice Traps from chests, those work exactly the same as before, as do freestanding item00 ice traps (thanks to the additional check for ITEM_FROM_FREESTANDING.
OoT and Ruto's Letter count as NPC's, so they get the FOWL text box and set a pending ice trap rather than immediately freezing, since Link weill be in the water. Link will get frozen the next time he touches land, which in the case of OoT is after the fade to white and right before the Song of Time check.
Fixes all the other softlocks I'm aware of, including Fishing, Bombchu Bowling, Skull Kid, and losing the second Gerudo Archery check.
* fix bgs check in player
* move bgs logic for tokensanity into MOD_NONE check
* set bgs flag before `Item_Give`ing
* move bgs flag into `MOD_NONE` check in girla
* use existing check in `z_player`
* Adds comment explaining the decision to default ITEM_FROM_NPC.
* Rename pendingIceTraps to pendingIceTrapCount
* Adds some RANDOTODO comments about cleaning up a couple things.
* Merge branch 'develop-zhora' into ztornn
* manually restore changes to `z_player.c`
* Fix after some ice trap prepwork from earlier
* Actual fix
* Woops
* More rupee names
* Actually fix it
* Add back comment
* Fix Skip Scarecrow Song
* Fix ruto's letter and LH sun stick rendering
* Also fixes it for treasure chest game
* Tweak: Rando French Wallet
* ADD: French Tycoon
* Hide dungeon items/notes by default
* [#1301] Fix issue with UI not restoring after getting an item from biggoron
* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c
* Update soh/src/overlays/actors/ovl_En_Go2/z_en_go2.c
* Fix random crash that only affected one person for some reason
Co-authored-by: Garrett Cox <garrettjcox@gmail.com>
Co-authored-by: Christopher Leggett <chris@leggett.dev>
Co-authored-by: PurpleHato <linkvssangoku.jr@gmail.com>
Co-authored-by: Sarge-117 <adam_branston@outlook.com>
Co-authored-by: briaguya <briaguya@alice>
Co-authored-by: aMannus <mannusmenting@gmail.com>
Co-authored-by: lil David <1337lilDavid@gmail.com>
Co-authored-by: Sarge-117 <108380086+Sarge-117@users.noreply.github.com>
Co-authored-by: louist103 <35883445+louist103@users.noreply.github.com>
496 lines
38 KiB
C++
496 lines
38 KiB
C++
#include "custom_messages.hpp"
|
|
#include "debug.hpp"
|
|
#include "shops.hpp"
|
|
#include "z64item.h"
|
|
|
|
#include <array>
|
|
#include <set>
|
|
#include <sstream>
|
|
|
|
namespace CustomMessages {
|
|
|
|
using namespace std::literals::string_literals;
|
|
|
|
class MessageEntryComp {
|
|
public:
|
|
bool operator()(const MessageEntry& lhs, const MessageEntry& rhs) const {
|
|
return lhs.id < rhs.id;
|
|
}
|
|
};
|
|
|
|
constexpr std::array EnglishDungeonNames = {
|
|
"Deku Tree",
|
|
"Dodongo's Cavern",
|
|
"Jabu Jabu's Belly",
|
|
"Forest Temple",
|
|
"Fire Temple",
|
|
"Water Temple",
|
|
"Spirit Temple",
|
|
"Shadow Temple",
|
|
"Bottom of the Well",
|
|
"Ice Cavern",
|
|
"Ganon's Tower",
|
|
"Gerudo Training Grounds",
|
|
"Gerudo Fortress",
|
|
"Ganon's Castle",
|
|
};
|
|
|
|
constexpr std::array FrenchDungeonNames = {
|
|
"Vénérable Arbre Mojo",
|
|
"Caverne Dodongo",
|
|
"Ventre de Jabu-Jabu",
|
|
"Temple de la Forêt",
|
|
"Temple du Feu",
|
|
"Temple de l'Eau",
|
|
"Temple de l'Esprit",
|
|
"Temple de l'Ombre",
|
|
"Puits",
|
|
"Caverne Polaire",
|
|
"Tour de Ganon",
|
|
"Gymnase Gerudo",
|
|
"Repaire des Voleurs",
|
|
"Château de Ganon",
|
|
};
|
|
|
|
constexpr std::array FrenchDungeonArticles = {
|
|
"du ",
|
|
"de la ",
|
|
"du ",
|
|
"du ",
|
|
"du ",
|
|
"du ",
|
|
"du ",
|
|
"du ",
|
|
"du ",
|
|
"de la ",
|
|
"",
|
|
"du ",
|
|
"de la ",
|
|
"du ",
|
|
};
|
|
|
|
constexpr std::array SpanishDungeonNames = {
|
|
"Gran Árbol Deku",
|
|
"Cueva de los Dodongos",
|
|
"Tripa de Jabu-Jabu",
|
|
"Templo del Bosque",
|
|
"Templo del Fuego",
|
|
"Templo del Agua",
|
|
"Templo del Espíritu",
|
|
"Templo de las Sombras",
|
|
"Fondo del pozo",
|
|
"Caverna de hielo",
|
|
"Torre de Ganon",
|
|
"Centro de Instrucción Gerudo",
|
|
"Fortaleza Gerudo",
|
|
"Castillo de Ganon",
|
|
};
|
|
|
|
constexpr std::array SpanishDungeonArticles = {
|
|
"del",
|
|
"de la",
|
|
"de la",
|
|
"del",
|
|
"del",
|
|
"del",
|
|
"del",
|
|
"del",
|
|
"del",
|
|
"de la",
|
|
"de la",
|
|
"del",
|
|
"de la",
|
|
"del",
|
|
};
|
|
|
|
constexpr std::array DungeonColors = {
|
|
QM_GREEN,
|
|
QM_RED,
|
|
QM_BLUE,
|
|
QM_GREEN,
|
|
QM_RED,
|
|
QM_BLUE,
|
|
QM_YELLOW,
|
|
QM_PINK,
|
|
QM_PINK,
|
|
QM_LBLUE,
|
|
QM_BLACK,
|
|
QM_YELLOW,
|
|
QM_YELLOW,
|
|
QM_RED,
|
|
};
|
|
|
|
std::set<MessageEntry, MessageEntryComp> messageEntries;
|
|
std::vector<MessageEntry> arrangedMessageEntries;
|
|
std::stringstream messageData;
|
|
std::string arrangedMessageData;
|
|
|
|
//textBoxType and textBoxPosition are defined here: https://wiki.cloudmodding.com/oot/Text_Format#Message_Id
|
|
void CreateMessage(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition,
|
|
std::string englishText, std::string frenchText, std::string spanishText) {
|
|
MessageEntry newEntry = { textId, unk_04, textBoxType, textBoxPosition, { 0 } };
|
|
|
|
while ((englishText.size() % 4) != 0) {
|
|
englishText += "\0"s;
|
|
}
|
|
messageData.seekg(0, messageData.end);
|
|
newEntry.info[ENGLISH_U].offset = (char*)((int)messageData.tellg());
|
|
newEntry.info[ENGLISH_U].length = englishText.size();
|
|
messageData << englishText;
|
|
|
|
while ((frenchText.size() % 4) != 0) {
|
|
frenchText += "\0"s;
|
|
}
|
|
messageData.seekg(0, messageData.end);
|
|
newEntry.info[FRENCH_U].offset = (char*)((int)messageData.tellg());
|
|
newEntry.info[FRENCH_U].length = frenchText.size();
|
|
messageData << frenchText;
|
|
|
|
while ((spanishText.size() % 4) != 0) {
|
|
spanishText += "\0"s;
|
|
}
|
|
messageData.seekg(0, messageData.end);
|
|
newEntry.info[SPANISH_U].offset = (char*)((int)messageData.tellg());
|
|
newEntry.info[SPANISH_U].length = spanishText.size();
|
|
messageData << spanishText;
|
|
|
|
messageEntries.insert(newEntry);
|
|
}
|
|
|
|
void CreateMessageFromTextObject(uint32_t textId, uint32_t unk_04, uint32_t textBoxType, uint32_t textBoxPosition, const Text& text) {
|
|
CreateMessage(textId, unk_04, textBoxType, textBoxPosition, text.GetEnglish(), text.GetFrench(), text.GetSpanish());
|
|
}
|
|
|
|
uint32_t NumMessages() {
|
|
return messageEntries.size();
|
|
}
|
|
|
|
std::pair<const char*, uint32_t> RawMessageEntryData() {
|
|
arrangedMessageEntries.assign(messageEntries.begin(), messageEntries.end());
|
|
const char* data = (const char*)arrangedMessageEntries.data();
|
|
uint32_t size = arrangedMessageEntries.size() * sizeof(MessageEntry);
|
|
return { data, size };
|
|
}
|
|
|
|
std::pair<const char*, uint32_t> RawMessageData() {
|
|
arrangedMessageData = messageData.str();
|
|
const char* data = arrangedMessageData.data();
|
|
uint32_t size = arrangedMessageData.size();
|
|
return { data, size };
|
|
}
|
|
|
|
void CreateAlwaysIncludedMessages() {
|
|
// Bombchu (10) Purchase Prompt
|
|
CreateMessage(0x8C, 0, 2, 3,
|
|
INSTANT_TEXT_ON()+"Bombchu (10): 99 Rupees"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Buy"+NEWLINE()+"Don't buy"+COLOR(QM_WHITE)+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+"Bombchus (10): 99 rubis"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Acheter"+NEWLINE()+"Ne pas acheter"+COLOR(QM_WHITE)+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+"Bombchus (10): 99 rupias"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Comprar"+NEWLINE()+"No comprar"+COLOR(QM_WHITE)+MESSAGE_END());
|
|
//Gold Skulltula Tokens (there are two text IDs the game uses)
|
|
for (const uint32_t textId : {0xB4, 0xB5}) {
|
|
CreateMessage(textId, 0, 2, 3,
|
|
INSTANT_TEXT_ON()+"You destroyed a "+COLOR(QM_RED)+"Gold Skulltula"+COLOR(QM_WHITE)+". You got a"+NEWLINE()+"token proving you destroyed it!"+NEWLINE()+NEWLINE()+"You have "+COLOR(QM_RED)+SKULLTULAS_DESTROYED()+COLOR(QM_WHITE)+" tokens!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+"Vous venez de détruire une "+COLOR(QM_RED)+"Skulltula d'or"+COLOR(QM_WHITE)+"!"+NEWLINE()+"Ce symbole prouve votre prouesse!"+NEWLINE()+NEWLINE()+"Vous avez "+COLOR(QM_RED)+SKULLTULAS_DESTROYED()+COLOR(QM_WHITE)+" jetons!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+"¡Has eliminado una "+COLOR(QM_RED)+"skulltula dorada"+COLOR(QM_WHITE)+" y has"+NEWLINE()+"conseguido un símbolo para probarlo!"+NEWLINE()+NEWLINE()+"¡Tienes "+COLOR(QM_RED)+SKULLTULAS_DESTROYED()+COLOR(QM_WHITE)+" símbolos!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
|
|
//Bombchu (10) Description
|
|
CreateMessage(0xBC, 0, 2, 3,
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+"Bombchu (10): 99 Rupees"+NEWLINE()+COLOR(QM_WHITE)+"These look like toy mice, but they're"+NEWLINE()+"actually self-propelled time bombs!"+INSTANT_TEXT_OFF()+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+"Bombchus (10): 99 rubis"+NEWLINE()+COLOR(QM_WHITE)+"Profilée comme une souris mécanique, il"+NEWLINE()+"s'agit en fait d'une bombe à retardement"+NEWLINE()+"autopropulsée!"+INSTANT_TEXT_OFF()+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+"Bombchus (10): 99 rupias"+NEWLINE()+COLOR(QM_WHITE)+"Aunque parezcan ratoncitos de juguete,"+NEWLINE()+"¡son bombas de relojería autopropulsadas!"+INSTANT_TEXT_OFF()+SHOP_MESSAGE_BOX()+MESSAGE_END());
|
|
//Boss Keys
|
|
for (uint32_t bossKey = 0; bossKey <= (DUNGEON_SHADOW_TEMPLE - DUNGEON_FOREST_TEMPLE); bossKey++) {
|
|
uint32_t dungeon = DUNGEON_FOREST_TEMPLE + bossKey;
|
|
CreateMessage(0x9D4 + bossKey, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"You got the "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Boss Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"Vous trouvez la "+COLOR(DungeonColors[dungeon])+"Clé d'Or "+NEWLINE()+FrenchDungeonArticles[dungeon]+" "+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"¡Tienes la "+COLOR(DungeonColors[dungeon])+"gran llave "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
CreateMessage(0x9D9, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"You got the "+COLOR(DungeonColors[DUNGEON_GANONS_CASTLE_FIRST_PART])+EnglishDungeonNames[DUNGEON_GANONS_CASTLE_FIRST_PART]+NEWLINE()+"Boss Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"Vous trouvez la "+COLOR(DungeonColors[DUNGEON_GANONS_CASTLE_FIRST_PART])+"Clé d'Or "+NEWLINE()+FrenchDungeonArticles[DUNGEON_GANONS_CASTLE_FIRST_PART]+" "+FrenchDungeonNames[DUNGEON_GANONS_CASTLE_FIRST_PART]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_BOSS)+INSTANT_TEXT_ON()+"¡Tienes la "+COLOR(DungeonColors[DUNGEON_GANONS_CASTLE_FIRST_PART])+"gran llave "+SpanishDungeonArticles[DUNGEON_GANONS_CASTLE_FIRST_PART]+NEWLINE()+SpanishDungeonNames[DUNGEON_GANONS_CASTLE_FIRST_PART]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
//Compasses
|
|
for (uint32_t dungeon = DUNGEON_DEKU_TREE; dungeon <= DUNGEON_ICE_CAVERN; dungeon++) {
|
|
CreateMessage(0x9DA + dungeon, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_COMPASS)+INSTANT_TEXT_ON()+"You got the "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Compass"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_COMPASS)+INSTANT_TEXT_ON()+"Vous trouvez la "+COLOR(DungeonColors[dungeon])+"boussole "+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_COMPASS)+INSTANT_TEXT_ON()+"¡Tienes la "+COLOR(DungeonColors[dungeon])+"brújula "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
//Maps
|
|
for (uint32_t dungeon = DUNGEON_DEKU_TREE; dungeon <= DUNGEON_ICE_CAVERN; dungeon++) {
|
|
CreateMessage(0x9E4 + dungeon, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_DUNGEON_MAP)+INSTANT_TEXT_ON()+"You got the "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Map"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_DUNGEON_MAP)+INSTANT_TEXT_ON()+"Vous trouvez la "+COLOR(DungeonColors[dungeon])+"carte "+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_DUNGEON_MAP)+INSTANT_TEXT_ON()+"¡Has obtenido el "+COLOR(DungeonColors[dungeon])+"mapa "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
//Small Keys
|
|
for (uint32_t smallKey = 0; smallKey <= (DUNGEON_BOTTOM_OF_THE_WELL - DUNGEON_FOREST_TEMPLE); smallKey++) {
|
|
uint32_t dungeon = DUNGEON_FOREST_TEMPLE + smallKey;
|
|
CreateMessage(0x9EE + smallKey, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Small Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez une "+COLOR(DungeonColors[dungeon])+"Petite Clé"+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido una "+COLOR(DungeonColors[dungeon])+"llave pequeña "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
for (uint32_t smallKey = 0; smallKey <= (DUNGEON_GANONS_CASTLE_FIRST_PART - DUNGEON_GERUDO_TRAINING_GROUNDS); smallKey++) {
|
|
uint32_t dungeon = DUNGEON_GERUDO_TRAINING_GROUNDS + smallKey;
|
|
CreateMessage(0x9F4 + smallKey, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Small Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez une "+COLOR(DungeonColors[dungeon])+"Petite Clé"+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido una "+COLOR(DungeonColors[dungeon])+"llave pequeña "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
//Key Rings
|
|
for (uint32_t smallKey = 0; smallKey <= (DUNGEON_BOTTOM_OF_THE_WELL - DUNGEON_FOREST_TEMPLE); smallKey++) {
|
|
uint32_t dungeon = DUNGEON_FOREST_TEMPLE + smallKey;
|
|
CreateMessage(0x9300 + smallKey, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Key Ring"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez un "+COLOR(DungeonColors[dungeon])+"trousseau"+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido un "+COLOR(DungeonColors[dungeon])+"llavero "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
for (uint32_t smallKey = 0; smallKey <= (DUNGEON_GANONS_CASTLE_FIRST_PART - DUNGEON_GERUDO_TRAINING_GROUNDS); smallKey++) {
|
|
uint32_t dungeon = DUNGEON_GERUDO_TRAINING_GROUNDS + smallKey;
|
|
CreateMessage(0x9306 + smallKey, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(DungeonColors[dungeon])+EnglishDungeonNames[dungeon]+NEWLINE()+"Key Ring"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez un "+COLOR(DungeonColors[dungeon])+"trousseau"+NEWLINE()+FrenchDungeonArticles[dungeon]+FrenchDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido un "+COLOR(DungeonColors[dungeon])+"llavero "+SpanishDungeonArticles[dungeon]+NEWLINE()+SpanishDungeonNames[dungeon]+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
//Tycoon's Wallet
|
|
CreateMessage(0x09F7, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_WALLET_GIANT)+INSTANT_TEXT_ON()+"You got a "+COLOR(QM_RED)+"Tycoon's Wallet"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+NEWLINE()+"It's gigantic! Now you can carry"+NEWLINE()+"up to "+COLOR(QM_YELLOW)+"999 "+COLOR(QM_WHITE)+COLOR(QM_YELLOW)+"Rupees"+COLOR(QM_WHITE)+"!"+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_WALLET_GIANT)+INSTANT_TEXT_ON()+"Vous obtenez la "+COLOR(QM_RED)+"Bourse de Magnat"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+NEWLINE()+"Elle peut contenir jusqu'à "+COLOR(QM_YELLOW)+"999 "+COLOR(QM_WHITE)+COLOR(QM_YELLOW)+"rubis"+COLOR(QM_WHITE)+"!"+NEWLINE()+"C'est gigantesque!"+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_WALLET_GIANT)+INSTANT_TEXT_ON()+"¡Has conseguido una "+COLOR(QM_RED)+"bolsa para ricachones"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+NEWLINE()+"¡Qué descomunal! Ya puedes llevar"+NEWLINE()+"hasta "+COLOR(QM_YELLOW)+"999 "+COLOR(QM_WHITE)+COLOR(QM_YELLOW)+"rupias"+COLOR(QM_WHITE)+"!"+MESSAGE_END());
|
|
//Saria's Song Default Hint
|
|
CreateMessage(0x0A00, 0, 2, 3,
|
|
UNSKIPPABLE()+"Have you tried talking to the gossip"+NEWLINE()+ "stones around Hyrule? They might have"+NEWLINE()+"some good advice... Hee hee!"+WAIT_FOR_INPUT()+"If you learn something from the gossip stones,"+NEWLINE()+"I will remember it!"+EVENT_TRIGGER()+MESSAGE_END(),
|
|
UNSKIPPABLE()+"As-tu parlé aux pierres à potins"+NEWLINE()+ "dans Hyrule? Elles sont de bons conseils..."+NEWLINE()+"Hi hi!"+WAIT_FOR_INPUT()+"Si elles te révèlent quelque chose,"+NEWLINE()+"je m'en souviendrai!"+EVENT_TRIGGER()+MESSAGE_END(),
|
|
UNSKIPPABLE()+"¿Has probado a consultarle a las"+NEWLINE()+ "piedras chismosas esparcidas por Hyrule? Puede"+NEWLINE()+"que sean de ayuda a tu empresa... ¡Ji, ji!"+WAIT_FOR_INPUT()+"¡Puedo recordarte todo lo que aprendas de ellas,"+NEWLINE()+"si así lo deseas!"+EVENT_TRIGGER()+MESSAGE_END());
|
|
//Poe Collector (when enough has been sold)
|
|
CreateMessage(0x70F8, 0, 0, 0,
|
|
UNSKIPPABLE()+"Wait a minute! WOW!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"You have earned enough points!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Young man, you are a genuine "+COLOR(QM_RED)+"ghost hunter"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Is that what you expected me to say?"+NEWLINE()+"Heh heh heh!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Because of you, I have extra inventory of"+NEWLINE()+COLOR(QM_RED)+"Big Poes"+COLOR(QM_WHITE)+", so this will be the last time I can"+NEWLINE()
|
|
+"buy one of these ghosts."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"You're thinking about what I promised would"+NEWLINE()+"happen when you earned enough points."+NEWLINE()+"Heh heh."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Don't worry. I didn't forget. Just take this."+MESSAGE_END(),
|
|
UNSKIPPABLE()+"Ooooh! WHOA!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Tu as obtenu suffisamment de points!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Tu es un véritable "+COLOR(QM_RED)+"chasseur de fantômes"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Il est content, hein?"+NEWLINE()+"Il est content le monsieur?"+NEWLINE()+"Hé hé hé!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Grâce à toi, mon stock d'"+COLOR(QM_RED)+"Âmes"+COLOR(QM_WHITE)+" est plein!"+NEWLINE()+"C'est donc la dernière fois que nous"+NEWLINE()+"faisons affaire."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Je sais, je sais..."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Nous avions passé un pacte..."+NEWLINE()+"Tu as eu tes points et je t'en félicite..."+NEWLINE()+"Hé hé hé!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Alors prends donc ceci, mon bon ami!"+MESSAGE_END(),
|
|
UNSKIPPABLE()+"¡Un momento! ¡OYE!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Has conseguido los puntos suficientes!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Jovencito, eres un auténtico "+COLOR(QM_RED)+"cazador de"+NEWLINE()+"fantasmas"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"¿Era eso lo que esperabas que dijera?"+NEWLINE()+"¡Je, je je!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Gracias a ti, ya tengo la cantidad necesaria"+NEWLINE()+"de "+COLOR(QM_RED)+"grandes poes"+COLOR(QM_WHITE)+", así que esta será la"+NEWLINE()
|
|
+"última vez que te compre unos de ese tipo."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¿Recuerdas lo que te dije que ocurriría"+NEWLINE()+"cuando tuvieses suficientes puntos?"+NEWLINE()+"Je, je, je."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Tranquilo, que no se me ha olvidado."+NEWLINE()+"Toma esto."+MESSAGE_END());
|
|
//Ice Trap
|
|
CreateMessage(0x9002, 0, 2, 3,
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+COLOR(QM_RED)+"FOOL!"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+COLOR(QM_RED)+"IDIOT!"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+COLOR(QM_RED)+"¡TONTO!"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
//Business Scrubs
|
|
//The less significant byte represents the price of the item
|
|
for (uint32_t price = 0; price <= 95; price += 5) {
|
|
CreateMessage(0x9000 + price, 0, 0, 0,
|
|
INSTANT_TEXT_ON()+"I'll sell you something good for "+COLOR(QM_RED)+std::to_string(price)+" Rupees"+COLOR(QM_WHITE)+"!"+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"OK"+NEWLINE()+"No way"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+"Je te vends un truc super pour "+COLOR(QM_RED)+std::to_string(price)+" Rubis"+COLOR(QM_WHITE)+"!"+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"D'accord"+NEWLINE()+"Hors de question"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+"¡Te puedo vender algo bueno por "+COLOR(QM_RED)+std::to_string(price)+" rupias"+COLOR(QM_WHITE)+"!"+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Vale"+NEWLINE()+"Ni hablar"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
//Poe Collector
|
|
//The last digit represent the number of poes needed to collect
|
|
for (uint32_t poes = 1; poes <= 10; poes++) {
|
|
CreateMessage(0x9080 + poes, 0, 0, 0,
|
|
UNSKIPPABLE()+"Oh, you brought a Poe today!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Hmmmm!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Very interesting! This is a "+COLOR(QM_RED)+"Big Poe"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"I'll buy it for "+COLOR(QM_RED)+"50 Rupees"+COLOR(QM_WHITE)+"."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"On top of that, I'll put "+COLOR(QM_RED)+"100 points "+COLOR(QM_WHITE)+"on"+NEWLINE()+"your card."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"If you earn "+COLOR(QM_RED)+std::to_string(poes * 100)+" points"+COLOR(QM_WHITE)+", you'll be a"+NEWLINE()+"happy man! Heh heh."+MESSAGE_END(),
|
|
|
|
UNSKIPPABLE()+"Oh! Tu as apporté un fantôme!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Hmmmm!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Magnifique!"+NEWLINE()+"C'est une "+COLOR(QM_RED)+"Âme"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Je t'en donne "+COLOR(QM_RED)+"50 Rubis"+COLOR(QM_WHITE)+"."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Et en plus, j'inscris "+COLOR(QM_RED)+"100 points "+COLOR(QM_WHITE)+NEWLINE()+"sur ta carte."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Obtiens "+COLOR(QM_RED)+std::to_string(poes * 100)+" points"+COLOR(QM_WHITE)+" et tu ne"+NEWLINE()+"seras pas déçu..."+NEWLINE()+"Hé hé hé."+MESSAGE_END(),
|
|
|
|
UNSKIPPABLE()+"¡Vaya! ¡Traes un poe!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Mmm! ¿A ver?"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Qué interesante! ¡Es un "+COLOR(QM_RED)+"gran poe"+COLOR(QM_WHITE)+"!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"Te daré "+COLOR(QM_RED)+"50 rupias "+COLOR(QM_WHITE)+"por él."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Y además agregaré "+COLOR(QM_RED)+"100 puntos "+COLOR(QM_WHITE)+"a tu"+NEWLINE()+"tarjeta."+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()
|
|
+"¡Si llegas a "+COLOR(QM_RED)+std::to_string(poes * 100)+" puntos"+COLOR(QM_WHITE)+", serás muy feliz!"+NEWLINE()+"Je, je, je..."+MESSAGE_END());
|
|
}
|
|
|
|
//Talon (this is to prevent accidentally skipping Malon in HC)
|
|
CreateMessage(0x9100, 0, 2, 0,
|
|
UNSKIPPABLE()+"You should go talk to my daughter Malon,"+NEWLINE()+"she has an item for you."+NEWLINE()+SET_SPEED(3)+"........."+SET_SPEED(0)+WAIT_FOR_INPUT()+"I have to think about some stuff now,"+NEWLINE()+"please don't distract me."+MESSAGE_END(),
|
|
UNSKIPPABLE()+"Zzzz... Muh... Malon..."+NEWLINE()+"Parler avec... Malon..."+NEWLINE()+SET_SPEED(3)+"........."+SET_SPEED(0)+WAIT_FOR_INPUT()+"Si fatigué..."+NEWLINE()+"Quelle vie..."+MESSAGE_END(),
|
|
UNSKIPPABLE()+"Habla con Malon, tiene algo que darte..."+SET_SPEED(3)+"........."+SET_SPEED(0)+MESSAGE_END());
|
|
|
|
//Bow Shooting Gallery reminder
|
|
CreateMessage(0x9140, 0, 0, 0,
|
|
UNSKIPPABLE()+"Wonderful! Bravo! Perfect!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Here's a fantastic present! But I have"+COLOR(QM_RED)+NEWLINE()+"something else "+COLOR(QM_WHITE)+"for you once you have a bow."+SET_SPEED(30)+" "+EVENT_TRIGGER()+MESSAGE_END(),
|
|
UNSKIPPABLE()+"Merveilleux! Bravo! C'est parfait!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"Voici un prix fantastique! J'aurai "+COLOR(QM_RED)+"autre chose"+COLOR(QM_WHITE)+NEWLINE()+"pour toi quand tu auras un arc."+SET_SPEED(30)+" "+EVENT_TRIGGER()+MESSAGE_END(),
|
|
UNSKIPPABLE()+"¡Espectacular! ¡Bravo! ¡Perfecto!"+WAIT_FOR_INPUT()+NEWLINE()+UNSKIPPABLE()+"¡Toma este sensacional regalo! Pero te tengo"+NEWLINE()+"guardado "+COLOR(QM_RED)+"algo más "+COLOR(QM_WHITE)+"para cuando traigas tu"+NEWLINE()+"propio arco."+SET_SPEED(30)+" "+EVENT_TRIGGER()+MESSAGE_END());
|
|
|
|
//Shopsanity items
|
|
//64 textboxes, 2 for each of 32 potential shopsanity items
|
|
for(uint32_t shopitems = 0; shopitems < NonShopItems.size(); shopitems++) {
|
|
Text name = NonShopItems[shopitems].Name;
|
|
std::string price = std::to_string(NonShopItems[shopitems].Price);
|
|
//Prevent names from being too long and overflowing textbox
|
|
if (name.GetEnglish() == "Piece of Heart (Treasure Chest Minigame)") {
|
|
name = Text{"Piece of Heart", "Quart de Coeur", "Pieza de corazón"};
|
|
} else if (name.GetEnglish() == "Green Rupee (Treasure Chest Minigame)") {
|
|
name = Text{"Green Rupee", "Rubis Vert", "Rupia verde"};
|
|
}
|
|
//Message to display when hovering over the item
|
|
if (NonShopItems[shopitems].Repurchaseable) { //Different checkbox for repurchaseable items
|
|
CreateMessage(0x9200+shopitems*2, 0, 0, 0,
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetEnglish()+": "+price+" Rupees"+NEWLINE()+COLOR(QM_WHITE)+"Special deal!"+NEWLINE()+"Buy as many as you want!"+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetFrench()+": "+price+" rubis"+NEWLINE()+COLOR(QM_WHITE)+"Offre spéciale!"+NEWLINE()+"Achetez-en à volonté!"+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetSpanish()+": "+price+" rupias"+NEWLINE()+COLOR(QM_WHITE)+"¡Oferta especial!"+NEWLINE()+"¡Compra todo lo que quieras!"+SHOP_MESSAGE_BOX()+MESSAGE_END());
|
|
}
|
|
else { //Normal textbox
|
|
CreateMessage(0x9200+shopitems*2, 0, 0, 0,
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetEnglish()+": "+price+" Rupees"+NEWLINE()+COLOR(QM_WHITE)+"Special deal! ONE LEFT!"+NEWLINE()+"Get it while it lasts!"+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetFrench()+": "+price+" rubis"+NEWLINE()+COLOR(QM_WHITE)+"Offre spéciale! DERNIER EN STOCK!"+NEWLINE()+"Faites vite!"+SHOP_MESSAGE_BOX()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+COLOR(QM_RED)+name.GetSpanish()+": "+price+" rupias"+NEWLINE()+COLOR(QM_WHITE)+"¡Oferta especial! ¡SOLO QUEDA UNA UNIDAD!"+NEWLINE()+"¡Hazte con ella antes de que se agote!"+SHOP_MESSAGE_BOX()+MESSAGE_END());
|
|
}
|
|
//Message to display when going to buy the item
|
|
CreateMessage(0x9200+shopitems*2+1, 0, 0, 0,
|
|
INSTANT_TEXT_ON()+name.GetEnglish()+": "+price+" Rupees"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Buy"+NEWLINE()+"Don't buy"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+name.GetFrench()+": "+price+" rubis"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Acheter"+NEWLINE()+"Ne pas acheter"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
INSTANT_TEXT_ON()+name.GetSpanish()+": "+price+" rupias"+INSTANT_TEXT_OFF()+NEWLINE()+NEWLINE()+TWO_WAY_CHOICE()+COLOR(QM_GREEN)+"Comprar"+NEWLINE()+"No comprar"+COLOR(QM_WHITE)+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
//easter egg
|
|
CreateMessage(0x96F, 0, 2, 2,
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Oh hey, you watched all the credits!"+NEWLINE()+CENTER_TEXT()+"Here's a prize for your patience."+NEWLINE()+CENTER_TEXT()+"Unlocking MQ and saving..."+NEWLINE()+NEWLINE()+CENTER_TEXT()+COLOR(QM_RED)+"Do not remove the Game Card"+NEWLINE()+CENTER_TEXT()+"or turn the power off."+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"The Legend of Zelda Ocarina of Time 3D"+NEWLINE()+CENTER_TEXT()+"Master Quest va être déverrouillé."+NEWLINE()+CENTER_TEXT()+"Sauvegarde... Veuillez patienter."+NEWLINE()+NEWLINE()+CENTER_TEXT()+COLOR(QM_RED)+"N'éteignez pas la console et"+NEWLINE()+CENTER_TEXT()+"ne retirez pas la carte de jeu"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Desbloqueando The Legend of Zelda"+NEWLINE()+CENTER_TEXT()+"Ocarina of Time 3D Master Quest."+NEWLINE()+CENTER_TEXT()+"Guardando. Espera un momento..."+NEWLINE()+NEWLINE()+CENTER_TEXT()+COLOR(QM_RED)+"No saques la tarjeta de juego"+NEWLINE()+CENTER_TEXT()+"ni apagues la consola."+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
CreateMessage(0x970, 0, 2, 3,
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Master Quest doesn't affect the Randomizer,"+NEWLINE()+CENTER_TEXT()+"so you can use 3 more save slots now."+NEWLINE()+NEWLINE()+CENTER_TEXT()+"Thanks for playing!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Vous pouvez désormais jouer à"+NEWLINE()+CENTER_TEXT()+"The Legend of Zelda Ocarina of Time 3D"+NEWLINE()+CENTER_TEXT()+"Master Quest!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"¡Ya puedes jugar The Legend of Zelda"+NEWLINE()+CENTER_TEXT()+"Ocarina of Time 3D Master Quest!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
|
|
//Messages for the new Lake Hylia switch
|
|
CreateMessage(0x346, 0, 1, 3,
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Water level control system."+NEWLINE()+CENTER_TEXT()+"Keep away!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Contrôle du niveau d'eau."+NEWLINE()+CENTER_TEXT()+"Ne pas toucher!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+INSTANT_TEXT_ON()+CENTER_TEXT()+"Control del nivel del agua."+NEWLINE()+CENTER_TEXT()+"¡No te acerques!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
CreateMessage(0x1B3, 0, 0, 3,
|
|
UNSKIPPABLE()+"This switch is rustier than you think."+WAIT_FOR_INPUT()+"Something must be wrong with the pipe"+NEWLINE()+"system in the Water Temple."+MESSAGE_END(),
|
|
UNSKIPPABLE()+"Cet interrupteur est très rouillé."+WAIT_FOR_INPUT()+"Quelque chose ne va pas avec"+NEWLINE()+"la tuyauterie du Temple de l'Eau."+MESSAGE_END(),
|
|
UNSKIPPABLE()+"El interruptor está más oxidado de lo que"+NEWLINE()+"aparenta."+WAIT_FOR_INPUT()+"Algo debe andar mal en el sistema de"+NEWLINE()+"cañerías del Templo del Agua."+MESSAGE_END());
|
|
|
|
//Treasure chest shop keys. If they're not randomized leave the base game text
|
|
if (Settings::ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_SINGLE_KEYS)) {
|
|
CreateMessage(0x0F3, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got a "+COLOR(QM_RED)+"Treasure Chest Shop"+NEWLINE()+"Small Key"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez une "+COLOR(QM_RED)+"Petite Clé"+NEWLINE()+"de la Chasse-aux-Trésors"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido una "+COLOR(QM_RED)+"llave pequeña del"+NEWLINE()+"Cofre del Tesoro"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
} else if (Settings::ShuffleChestMinigame.Is(SHUFFLECHESTMINIGAME_PACK)) {
|
|
CreateMessage(0x0F3, 0, 2, 3,
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"You got all 6 "+COLOR(QM_RED)+"Treasure Chest Shop"+NEWLINE()+"Small Keys"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"Vous trouvez les "+COLOR(QM_RED)+"petites clés"+NEWLINE()+"de la Chasse-aux-Trésors"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END(),
|
|
UNSKIPPABLE()+ITEM_OBTAINED(ITEM_KEY_SMALL)+INSTANT_TEXT_ON()+"¡Has obtenido todas las 6 "+COLOR(QM_RED)+"llaves"+NEWLINE()+"pequeñas del Cofre del Tesoro"+COLOR(QM_WHITE)+"!"+INSTANT_TEXT_OFF()+MESSAGE_END());
|
|
}
|
|
}
|
|
|
|
Text AddColorsAndFormat(Text text, const std::vector<uint8_t>& colors /*= {}*/) {
|
|
|
|
//for each language
|
|
for (std::string* textStr : {&text.english, &text.french, &text.spanish}) {
|
|
|
|
//insert playername
|
|
size_t atSymbol = textStr->find('@');
|
|
while (atSymbol != std::string::npos) {
|
|
textStr->replace(atSymbol, 1, PLAYER_NAME());
|
|
atSymbol = textStr->find('@');
|
|
}
|
|
//insert newlines either manually or when encountering a '&'
|
|
constexpr size_t lineLength = 44;
|
|
size_t lastNewline = 0;
|
|
while (lastNewline + lineLength < textStr->length()) {
|
|
size_t carrot = textStr->find('^', lastNewline);
|
|
size_t ampersand = textStr->find('&', lastNewline);
|
|
size_t lastSpace = textStr->rfind(' ', lastNewline + lineLength);
|
|
size_t lastPeriod = textStr->rfind('.', lastNewline + lineLength);
|
|
//replace '&' first if it's within the newline range
|
|
if (ampersand < lastNewline + lineLength) {
|
|
textStr->replace(ampersand, 1, NEWLINE());
|
|
lastNewline = ampersand + NEWLINE().length();
|
|
//or move the lastNewline cursor to the next line if a '^' is encountered
|
|
} else if (carrot < lastNewline + lineLength) {
|
|
lastNewline = carrot + 1;
|
|
//some lines need to be split but don't have spaces, look for periods instead
|
|
} else if (lastSpace == std::string::npos) {
|
|
textStr->replace(lastPeriod, 1, "."+NEWLINE());
|
|
lastNewline = lastPeriod + NEWLINE().length() + 1;
|
|
} else {
|
|
textStr->replace(lastSpace, 1, NEWLINE());
|
|
lastNewline = lastSpace + NEWLINE().length();
|
|
}
|
|
}
|
|
//clean up any remaining '&' characters
|
|
size_t ampersand = textStr->find('&');
|
|
while (ampersand != std::string::npos) {
|
|
textStr->replace(ampersand, 1, NEWLINE());
|
|
ampersand = textStr->find('&');
|
|
}
|
|
|
|
//insert box break
|
|
size_t carrotSymbol = textStr->find('^');
|
|
while (carrotSymbol != std::string::npos) {
|
|
textStr->replace(carrotSymbol, 1, INSTANT_TEXT_OFF()+WAIT_FOR_INPUT()+INSTANT_TEXT_ON());
|
|
carrotSymbol = textStr->find('^');
|
|
}
|
|
//add colors
|
|
for (auto color : colors) {
|
|
size_t firstHashtag = textStr->find('#');
|
|
if (firstHashtag != std::string::npos) {
|
|
textStr->replace(firstHashtag, 1, COLOR(color));
|
|
size_t secondHashtag = textStr->find('#');
|
|
if (secondHashtag == std::string::npos) {
|
|
CitraPrint("ERROR: Couldn't find second '#' in " + (*textStr));
|
|
} else {
|
|
textStr->replace(secondHashtag, 1, COLOR(QM_WHITE));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return Text{"","",""}+UNSKIPPABLE()+INSTANT_TEXT_ON()+text+INSTANT_TEXT_OFF()+MESSAGE_END();
|
|
}
|
|
|
|
void ClearMessages() {
|
|
messageEntries.clear();
|
|
arrangedMessageEntries.clear();
|
|
messageData.str("");
|
|
arrangedMessageData = "";
|
|
}
|
|
|
|
std::string MESSAGE_END() { return "\x7F\x00"s; }
|
|
std::string WAIT_FOR_INPUT() { return "\x7F\x01"s; }
|
|
std::string HORIZONTAL_SPACE(uint8_t x) {
|
|
return "\x7F\x02"s + char(x);
|
|
}
|
|
std::string GO_TO(uint16_t x) {
|
|
return "\x7F\x03"s + char(x >> 8) + char(x & 0x00FF);
|
|
}
|
|
std::string INSTANT_TEXT_ON() { return "\x7F\x04"s; }
|
|
std::string INSTANT_TEXT_OFF() { return "\x7F\x05"s; }
|
|
std::string SHOP_MESSAGE_BOX() { return "\x7F\x06\x00"s; }
|
|
std::string EVENT_TRIGGER() { return "\x7F\x07"s; }
|
|
std::string DELAY_FRAMES(uint8_t x) {
|
|
return "\x7F\x08"s + char(x);
|
|
}
|
|
std::string CLOSE_AFTER(uint8_t x) {
|
|
return "\x7F\x0A"s + char(x);
|
|
}
|
|
std::string PLAYER_NAME() { return "\x7F\x0B"s; }
|
|
std::string PLAY_OCARINA() { return "\x7F\x0C"s; }
|
|
std::string ITEM_OBTAINED(uint8_t x) {
|
|
return "\x7F\x0F"s + char(x);
|
|
}
|
|
std::string SET_SPEED(uint8_t x) {
|
|
return "\x7F\x10"s + char(x);
|
|
}
|
|
std::string SKULLTULAS_DESTROYED() { return "\x7F\x15"s; }
|
|
std::string CURRENT_TIME() { return "\x7F\x17"s; }
|
|
std::string UNSKIPPABLE() { return "\x7F\x19"s; }
|
|
std::string TWO_WAY_CHOICE() { return "\x7F\x1A\xFF\xFF\xFF\xFF"s; }
|
|
std::string NEWLINE() { return "\x7F\x1C"s; }
|
|
std::string COLOR(uint8_t x) { return "\x7F\x1D"s + char(x); }
|
|
std::string CENTER_TEXT() { return "\x7F\x1E"s; }
|
|
std::string IF_NOT_MQ() { return "\x7F\x29"s; }
|
|
std::string MQ_ELSE() { return "\x7F\x2A"s; }
|
|
std::string MQ_END() { return "\x7F\x2B"s; }
|
|
}
|