mirror of
https://github.com/zeldaret/oot.git
synced 2025-07-04 15:04:31 +00:00
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 <Dragorn421@users.noreply.github.com>
This commit is contained in:
parent
d42307561a
commit
fd24ad6e67
12 changed files with 343 additions and 290 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue