mirror of
https://github.com/zeldaret/oot
synced 2026-05-24 07:11:01 -04:00
fd24ad6e67
* `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>
199 lines
6.9 KiB
C
199 lines
6.9 KiB
C
#include "global.h"
|
|
#include "z64quest_hint_commands.h"
|
|
|
|
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),
|
|
};
|
|
|
|
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 QuestHint_CheckCondition(QuestHintCmd* hintCmd) {
|
|
s32 type = hintCmd->byte0 & 0x1E;
|
|
u16 flag;
|
|
|
|
switch (type) {
|
|
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,
|
|
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);
|
|
}
|
|
}
|
|
|
|
LOG_STRING("企画外 条件", "../z_elf_message.c", 156); // "Unplanned conditions"
|
|
ASSERT(0, "0", "../z_elf_message.c", 157);
|
|
|
|
return false;
|
|
}
|
|
|
|
u32 QuestHint_CheckConditionChain(QuestHintCmd** hintCmdPtr) {
|
|
u32 allConditionsMet = true;
|
|
|
|
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;
|
|
}
|
|
|
|
*hintCmdPtr += 1;
|
|
}
|
|
|
|
if (allConditionsMet) {
|
|
return QuestHint_CheckCondition(*hintCmdPtr);
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
u32 QuestHint_CheckRandomCondition(QuestHintCmd** hintCmdPtr) {
|
|
QuestHintCmd* hintCmd = *hintCmdPtr;
|
|
u32 conditions[10];
|
|
s32 i = 0;
|
|
s32 totalChecked = 0;
|
|
s32 rand;
|
|
|
|
do {
|
|
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 none of the conditions checked were satisfied, there are none to use
|
|
if (i == 0) {
|
|
return false;
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
*hintCmdPtr += 1;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
u16 QuestHint_GetTextIdFromScript(QuestHintCmd* hintCmd) {
|
|
while (true) {
|
|
switch (hintCmd->byte0 & 0xE0) {
|
|
case (QUEST_HINT_TYPE_CHECK << 5):
|
|
if (QuestHint_CheckCondition(hintCmd)) {
|
|
return hintCmd->byte2 | 0x100;
|
|
}
|
|
break;
|
|
|
|
case (QUEST_HINT_TYPE_CHAIN << 5):
|
|
if (QuestHint_CheckConditionChain(&hintCmd)) {
|
|
return hintCmd->byte2 | 0x100;
|
|
}
|
|
break;
|
|
|
|
case (QUEST_HINT_TYPE_RANDOM << 5):
|
|
if (QuestHint_CheckRandomCondition(&hintCmd)) {
|
|
return hintCmd->byte2 | 0x100;
|
|
}
|
|
break;
|
|
|
|
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 (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);
|
|
}
|
|
|
|
hintCmd++;
|
|
}
|
|
}
|
|
|
|
u16 QuestHint_GetSariaTextId(PlayState* play) {
|
|
Player* player = GET_PLAYER(play);
|
|
QuestHintCmd* sariaQuestHints;
|
|
|
|
if (!LINK_IS_ADULT) {
|
|
if (Actor_FindNearby(play, &player->actor, ACTOR_EN_SA, 4, 800.0f) == NULL) {
|
|
sariaQuestHints = sChildSariaQuestHints;
|
|
} else {
|
|
return 0x0160; // Special text about Saria preferring to talk to you face-to-face
|
|
}
|
|
} else {
|
|
sariaQuestHints = sAdultSariaQuestHints;
|
|
}
|
|
|
|
return QuestHint_GetTextIdFromScript(sariaQuestHints);
|
|
}
|
|
|
|
u16 QuestHint_GetNaviTextId(PlayState* play) {
|
|
if (play->naviQuestHints == NULL) {
|
|
return 0;
|
|
} else {
|
|
return QuestHint_GetTextIdFromScript(play->naviQuestHints);
|
|
}
|
|
}
|