Fix Skull Tokens from Chests locking you in place (#5198)

* temp fix for chest skulltulas

* Implement way to load a vanilla message into a CustomMessage

* dynamically inserts autodismiss text code to skulltula text.
This commit is contained in:
Christopher Leggett 2025-03-24 17:21:09 -04:00 committed by GitHub
parent bddef32a5a
commit 43510e5ad9
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
4 changed files with 50 additions and 3 deletions

View file

@ -114,6 +114,44 @@ CustomMessage::CustomMessage(Text text, TextBoxType type_,TextBoxPosition positi
messages[LANGUAGE_FRA] = text.GetFrench(); messages[LANGUAGE_FRA] = text.GetFrench();
} }
typedef struct {
u16 textId;
u8 typePos;
const char* segment;
u32 msgSize;
} MessageTableEntry;
extern "C" MessageTableEntry* sNesMessageEntryTablePtr;
extern "C" MessageTableEntry* sGerMessageEntryTablePtr;
extern "C" MessageTableEntry* sFraMessageEntryTablePtr;
CustomMessage CustomMessage::LoadVanillaMessageTableEntry(uint16_t textId) {
const char* foundSeg;
const char* nextSeg;
MessageTableEntry* msgEntry = sNesMessageEntryTablePtr;
u16 bufferId = textId;
CustomMessage msg;
if (gSaveContext.language == LANGUAGE_GER) {
msgEntry = sGerMessageEntryTablePtr;
} else if (gSaveContext.language == LANGUAGE_FRA) {
msgEntry = sFraMessageEntryTablePtr;
}
while (msgEntry->textId != 0xFFFF) {
if (msgEntry->textId == bufferId) {
TextBoxPosition position = static_cast<TextBoxPosition>(msgEntry->typePos & 0xF);
TextBoxType type = static_cast<TextBoxType>(msgEntry->typePos >> 4);
// uint8_t icon = msgEntry->segment[1];
std::string message = std::string(msgEntry->segment , msgEntry->msgSize);
msg = CustomMessage(message, type, position);
// msg.Format(static_cast<ItemID>(icon));
return msg;
}
msgEntry++;
}
return CustomMessage();
}
const std::string CustomMessage::GetEnglish(MessageFormat format) const { const std::string CustomMessage::GetEnglish(MessageFormat format) const {
return GetForLanguage(LANGUAGE_ENG, format); return GetForLanguage(LANGUAGE_ENG, format);
} }

View file

@ -47,6 +47,8 @@ class CustomMessage {
CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM); CustomMessage(std::string english_, std::vector<std::string> colors_, std::vector<bool> capital_ = {}, TextBoxType type_ = TEXTBOX_TYPE_BLACK, TextBoxPosition position_ = TEXTBOX_POS_BOTTOM);
CustomMessage(Text text, 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 MESSAGE_END() ;
static std::string ITEM_OBTAINED(uint8_t x) ; static std::string ITEM_OBTAINED(uint8_t x) ;
static std::string NEWLINE() ; static std::string NEWLINE() ;

View file

@ -236,6 +236,7 @@ void RandomizerOnFlagSetHandler(int16_t flagType, int16_t flag) {
RandomizerCheck rc = GetRandomizerCheckFromFlag(flagType, flag); RandomizerCheck rc = GetRandomizerCheckFromFlag(flagType, flag);
if (rc == RC_UNKNOWN_CHECK) return; if (rc == RC_UNKNOWN_CHECK) return;
if (flagType == FLAG_GS_TOKEN && Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF)) return;
auto loc = Rando::Context::GetInstance()->GetItemLocation(rc); auto loc = Rando::Context::GetInstance()->GetItemLocation(rc);
if (loc == nullptr || loc->HasObtained() || loc->GetPlacedRandomizerGet() == RG_NONE) return; if (loc == nullptr || loc->HasObtained() || loc->GetPlacedRandomizerGet() == RG_NONE) return;
@ -1610,7 +1611,6 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
case VB_GIVE_ITEM_FROM_LAB_DIVE: case VB_GIVE_ITEM_FROM_LAB_DIVE:
case VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG: case VB_GIVE_ITEM_FROM_SKULL_KID_SARIAS_SONG:
case VB_GIVE_ITEM_FROM_MAN_ON_ROOF: case VB_GIVE_ITEM_FROM_MAN_ON_ROOF:
case VB_GIVE_ITEM_SKULL_TOKEN:
case VB_GIVE_ITEM_FROM_BLUE_WARP: case VB_GIVE_ITEM_FROM_BLUE_WARP:
case VB_GIVE_ITEM_FAIRY_OCARINA: case VB_GIVE_ITEM_FAIRY_OCARINA:
case VB_GIVE_ITEM_WEIRD_EGG: case VB_GIVE_ITEM_WEIRD_EGG:
@ -1626,6 +1626,9 @@ void RandomizerOnVanillaBehaviorHandler(GIVanillaBehavior id, bool* should, va_l
case VB_GIVE_ITEM_SHADOW_MEDALLION: case VB_GIVE_ITEM_SHADOW_MEDALLION:
*should = false; *should = false;
break; break;
case VB_GIVE_ITEM_SKULL_TOKEN:
*should = (Rando::Context::GetInstance()->GetOption(RSK_SHUFFLE_TOKENS).Is(RO_TOKENSANITY_OFF));
break;
default: default:
break; break;
} }

View file

@ -2379,7 +2379,7 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) { if (CVarGetInteger(CVAR_ENHANCEMENT("InjectItemCounts.GoldSkulltula"), 0) != 0) {
// The freeze text cannot be manually dismissed and must be auto-dismissed. // 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 // 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. // 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 // 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. // animation until the text box auto-dismisses.
// RANDOTODO: Implement a way to determine if an item came from a skulltula and // RANDOTODO: Implement a way to determine if an item came from a skulltula and
@ -2395,7 +2395,11 @@ extern "C" int CustomMessage_RetrieveIfExists(PlayState* play) {
s16 gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0); s16 gsCount = gSaveContext.inventory.gsTokens + (IS_RANDO ? 1 : 0);
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED);
messageEntry.Replace("[[gsCount]]", std::to_string(gsCount)); 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)) && } else if ((IS_RANDO || CVarGetInteger(CVAR_ENHANCEMENT("BetterBombchuShopping"), 0)) &&
(textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) { (textId == TEXT_BUY_BOMBCHUS_10_DESC || textId == TEXT_BUY_BOMBCHUS_10_PROMPT)) {
messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED); messageEntry = CustomMessageManager::Instance->RetrieveMessage(customMessageTableID, textId, MF_FORMATTED);