diff --git a/include/functions.h b/include/functions.h index 13c1ff510f..05246bbd01 100644 --- a/include/functions.h +++ b/include/functions.h @@ -797,8 +797,8 @@ void GetItem_Draw(PlayState* play, s16 drawId); void SfxSource_InitAll(PlayState* play); void SfxSource_UpdateAll(PlayState* play); void SfxSource_PlaySfxAtFixedWorldPos(PlayState* play, Vec3f* worldPos, s32 duration, u16 sfxId); -u16 ElfMessage_GetSariaText(PlayState* play); -u16 ElfMessage_GetCUpText(PlayState* play); +u16 QuestHint_GetSariaTextId(PlayState* play); +u16 QuestHint_GetNaviTextId(PlayState* play); u16 Text_GetFaceReaction(PlayState* play, u32 reactionSet); void Flags_UnsetAllEnv(PlayState* play); void Flags_SetEnv(PlayState* play, s16 flag); diff --git a/include/z64.h b/include/z64.h index d351794d1b..eb0825f5e8 100644 --- a/include/z64.h +++ b/include/z64.h @@ -1131,7 +1131,7 @@ typedef struct { /* 0x01 */ u8 byte1; /* 0x02 */ u8 byte2; /* 0x03 */ u8 byte3; -} ElfMessage; // size = 0x4 +} QuestHintCmd; // size = 0x4 typedef struct { /* 0x00 */ u8 numActors; @@ -1193,7 +1193,7 @@ typedef struct PlayState { /* 0x11E00 */ EntranceEntry* setupEntranceList; /* 0x11E04 */ s16* setupExitList; /* 0x11E08 */ Path* setupPathList; - /* 0x11E0C */ ElfMessage* cUpElfMsgs; + /* 0x11E0C */ QuestHintCmd* naviQuestHints; /* 0x11E10 */ void* specialEffects; /* 0x11E14 */ u8 skyboxId; /* 0x11E15 */ s8 transitionTrigger; // "fade_direction" diff --git a/include/z64elf_message.h b/include/z64elf_message.h deleted file mode 100644 index d6f545b3f0..0000000000 --- a/include/z64elf_message.h +++ /dev/null @@ -1,129 +0,0 @@ -#ifndef Z64ELF_MESSAGE_H -#define Z64ELF_MESSAGE_H - -#include "ultra64.h" - -// Checks the condition and exits the script if the check passes -#define ELF_MSG_TYPE_CHECK 0 -// ? (unused) -#define ELF_MSG_TYPE_UNK_1 1 -// ? (unused) -#define ELF_MSG_TYPE_UNK_2 2 -// Checks the condition and skips forward by some number of commands if the check passes -#define ELF_MSG_TYPE_SKIP 3 -// Always ends the script, returning the text id for this command -#define ELF_MSG_TYPE_END 7 - -// Check an eventChkInf flag -#define ELF_MSG_CONDITION_FLAG 0 -// Check a dungeon item (map, compass, boss key) -#define ELF_MSG_CONDITION_DUNGEON_ITEM 1 -// Check if an item is in an item slot -#define ELF_MSG_CONDITION_ITEM 2 -// "Other" conditions described below -#define ELF_MSG_CONDITION_OTHER 3 - -// Check what strength upgrade has been obtained so far -#define ELF_MSG_CONDITION_STRENGTH_UPG 0 -// Check if specific boots have been obtained so far -#define ELF_MSG_CONDITION_BOOTS 1 -// Check if a particular song has been obtained -#define ELF_MSG_CONDITION_SONG 2 -// Check if a particular medallion has been obtained -#define ELF_MSG_CONDITION_MEDALLION 3 -// Check if the magic meter has been obtained -#define ELF_MSG_CONDITION_MAGIC 4 - -/* - * Bitpack byte 0 - */ -#define ELF_MSG_B0(type, cond_type, tf) \ - _SHIFTL(ELF_MSG_TYPE_##type, 5, 3) | \ - _SHIFTL(ELF_MSG_CONDITION_##cond_type, 1, 4) | \ - _SHIFTL(tf, 0, 1) - -/* - * Bitpack byte 1 - */ -#define ELF_MSG_B1(cond_type, data) \ - _SHIFTL(ELF_MSG_CONDITION_##cond_type, 4, 4) | \ - _SHIFTL(data, 0, 4) - -/* - * Other bytes - */ -#define ELF_MSG_B(data) \ - _SHIFTL(data, 0, 8) - -/* - * Command macros - */ - -#define ELF_MSG_FLAG(type, textId, tf, flag) \ - { \ - ELF_MSG_B0(type, FLAG, tf), \ - ELF_MSG_B(flag), \ - ELF_MSG_B(textId), \ - ELF_MSG_B(0), \ - } - -#define ELF_MSG_END(textId) \ - ELF_MSG_FLAG(END, textId, false, 0) - -#define ELF_MSG_DUNGEON_ITEM(type, textId, tf, itemId) \ - { \ - ELF_MSG_B0(type, DUNGEON_ITEM, tf), \ - ELF_MSG_B(itemId), \ - ELF_MSG_B(textId), \ - ELF_MSG_B(0), \ - } - -#define ELF_MSG_ITEM(type, textId, tf, slotItemId, itemId) \ - { \ - ELF_MSG_B0(type, ITEM, tf), \ - ELF_MSG_B(slotItemId), \ - ELF_MSG_B(textId), \ - ELF_MSG_B(itemId), \ - } - -#define ELF_MSG_STRENGTH_UPG(type, textId, tf, strUpg) \ - { \ - ELF_MSG_B0(type, OTHER, tf), \ - ELF_MSG_B1(STRENGTH_UPG, strUpg), \ - ELF_MSG_B(textId), \ - ELF_MSG_B(0), \ - } - -#define ELF_MSG_BOOTS(type, textId, tf, itemId) \ - { \ - ELF_MSG_B0(type, OTHER, tf), \ - ELF_MSG_B1(BOOTS, 0), \ - ELF_MSG_B(textId), \ - ELF_MSG_B(itemId), \ - } - -#define ELF_MSG_SONG(type, textId, tf, itemId) \ - { \ - ELF_MSG_B0(type, OTHER, tf), \ - ELF_MSG_B1(SONG, 0), \ - ELF_MSG_B(textId), \ - ELF_MSG_B(itemId), \ - } - -#define ELF_MSG_MEDALLION(type, textId, tf, itemId) \ - { \ - ELF_MSG_B0(type, OTHER, tf), \ - ELF_MSG_B1(MEDALLION, 0), \ - ELF_MSG_B(textId), \ - ELF_MSG_B(itemId), \ - } - -#define ELF_MSG_MAGIC(type, textId, tf) \ - { \ - ELF_MSG_B0(type, OTHER, tf), \ - ELF_MSG_B1(MAGIC, 0), \ - ELF_MSG_B(textId), \ - ELF_MSG_B(0), \ - } - -#endif diff --git a/include/z64quest_hint_commands.h b/include/z64quest_hint_commands.h new file mode 100644 index 0000000000..62f262f39b --- /dev/null +++ b/include/z64quest_hint_commands.h @@ -0,0 +1,150 @@ +#ifndef Z64QUEST_HINT_COMMANDS_H +#define Z64QUEST_HINT_COMMANDS_H + +#include "ultra64.h" + +/* + * Hint Command Types + */ + +// Checks the condition and exits the script if the check passes +#define QUEST_HINT_TYPE_CHECK 0 + +// Checks a chain of conditions and only evaluates the last entry +// if all conditions leading up to it were also true +#define QUEST_HINT_TYPE_CHAIN 1 + +// Checks a chain of conditionals and will return a randomly chosen entry among +// the conditions that evaluated to true +#define QUEST_HINT_TYPE_RANDOM 2 + +// Checks the condition and skips forward by specified number of commands if the check passes +// Note that the amount of entries to skip is specified in the field where the textId would usually go +#define QUEST_HINT_TYPE_SKIP 3 + +// Always ends the script, returning the text id for this command +#define QUEST_HINT_TYPE_END 7 + +/* + * Hint Condition Types + */ + +// Check an eventChkInf flag +#define QUEST_HINT_CONDITION_FLAG 0 + +// Check a dungeon item (map, compass, boss key) +#define QUEST_HINT_CONDITION_DUNGEON_ITEM 1 + +// Check if an item is in an item slot +#define QUEST_HINT_CONDITION_ITEM 2 + +// "Other" conditions described below +#define QUEST_HINT_CONDITION_OTHER 3 + +/* + * "Other" Condition Types + */ + +// Check what strength upgrade has been obtained so far +#define QUEST_HINT_CONDITION_STRENGTH_UPG 0 + +// Check if specific boots have been obtained so far +#define QUEST_HINT_CONDITION_BOOTS 1 + +// Check if a particular song has been obtained +#define QUEST_HINT_CONDITION_SONG 2 + +// Check if a particular medallion has been obtained +#define QUEST_HINT_CONDITION_MEDALLION 3 + +// Check if the magic meter has been obtained +#define QUEST_HINT_CONDITION_MAGIC 4 + +/* + * Byte pack macros + */ + +#define HINT_B0(type, condType, tf) \ + _SHIFTL(QUEST_HINT_TYPE_##type, 5, 3) | \ + _SHIFTL(condType, 1, 4) | \ + _SHIFTL(tf, 0, 1) + +#define HINT_B1(condType, data) \ + _SHIFTL(condType, 4, 4) | \ + _SHIFTL(data, 0, 4) + +#define HINT_B(data) \ + _SHIFTL(data, 0, 8) + +/* + * Command macros + */ + +#define QUEST_HINT_FLAG(type, flag, tf, textId) \ + { \ + HINT_B0(type, QUEST_HINT_CONDITION_FLAG, tf), \ + HINT_B(flag), \ + HINT_B(textId), \ + HINT_B(0), \ + } + +#define QUEST_HINT_END(textId) \ + QUEST_HINT_FLAG(END, 0, false, textId) + +#define QUEST_HINT_DUNGEON_ITEM(type, itemId, tf, textId) \ + { \ + HINT_B0(type, QUEST_HINT_CONDITION_DUNGEON_ITEM, tf), \ + HINT_B(itemId), \ + HINT_B(textId), \ + HINT_B(0), \ + } + +#define QUEST_HINT_ITEM(type, slotItemId, itemId, tf, textId) \ + { \ + HINT_B0(type, QUEST_HINT_CONDITION_ITEM, tf), \ + HINT_B(slotItemId), \ + HINT_B(textId), \ + HINT_B(itemId), \ + } + +#define QUEST_HINT_STRENGTH_UPG(type, strUpg, tf, textId) \ + { \ + HINT_B0(type, QUEST_HINT_CONDITION_OTHER, tf), \ + HINT_B1(QUEST_HINT_CONDITION_STRENGTH_UPG, strUpg), \ + HINT_B(textId), \ + HINT_B(0), \ + } + +#define QUEST_HINT_BOOTS(type, itemId, tf, textId) \ + { \ + HINT_B0(type, QUEST_HINT_CONDITION_OTHER, tf), \ + HINT_B1(QUEST_HINT_CONDITION_BOOTS, 0), \ + HINT_B(textId), \ + HINT_B(itemId), \ + } + +#define QUEST_HINT_SONG(type, itemId, tf, textId) \ + { \ + HINT_B0(type, QUEST_HINT_CONDITION_OTHER, tf), \ + HINT_B1(QUEST_HINT_CONDITION_SONG, 0), \ + HINT_B(textId), \ + HINT_B(itemId), \ + } + +#define QUEST_HINT_MEDALLION(type, itemId, tf, textId) \ + { \ + HINT_B0(type, QUEST_HINT_CONDITION_OTHER, tf), \ + HINT_B1(QUEST_HINT_CONDITION_MEDALLION, 0), \ + HINT_B(textId), \ + HINT_B(itemId), \ + } + +#define QUEST_HINT_MAGIC(type, tf, textId) \ + { \ + HINT_B0(type, QUEST_HINT_CONDITION_OTHER, tf), \ + HINT_B1(QUEST_HINT_CONDITION_MAGIC, 0), \ + HINT_B(textId), \ + HINT_B(0), \ + } + +#endif diff --git a/include/z64scene.h b/include/z64scene.h index d0d96c91c1..4dc2d54696 100644 --- a/include/z64scene.h +++ b/include/z64scene.h @@ -223,7 +223,7 @@ typedef struct { typedef struct { /* 0x00 */ u8 code; - /* 0x01 */ u8 cUpElfMsgNum; + /* 0x01 */ u8 naviQuestHintFileId; /* 0x04 */ u32 keepObjectId; } SCmdSpecialFiles; @@ -469,6 +469,14 @@ typedef enum { #define SCENE_CAM_TYPE_FIXED_MARKET 0x40 // Camera exhibits fixed behaviors and delays textboxes by a small amount before they start to appear #define SCENE_CAM_TYPE_SHOOTING_GALLERY 0x50 // Unreferenced in code, and used only by the main layer of the shooting gallery scene +// navi hints +// TODO: make ZAPD use this enum for `SCENE_CMD_SPECIAL_FILES` +typedef enum { + NAVI_QUEST_HINTS_NONE, + NAVI_QUEST_HINTS_OVERWORLD, + NAVI_QUEST_HINTS_DUNGEON +} NaviQuestHintFileId; + // Scene commands typedef enum { @@ -522,8 +530,8 @@ typedef enum { #define SCENE_CMD_ENTRANCE_LIST(entranceList) \ { SCENE_CMD_ID_ENTRANCE_LIST, 0, CMD_PTR(entranceList) } -#define SCENE_CMD_SPECIAL_FILES(elfMessageFile, keepObjectId) \ - { SCENE_CMD_ID_SPECIAL_FILES, elfMessageFile, CMD_W(keepObjectId) } +#define SCENE_CMD_SPECIAL_FILES(naviQuestHintFileId, keepObjectId) \ + { SCENE_CMD_ID_SPECIAL_FILES, naviQuestHintFileId, CMD_W(keepObjectId) } #define SCENE_CMD_ROOM_BEHAVIOR(curRoomUnk3, curRoomUnk2, showInvisActors, disableWarpSongs) \ { SCENE_CMD_ID_ROOM_BEHAVIOR, curRoomUnk3, \ diff --git a/src/code/z_elf_message.c b/src/code/z_elf_message.c index e05b5798f0..abb3cfef6b 100644 --- a/src/code/z_elf_message.c +++ b/src/code/z_elf_message.c @@ -1,60 +1,69 @@ #include "global.h" -#include "z64elf_message.h" +#include "z64quest_hint_commands.h" -ElfMessage sChildSariaMsgs[] = { - ELF_MSG_STRENGTH_UPG(SKIP, 3, false, 0), - ELF_MSG_FLAG(CHECK, 0x61, false, EVENTCHKINF_37), - ELF_MSG_END(0x64), - ELF_MSG_FLAG(CHECK, 0x62, false, EVENTCHKINF_25), - ELF_MSG_FLAG(CHECK, 0x63, false, EVENTCHKINF_37), - ELF_MSG_FLAG(CHECK, 0x65, false, EVENTCHKINF_43), - ELF_MSG_MEDALLION(CHECK, 0x66, false, ITEM_MEDALLION_FOREST), - ELF_MSG_MEDALLION(CHECK, 0x66, false, ITEM_MEDALLION_FIRE), - ELF_MSG_MEDALLION(CHECK, 0x66, false, ITEM_MEDALLION_WATER), - ELF_MSG_SONG(CHECK, 0x67, false, ITEM_SONG_STORMS), - ELF_MSG_MEDALLION(CHECK, 0x68, false, ITEM_MEDALLION_SPIRIT), - ELF_MSG_MEDALLION(CHECK, 0x68, false, ITEM_MEDALLION_SHADOW), - ELF_MSG_END(0x69), +QuestHintCmd sChildSariaQuestHints[] = { + QUEST_HINT_STRENGTH_UPG(SKIP, 0, false, 3), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_37, false, 0x61), + QUEST_HINT_END(0x64), + + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_25, false, 0x62), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_37, false, 0x63), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_43, false, 0x65), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_FOREST, false, 0x66), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_FIRE, false, 0x66), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_WATER, false, 0x66), + QUEST_HINT_SONG(CHECK, ITEM_SONG_STORMS, false, 0x67), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_SPIRIT, false, 0x68), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_SHADOW, false, 0x68), + QUEST_HINT_END(0x69), }; -ElfMessage sAdultSariaMsgs[] = { - ELF_MSG_MEDALLION(CHECK, 0x6A, false, ITEM_MEDALLION_FOREST), - ELF_MSG_MEDALLION(CHECK, 0x6B, false, ITEM_MEDALLION_FIRE), - ELF_MSG_MEDALLION(CHECK, 0x6B, false, ITEM_MEDALLION_WATER), - ELF_MSG_MEDALLION(CHECK, 0x6C, false, ITEM_MEDALLION_SPIRIT), - ELF_MSG_MEDALLION(CHECK, 0x6C, false, ITEM_MEDALLION_SHADOW), - ELF_MSG_END(0x6D), +QuestHintCmd sAdultSariaQuestHints[] = { + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_FOREST, false, 0x6A), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_FIRE, false, 0x6B), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_WATER, false, 0x6B), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_SPIRIT, false, 0x6C), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_SHADOW, false, 0x6C), + QUEST_HINT_END(0x6D), }; -u32 ElfMessage_CheckCondition(ElfMessage* msg) { - s32 type = msg->byte0 & 0x1E; +u32 QuestHint_CheckCondition(QuestHintCmd* hintCmd) { + s32 type = hintCmd->byte0 & 0x1E; u16 flag; switch (type) { - case (ELF_MSG_CONDITION_FLAG << 1): - flag = 1 << (msg->byte1 & 0x0F); - return ((msg->byte0 & 1) == 1) == ((flag & gSaveContext.eventChkInf[(msg->byte1 & 0xF0) >> 4]) != 0); - case (ELF_MSG_CONDITION_DUNGEON_ITEM << 1): - return ((msg->byte0 & 1) == 1) == - (CHECK_DUNGEON_ITEM(msg->byte1 - ITEM_KEY_BOSS, gSaveContext.mapIndex) != 0); - case (ELF_MSG_CONDITION_ITEM << 1): - return ((msg->byte0 & 1) == 1) == (msg->byte3 == INV_CONTENT(msg->byte1)); - case (ELF_MSG_CONDITION_OTHER << 1): - switch (msg->byte1 & 0xF0) { - case (ELF_MSG_CONDITION_STRENGTH_UPG << 4): - return ((msg->byte0 & 1) == 1) == ((msg->byte1 & 0x0F) == CUR_UPG_VALUE(UPG_STRENGTH)); - case (ELF_MSG_CONDITION_BOOTS << 4): - return ((msg->byte0 & 1) == 1) == + case (QUEST_HINT_CONDITION_FLAG << 1): + flag = 1 << (hintCmd->byte1 & 0x0F); + return ((hintCmd->byte0 & 1) == 1) == + ((flag & gSaveContext.eventChkInf[(hintCmd->byte1 & 0xF0) >> 4]) != 0); + + case (QUEST_HINT_CONDITION_DUNGEON_ITEM << 1): + return ((hintCmd->byte0 & 1) == 1) == + (CHECK_DUNGEON_ITEM(hintCmd->byte1 - ITEM_KEY_BOSS, gSaveContext.mapIndex) != 0); + + case (QUEST_HINT_CONDITION_ITEM << 1): + return ((hintCmd->byte0 & 1) == 1) == (hintCmd->byte3 == INV_CONTENT(hintCmd->byte1)); + + case (QUEST_HINT_CONDITION_OTHER << 1): + switch (hintCmd->byte1 & 0xF0) { + case (QUEST_HINT_CONDITION_STRENGTH_UPG << 4): + return ((hintCmd->byte0 & 1) == 1) == ((hintCmd->byte1 & 0x0F) == CUR_UPG_VALUE(UPG_STRENGTH)); + + case (QUEST_HINT_CONDITION_BOOTS << 4): + return ((hintCmd->byte0 & 1) == 1) == (CHECK_OWNED_EQUIP(EQUIP_TYPE_BOOTS, - msg->byte3 - ITEM_BOOTS_KOKIRI + EQUIP_INV_BOOTS_KOKIRI) != 0); - case (ELF_MSG_CONDITION_SONG << 4): - return ((msg->byte0 & 1) == 1) == - (CHECK_QUEST_ITEM(msg->byte3 - ITEM_SONG_MINUET + QUEST_SONG_MINUET) != 0); - case (ELF_MSG_CONDITION_MEDALLION << 4): - return ((msg->byte0 & 1) == 1) == - (CHECK_QUEST_ITEM(msg->byte3 - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST) != 0); - case (ELF_MSG_CONDITION_MAGIC << 4): - return ((msg->byte0 & 1) == 1) == (((void)0, gSaveContext.isMagicAcquired) != 0); + hintCmd->byte3 - ITEM_BOOTS_KOKIRI + EQUIP_INV_BOOTS_KOKIRI) != 0); + + case (QUEST_HINT_CONDITION_SONG << 4): + return ((hintCmd->byte0 & 1) == 1) == + (CHECK_QUEST_ITEM(hintCmd->byte3 - ITEM_SONG_MINUET + QUEST_SONG_MINUET) != 0); + + case (QUEST_HINT_CONDITION_MEDALLION << 4): + return ((hintCmd->byte0 & 1) == 1) == + (CHECK_QUEST_ITEM(hintCmd->byte3 - ITEM_MEDALLION_FOREST + QUEST_MEDALLION_FOREST) != 0); + + case (QUEST_HINT_CONDITION_MAGIC << 4): + return ((hintCmd->byte0 & 1) == 1) == (((void)0, gSaveContext.isMagicAcquired) != 0); } } @@ -64,111 +73,126 @@ u32 ElfMessage_CheckCondition(ElfMessage* msg) { return false; } -u32 func_8006BE88(ElfMessage** msgp) { - u32 temp = true; +u32 QuestHint_CheckConditionChain(QuestHintCmd** hintCmdPtr) { + u32 allConditionsMet = true; - while (((*msgp)->byte0 & 0xE0) == (ELF_MSG_TYPE_UNK_1 << 5)) { - if (!ElfMessage_CheckCondition(*msgp)) { - temp = false; + while (((*hintCmdPtr)->byte0 & 0xE0) == (QUEST_HINT_TYPE_CHAIN << 5)) { + // if any of the conditions checked in the chain are not met, + // the whole chain is considered false + if (!QuestHint_CheckCondition(*hintCmdPtr)) { + allConditionsMet = false; } - *msgp += 1; + + *hintCmdPtr += 1; } - if (temp) { - return ElfMessage_CheckCondition(*msgp); + if (allConditionsMet) { + return QuestHint_CheckCondition(*hintCmdPtr); } else { return false; } } -u32 func_8006BF1C(ElfMessage** msgp) { - ElfMessage* msg = *msgp; - u32 sp44[10]; - s32 temp1 = 0; - s32 temp2 = 0; - s32 temp3; +u32 QuestHint_CheckRandomCondition(QuestHintCmd** hintCmdPtr) { + QuestHintCmd* hintCmd = *hintCmdPtr; + u32 conditions[10]; + s32 i = 0; + s32 totalChecked = 0; + s32 rand; do { - sp44[temp2] = ElfMessage_CheckCondition(msg); - temp1 += sp44[temp2]; - temp2++; - msg++; - } while ((msg->byte0 & 0xE0) == (ELF_MSG_TYPE_UNK_2 << 5)); + conditions[totalChecked] = QuestHint_CheckCondition(hintCmd); + // i is incremented if the condition was met + i += conditions[totalChecked]; + totalChecked++; + hintCmd++; + } while ((hintCmd->byte0 & 0xE0) == (QUEST_HINT_TYPE_RANDOM << 5)); - if (temp1 == 0) { + // if none of the conditions checked were satisfied, there are none to use + if (i == 0) { return false; } - temp3 = Rand_ZeroFloat(temp1); - for (temp1 = 0; temp1 < temp2; temp1++) { - if (sp44[temp1]) { - if (temp3 > 0) { - temp3--; + // choose a random number between 0 and the total amount of conditions met + rand = Rand_ZeroFloat(i); + + for (i = 0; i < totalChecked; i++) { + // keep decrementing the random number until it reaches 0 then use that hint + if (conditions[i]) { + if (rand > 0) { + rand--; } else { return true; } } - *msgp += 1; + + *hintCmdPtr += 1; } return false; } -u16 ElfMessage_GetTextFromMsgs(ElfMessage* msg) { +u16 QuestHint_GetTextIdFromScript(QuestHintCmd* hintCmd) { while (true) { - switch (msg->byte0 & 0xE0) { - case (ELF_MSG_TYPE_CHECK << 5): - if (ElfMessage_CheckCondition(msg)) { - return msg->byte2 | 0x100; + switch (hintCmd->byte0 & 0xE0) { + case (QUEST_HINT_TYPE_CHECK << 5): + if (QuestHint_CheckCondition(hintCmd)) { + return hintCmd->byte2 | 0x100; } break; - case (ELF_MSG_TYPE_UNK_1 << 5): - if (func_8006BE88(&msg)) { - return msg->byte2 | 0x100; + + case (QUEST_HINT_TYPE_CHAIN << 5): + if (QuestHint_CheckConditionChain(&hintCmd)) { + return hintCmd->byte2 | 0x100; } break; - case (ELF_MSG_TYPE_UNK_2 << 5): - if (func_8006BF1C(&msg)) { - return msg->byte2 | 0x100; + + case (QUEST_HINT_TYPE_RANDOM << 5): + if (QuestHint_CheckRandomCondition(&hintCmd)) { + return hintCmd->byte2 | 0x100; } break; - case (ELF_MSG_TYPE_SKIP << 5): - if (ElfMessage_CheckCondition(msg)) { - msg += msg->byte2; - msg--; + + case (QUEST_HINT_TYPE_SKIP << 5): + if (QuestHint_CheckCondition(hintCmd)) { + hintCmd += hintCmd->byte2; // skip the specified amount + hintCmd--; // decrement by 1 because it will be incremented again below } break; - case (ELF_MSG_TYPE_END << 5): - return msg->byte2 | 0x100; + + case (QUEST_HINT_TYPE_END << 5): + return hintCmd->byte2 | 0x100; + default: LOG_STRING("企画外 条件", "../z_elf_message.c", 281); // "Unplanned conditions" ASSERT(0, "0", "../z_elf_message.c", 282); } - msg++; + + hintCmd++; } } -u16 ElfMessage_GetSariaText(PlayState* play) { +u16 QuestHint_GetSariaTextId(PlayState* play) { Player* player = GET_PLAYER(play); - ElfMessage* msgs; + QuestHintCmd* sariaQuestHints; if (!LINK_IS_ADULT) { if (Actor_FindNearby(play, &player->actor, ACTOR_EN_SA, 4, 800.0f) == NULL) { - msgs = sChildSariaMsgs; + sariaQuestHints = sChildSariaQuestHints; } else { return 0x0160; // Special text about Saria preferring to talk to you face-to-face } } else { - msgs = sAdultSariaMsgs; + sariaQuestHints = sAdultSariaQuestHints; } - return ElfMessage_GetTextFromMsgs(msgs); + return QuestHint_GetTextIdFromScript(sariaQuestHints); } -u16 ElfMessage_GetCUpText(PlayState* play) { - if (play->cUpElfMsgs == NULL) { +u16 QuestHint_GetNaviTextId(PlayState* play) { + if (play->naviQuestHints == NULL) { return 0; } else { - return ElfMessage_GetTextFromMsgs(play->cUpElfMsgs); + return QuestHint_GetTextIdFromScript(play->naviQuestHints); } } diff --git a/src/code/z_play.c b/src/code/z_play.c index 16948ad770..542eb08ce6 100644 --- a/src/code/z_play.c +++ b/src/code/z_play.c @@ -1404,7 +1404,7 @@ void Play_InitScene(PlayState* this, s32 spawn) { this->unk_11DFC = NULL; this->setupEntranceList = NULL; this->setupExitList = NULL; - this->cUpElfMsgs = NULL; + this->naviQuestHints = NULL; this->setupPathList = NULL; this->numSetupActors = 0; Object_InitBank(this, &this->objectCtx); diff --git a/src/code/z_scene.c b/src/code/z_scene.c index ac1c779ef5..10de2959cc 100644 --- a/src/code/z_scene.c +++ b/src/code/z_scene.c @@ -1,7 +1,7 @@ #include "global.h" #include "vt.h" -RomFile sNaviMsgFiles[]; +RomFile sNaviQuestHintFiles[]; s32 Object_Spawn(ObjectContext* objectCtx, s16 objectId) { u32 size; @@ -231,8 +231,8 @@ void Scene_CommandSpecialFiles(PlayState* play, SceneCmd* cmd) { gSegments[5] = VIRTUAL_TO_PHYSICAL(play->objectCtx.status[play->objectCtx.subKeepIndex].segment); } - if (cmd->specialFiles.cUpElfMsgNum != 0) { - play->cUpElfMsgs = Play_LoadFile(play, &sNaviMsgFiles[cmd->specialFiles.cUpElfMsgNum - 1]); + if (cmd->specialFiles.naviQuestHintFileId != NAVI_QUEST_HINTS_NONE) { + play->naviQuestHints = Play_LoadFile(play, &sNaviQuestHintFiles[cmd->specialFiles.naviQuestHintFileId - 1]); } } @@ -498,7 +498,7 @@ void (*gSceneCmdHandlers[SCENE_CMD_ID_MAX])(PlayState*, SceneCmd*) = { Scene_CommandMiscSettings, // SCENE_CMD_ID_MISC_SETTINGS }; -RomFile sNaviMsgFiles[] = { +RomFile sNaviQuestHintFiles[] = { ROM_FILE(elf_message_field), ROM_FILE(elf_message_ydan), ROM_FILE_UNSET, diff --git a/src/elf_message/elf_message_field.c b/src/elf_message/elf_message_field.c index cd48f53ff3..406a975c97 100644 --- a/src/elf_message/elf_message_field.c +++ b/src/elf_message/elf_message_field.c @@ -1,33 +1,33 @@ #include "global.h" -#include "z64elf_message.h" +#include "z64quest_hint_commands.h" -ElfMessage gOverworldNaviMsgs[] = { - ELF_MSG_FLAG(CHECK, 0x40, false, EVENTCHKINF_05), - ELF_MSG_FLAG(CHECK, 0x41, false, EVENTCHKINF_09), - ELF_MSG_FLAG(CHECK, 0x42, false, EVENTCHKINF_12), - ELF_MSG_FLAG(CHECK, 0x43, false, EVENTCHKINF_TALON_RETURNED_FROM_CASTLE), - ELF_MSG_FLAG(CHECK, 0x44, false, EVENTCHKINF_40), - ELF_MSG_SONG(CHECK, 0x45, false, ITEM_SONG_SARIA), - ELF_MSG_STRENGTH_UPG(CHECK, 0x46, true, 0), - ELF_MSG_FLAG(CHECK, 0x47, false, EVENTCHKINF_25), - ELF_MSG_MAGIC(CHECK, 0x48, false), - ELF_MSG_FLAG(CHECK, 0x49, false, EVENTCHKINF_33), - ELF_MSG_FLAG(CHECK, 0x4A, false, EVENTCHKINF_37), - ELF_MSG_FLAG(CHECK, 0x4B, false, EVENTCHKINF_80), - ELF_MSG_FLAG(CHECK, 0x4C, false, EVENTCHKINF_43), - ELF_MSG_FLAG(CHECK, 0x4D, false, EVENTCHKINF_45), - ELF_MSG_ITEM(CHECK, 0x4E, true, ITEM_HOOKSHOT, ITEM_NONE), - ELF_MSG_MEDALLION(CHECK, 0x50, false, ITEM_MEDALLION_FOREST), - ELF_MSG_MEDALLION(CHECK, 0x51, false, ITEM_MEDALLION_FIRE), - ELF_MSG_BOOTS(CHECK, 0x52, false, ITEM_BOOTS_IRON), - ELF_MSG_MEDALLION(CHECK, 0x53, false, ITEM_MEDALLION_WATER), - ELF_MSG_FLAG(CHECK, 0x54, false, EVENTCHKINF_AA), - ELF_MSG_ITEM(CHECK, 0x55, true, ITEM_LENS, ITEM_NONE), - ELF_MSG_MEDALLION(CHECK, 0x57, false, ITEM_MEDALLION_SHADOW), - ELF_MSG_SONG(CHECK, 0x58, false, ITEM_SONG_REQUIEM), - ELF_MSG_STRENGTH_UPG(CHECK, 0x56, true, 1), - ELF_MSG_MEDALLION(CHECK, 0x5A, false, ITEM_MEDALLION_SPIRIT), - ELF_MSG_ITEM(CHECK, 0x5B, true, ITEM_ARROW_LIGHT, ITEM_NONE), - ELF_MSG_FLAG(CHECK, 0x5C, false, EVENTCHKINF_C3), - ELF_MSG_END(0x5F), +QuestHintCmd gOverworldNaviQuestHints[] = { + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_05, false, 0x40), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_09, false, 0x41), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_12, false, 0x42), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_TALON_RETURNED_FROM_CASTLE, false, 0x43), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_40, false, 0x44), + QUEST_HINT_SONG(CHECK, ITEM_SONG_SARIA, false, 0x45), + QUEST_HINT_STRENGTH_UPG(CHECK, 0, true, 0x46), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_25, false, 0x47), + QUEST_HINT_MAGIC(CHECK, false, 0x48), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_33, false, 0x49), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_37, false, 0x4A), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_80, false, 0x4B), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_43, false, 0x4C), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_45, false, 0x4D), + QUEST_HINT_ITEM(CHECK, ITEM_HOOKSHOT, ITEM_NONE, true, 0x4E), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_FOREST, false, 0x50), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_FIRE, false, 0x51), + QUEST_HINT_BOOTS(CHECK, ITEM_BOOTS_IRON, false, 0x52), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_WATER, false, 0x53), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_AA, false, 0x54), + QUEST_HINT_ITEM(CHECK, ITEM_LENS, ITEM_NONE, true, 0x55), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_SHADOW, false, 0x57), + QUEST_HINT_SONG(CHECK, ITEM_SONG_REQUIEM, false, 0x58), + QUEST_HINT_STRENGTH_UPG(CHECK, 1, true, 0x56), + QUEST_HINT_MEDALLION(CHECK, ITEM_MEDALLION_SPIRIT, false, 0x5A), + QUEST_HINT_ITEM(CHECK, ITEM_ARROW_LIGHT, ITEM_NONE, true, 0x5B), + QUEST_HINT_FLAG(CHECK, EVENTCHKINF_C3, false, 0x5C), + QUEST_HINT_END(0x5F), }; diff --git a/src/elf_message/elf_message_ydan.c b/src/elf_message/elf_message_ydan.c index 54050e372e..21b5fe89fa 100644 --- a/src/elf_message/elf_message_ydan.c +++ b/src/elf_message/elf_message_ydan.c @@ -1,6 +1,6 @@ #include "global.h" -#include "z64elf_message.h" +#include "z64quest_hint_commands.h" -ElfMessage gDungeonNaviMsgs[] = { - ELF_MSG_END(0x5F), +QuestHintCmd gDungeonNaviQuestHints[] = { + QUEST_HINT_END(0x5F), }; diff --git a/src/overlays/actors/ovl_En_Elf/z_en_elf.c b/src/overlays/actors/ovl_En_Elf/z_en_elf.c index 202a2910be..44981db664 100644 --- a/src/overlays/actors/ovl_En_Elf/z_en_elf.c +++ b/src/overlays/actors/ovl_En_Elf/z_en_elf.c @@ -1267,7 +1267,7 @@ void func_80A05040(Actor* thisx, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { switch (play->msgCtx.choiceIndex) { case 0: // yes - Message_ContinueTextbox(play, ElfMessage_GetSariaText(play)); + Message_ContinueTextbox(play, QuestHint_GetSariaTextId(play)); this->actor.update = func_80A05114; break; case 1: // no @@ -1301,7 +1301,7 @@ void func_80A05188(Actor* thisx, PlayState* play) { func_80A04DE4(this, play); if ((Message_GetState(&play->msgCtx) == TEXT_STATE_EVENT) && Message_ShouldAdvance(play)) { - Message_ContinueTextbox(play, ElfMessage_GetSariaText(play)); + Message_ContinueTextbox(play, QuestHint_GetSariaTextId(play)); this->actor.update = func_80A05114; } @@ -1310,7 +1310,7 @@ void func_80A05188(Actor* thisx, PlayState* play) { // ask to talk to navi void func_80A05208(Actor* thisx, PlayState* play) { - s32 naviCUpText; + s32 naviTextId; EnElf* this = (EnElf*)thisx; func_80A04DE4(this, play); @@ -1318,10 +1318,10 @@ void func_80A05208(Actor* thisx, PlayState* play) { if ((Message_GetState(&play->msgCtx) == TEXT_STATE_CHOICE) && Message_ShouldAdvance(play)) { switch (play->msgCtx.choiceIndex) { case 0: // yes - naviCUpText = ElfMessage_GetCUpText(play); + naviTextId = QuestHint_GetNaviTextId(play); - if (naviCUpText != 0) { - Message_ContinueTextbox(play, naviCUpText); + if (naviTextId != 0) { + Message_ContinueTextbox(play, naviTextId); } else { Message_ContinueTextbox(play, 0x15F); } @@ -1379,7 +1379,7 @@ void func_80A053F0(Actor* thisx, PlayState* play) { if (player->naviTextId == 0) { if (player->unk_664 == NULL) { if (((gSaveContext.naviTimer >= 600) && (gSaveContext.naviTimer <= 3000)) || (nREG(89) != 0)) { - player->naviTextId = ElfMessage_GetCUpText(play); + player->naviTextId = QuestHint_GetNaviTextId(play); if (player->naviTextId == 0x15F) { player->naviTextId = 0; @@ -1395,7 +1395,7 @@ void func_80A053F0(Actor* thisx, PlayState* play) { func_800F4524(&gSfxDefaultPos, NA_SE_VO_SK_LAUGH, 0x20); thisx->focus.pos = thisx->world.pos; - if (thisx->textId == ElfMessage_GetCUpText(play)) { + if (thisx->textId == QuestHint_GetNaviTextId(play)) { this->fairyFlags |= 0x80; gSaveContext.naviTimer = 3001; } diff --git a/tools/disasm_elf_msg.py b/tools/disasm_elf_msg.py index 19ef491ddc..81c66064bf 100644 --- a/tools/disasm_elf_msg.py +++ b/tools/disasm_elf_msg.py @@ -210,32 +210,32 @@ def disas_elfmsgs(start): if condition_type == 0: if elf_message_type == 0xE0 and b1 == 0 and not (b0 & 1): - print(f"ELF_MSG_END({ARG_1}),") + print(f"QUEST_HINT_END({ARG_1}),") else: - print(f"ELF_MSG_FLAG({ARG_0}, {ARG_1}, {ARG_2}, 0x{b1:02X}), /* eventChkInf[{(b1 >> 4) & 0xF}] & 0x{1 << (b1 & 0xF):X} */") + print(f"QUEST_HINT_FLAG({ARG_0}, {ARG_1}, {ARG_2}, 0x{b1:02X}), /* eventChkInf[{(b1 >> 4) & 0xF}] & 0x{1 << (b1 & 0xF):X} */") assert b3 == 0 elif condition_type == 2: - print(f"ELF_MSG_DUNGEON_ITEM({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b1]}),") + print(f"QUEST_HINT_DUNGEON_ITEM({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b1]}),") assert b3 == 0 elif condition_type == 4: - print(f"ELF_MSG_ITEM({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b1]}, {item_ids[b3]}),") + print(f"QUEST_HINT_ITEM({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b1]}, {item_ids[b3]}),") elif condition_type == 6: condition_other_type = b1 & 0xF0 if condition_other_type == 0: - print(f"ELF_MSG_STRENGTH_UPG({ARG_0}, {ARG_1}, {ARG_2}, {b1 & 0xF}),") + print(f"QUEST_HINT_STRENGTH_UPG({ARG_0}, {ARG_1}, {ARG_2}, {b1 & 0xF}),") assert b3 == 0 elif condition_other_type == 0x10: - print(f"ELF_MSG_BOOTS({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),") + print(f"QUEST_HINT_BOOTS({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),") assert (b1 & 0xF) == 0 elif condition_other_type == 0x20: - print(f"ELF_MSG_SONG({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),") + print(f"QUEST_HINT_SONG({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),") assert (b1 & 0xF) == 0 elif condition_other_type == 0x30: - print(f"ELF_MSG_MEDALLION({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),") + print(f"QUEST_HINT_MEDALLION({ARG_0}, {ARG_1}, {ARG_2}, {item_ids[b3]}),") assert (b1 & 0xF) == 0 elif condition_other_type == 0x40: - print(f"ELF_MSG_MAGIC({ARG_0}, {ARG_1}, {ARG_2}),") + print(f"QUEST_HINT_MAGIC({ARG_0}, {ARG_1}, {ARG_2}),") assert (b1 & 0xF) == 0 assert b3 == 0 else: