From fd24ad6e672c3175cce03d5b7f5fe2b7000f45c7 Mon Sep 17 00:00:00 2001 From: fig02 Date: Sat, 15 Oct 2022 13:24:13 -0400 Subject: [PATCH] Document elf_message scripting system (#1398) * `cUpElfMsgs` -> `cUpMsgs` Motivation: ElfMessage is the name of the system that handles c-up messages from navi, but also messages from child/adult saria so it would make sense to name this after the system name like "ElfMsg" but "cUpElf" primarily reads like (to me) "c up navi" since the actor implementing navi is EnElf I think it'd be better to clear that confusion between "navi" and "elfmsg system" by just not using "elf" in the name * Standardize c-up navi messages ElfMessage data to be named after "CUp" * -> "Navi" * Make symbols in `elf_message_` segments static * new docs * change commands, format * introduce navi file id * use enum * remove concat * add clarifying comment for skip * concat cmd type * Hints -> QuestHint * rename command header * s -> g * missed enum name * singular * missed one Co-authored-by: Dragorn421 --- include/functions.h | 4 +- include/z64.h | 4 +- include/z64elf_message.h | 129 ------------- include/z64quest_hint_commands.h | 150 +++++++++++++++ include/z64scene.h | 14 +- src/code/z_elf_message.c | 222 ++++++++++++---------- src/code/z_play.c | 2 +- src/code/z_scene.c | 8 +- src/elf_message/elf_message_field.c | 60 +++--- src/elf_message/elf_message_ydan.c | 6 +- src/overlays/actors/ovl_En_Elf/z_en_elf.c | 16 +- tools/disasm_elf_msg.py | 18 +- 12 files changed, 343 insertions(+), 290 deletions(-) delete mode 100644 include/z64elf_message.h create mode 100644 include/z64quest_hint_commands.h 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: