Refactor Hint Creation and add support for hint Copies and fixed number of hints. (#3205)

* Initial implementation of no-duplicates of special hints

* stupid fixes

* Impa's song will no longer be hinted when you skip child zelda

* fix building

* Fix Loading spoiler logs causing corrupt hints, remove disabled warp song shuffle text from spoiler logs

* Remove Sheik and Saria hints from the spoiler log when are not enabled

* Prevent Magic hinted by Saria and Light Arrows hinted by Sheik from being hinted elsewhere unless they are locked by that item.

* Prevent the Final Frogs gossip stone hint from spawning when the special final frogs hint is enabled.

* Fix building after rebasing in deduplication

* redelete keys.hpp

* Remove Sheik and Saria hints from the spoiler log when are not enabled

* Prevent the Final Frogs gossip stone hint from spawning when the special final frogs hint is enabled.

* First part of copies implementation

* Refactor hint system (broken)

* fix building

* fix obvious errors

* fix fixed hints doubling after failing to place a hint

* Fix bugs with hint distrabution

* Split PlaceRandomHint and fix hint bugs

* Merge special hint functions, move special hint text to the HintTable, expand LightArrow hint category into OtherHint category.

* Fix remaining hint distribution errors

* Forgot to stage dampe diary update

* Restore building after conflict resolution

* fix SetAllInRegionAsHinted
This commit is contained in:
Pepper0ni 2023-11-02 16:42:33 +00:00 committed by GitHub
parent 15ebcd30fb
commit 051314e8b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 480 additions and 543 deletions

View File

@ -1098,20 +1098,13 @@ int Fill() {
printf("Done");
ctx->CreateItemOverrides();
CreateEntranceOverrides();
//Always execute ganon hint generation for the funny line
CreateGanonAndSheikText();
CreateAltarText();
CreateDampesDiaryText();
CreateGregRupeeHint();
CreateSariaText();
if (GossipStoneHints.IsNot(HINTS_NO_HINTS)) {
printf("\x1b[10;10HCreating Hints...");
CreateAllHints();
printf("Done");
}
if (ShuffleMerchants.Is(SHUFFLEMERCHANTS_HINTS)) {
CreateMerchantsHints();
}
//funny ganon line
Text ganonText = RandomElement(GetHintCategory(HintCategory::GanonLine)).GetText();
CreateMessageFromTextObject(0x70CB, 0, 2, 3, AddColorsAndFormat(ganonText));
SetGanonText(ganonText);
CreateAllHints();
CreateWarpSongTexts();
return 1;
}

View File

@ -21,7 +21,9 @@ void ClearProgress();
void VanillaFill();
int Fill();
std::vector<RandomizerCheck> GetEmptyLocations(std::vector<RandomizerCheck> allowedLocations);
std::vector<RandomizerCheck> GetAccessibleLocations(const std::vector<RandomizerCheck>& allowedLocations,
SearchMode mode = SearchMode::ReachabilitySearch, std::string ignore = "",
bool checkPoeCollectorAccess = false,
bool checkOtherEntranceAccess = false);
bool checkOtherEntranceAccess = false);

View File

@ -472,7 +472,7 @@ void HintTable_Init() {
Text{ "a #cow behind webs# in a grotto gifts", /*french*/ "la #vache derrière les toiles# d'une grotte donne",
/*spanish*/ "una #vaca tras la telaraña# de una cueva brinda" });
hintTable[RHT_ZR_FROGS_OCARINA_GAME] = HintText::Always(
hintTable[RHT_ZR_FROGS_OCARINA_GAME] = HintText::Sometimes(
{
// obscure text
Text{ "an #amphibian feast# yields", /*french*/ "un #festin d'amphibiens# donne",
@ -2949,7 +2949,7 @@ void HintTable_Init() {
| LIGHT ARROW LOCATION TEXT|
---------------------------*/
hintTable[RHT_LIGHT_ARROW_LOCATION_HINT] = HintText::LightArrow({
hintTable[RHT_LIGHT_ARROW_LOCATION_HINT] = HintText::OtherHint({
// obscure text
Text{
"Ha ha ha... You'll never beat me by reflecting my lightning bolts and unleashing the arrows from ",
@ -2959,7 +2959,7 @@ void HintTable_Init() {
"Ja, ja, ja... Nunca me derrotarás reflejando mis esferas de energía y desplegando la flecha de luz de " },
});
hintTable[RHT_SHEIK_LIGHT_ARROW_HINT] = HintText::LightArrow({
hintTable[RHT_SHEIK_LIGHT_ARROW_HINT] = HintText::OtherHint({
// obscure text
Text{
"I overheard Ganondorf say that he misplaced the %yLight Arrows%w in&%r",
@ -2974,6 +2974,70 @@ void HintTable_Init() {
Text{ "your pocket", /*french*/ "tes poches", /*spanish*/ "tu bolsillo" },
});
/*--------------------------
| OTHER HINT TEXT |
---------------------------*/
hintTable[RHT_DAMPE_DIARY01] = HintText::OtherHint({
// obscure text
Text{
"Whoever reads this, please enter %r",
/*french*/
"Toi qui lit ce journal, rends-toi dans %r",
/*german?*/
"Wer immer dies liest, der möge folgenden Ort aufsuchen: %r"},
});
hintTable[RHT_DAMPE_DIARY02] = HintText::OtherHint({
// obscure text
Text{
"%w. I will let you have my stretching, shrinking keepsake.^I'm waiting for you.&--Dampé",
/*french*/
"%w. Et peut-être auras-tu droit à mon précieux %rtrésor%w.^Je t'attends...&--Igor",
/*german?*/
"%w. Ihm gebe ich meinen langen, kurzen Schatz.^Ich warte!&Boris"},
});
hintTable[RHT_GREG_HINT01] = HintText::OtherHint({
// obscure text
Text{
"By the way, if you're interested, I saw the shiniest %gGreen Rupee%w somewhere in%g ",
/*french*/
"Au fait, si ça t'intéresse, j'ai aperçu le plus éclatant des %gRubis Verts%w quelque part à %g",
/*spanish*/
""},
});
hintTable[RHT_GREG_HINT02] = HintText::OtherHint({
// obscure text
Text{
"%w.^It's said to have %rmysterious powers%w...^But then, it could just be another regular rupee.&Oh well.",
/*french*/
"%w. On dit qu'il possède des pouvoirs mystérieux... Mais bon, ça pourrait juste être un autre rubis ordinaire.",
/*spanish*/
""},
});
hintTable[RHT_SARIA_TEXT01] = HintText::OtherHint({
// obscure text
Text{
"Did you feel the %gsurge of magic%w recently? A mysterious bird told me it came from %g",
/*french*/
"As-tu récemment ressenti une vague de %gpuissance magique%w? Un mystérieux hibou m'a dit qu'elle provenait du %g",
/*spanish*/
""},
});
hintTable[RHT_SARIA_TEXT02] = HintText::OtherHint({
// obscure text
Text{
"%w.^You should check that place out, @!$C",
/*french*/
"%w. Tu devrais aller y jeter un coup d'oeil, @!$C",
/*spanish*/
"%w.$C"},
});
/*--------------------------
| GANON LINE TEXT |
---------------------------*/

File diff suppressed because it is too large Load Diff

View File

@ -12,7 +12,6 @@
struct HintDistributionSetting {
HintType type;
uint8_t order;
size_t weight;
uint8_t fixed;
uint8_t copies;
@ -42,7 +41,7 @@ enum class HintCategory {
LACS,
Altar,
Validation,
LightArrow,
OtherHint,
GanonLine,
MerchantsDialogs,
};
@ -112,9 +111,9 @@ public:
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::Validation};
}
static auto LightArrow(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::LightArrow};
} //RANDOTODO Concert to generic special hints?
static auto OtherHint(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::OtherHint};
}
static auto GanonLine(std::vector<Text>&& obscureText, std::vector<Text>&& ambiguousText = {}, Text&& clearText = {}) {
return HintText{std::move(obscureText), std::move(ambiguousText), std::move(clearText), HintCategory::GanonLine};
@ -197,22 +196,17 @@ using ConditionalAlwaysHint = std::pair<RandomizerCheck, std::function<bool()>>;
//10 dungeons as GTG and GC are excluded
extern std::array<DungeonInfo, 10> dungeonInfoData;
extern std::array<ConditionalAlwaysHint, 10> conditionalAlwaysHints;
extern RandomizerHintTextKey GetHintRegionHintKey(const RandomizerRegion area);
extern void CreateAllHints();
extern void CreateMerchantsHints();
extern void CreateWarpSongTexts();
extern void CreateDampesDiaryText();
extern void CreateGregRupeeHint();
extern void CreateSariaText();
extern void CreateGanonAndSheikText();
extern void CreateAltarText();
Text& GetChildAltarText();
Text& GetAdultAltarText();
Text& GetGanonText();
void SetGanonText(Text text);
Text& GetGanonHintText();
Text& GetDampeHintText();
Text& GetGregHintText();
@ -226,6 +220,7 @@ Text& GetWarpRequiemText();
Text& GetWarpNocturneText();
Text& GetWarpPreludeText();
std::string GetDampeHintLoc();
std::string GetLightArrowHintLoc();
std::string GetDampeHintLoc();
std::string GetGregHintLoc();
std::string GetSariaHintLoc();

View File

@ -37,7 +37,7 @@ using json = nlohmann::ordered_json;
json jsonData;
std::map<RandomizerHintTextKey, Rando::ItemLocation*> hintedLocations;
extern std::unordered_map<HintType, std::string> hintTypeNames;
extern std::array<std::string, HINT_TYPE_MAX> hintTypeNames;
extern std::array<std::string, 17> hintCategoryNames;
extern Area* GetHintRegion(uint32_t);
@ -775,7 +775,7 @@ static void WriteHints(int language) {
}
if (Settings::GregHintText){
jsonData["gregText"] = gregText;
jsonData["gregLoc"] = Rando::StaticData::GetLocation(GetItemLocation(RG_GREG_RUPEE)->GetRandomizerCheck())->GetName();
jsonData["gregLoc"] = GetGregHintLoc();
}
if (Settings::SariaHintText){
jsonData["sariaText"] = sariaText;
@ -804,16 +804,16 @@ static void WriteHints(int language) {
std::string textStr = AutoFormatHintTextString(unformattedHintTextString);
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["hint"] = textStr;
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["type"] = hintTypeNames.find(hintType)->second;
if (hintType == HINT_TYPE_ITEM || hintType == HINT_TYPE_NAMED_ITEM || hintType == HINT_TYPE_WOTH) {
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["type"] = hintTypeNames[(int)hintType];
if ((hintType >= HINT_TYPE_ALWAYS && hintType < HINT_TYPE_JUNK) || hintType == HINT_TYPE_WOTH) {
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["item"] = hintedLocation->GetPlacedItemName().GetEnglish();
if (hintType != HINT_TYPE_NAMED_ITEM || hintType == HINT_TYPE_WOTH) {
if (hintType != HINT_TYPE_NAMED_ITEM) {
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["location"] =
Rando::StaticData::GetLocation(hintedLocation->GetRandomizerCheck())->GetName();
}
}
if (hintType != HINT_TYPE_TRIAL && hintType != HINT_TYPE_JUNK) {
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["area"] = hint->GetHintedRegion();
jsonData["hints"][Rando::StaticData::GetLocation(key)->GetName()]["area"] = hint->GetHintedRegion(); //RANDOTODO find elegent way to capitalise this
}
}
}

View File

@ -36,7 +36,7 @@ extern "C" uint32_t ResourceMgr_IsGameMasterQuest();
extern "C" uint32_t ResourceMgr_IsSceneMasterQuest(s16 sceneNum);
extern std::map<RandomizerCheckArea, std::string> rcAreaNames;
extern std::unordered_map<HintType, std::string> hintTypeNames;
extern std::array<std::string, HINT_TYPE_MAX> hintTypeNames;
using json = nlohmann::json;
using namespace std::literals::string_literals;
@ -139,6 +139,18 @@ Randomizer::Randomizer() {
item.GetName().french,
};
}
for (auto area : rcAreaNames) {
SpoilerfileAreaNameToEnum[area.second] = area.first;
}
SpoilerfileAreaNameToEnum["Inside Ganon's Castle"] = RCAREA_GANONS_CASTLE;
SpoilerfileAreaNameToEnum["the Lost Woods"] = RCAREA_LOST_WOODS;
SpoilerfileAreaNameToEnum["the Market"] = RCAREA_MARKET;
SpoilerfileAreaNameToEnum["the Graveyard"] = RCAREA_GRAVEYARD;
SpoilerfileAreaNameToEnum["Haunted Wasteland"] = RCAREA_WASTELAND;
SpoilerfileAreaNameToEnum["outside Ganon's Castle"] = RCAREA_HYRULE_CASTLE;
for (int c = 0; c < hintTypeNames.size(); c++) {
SpoilerfileHintTypeNameToEnum[hintTypeNames[c]] = (HintType)c;
}
}
Sprite* Randomizer::GetSeedTexture(uint8_t index) {

View File

@ -31,23 +31,23 @@ typedef enum {
} RandomizerCheckStatus;
typedef enum {
HINT_TYPE_STATIC,
HINT_TYPE_TRIAL,
HINT_TYPE_ALWAYS,
HINT_TYPE_WOTH, // Way of the Hero
HINT_TYPE_BARREN,
HINT_TYPE_ENTRANCE,
HINT_TYPE_ALWAYS,
HINT_TYPE_SOMETIMES,
HINT_TYPE_RANDOM,
HINT_TYPE_ITEM,
HINT_TYPE_SONG,
HINT_TYPE_OVERWORLD,
HINT_TYPE_DUNGEON,
HINT_TYPE_JUNK,
HINT_TYPE_NAMED_ITEM,
HINT_TYPE_STATIC, // For special hints, like Light Arrows or Hookshot Hints
HINT_TYPE_RANDOM,
HINT_TYPE_JUNK,
HINT_TYPE_MAX
} HintType;
// Check types based on main settings
typedef enum {
RCTYPE_STANDARD, // Base set of rando checks
@ -3182,6 +3182,13 @@ typedef enum {
RHT_SHEIK_LIGHT_ARROW_HINT,
// Your Pocket
RHT_YOUR_POCKET,
// Other Hints
RHT_DAMPE_DIARY01,
RHT_DAMPE_DIARY02,
RHT_GREG_HINT01,
RHT_GREG_HINT02,
RHT_SARIA_TEXT01,
RHT_SARIA_TEXT02,
// Ganon Line
RHT_GANON_LINE01,
RHT_GANON_LINE02,