mirror of
https://github.com/zeldaret/ss
synced 2026-05-24 23:21:41 -04:00
1889 lines
61 KiB
C++
1889 lines
61 KiB
C++
#include "d/d_message.h"
|
|
|
|
#include "c/c_math.h"
|
|
#include "common.h"
|
|
#include "d/a/d_a_item.h"
|
|
#include "d/a/d_a_itembase.h"
|
|
#include "d/a/d_a_player.h"
|
|
#include "d/d_base.h"
|
|
#include "d/d_player.h"
|
|
#include "d/d_pouch.h"
|
|
#include "d/d_sc_game.h"
|
|
#include "d/d_stage.h"
|
|
#include "d/d_stage_mgr.h"
|
|
#include "d/d_tag_processor.h"
|
|
#include "d/d_textunk.h"
|
|
#include "d/flag/itemflag_manager.h"
|
|
#include "d/flag/sceneflag_manager.h"
|
|
#include "d/flag/storyflag_manager.h"
|
|
#include "d/lyt/d_lyt_control_game.h"
|
|
#include "d/lyt/d_lyt_demo_dowsing.h"
|
|
#include "d/lyt/d_lyt_map.h"
|
|
#include "d/lyt/d_lyt_mini_game.h"
|
|
#include "d/lyt/meter/d_lyt_meter.h"
|
|
#include "d/lyt/msg_window/d_lyt_msg_window.h"
|
|
#include "d/snd/d_snd_small_effect_mgr.h"
|
|
#include "egg/core/eggHeap.h"
|
|
#include "f/f_base.h"
|
|
#include "f/f_profile.h"
|
|
#include "f/f_profile_name.h"
|
|
#include "libms/flowfile.h"
|
|
#include "libms/libms.h"
|
|
#include "libms/msgfile.h"
|
|
#include "sized_string.h"
|
|
#include "toBeSorted/arc_managers/oarc_manager.h"
|
|
#include "toBeSorted/blur_and_palette_manager.h"
|
|
#include "toBeSorted/dowsing_target.h"
|
|
#include "toBeSorted/event_manager.h"
|
|
#include "toBeSorted/fi_context.h"
|
|
#include "toBeSorted/file_manager.h"
|
|
#include "toBeSorted/minigame_mgr.h"
|
|
#include "toBeSorted/music_mgrs.h"
|
|
#include "toBeSorted/unk_save_time.h"
|
|
|
|
#include "rvl/OS.h"
|
|
|
|
#include <cstring>
|
|
#include <stdio.h>
|
|
|
|
s32 dFlow_c::sExitId = -1;
|
|
|
|
dFlow_c::dFlow_c() {
|
|
field_0x14 = 0;
|
|
mpMsbf = nullptr;
|
|
mCurrentFlowIndex = -1;
|
|
field_0x0E = 0;
|
|
field_0x0F = 0;
|
|
field_0x10 = 1;
|
|
field_0x3C = 0;
|
|
field_0x40 = -1;
|
|
field_0x44 = -1;
|
|
mNextFiFlow = -1;
|
|
mDelayTimer = 0;
|
|
mFiSpeechArgument = -1;
|
|
}
|
|
|
|
dFlow_c::~dFlow_c() {}
|
|
|
|
u16 dFlow_c::findEntryPoint(u16 labelPart1, u16 labelPart2) {
|
|
char buf[8];
|
|
for (int i = 0; i < 8; i++) {
|
|
buf[i] = '\0';
|
|
}
|
|
u16 ret = 0xFFFF;
|
|
if (labelPart1 < 100) {
|
|
sprintf(buf, "%03d_%03d", labelPart1, labelPart2);
|
|
} else {
|
|
sprintf(buf, "%03d_%02d", labelPart1, labelPart2);
|
|
}
|
|
for (int i = 0; i < 80; i++) {
|
|
if (dMessage_c::getMsbfInfoForIndex(i) != nullptr) {
|
|
int entry = LMS_GetEntrypoint(dMessage_c::getMsbfInfoForIndex(i), buf);
|
|
if (entry >= 0) {
|
|
mpMsbf = dMessage_c::getMsbfInfoForIndex(i);
|
|
s32 fileNumber = dMessage_c::getMsbtIndexForMsbfIndex(i);
|
|
ret = entry;
|
|
dMessage_c::getInstance()->setCurrentTextFileNumber(fileNumber);
|
|
}
|
|
}
|
|
}
|
|
|
|
const char *arcName = dMessage_c::getArcNameByIndex(labelPart1 / 100, true);
|
|
dLytMsgWindow_c::getInstance()->setCurrentFlowFilename(arcName);
|
|
dLytMsgWindow_c::getInstance()->setCurrentEntrypointName(buf);
|
|
return ret;
|
|
}
|
|
|
|
u16 dFlow_c::findEntryPoint(const char *label) {
|
|
u16 ret = 0xFFFF;
|
|
for (int i = 0; i < 80; i++) {
|
|
if (dMessage_c::getMsbfInfoForIndex(i) != nullptr) {
|
|
int entry = LMS_GetEntrypoint(dMessage_c::getMsbfInfoForIndex(i), label);
|
|
if (entry >= 0) {
|
|
mpMsbf = dMessage_c::getMsbfInfoForIndex(i);
|
|
s32 fileNumber = dMessage_c::getMsbtIndexForMsbfIndex(i);
|
|
ret = entry;
|
|
dMessage_c::getInstance()->setCurrentTextFileNumber(fileNumber);
|
|
}
|
|
}
|
|
}
|
|
|
|
const char *arcName = dMessage_c::getArcNameByIndex(dLytMsgWindow_c::fn_800D7B40() / 10000, true);
|
|
dLytMsgWindow_c::getInstance()->setCurrentFlowFilename(arcName);
|
|
dLytMsgWindow_c::getInstance()->setCurrentEntrypointName(label);
|
|
return ret;
|
|
}
|
|
|
|
void dFlow_c::setNext(u16 next) {
|
|
if (next != 0xFFFF) {
|
|
if (mCurrentFlowIndex != next) {
|
|
mCurrentFlowIndex = next;
|
|
} else {
|
|
clear();
|
|
}
|
|
} else {
|
|
clear();
|
|
}
|
|
}
|
|
|
|
void dFlow_c::advanceFlow() {
|
|
bool keepGoing = true;
|
|
|
|
if (dLytMsgWindow_c::getInstance()->getTagProcessor()->getField_0x8FC() >= 0 &&
|
|
dLytMsgWindow_c::getInstance()->getTagProcessor()->getField_0x900() >= 0) {
|
|
triggerEntryPoint(
|
|
dLytMsgWindow_c::getInstance()->getTagProcessor()->getField_0x8FC(),
|
|
dLytMsgWindow_c::getInstance()->getTagProcessor()->getField_0x900()
|
|
);
|
|
field_0x0F = 1;
|
|
dLytMsgWindow_c::getInstance()->getTagProcessor()->setFields_0x8FC_0x900(-1, -1);
|
|
} else {
|
|
while (keepGoing && !vt_0x18() && !dLytMsgWindow_c::getInstance()->getField_0x815() && !checkField0x3C()) {
|
|
MsbFlowInfo *element = LMS_GetFlowElement(mpMsbf, mCurrentFlowIndex);
|
|
s32 prevIdx = mCurrentFlowIndex;
|
|
s32 type = element->type;
|
|
mCurrentTextLabelName = "";
|
|
switch (type) {
|
|
case FLOW_MESSAGE: keepGoing = handleMessage(); break;
|
|
case FLOW_BRANCH: keepGoing = handleBranch(); break;
|
|
case FLOW_EVENT:
|
|
handleEvent();
|
|
keepGoing = false;
|
|
break;
|
|
case FLOW_ENTRY: keepGoing = handleEntry(); break;
|
|
case FLOW_JUMP: keepGoing = handleJump(); break;
|
|
}
|
|
field_0x10 = prevIdx != mCurrentFlowIndex;
|
|
if (field_0x10) {
|
|
memcpy(&mFlowInfo, element, sizeof(MsbFlowInfo));
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
bool dFlow_c::advanceUntilEvent(s32 searchParam3, s32 *pOutParams1n2) {
|
|
return advanceUntil(FLOW_EVENT, searchParam3, pOutParams1n2) == true;
|
|
}
|
|
|
|
bool dFlow_c::vt_0x18() const {
|
|
bool ret = false;
|
|
if (field_0x0E && dLytMsgWindow_c::getInstance()->getField_0x815() == false) {
|
|
ret = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
struct FlowSoundDef {
|
|
/* 0x00 */ u32 mParams;
|
|
/* 0x04 */ u32 mSoundMgr;
|
|
/* 0x08 */ WZSound mSoundId;
|
|
};
|
|
|
|
static const FlowSoundDef sSoundDefs[] = {
|
|
{ 1, 0, FAN_ITEM_GET_MINI},
|
|
{ 2, 0, FAN_ITEM_GET},
|
|
{ 3, 0, FAN_HEART_GET},
|
|
{ 4, 1, SE_S_MSG_IMPORTANT},
|
|
{ 5, 1, SE_S_REACTION},
|
|
{ 6, 1, SE_S_MSG_GOOD},
|
|
{ 7, 1, SE_S_MSG_PRESAGE},
|
|
{ 8, 0, FAN_TRANSITION_IMPACT_01},
|
|
{ 9, 1, SE_S_READ_RIDDLE_A},
|
|
{10, 1, SE_S_READ_RIDDLE_B},
|
|
};
|
|
|
|
void dFlow_c::playSound(u32 params) {
|
|
if (params >= 1000) {
|
|
fn_80364FD0(ENEMY_SOUND_MGR, params);
|
|
return;
|
|
}
|
|
if (params >= 100) {
|
|
fn_803858D0(ENEMY_BGM_RELATED_MGR);
|
|
return;
|
|
}
|
|
|
|
s32 idx = -1;
|
|
for (int i = 0; i < 10; i++) {
|
|
if (sSoundDefs[i].mParams == params) {
|
|
idx = i;
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (idx < 0) {
|
|
return;
|
|
}
|
|
|
|
switch (sSoundDefs[idx].mSoundMgr) {
|
|
case 0: AnotherSoundMgr__playSound(FANFARE_SOUND_MGR, sSoundDefs[idx].mSoundId); break;
|
|
case 1: dSndSmallEffectMgr_c::GetInstance()->playSound(sSoundDefs[idx].mSoundId); break;
|
|
}
|
|
}
|
|
|
|
bool dFlow_c::handleEventInternal(const MsbFlowInfo *element) {
|
|
u32 params1n2 = element->params1n2;
|
|
switch (element->param3) {
|
|
case EVENT_SET_STORYFLAG:
|
|
StoryflagManager::sInstance->setFlag(params1n2);
|
|
if (params1n2 == 0x52) {
|
|
dLytMeter_c::GetInstance()->setMeterField_0x13775(true);
|
|
}
|
|
if (dLytMsgWindow_c::fn_800D7B40() != 50013 && dLytMsgWindow_c::fn_800D7B40() != 20061) {
|
|
if (params1n2 == 100 || params1n2 == 64 || params1n2 == 271 || params1n2 == 81 || params1n2 == 668 ||
|
|
params1n2 == 669) {
|
|
FileManager::GetInstance()->setDowsingSlotIdx(DowsingTarget::SLOT_STORY_EVENT);
|
|
} else if (params1n2 == 106 || params1n2 == 107) {
|
|
FileManager::GetInstance()->setDowsingSlotIdx(DowsingTarget::SLOT_QUEST);
|
|
}
|
|
}
|
|
break;
|
|
case EVENT_UNSET_STORYFLAG: StoryflagManager::sInstance->unsetFlag(params1n2); break;
|
|
case EVENT_SET_SCENEFLAG:
|
|
dStageMgr_c::GetInstance()->getFlagIndex();
|
|
SceneflagManager::sInstance->setFlag(0x3F, (params1n2 >> 16) & 0xFFFF);
|
|
break;
|
|
case EVENT_UNSET_SCENEFLAG:
|
|
dStageMgr_c::GetInstance()->getFlagIndex();
|
|
SceneflagManager::sInstance->unsetFlag(0x3F, (params1n2 >> 16) & 0xFFFF);
|
|
break;
|
|
case EVENT_SET_ZONEFLAG:
|
|
dStageMgr_c::GetInstance()->getFlagIndex();
|
|
SceneflagManager::sInstance->setZoneflag_i(
|
|
dStage_c::GetInstance()->getCurrRoomId(), (params1n2 >> 16) & 0xFFFF
|
|
);
|
|
break;
|
|
case EVENT_UNSET_ZONEFLAG:
|
|
dStageMgr_c::GetInstance()->getFlagIndex();
|
|
SceneflagManager::sInstance->unsetZoneflag_i(
|
|
dStage_c::GetInstance()->getCurrRoomId(), (params1n2 >> 16) & 0xFFFF
|
|
);
|
|
break;
|
|
case EVENT_DELAY:
|
|
mDelayTimer++;
|
|
if (mDelayTimer < params1n2) {
|
|
return false;
|
|
}
|
|
mDelayTimer = 0;
|
|
break;
|
|
case EVENT_LOAD_FI_FLOW:
|
|
if (params1n2 == -1) {
|
|
s32 hi, lo;
|
|
s32 selectedOption = dLytMsgWindow_c::getInstance()->getTextOptionSelection();
|
|
mFiInfo0 = FiContext::getGlobalFiInfo0(selectedOption);
|
|
switch (mFiInfo0) {
|
|
case FiContext::KEN8_Summary: {
|
|
hi = 6;
|
|
lo = 1;
|
|
mFiSpeechArgument = FiContext::getNaviTableProgressSummary();
|
|
break;
|
|
}
|
|
case 11:
|
|
// TODO: Is this one actually used? It completely duplicates
|
|
// KEN8_Hint (case 1) down below...
|
|
hi = 6;
|
|
lo = 100;
|
|
mFiSpeechArgument = FiContext::getFiAdviceHintEntry();
|
|
break;
|
|
case FiContext::KEN8_Objective: {
|
|
hi = 6;
|
|
lo = 200;
|
|
mFiSpeechArgument = FiContext::getObjective();
|
|
break;
|
|
}
|
|
case FiContext::KEN8_Analysis: {
|
|
FiAnalysisHandle handle = FiContext::getNaviTableEquipmentCheckEntry();
|
|
if (handle.isValid()) {
|
|
hi = 6;
|
|
lo = 300;
|
|
} else {
|
|
hi = 6;
|
|
lo = 301;
|
|
}
|
|
mFiSpeechArgument = 5;
|
|
break;
|
|
}
|
|
case FiContext::KEN8_PlayTime:
|
|
hi = 6;
|
|
lo = 800;
|
|
break;
|
|
case FiContext::KEN8_Advice:
|
|
hi = 6;
|
|
lo = 802;
|
|
break;
|
|
case FiContext::KEN8_Hint: {
|
|
hi = 6;
|
|
lo = 100;
|
|
mFiSpeechArgument = FiContext::getFiAdviceHintEntry();
|
|
break;
|
|
}
|
|
case FiContext::KEN8_Rumors:
|
|
hi = 6;
|
|
lo = 900;
|
|
break;
|
|
}
|
|
FiContext::do_setAdviceOptions(FiContext::getGlobalFiInfo0(selectedOption));
|
|
mNextFiFlow = lo + hi * 1000;
|
|
} else {
|
|
triggerEntryPoint((params1n2 >> 16) & 0xFFFF, params1n2 & 0xFFFF);
|
|
field_0x0F = 1;
|
|
}
|
|
break;
|
|
case EVENT_RUPEES:
|
|
if (dMessage_c::getInstance()->getField_0x2FC() != -1) {
|
|
dMessage_c::getInstance()->setField_0x2FC(0x3C);
|
|
}
|
|
dAcItem_c::addRupees(params1n2);
|
|
if ((s32)params1n2 > 0) {
|
|
dLytMeter_c::setRupyField_0x8AD(1);
|
|
}
|
|
break;
|
|
case EVENT_SET_ITEM: {
|
|
u16 flag = params1n2 & 0xFFFF;
|
|
ItemflagManager::sInstance->setItemFlag(flag);
|
|
switch (params1n2) {
|
|
case ITEM_FARORES_COURAGE:
|
|
case ITEM_NAYRUS_WISDOM:
|
|
case ITEM_DINS_POWER:
|
|
case ITEM_SOTH: FileManager::GetInstance()->setDowsingSlotIdx(DowsingTarget::SLOT_STORY_EVENT); break;
|
|
}
|
|
break;
|
|
}
|
|
case EVENT_EXIT: {
|
|
u16 id = (params1n2 >> 16) & 0xFFFF;
|
|
sExitId = id;
|
|
if ((params1n2 & 0xFFFF) == 1) {
|
|
dScGame_c::GetInstance()->triggerExit(
|
|
dStage_c::GetInstance()->getCurrRoomId(), id, SpawnInfo::RETAIN_TOD, SpawnInfo::NO_TRIAL
|
|
);
|
|
} else {
|
|
dScGame_c::GetInstance()->triggerExit(
|
|
dStage_c::GetInstance()->getCurrRoomId(), id, SpawnInfo::RETAIN_TOD, SpawnInfo::RETAIN_TRIAL
|
|
);
|
|
}
|
|
return 0;
|
|
}
|
|
case EVENT_12:
|
|
if (params1n2 == 1) {
|
|
dMessage_c::getInstance()->setField_0x2FC(-1);
|
|
} else {
|
|
dLytMeter_c::setRupyField_0x8AC(1);
|
|
dMessage_c::getInstance()->setField_0x2FC(0);
|
|
}
|
|
break;
|
|
case EVENT_COUNTER_THRESHOLD: {
|
|
u16 counter = (params1n2 >> 16) & 0xFFFF;
|
|
u16 threshold = (params1n2 & 0xFFFF);
|
|
if (counter == 0x1F5) {
|
|
counter = dAcItem_c::getRupeeCounter();
|
|
} else if (counter == 0x1ED) {
|
|
counter = dAcItem_c::getTotalSeedCount();
|
|
} else if (counter == 0x1F2) {
|
|
counter = dAcItem_c::getTotalArrowCount();
|
|
} else if (counter == 0x1F3) {
|
|
counter = dAcItem_c::getTotalBombCount();
|
|
} else {
|
|
counter = ItemflagManager::sInstance->getItemCounterOrFlag(counter);
|
|
}
|
|
|
|
if (counter >= threshold) {
|
|
mResultFromCounterCheck = 0;
|
|
} else {
|
|
mResultFromCounterCheck = 1;
|
|
}
|
|
break;
|
|
}
|
|
case EVENT_PLAY_SOUND: playSound(params1n2); break;
|
|
case EVENT_ADD_ITEM: {
|
|
u16 flag = (params1n2 >> 16) & 0xFFFF;
|
|
s16 change = (s16)(params1n2 & 0xFFFF);
|
|
s32 value = ItemflagManager::sInstance->getItemCounterOrFlag(flag);
|
|
value += change;
|
|
if (value < 0) {
|
|
value = 0;
|
|
} else if (value > 0x8000) {
|
|
value = 0x7FFF;
|
|
}
|
|
ItemflagManager::sInstance->setItemFlagOrCounterToValue(flag, value);
|
|
break;
|
|
}
|
|
case EVENT_SET_TEMPFLAG:
|
|
dStageMgr_c::GetInstance()->getFlagIndex();
|
|
SceneflagManager::sInstance->setTempflag_i(0x3F, (params1n2 >> 16) & 0xFFFF);
|
|
break;
|
|
case EVENT_UNSET_TEMPFLAG:
|
|
dStageMgr_c::GetInstance()->getFlagIndex();
|
|
SceneflagManager::sInstance->unsetTempflag_i(0x3F, (params1n2 >> 16) & 0xFFFF);
|
|
break;
|
|
case EVENT_LIGHT_PILLAR_30: {
|
|
s8 p4 = (params1n2 >> 24) & 0xFF;
|
|
s8 p1 = params1n2 & 0xFF;
|
|
s8 p3 = (params1n2 >> 16) & 0xFF;
|
|
s8 p2 = (params1n2 >> 8) & 0xFF;
|
|
s32 val = 1;
|
|
switch (p1) {
|
|
case 1: val = 4; break;
|
|
case 2: val = 3; break;
|
|
case 3: val = 5; break;
|
|
case 5: val = 7; break;
|
|
case 6: val = 8; break;
|
|
case 7: val = 9; break;
|
|
}
|
|
dMessage_c::getInstance()->setField_0x32C(val);
|
|
dMessage_c::getInstance()->setField_0x329(true);
|
|
if (dMessage_c::getInstance()->getField_0x328() == 0) {
|
|
dMessage_c::getInstance()->setField_0x328(1);
|
|
dMessage_c::getInstance()->clearLightPillarRelatedArgs();
|
|
if (dLytControlGame_c::getInstance()->isStateNormalOrNotInEvent()) {
|
|
dLytControlGame_c::getInstance()->somehowRelatedToEnteringLightPillars(val, p3, p2);
|
|
}
|
|
} else {
|
|
dLytMap_c::getInstance()->lightPillarRelated(val, p3, p2);
|
|
}
|
|
dMessage_c::getInstance()->storeLightPillarRelatedArg(p4);
|
|
break;
|
|
}
|
|
case EVENT_LIGHT_PILLAR_34: {
|
|
// TODO what do these modes do?
|
|
if (params1n2 == 1) {
|
|
if (!dLytControlGame_c::getInstance()->isNotInStateMap()) {
|
|
dLytControlGame_c::getInstance()->fn_802CCD40(true);
|
|
}
|
|
} else if (params1n2 == 2) {
|
|
dMessage_c::getInstance()->setField_0x330(1);
|
|
if (dMessage_c::getInstance()->getField_0x32C() != 4 &&
|
|
dMessage_c::getInstance()->getField_0x32C() != 12) {
|
|
dMessage_c::getInstance()->setField_0x32A(1);
|
|
}
|
|
} else {
|
|
if (dMessage_c::getInstance()->getField_0x32C() != 4 &&
|
|
dMessage_c::getInstance()->getField_0x32C() != 12) {
|
|
dMessage_c::getInstance()->setField_0x32A(1);
|
|
}
|
|
}
|
|
dMessage_c::getInstance()->setField_0x328(0);
|
|
break;
|
|
}
|
|
case EVENT_SET_STORYFLAG_217:
|
|
StoryflagManager::sInstance->setFlagOrCounterToValue(
|
|
217, dLytMsgWindow_c::getInstance()->getTextOptionSelection()
|
|
);
|
|
break;
|
|
case EVENT_DEMO_METER_ITEM_SELECT: return dLytMeter_c::GetInstance()->itemSelectDemoRelated(params1n2);
|
|
case EVENT_CAMERA_42: {
|
|
s32 p1 = (params1n2 >> 16) & 0xFFFF;
|
|
s32 p2 = params1n2 & 0xFFFF;
|
|
dScGame_c::getCamera(0)->doFn_800918E0(p1, p2);
|
|
break;
|
|
}
|
|
case EVENT_LYT_MINI_GAME: {
|
|
if (dMessage_c::getInstance()->getField_0x340() != 0) {
|
|
// cancel something minigame related if running
|
|
clearMinigame();
|
|
}
|
|
// start something minigame related
|
|
dMessage_c::getInstance()->setMiniGameVariant(params1n2);
|
|
createLytMiniGame();
|
|
break;
|
|
}
|
|
case EVENT_LYT_MINI_GAME_END:
|
|
// cancel something minigame related
|
|
clearMinigame();
|
|
break;
|
|
case EVENT_46: dMessage_c::getInstance()->setField_0x344(params1n2); break;
|
|
case EVENT_RESET_STORYFLAG: StoryflagManager::sInstance->setFlagOrCounterToValue(params1n2 & 0xFFFF, 0); break;
|
|
case EVENT_SET_ITEMFLAG: dAcItem_c::setFlag(params1n2 & 0xFFFF); break;
|
|
case EVENT_PALETTE: {
|
|
s16 p1 = (params1n2 >> 16) & 0xFFFF;
|
|
s16 p2 = params1n2 & 0xFFFF;
|
|
if (&BlurAndPaletteManager::GetInstance() != nullptr) {
|
|
BlurAndPaletteManager::GetInstance().fn_80024240(-1, p1, p2);
|
|
}
|
|
break;
|
|
}
|
|
case EVENT_DEMO_DOWSING:
|
|
if (dLytDemoDowsing_c::GetInstance() != nullptr) {
|
|
dLytDemoDowsing_c::GetInstance()->start();
|
|
}
|
|
break;
|
|
case EVENT_DEMO_METER_DOWSING: return dLytMeter_c::GetInstance()->dowsingDemoRelated(params1n2); break;
|
|
case EVENT_DEMO_METER_MINUS_BTN: return dLytMeter_c::GetInstance()->minusBtnDemoRelated(params1n2); break;
|
|
case EVENT_SELECT_STORY_DOWSING:
|
|
FileManager::GetInstance()->setDowsingSlotIdx(DowsingTarget::SLOT_STORY_EVENT);
|
|
break;
|
|
case EVENT_DEMO_COLLECTION_SCREEN:
|
|
if (!MinigameManager::isInMinigameState(MinigameManager::INSECT_CAPTURE)) {
|
|
dLytControlGame_c::getInstance()->openCollectionScreenDemo();
|
|
}
|
|
break;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool dFlow_c::handleEvent() {
|
|
MsbFlowInfo *element = LMS_GetFlowElement(mpMsbf, mCurrentFlowIndex);
|
|
u16 next = element->next;
|
|
if (handleEventInternal(element)) {
|
|
if (next != 0xFFFF) {
|
|
setNext(next);
|
|
if (checkField0x3C()) {
|
|
field_0x40 = mCurrentFlowIndex;
|
|
field_0x44 = dLytMsgWindow_c::fn_800D7B40();
|
|
}
|
|
} else if (field_0x0F != 0) {
|
|
field_0x0F = 0;
|
|
} else {
|
|
clear();
|
|
}
|
|
return true;
|
|
} else {
|
|
return false;
|
|
}
|
|
}
|
|
|
|
bool dFlow_c::handleMessage() {
|
|
char label[40];
|
|
MsbFlowInfo *flow = LMS_GetFlowElement(mpMsbf, mCurrentFlowIndex);
|
|
int hasLabel = LMS_GetLabelByTextIndex(
|
|
dMessage_c::getMsbtInfoForIndex(dMessage_c::getInstance()->getCurrentTextFileNumber()), flow->param4, label
|
|
);
|
|
mCurrentTextLabelName.set(label);
|
|
u16 next = flow->next;
|
|
// Does this make sense? Result is unused...
|
|
LMS_GetAttribute(dMessage_c::getMsbtInfoForIndex(dMessage_c::getInstance()->getCurrentTextFileNumber()), hasLabel);
|
|
if (mCurrentTextLabelName == "KEN0_08") {
|
|
// "After winning the race in the Wing Ceremony..."
|
|
// Current objective - use value from FiContext::getObjective?
|
|
if (mFiSpeechArgument < 0) {
|
|
mFiSpeechArgument = 8;
|
|
}
|
|
mCurrentTextLabelName.sprintf("KEN0_%02d", mFiSpeechArgument);
|
|
} else if (mCurrentTextLabelName == "KEN1_000") {
|
|
// "This is Skyloft..."
|
|
// Area analysis - use value from FiContext::???
|
|
if (mFiSpeechArgument < 0) {
|
|
mFiSpeechArgument = 0;
|
|
}
|
|
mCurrentTextLabelName.sprintf("KEN1_%03d", mFiSpeechArgument);
|
|
} else if (mCurrentTextLabelName == "KEN2_000") {
|
|
// "To search for Zelda..."
|
|
// Hint - use value from FiContext::getFiAdviceHintEntry?
|
|
if (mFiSpeechArgument < 0) {
|
|
mFiSpeechArgument = 2;
|
|
}
|
|
mCurrentTextLabelName.sprintf("KEN2_%03d", mFiSpeechArgument);
|
|
} else if (mCurrentTextLabelName == "KEN3_500") {
|
|
// "Master, your current selection of pouch items is..."
|
|
// Equipment focus
|
|
FiAnalysisHandle analysis = FiContext::getNaviTableEquipmentCheckEntry();
|
|
SizedString<16> label;
|
|
label.sprintf("KEN3_%03d", analysis.getEquipmentFocus());
|
|
dLytMsgWindow_c::getInstance()->getTagProcessor()->setStringArg(
|
|
dMessage_c::getTextMessageByLabel(label, true, nullptr, nullptr), 0
|
|
);
|
|
} else if (mCurrentTextLabelName == "KEN3_000") {
|
|
// "You are located in the Sealed Grounds..."
|
|
// Threat assessment
|
|
FiAnalysisHandle analysis = FiContext::getNaviTableEquipmentCheckEntry();
|
|
s16 value = analysis.getAreaIndexForFiAreaName();
|
|
if (value < 0) {
|
|
value = 0;
|
|
}
|
|
mCurrentTextLabelName.sprintf("KEN3_%03d", value);
|
|
} else if (mCurrentTextLabelName == "KEN3_501") {
|
|
// "Suitability to current location is..."
|
|
// Suitability analysis
|
|
FiAnalysisHandle analysis = FiContext::getNaviTableEquipmentCheckEntry();
|
|
s32 arg = analysis.getSuitabilityPercentageArg();
|
|
dLytMsgWindow_c::getInstance()->setNumericArg0(arg);
|
|
} else if (mCurrentTextLabelName == "KEN3_100") {
|
|
// "My projections indicate that equipping..."
|
|
// Equipment recommendation
|
|
FiAnalysisHandle analysis = FiContext::getNaviTableEquipmentCheckEntry();
|
|
s16 value = analysis.getEquipmentRecommendation();
|
|
if (value < 0) {
|
|
value = 0;
|
|
}
|
|
mCurrentTextLabelName.sprintf("KEN3_%03d", value);
|
|
} else if (mCurrentTextLabelName == "KEN3_200") {
|
|
// "To make matters worse, your Wooden Shield..."
|
|
// Shield danger (wooden vs fire, iron vs electrical)
|
|
FiAnalysisHandle analysis = FiContext::getNaviTableEquipmentCheckEntry();
|
|
s16 value = analysis.getShieldMessage();
|
|
if (value < 0) {
|
|
value = 0;
|
|
}
|
|
mCurrentTextLabelName.sprintf("KEN3_%03d", value);
|
|
} else if (mCurrentTextLabelName == "KEN4_000") {
|
|
// Your hearts have decreased quite dramatically...
|
|
s32 fiHelpIndex = FiContext::getHelpIndex();
|
|
if (fiHelpIndex < 0) {
|
|
fiHelpIndex = 0;
|
|
}
|
|
if (fiHelpIndex == 5) {
|
|
StoryflagManager::sInstance->setFlag(727);
|
|
}
|
|
mCurrentTextLabelName.sprintf("KEN4_%03d", fiHelpIndex);
|
|
} else if (mCurrentTextLabelName == "KEN5_000") {
|
|
// This is...
|
|
s32 targetActorId = FiContext::getTargetActorId();
|
|
if (targetActorId < 0) {
|
|
targetActorId = 0;
|
|
}
|
|
if (targetActorId <= 480) {
|
|
mCurrentTextLabelName.sprintf("KEN5_%03d", targetActorId);
|
|
} else {
|
|
// "My apologies. I have no relevant information on the subject in my sizable memory."
|
|
// FiHead
|
|
mCurrentTextLabelName.sprintf("KEN7_000");
|
|
}
|
|
} else if (mCurrentTextLabelName == "KEN6_000") {
|
|
// "Target lock: ..."
|
|
s32 targetActorId = FiContext::getTargetActorId();
|
|
if (targetActorId < 0) {
|
|
targetActorId = 0;
|
|
}
|
|
if (targetActorId <= 91) {
|
|
mCurrentTextLabelName.sprintf("KEN6_%03d", targetActorId);
|
|
} else {
|
|
mCurrentTextLabelName.sprintf("KEN7_000");
|
|
}
|
|
} else if (mCurrentTextLabelName == "KEN6_107") {
|
|
// "You have defeated <X> of this type of enemy. My analysis shows that your battle performance..."
|
|
s32 targetActorId = FiContext::getTargetActorId();
|
|
if (targetActorId < 0) {
|
|
targetActorId = 0;
|
|
}
|
|
u16 killCount = FileManager::GetInstance()->getEnemyKillCount(targetActorId);
|
|
u8 performance = FiContext::rateBattlePerformance(targetActorId);
|
|
if (performance == 0xFF) {
|
|
dLytMsgWindow_c::getInstance()->setNumericArg0(killCount);
|
|
// "You have defeated <X> of this enemy type. I am unable to analyze your battle performance..."
|
|
mCurrentTextLabelName.sprintf("KEN6_108");
|
|
} else {
|
|
dLytMsgWindow_c::getInstance()->setNumericArg0(killCount);
|
|
SizedString<16> tmpLabel;
|
|
// "very strong, ..., very weak"
|
|
tmpLabel.sprintf("KEN6_1%02d", performance);
|
|
dLytMsgWindow_c::getInstance()->getTagProcessor()->setStringArg(
|
|
dMessage_c::getTextMessageByLabel(tmpLabel, true, nullptr, nullptr), 0
|
|
);
|
|
}
|
|
} else if (mCurrentTextLabelName == "KEN7_000") {
|
|
// "My apologies. I have no relevant information on the subject in my sizable memory."
|
|
s32 targetActorId = FiContext::getTargetActorId();
|
|
if (targetActorId < 0) {
|
|
targetActorId = 0;
|
|
}
|
|
if (targetActorId <= 561) {
|
|
// object info
|
|
mCurrentTextLabelName.sprintf("KEN7_%03d", targetActorId);
|
|
} else {
|
|
mCurrentTextLabelName.sprintf("KEN7_000");
|
|
}
|
|
} else if (mCurrentTextLabelName == "KEN8_000" || mCurrentTextLabelName == "KEN2_096") {
|
|
// "Current Session Play Time: ... Total Play Time: ..."
|
|
s32 seconds = OS_TICKS_TO_SEC(SaveTimeRelated::GetInstance()->getField_0x08());
|
|
s32 minutes_ = seconds / 60;
|
|
s32 minutes = minutes_ % 60;
|
|
s32 hours = seconds / 3600;
|
|
if (hours > 99) {
|
|
hours = 99;
|
|
minutes = 59;
|
|
}
|
|
s32 seconds1 = OS_TICKS_TO_SEC(SaveTimeRelated::GetInstance()->fn_801907D0());
|
|
s32 minutes1_ = seconds1 / 60;
|
|
s32 minutes1 = minutes1_ % 60;
|
|
s32 hours1 = seconds1 / 3600;
|
|
if (hours1 > 999) {
|
|
hours1 = 999;
|
|
minutes1 = 59;
|
|
}
|
|
s32 time[4] = {hours, minutes, hours1, minutes1};
|
|
dLytMsgWindow_c::getInstance()->setNumericArgs(time, 4);
|
|
} else if (mCurrentTextLabelName == "KEN9_000") {
|
|
// Random hint
|
|
s32 v;
|
|
if (StoryflagManager::sInstance->getCounterOrFlag(530)) {
|
|
// "When you require my analysis..."
|
|
v = 200;
|
|
} else if (dStageMgr_c::GetInstance()->getSTIFbyte4() == 0) {
|
|
// Sky rumor
|
|
v = cM::rndInt(30);
|
|
} else {
|
|
// Elsewhere rumor
|
|
v = cM::rndInt(30) + 30;
|
|
}
|
|
mCurrentTextLabelName.sprintf("KEN9_%03d", v);
|
|
}
|
|
|
|
if (dLytMsgWindow_c::getInstance()->setCurrentLabelName(mCurrentTextLabelName, false) == true) {
|
|
if (!dLytMsgWindow_c::getInstance()->getField_0x80D()) {
|
|
field_0x14 = 1;
|
|
}
|
|
if (next != 0xFFFF) {
|
|
setNext(next);
|
|
} else {
|
|
clear();
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
u16 dFlow_c::getSwitchChoice(const MsbFlowInfo *element, u16 param) const {
|
|
u16 result = 0;
|
|
if (param < BRANCH_14 || param > BRANCH_16) {
|
|
result = (this->*(sBranchHandlers[param]))(element);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
inline void syncFiButtonText(s32 argIdx, s32 btnIdx) {
|
|
dTagProcessor_c *p = dLytMsgWindow_c::getInstance()->getTagProcessor();
|
|
p->setStringArg(FiContext::getMessageForFiInfo(argIdx), btnIdx);
|
|
}
|
|
|
|
inline void setFiButtonTextDirectly(s32 textLabel, s32 btnIdx) {
|
|
dTagProcessor_c *p = dLytMsgWindow_c::getInstance()->getTagProcessor();
|
|
p->setStringArg(FiContext::getButtonText(textLabel), btnIdx);
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler00(const MsbFlowInfo *element) const {
|
|
return dLytMsgWindow_c::getInstance()->getTextOptionSelection();
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler01(const MsbFlowInfo *element) const {
|
|
return dLytMsgWindow_c::getInstance()->getTextOptionSelection();
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler02(const MsbFlowInfo *element) const {
|
|
if (FiContext::getIsInFiMainMenuChecked()) {
|
|
if (dLytMsgWindow_c::getInstance()->getTextOptionSelection() == 0 &&
|
|
FiContext::getGlobalFiInfo0(0) == FiContext::KEN8_Advice) {
|
|
// HACK (?): If the user presses "Advice" on the Fi main menu,
|
|
// which is known to be button 0, update Fi's buttons since that
|
|
// menu isn't entirely integrated into the flow
|
|
FiContext::do_resetAdviceOptions();
|
|
syncFiButtonText(0, 0);
|
|
syncFiButtonText(1, 1);
|
|
syncFiButtonText(2, 2);
|
|
} else {
|
|
FiContext::setIsInFiMainMenu(false);
|
|
}
|
|
}
|
|
return dLytMsgWindow_c::getInstance()->getTextOptionSelection();
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler03(const MsbFlowInfo *element) const {
|
|
return !StoryflagManager::sInstance->getCounterOrFlag(element->params1n2);
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler04(const MsbFlowInfo *element) const {
|
|
return 0;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler05(const MsbFlowInfo *element) const {
|
|
return !SceneflagManager::sInstance->checkZoneflag_i(
|
|
dStage_c::GetInstance()->getCurrRoomId(), element->params1n2 & 0xFFFF
|
|
);
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler06(const MsbFlowInfo *element) const {
|
|
return !SceneflagManager::sInstance->checkFlag(0x3F, (element->params1n2 & 0xFFFF));
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler07(const MsbFlowInfo *element) const {
|
|
return mResultFromCounterCheck != 0;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler08(const MsbFlowInfo *element) const {
|
|
return mResultFromCounterCheck != 0;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler09(const MsbFlowInfo *element) const {
|
|
return !SceneflagManager::sInstance->checkTempflag_i(0x3F, element->params1n2 & 0xFFFF);
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler10(const MsbFlowInfo *element) const {
|
|
u16 threshold = element->params1n2 & 0xFFFF;
|
|
return threshold > dAcItem_c::getRupeeCounter();
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler11(const MsbFlowInfo *element) const {
|
|
return (s32)(cM::rnd() * 2.0f);
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler12(const MsbFlowInfo *element) const {
|
|
return (s32)(cM::rnd() * 3.0f);
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler13(const MsbFlowInfo *element) const {
|
|
return (s32)(cM::rnd() * 4.0f);
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler14(const MsbFlowInfo *element) const {
|
|
return 0;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler15(const MsbFlowInfo *element) const {
|
|
return 0;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler16(const MsbFlowInfo *element) const {
|
|
return 0;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler17(const MsbFlowInfo *element) const {
|
|
bool ret = false;
|
|
if (adventurePouchFindItemSlot(ITEM_NONE) != POUCH_SLOT_NONE) {
|
|
ret = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler18(const MsbFlowInfo *element) const {
|
|
bool ret = false;
|
|
if (!getLinkPtr()->isItemFairyFromBugnet()) {
|
|
ret = true;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler19(const MsbFlowInfo *element) const {
|
|
u16 ret = 1;
|
|
switch (element->params1n2 & 0xFFFF) {
|
|
case 0:
|
|
if (dAcPy_c::getCurrentlyEquippedShieldType() != 4) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (adventurePouchFindItemSlot(ITEM_BOTTLE) != POUCH_SLOT_NONE) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 2:
|
|
if (adventurePouchFindItemSlot(ITEM_HOT_SOUP) != POUCH_SLOT_NONE) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 3:
|
|
if (adventurePouchFindItemSlot(ITEM_COLD_SOUP) != POUCH_SLOT_NONE) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 4:
|
|
if (adventurePouchFindItemSlot(ITEM_STAMINA_POTION) != POUCH_SLOT_NONE ||
|
|
adventurePouchFindItemSlot(ITEM_STAMINA_POTION_PLUS) != POUCH_SLOT_NONE) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 5:
|
|
if (adventurePouchFindItemSlot(ITEM_MUSHROOM_SPORES) != POUCH_SLOT_NONE ||
|
|
adventurePouchFindItemSlot(ITEM_GLITTERING_SPORES) != POUCH_SLOT_NONE) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 6: {
|
|
FiAnalysisHandle handle = FiContext::getNaviTableEquipmentCheckEntry();
|
|
switch (handle.getThreatenedShield()) {
|
|
case 0:
|
|
if (dAcPy_c::getCurrentlyEquippedShieldType() == 0) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 1:
|
|
if (dAcPy_c::getCurrentlyEquippedShieldType() == 1) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
case 7:
|
|
if (adventurePouchFindItemSlot(ITEM_SACRED_WATER) != POUCH_SLOT_NONE) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 8:
|
|
if (adventurePouchCountItem(ITEM_HEART_MEDAL) != 0) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
case 9:
|
|
if (hasAnyShields()) {
|
|
ret = 0;
|
|
}
|
|
break;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler20(const MsbFlowInfo *element) const {
|
|
u16 ret = 0;
|
|
if (itemCheckFindItemSlot(ITEM_NONE) != ITEM_CHECK_SLOT_NONE) {
|
|
ret = 1;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler21(const MsbFlowInfo *element) const {
|
|
u16 ret = 0;
|
|
if (shouldHideKillCountForActor(FiContext::getTargetActorId())) {
|
|
ret = 1;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
u16 dFlow_c::branchHandler22(const MsbFlowInfo *element) const {
|
|
u16 ret = StoryflagManager::sInstance->getCounterOrFlag(692);
|
|
if (ret > 3) {
|
|
ret = 3;
|
|
}
|
|
return ret;
|
|
}
|
|
|
|
dFlow_c::BranchHandler dFlow_c::sBranchHandlers[] = {
|
|
&dFlow_c::branchHandler00, // BRANCH_SELECTED_OPTION_0
|
|
&dFlow_c::branchHandler01, // BRANCH_SELECTED_OPTION_1
|
|
&dFlow_c::branchHandler02, // BRANCH_SELECTED_OPTION_FI
|
|
&dFlow_c::branchHandler03, // BRANCH_STORYFLAG
|
|
&dFlow_c::branchHandler04, // BRANCH_NONE
|
|
&dFlow_c::branchHandler05, // BRANCH_ZONEFLAG
|
|
&dFlow_c::branchHandler06, // BRANCH_SCENEFLAG
|
|
&dFlow_c::branchHandler07, // BRANCH_EVENT_COUNTER_THRESHOLD_1
|
|
&dFlow_c::branchHandler08, // BRANCH_EVENT_COUNTER_THRESHOLD_2
|
|
&dFlow_c::branchHandler09, // BRANCH_TEMPFLAG
|
|
&dFlow_c::branchHandler10, // BRANCH_CURRENT_RUPEES
|
|
&dFlow_c::branchHandler11, // BRANCH_RAND_2
|
|
&dFlow_c::branchHandler12, // BRANCH_RAND_3
|
|
&dFlow_c::branchHandler13, // BRANCH_RAND_4
|
|
&dFlow_c::branchHandler14, // BRANCH_14
|
|
&dFlow_c::branchHandler15, // BRANCH_15
|
|
&dFlow_c::branchHandler16, // BRANCH_16
|
|
&dFlow_c::branchHandler17, // BRANCH_FREE_SPACE_IN_POUCH
|
|
&dFlow_c::branchHandler18, // BRANCH_18
|
|
&dFlow_c::branchHandler19, // BRANCH_19
|
|
&dFlow_c::branchHandler20, // BRANCH_FREE_SPACE_IN_ITEM_CHECK
|
|
&dFlow_c::branchHandler21, // BRANCH_TARGET_ACTOR_HAS_KILL_COUNT
|
|
&dFlow_c::branchHandler22, // BRANCH_22
|
|
};
|
|
|
|
bool dFlow_c::handleBranch() {
|
|
MsbFlowInfo *info = LMS_GetFlowElement(mpMsbf, mCurrentFlowIndex);
|
|
u16 next = getSwitchChoice(info, info->param3);
|
|
u16 *branchPoints = LMS_GetBranchPoints(mpMsbf, mCurrentFlowIndex);
|
|
if (info->param5 != 0xFFFF) {
|
|
setNext(branchPoints[next]);
|
|
} else {
|
|
clear();
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool dFlow_c::handleEntry() {
|
|
MsbFlowInfo *element = LMS_GetFlowElement(mpMsbf, mCurrentFlowIndex);
|
|
setNext(element->next);
|
|
return true;
|
|
}
|
|
|
|
bool dFlow_c::handleJump() {
|
|
// unimplemented
|
|
return true;
|
|
}
|
|
|
|
void dFlow_c::triggerEntryPoint(s32 labelPart1, s32 labelPart2) {
|
|
if (labelPart1 == 6) {
|
|
// "Your hearts have decreased quite dramatically..."
|
|
// 400 -> may introduce heart dowsing
|
|
// 401 -> no heart dowsing introduction
|
|
if (labelPart2 == 400) {
|
|
FiContext::setField_0x48(true);
|
|
labelPart2 = 401;
|
|
} else if (labelPart2 == 401) {
|
|
StoryflagManager::sInstance->setFlag(808);
|
|
// Don't introduce heart dowsing in areas where you might
|
|
// not be able to dowse
|
|
if (dStageMgr_c::GetInstance()->isAreaTypeNormal()) {
|
|
labelPart2 = 400;
|
|
} else {
|
|
labelPart2 = 401;
|
|
}
|
|
} else if (labelPart2 == 402 && (dLytMsgWindow_c::getInstance()->getTagProcessor()->getField_0x8FC() < 0 ||
|
|
dLytMsgWindow_c::getInstance()->getTagProcessor()->getField_0x900() < 0)) {
|
|
// "You have elected to engage Hero Mode..."
|
|
FiContext::setField_0x4A(true);
|
|
labelPart2 = 401;
|
|
}
|
|
}
|
|
|
|
if (labelPart1 == 6 && labelPart2 == 801) {
|
|
// "You called for me, Master?"
|
|
FiContext::do_prepareFiCallOptions();
|
|
FiContext::setIsInFiMainMenu(true);
|
|
FiContext::do_fn_8016CB40();
|
|
syncFiButtonText(0, 0);
|
|
syncFiButtonText(1, 1);
|
|
syncFiButtonText(2, 2);
|
|
setFiButtonTextDirectly(FiContext::KEN8_Nevermind, 3);
|
|
} else if (labelPart1 == 6 && labelPart2 == 802) {
|
|
// Doesn't seem to exist in the files
|
|
FiContext::setIsInFiMainMenu(true);
|
|
syncFiButtonText(0, 0);
|
|
syncFiButtonText(1, 1);
|
|
syncFiButtonText(2, 2);
|
|
setFiButtonTextDirectly(FiContext::KEN8_Nevermind, 3);
|
|
}
|
|
u16 entry = findEntryPoint(labelPart1, labelPart2);
|
|
start(entry);
|
|
}
|
|
|
|
void dFlow_c::triggerEntryPoint(const char *label) {
|
|
u16 entry = findEntryPoint(label);
|
|
start(entry);
|
|
}
|
|
|
|
u16 dFlow_c::getField_0x44() const {
|
|
return field_0x44;
|
|
}
|
|
|
|
u16 dFlow_c::getNextFiFlow() const {
|
|
return mNextFiFlow;
|
|
}
|
|
|
|
bool dFlow_c::triggerEntryPointChecked(s32 labelPart1, s32 labelPart2) {
|
|
if (checkField0x3C()) {
|
|
s32 old = field_0x40;
|
|
dFlow_c::triggerEntryPoint(labelPart1, labelPart2);
|
|
setNext(old);
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void dFlow_c::setField0x3C() {
|
|
field_0x3C = 1;
|
|
}
|
|
|
|
bool dFlow_c::checkField0x3C() const {
|
|
return field_0x3C == 1;
|
|
}
|
|
|
|
extern "C" dFlow_c *CURRENT_ACTOR_EVENT_FLOW_MANAGER;
|
|
void dFlow_c::start(u16 entry) {
|
|
field_0x0E = 0;
|
|
field_0x0F = 0;
|
|
field_0x3C = 0;
|
|
field_0x40 = -1;
|
|
field_0x44 = -1;
|
|
mNextFiFlow = -1;
|
|
mDelayTimer = 0;
|
|
std::memset(&mFlowInfo, 0, sizeof(MsbFlowInfo));
|
|
CURRENT_ACTOR_EVENT_FLOW_MANAGER = this;
|
|
field_0x0C = 0xFFFF;
|
|
mCurrentFlowIndex = -1;
|
|
field_0x10 = 1;
|
|
setNext(entry);
|
|
}
|
|
|
|
bool dFlow_c::advanceUntil(s32 searchType, s32 searchParam3, s32 *pOutParams1n2) {
|
|
bool keepGoing = true;
|
|
while (keepGoing && !vt_0x18()) {
|
|
MsbFlowInfo *element = LMS_GetFlowElement(mpMsbf, mCurrentFlowIndex);
|
|
s32 type = element->type;
|
|
if (searchType == type) {
|
|
if (element->type == FLOW_EVENT) {
|
|
if (element->param3 == searchParam3) {
|
|
if (pOutParams1n2 != nullptr) {
|
|
*pOutParams1n2 = element->params1n2;
|
|
}
|
|
return true;
|
|
}
|
|
} else {
|
|
return true;
|
|
}
|
|
}
|
|
switch (type) {
|
|
case FLOW_MESSAGE:
|
|
// Skip text processing, simply advance
|
|
setNext(element->next);
|
|
keepGoing = true;
|
|
break;
|
|
case FLOW_BRANCH:
|
|
if (element->param3 <= BRANCH_SELECTED_OPTION_FI) {
|
|
// Skip evaluating if next branch depends on user input
|
|
keepGoing = false;
|
|
} else {
|
|
// Otherwise
|
|
keepGoing = handleBranch();
|
|
}
|
|
break;
|
|
case FLOW_EVENT:
|
|
switch (element->param3) {
|
|
case EVENT_LOAD_FI_FLOW:
|
|
case EVENT_COUNTER_THRESHOLD:
|
|
case 27: keepGoing = handleEvent(); continue;
|
|
case EVENT_LIGHT_PILLAR_34:
|
|
if (element->params1n2 == 2) {
|
|
keepGoing = false;
|
|
continue;
|
|
}
|
|
// fall-through
|
|
default:
|
|
setNext(element->next);
|
|
keepGoing = true;
|
|
break;
|
|
}
|
|
break;
|
|
case FLOW_ENTRY: keepGoing = handleEntry(); break;
|
|
case FLOW_JUMP: keepGoing = handleJump(); break;
|
|
}
|
|
}
|
|
return 0;
|
|
}
|
|
|
|
// TODO: Used KEN6 as reference, will be set from dAcBase_c::targetFiTextId (0x114)
|
|
static const s32 sActorsWithoutKillCount[] = {
|
|
0, // Remlit (Day)
|
|
1, // Remlit (Night)
|
|
10, // Moldarach
|
|
46, // Stalmaster
|
|
47, // LD-002S Scervo
|
|
48, // Koloktos
|
|
49, // Ghirahim (G1)
|
|
50, // Ghirahim (G2)
|
|
51, // Ghirahim (G3.1)
|
|
52, // The Imprisoned
|
|
53, // The Imprisoned
|
|
54, // The Imprisoned
|
|
55, // Demise
|
|
65, // Scaldera
|
|
67, // <?>
|
|
77, // Tentalus
|
|
81, // Peahat
|
|
87, // Sentrobe Bomb
|
|
88, // LD-003D Dreadfuse
|
|
89, // Ghirahim (G3.2)
|
|
90, // Ghirahim (G3.3)
|
|
-1 // <end of array>
|
|
};
|
|
|
|
bool dFlow_c::shouldHideKillCountForActor(s32 id) const {
|
|
for (s32 i = 0; sActorsWithoutKillCount[i] >= 0; i++) {
|
|
if (sActorsWithoutKillCount[i] == id) {
|
|
return true;
|
|
}
|
|
}
|
|
return false;
|
|
}
|
|
|
|
void dFlow_c::clear() {
|
|
mCurrentFlowIndex = -1;
|
|
field_0x0E = 1;
|
|
field_0x3C = 0;
|
|
field_0x40 = -1;
|
|
field_0x44 = -1;
|
|
}
|
|
|
|
void dFlow_c::createLytMiniGame() {
|
|
if (dLytMiniGame_c::GetInstance() == nullptr) {
|
|
switch (dMessage_c::getInstance()->getMiniGameVariant()) {
|
|
case 0:
|
|
dBase_c::createBase(fProfile::LYT_MINI_GAME, dLytControlGame_c::getInstance(), 11, fBase_c::OTHER);
|
|
break;
|
|
case 1:
|
|
dBase_c::createBase(fProfile::LYT_MINI_GAME, dLytControlGame_c::getInstance(), 10, fBase_c::OTHER);
|
|
break;
|
|
case 2:
|
|
dBase_c::createBase(fProfile::LYT_MINI_GAME, dLytControlGame_c::getInstance(), 12, fBase_c::OTHER);
|
|
break;
|
|
case 3:
|
|
dBase_c::createBase(fProfile::LYT_MINI_GAME, dLytControlGame_c::getInstance(), 14, fBase_c::OTHER);
|
|
break;
|
|
case 4:
|
|
dBase_c::createBase(fProfile::LYT_MINI_GAME, dLytControlGame_c::getInstance(), 13, fBase_c::OTHER);
|
|
break;
|
|
case 5:
|
|
dBase_c::createBase(fProfile::LYT_MINI_GAME, dLytControlGame_c::getInstance(), 2, fBase_c::OTHER);
|
|
break;
|
|
case 6:
|
|
dBase_c::createBase(fProfile::LYT_MINI_GAME, dLytControlGame_c::getInstance(), 16, fBase_c::OTHER);
|
|
break;
|
|
case 7:
|
|
dBase_c::createBase(fProfile::LYT_MINI_GAME, dLytControlGame_c::getInstance(), 15, fBase_c::OTHER);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dFlow_c::clearMinigame() {
|
|
if (dMessage_c::getInstance()->getField_0x340()) {
|
|
switch (dMessage_c::getInstance()->getMiniGameVariant()) {
|
|
case 0:
|
|
case 1:
|
|
case 4:
|
|
case 5:
|
|
if (dLytMiniGame_c::GetInstance() != nullptr) {
|
|
dLytMiniGame_c::GetInstance()->scoreRelated();
|
|
}
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
case 6:
|
|
case 7:
|
|
if (dLytMiniGame_c::GetInstance() != nullptr) {
|
|
dLytMiniGame_c::GetInstance()->timeRelated();
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
dMessage_c::getInstance()->setField_0x340(0);
|
|
dMessage_c::getInstance()->setMiniGameVariant(8);
|
|
}
|
|
|
|
SPECIAL_BASE_PROFILE(MESSAGE, dMessage_c, fProfile::MESSAGE, 0x2A8, 0);
|
|
|
|
static const char *sMsbtFileNames[82] = {
|
|
"000-Test.msbt",
|
|
"001-Action.msbt",
|
|
"002-System.msbt",
|
|
"003-ItemGet.msbt",
|
|
"004-Object.msbt",
|
|
"005-Tutorial.msbt",
|
|
"006-KenseiNormal.msbt",
|
|
"006-1KenseiNormal.msbt",
|
|
"006-2KenseiNormal.msbt",
|
|
"006-3KenseiNormal.msbt",
|
|
"006-4KenseiNormal.msbt",
|
|
"006-5KenseiNormal.msbt",
|
|
"006-6KenseiNormal.msbt",
|
|
"006-7KenseiNormal.msbt",
|
|
"006-8KenseiNormal.msbt",
|
|
"006-9KenseiNormal.msbt",
|
|
"007-MapText.msbt",
|
|
"008-Hint.msbt",
|
|
"word.msbt",
|
|
"100-Town.msbt",
|
|
"101-Shop.msbt",
|
|
"102-Zelda.msbt",
|
|
"103-DaiShinkan.msbt",
|
|
"104-Rival.msbt",
|
|
"105-Terry.msbt",
|
|
"106-DrugStore.msbt",
|
|
"107-Kanban.msbt",
|
|
"108-ShinkanA.msbt",
|
|
"109-TakeGoron.msbt",
|
|
"110-DivingGame.msbt",
|
|
"111-FortuneTeller.msbt",
|
|
"112-Trustee.msbt",
|
|
"113-RemodelStore.msbt",
|
|
"114-Friend.msbt",
|
|
"115-Town2.msbt",
|
|
"116-InsectGame.msbt",
|
|
"117-Pumpkin.msbt",
|
|
"118-Town3.msbt",
|
|
"119-Captain.msbt",
|
|
"120-Nushi.msbt",
|
|
"121-AkumaKun.msbt",
|
|
"122-Town4.msbt",
|
|
"123-Town5.msbt",
|
|
"124-Town6.msbt",
|
|
"125-D3.msbt",
|
|
"150-Siren.msbt",
|
|
"198-Test.msbt",
|
|
"199-Demo.msbt",
|
|
"200-Forest.msbt",
|
|
"201-ForestD1.msbt",
|
|
"202-ForestD2.msbt",
|
|
"203-ForestF2.msbt",
|
|
"204-ForestF3.msbt",
|
|
"250-ForestSiren.msbt",
|
|
"251-Salvage.msbt",
|
|
"299-Demo.msbt",
|
|
"300-Mountain.msbt",
|
|
"301-MountainD1.msbt",
|
|
"302-Anahori.msbt",
|
|
"303-MountainF2.msbt",
|
|
"304-MountainD2.msbt",
|
|
"305-MountainF3.msbt",
|
|
"350-MountainSiren.msbt",
|
|
"351-Salvage.msbt",
|
|
"399-Demo.msbt",
|
|
"400-Desert.msbt",
|
|
"401-DesertD2.msbt",
|
|
"402-DesertF2.msbt",
|
|
"403-DesertD1.msbt",
|
|
"404-DesertF3.msbt",
|
|
"405-DesertD2Clear.msbt",
|
|
"406-TrolleyRace.msbt",
|
|
"450-DesertSiren.msbt",
|
|
"451-Salvage.msbt",
|
|
"460-RairyuMinigame.msbt",
|
|
"499-Demo.msbt",
|
|
"500-CenterField.msbt",
|
|
"501-Inpa.msbt",
|
|
"502-CenterFieldBack.msbt",
|
|
"503-Goron.msbt",
|
|
"510-Salvage.msbt",
|
|
"599-Demo.msbt",
|
|
};
|
|
|
|
static char *sMsbfFileNames[80] = {
|
|
"000-Test.msbf",
|
|
"001-Action.msbf",
|
|
"002-System.msbf",
|
|
"003-ItemGet.msbf",
|
|
"004-Object.msbf",
|
|
"005-Tutorial.msbf",
|
|
"006-KenseiNormal.msbf",
|
|
"006-1KenseiNormal.msbf",
|
|
"006-2KenseiNormal.msbf",
|
|
"006-3KenseiNormal.msbf",
|
|
"006-4KenseiNormal.msbf",
|
|
"006-5KenseiNormal.msbf",
|
|
"006-6KenseiNormal.msbf",
|
|
"006-7KenseiNormal.msbf",
|
|
"006-8KenseiNormal.msbf",
|
|
"006-9KenseiNormal.msbf",
|
|
"008-Hint.msbf",
|
|
"100-Town.msbf",
|
|
"101-Shop.msbf",
|
|
"102-Zelda.msbf",
|
|
"103-DaiShinkan.msbf",
|
|
"104-Rival.msbf",
|
|
"105-Terry.msbf",
|
|
"106-DrugStore.msbf",
|
|
"107-Kanban.msbf",
|
|
"108-ShinkanA.msbf",
|
|
"109-TakeGoron.msbf",
|
|
"110-DivingGame.msbf",
|
|
"111-FortuneTeller.msbf",
|
|
"112-Trustee.msbf",
|
|
"113-RemodelStore.msbf",
|
|
"114-Friend.msbf",
|
|
"115-Town2.msbf",
|
|
"116-InsectGame.msbf",
|
|
"117-Pumpkin.msbf",
|
|
"118-Town3.msbf",
|
|
"119-Captain.msbf",
|
|
"120-Nushi.msbf",
|
|
"121-AkumaKun.msbf",
|
|
"122-Town4.msbf",
|
|
"123-Town5.msbf",
|
|
"124-Town6.msbf",
|
|
"125-D3.msbf",
|
|
"150-Siren.msbf",
|
|
"198-Test.msbf",
|
|
"199-Demo.msbf",
|
|
"200-Forest.msbf",
|
|
"201-ForestD1.msbf",
|
|
"202-ForestD2.msbf",
|
|
"203-ForestF2.msbf",
|
|
"204-ForestF3.msbf",
|
|
"250-ForestSiren.msbf",
|
|
"251-Salvage.msbf",
|
|
"299-Demo.msbf",
|
|
"300-Mountain.msbf",
|
|
"301-MountainD1.msbf",
|
|
"302-Anahori.msbf",
|
|
"303-MountainF2.msbf",
|
|
"304-MountainD2.msbf",
|
|
"305-MountainF3.msbf",
|
|
"350-MountainSiren.msbf",
|
|
"351-Salvage.msbf",
|
|
"399-Demo.msbf",
|
|
"400-Desert.msbf",
|
|
"401-DesertD2.msbf",
|
|
"402-DesertF2.msbf",
|
|
"403-DesertD1.msbf",
|
|
"404-DesertF3.msbf",
|
|
"405-DesertD2Clear.msbf",
|
|
"406-TrolleyRace.msbf",
|
|
"450-DesertSiren.msbf",
|
|
"451-Salvage.msbf",
|
|
"460-RairyuMinigame.msbf",
|
|
"499-Demo.msbf",
|
|
"500-CenterField.msbf",
|
|
"501-Inpa.msbf",
|
|
"502-CenterFieldBack.msbf",
|
|
"503-Goron.msbf",
|
|
"510-Salvage.msbf",
|
|
"599-Demo.msbf",
|
|
};
|
|
|
|
dMessage_c *dMessage_c::sInstance;
|
|
dTagProcessor_c *dMessage_c::sTagProcessor;
|
|
|
|
static void *msbAlloc(size_t size) {
|
|
if (UnkTextThing::getInstance()->getShouldHookAllocations() == false) {
|
|
return EGG::Heap::alloc(size, 0x20, nullptr);
|
|
} else {
|
|
return UnkTextThing::getInstance()->allocUnk(size, 0x20);
|
|
}
|
|
}
|
|
|
|
static void msbFree(void *ptr) {
|
|
if (UnkTextThing::getInstance()->getShouldHookAllocations() == false) {
|
|
EGG::Heap::free(ptr, nullptr);
|
|
} else {
|
|
UnkTextThing::getInstance()->destroyUnk(ptr);
|
|
}
|
|
}
|
|
|
|
dMessage_c::dMessage_c() {
|
|
sInstance = this;
|
|
}
|
|
|
|
int dMessage_c::create() {
|
|
mLanguage = getLanguageIdentifier();
|
|
|
|
mCurrentTextFileNumber = -1;
|
|
field_0x2FC = 0;
|
|
field_0x344 = 0;
|
|
LMS_SetMemFuncs(msbAlloc, msbFree);
|
|
setZevFromMsbArc();
|
|
|
|
for (s32 i = 0; i < 82; i++) {
|
|
SizedString<0x40> fileName = getMsbtFileName(i);
|
|
s32 num = getMsbtNumberByIndex(i);
|
|
void *data = getDataFromMsbArc(num, fileName, true);
|
|
if (data == nullptr) {
|
|
mpMsgs[i] = nullptr;
|
|
} else {
|
|
mpMsgs[i] = LMS_InitMessage(data);
|
|
}
|
|
}
|
|
|
|
for (s32 i = 0; i < 80; i++) {
|
|
SizedString<0x40> fileName = getMsbfFileName(i);
|
|
s32 num = getMsbfNumberByIndex(i);
|
|
void *data = getDataFromMsbArc(num, fileName, true);
|
|
if (data == nullptr) {
|
|
mpFlows[i] = nullptr;
|
|
} else {
|
|
mpFlows[i] = LMS_InitFlow(data);
|
|
}
|
|
}
|
|
|
|
sTagProcessor = new dTagProcessor_c();
|
|
FiContext::create();
|
|
reset();
|
|
return SUCCEEDED;
|
|
}
|
|
|
|
int dMessage_c::doDelete() {
|
|
UnkTextThing::getInstance()->destroy();
|
|
if (sTagProcessor != nullptr) {
|
|
delete sTagProcessor;
|
|
sTagProcessor = nullptr;
|
|
}
|
|
|
|
for (int i = 0; i < 82; i++) {
|
|
if (mpMsgs[i] != nullptr) {
|
|
LMS_CloseMessage(mpMsgs[i]);
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < 80; i++) {
|
|
if (mpFlows[i] != nullptr) {
|
|
LMS_CloseFlow(mpFlows[i]);
|
|
}
|
|
}
|
|
return SUCCEEDED;
|
|
}
|
|
|
|
int dMessage_c::execute() {
|
|
if (field_0x2FC != 0 && !EventManager::isInEvent()) {
|
|
field_0x2FC = 0;
|
|
}
|
|
|
|
if (field_0x2FC > 0) {
|
|
field_0x2FC--;
|
|
}
|
|
executeMinigame();
|
|
sTagProcessor->execute();
|
|
|
|
return SUCCEEDED;
|
|
}
|
|
|
|
int dMessage_c::draw() {
|
|
return SUCCEEDED;
|
|
}
|
|
|
|
const wchar_t *dMessage_c::getTextMessageByLabel(const char *label, bool global, wchar_t *dstBuf, u32 maxLen) {
|
|
return sInstance->getTextMessageByLabelInternal(label, nullptr, global, dstBuf, maxLen);
|
|
}
|
|
|
|
const wchar_t *dMessage_c::getTextMessageByLabel(
|
|
const char *label, dTagProcessor_c *pTagProcessor, bool global, wchar_t *dstBuf, u32 maxLen
|
|
) {
|
|
return sInstance->getTextMessageByLabelInternal(label, pTagProcessor, global, dstBuf, maxLen);
|
|
}
|
|
|
|
const wchar_t *dMessage_c::formatText(const wchar_t *text) {
|
|
return sInstance->formatTextInternal(text);
|
|
}
|
|
|
|
const wchar_t *dMessage_c::getTextMessageByLabelInternal(
|
|
const char *label, dTagProcessor_c *pTagProcessor, bool global, wchar_t *dstBuf, u32 maxLen
|
|
) {
|
|
s32 fileIndex = mCurrentTextFileNumber;
|
|
MsbtInfo *info = nullptr;
|
|
|
|
if (global) {
|
|
fileIndex = getMsbtIndexForLabelInternal(label);
|
|
}
|
|
|
|
if (fileIndex >= 0) {
|
|
info = getMsbtInfoForIndex(fileIndex);
|
|
}
|
|
|
|
const wchar_t *text = LMS_GetTextByLabel(info, label);
|
|
if (pTagProcessor == nullptr) {
|
|
pTagProcessor = sTagProcessor;
|
|
}
|
|
|
|
u32 outLen = 0;
|
|
s32 textIdx = LMS_GetTextIndexByLabel(info, label);
|
|
MsbtAttrInfo *att = LMS_GetAttribute(info, textIdx);
|
|
pTagProcessor->setMsgWindowSubtype(att->c_0x00);
|
|
pTagProcessor->setField_0x90D(att->c_0x01);
|
|
|
|
// Strip trailing newline
|
|
wchar_t *end;
|
|
s32 i;
|
|
|
|
if (dstBuf != nullptr) {
|
|
pTagProcessor->format(nullptr, text, dstBuf, maxLen, &outLen, nullptr);
|
|
i = outLen - 1;
|
|
end = &dstBuf[i];
|
|
for (; i > 0; i--) {
|
|
if (*end != L'\n') {
|
|
break;
|
|
}
|
|
*end-- = L'\0';
|
|
}
|
|
// no return - might be intentional since dstBuf already has the result
|
|
} else {
|
|
static wchar_t sBuf[0x400] = {};
|
|
pTagProcessor->format(nullptr, text, sBuf, ARRAY_LENGTH(sBuf) - 1, &outLen, nullptr);
|
|
i = outLen - 1;
|
|
end = &sBuf[i];
|
|
for (; i > 0; i--) {
|
|
if (*end != L'\n') {
|
|
break;
|
|
}
|
|
*end = L'\0';
|
|
end--;
|
|
}
|
|
|
|
return sBuf;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
const wchar_t *dMessage_c::formatTextInternal(const wchar_t *text) {
|
|
u32 outLen = 0;
|
|
static wchar_t sBuf[0x200] = {};
|
|
sTagProcessor->format(nullptr, text, sBuf, ARRAY_LENGTH(sBuf), &outLen, nullptr);
|
|
s32 i = outLen - 1;
|
|
wchar_t *end = &sBuf[i];
|
|
for (; i > 0; i--) {
|
|
if (*end != L'\n') {
|
|
break;
|
|
}
|
|
*end = L'\0';
|
|
end--;
|
|
}
|
|
|
|
return sBuf;
|
|
}
|
|
|
|
bool dMessage_c::isValidTextLabel(const char *name) {
|
|
return sInstance->checkIsValidTextLabel(name);
|
|
}
|
|
|
|
bool dMessage_c::checkIsValidTextLabel(const char *name) {
|
|
if (name == nullptr) {
|
|
return false;
|
|
}
|
|
return getTextIndexForLabel(name) >= 0;
|
|
}
|
|
|
|
const char *dMessage_c::getMsbtFileName(s32 idx) {
|
|
static SizedString<128> sPath;
|
|
|
|
s32 arcIdx = getArcIndexForFile(sMsbtFileNames[idx]);
|
|
const char *arcName = getArcNameByIndex(arcIdx, true);
|
|
sPath.sprintf("%s/%s", arcName, sMsbtFileNames[idx]);
|
|
return sPath;
|
|
}
|
|
|
|
const char *dMessage_c::getMsbfFileName(s32 idx) {
|
|
static SizedString<128> sPath;
|
|
|
|
s32 arcIdx = getArcIndexForFile(sMsbfFileNames[idx]);
|
|
const char *arcName = getArcNameByIndex(arcIdx, true);
|
|
sPath.sprintf("%s/%s", arcName, sMsbfFileNames[idx]);
|
|
return sPath;
|
|
}
|
|
|
|
s32 dMessage_c::getMsbtNumberByIndex(s32 index) {
|
|
return atoi(getMsbtFileName(index));
|
|
}
|
|
|
|
s32 dMessage_c::getMsbfNumberByIndex(s32 index) {
|
|
return atoi(getMsbfFileName(index));
|
|
}
|
|
|
|
// Skipping 007-MapText.msbt and word.msbt
|
|
static const s32 sMsbfToMsbt[] = {
|
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 17, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28,
|
|
29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55,
|
|
56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81,
|
|
};
|
|
|
|
s32 dMessage_c::getMsbtIndexForMsbfIndex(s32 index) {
|
|
return sMsbfToMsbt[index];
|
|
}
|
|
|
|
s32 dMessage_c::getTextIndexForLabel(const char *label) {
|
|
s32 idx = getMsbtIndexForLabelInternal(label);
|
|
MsbtInfo *info = nullptr;
|
|
if (idx >= 0) {
|
|
info = getMsbtInfoForIndex(idx);
|
|
}
|
|
return LMS_GetTextIndexByLabel(info, label);
|
|
}
|
|
|
|
s32 dMessage_c::getMsbtIndexForLabel(const char *label) {
|
|
return sInstance->getMsbtIndexForLabelInternal(label);
|
|
}
|
|
|
|
s32 dMessage_c::getMsbtIndexForLabelInternal(const char *label) {
|
|
if (mCurrentTextFileNumber <= 81) {
|
|
MsbtInfo *info = getMsbtInfoForIndex(mCurrentTextFileNumber);
|
|
if (LMS_GetTextIndexByLabel(info, label) >= 0) {
|
|
return mCurrentTextFileNumber;
|
|
}
|
|
}
|
|
|
|
for (s32 i = 0; i < 82; i++) {
|
|
if (getMsbtInfoForIndex(i) != nullptr) {
|
|
if (LMS_GetTextIndexByLabel(getMsbtInfoForIndex(i), label) >= 0) {
|
|
return i;
|
|
}
|
|
}
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
MsbtInfo *dMessage_c::getMsbtInfoForIndex(s32 index) {
|
|
return sInstance->getMsbtInfoForIndexInternal(index);
|
|
}
|
|
|
|
MsbtInfo *dMessage_c::getMsbtInfoForIndexInternal(s32 index) {
|
|
UnkTextThing *thing = UnkTextThing::getInstance();
|
|
MsbtInfo *overrideMsbt = thing->getOverrideMsbtInfo(index);
|
|
if (overrideMsbt != nullptr && thing->getShouldOverrideData() == true) {
|
|
return overrideMsbt;
|
|
}
|
|
return mpMsgs[index];
|
|
}
|
|
|
|
MsbfInfo *dMessage_c::getMsbfInfoForIndex(s32 index) {
|
|
return sInstance->getMsbfInfoForIndexInternal(index);
|
|
}
|
|
|
|
MsbfInfo *dMessage_c::getMsbfInfoForIndexInternal(s32 index) {
|
|
UnkTextThing *thing = UnkTextThing::getInstance();
|
|
MsbfInfo *overrideMsbf = thing->getOverrideMsbfInfo(index);
|
|
if (overrideMsbf != nullptr && thing->getShouldOverrideData() == true) {
|
|
return overrideMsbf;
|
|
}
|
|
return mpFlows[index];
|
|
}
|
|
|
|
u32 dMessage_c::getLightPillarRelatedArg(s32 arg) {
|
|
return field_0x300[arg];
|
|
}
|
|
|
|
void dMessage_c::storeLightPillarRelatedArg(u32 arg) {
|
|
for (s32 i = 0; i < ARRAY_LENGTH(field_0x300); i++) {
|
|
if (field_0x300[i] == 0xFFFFFFFF) {
|
|
field_0x300[i] = arg;
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dMessage_c::clearLightPillarRelatedArgs() {
|
|
for (s32 i = 0; i < ARRAY_LENGTH(field_0x300); i++) {
|
|
field_0x300[i] = 0xFFFFFFFF;
|
|
}
|
|
}
|
|
|
|
void dMessage_c::executeMinigame() {
|
|
if (mMiniGameVariant == 8) {
|
|
return;
|
|
}
|
|
if (!dMessage_c::getInstance()->getField_0x340()) {
|
|
switch (mMiniGameVariant) {
|
|
case 0:
|
|
case 1:
|
|
case 4:
|
|
case 5:
|
|
if (dLytMiniGame_c::GetInstance() != nullptr) {
|
|
dLytMiniGame_c::GetInstance()->scoreRelatedExecute();
|
|
dLytMiniGame_c::GetInstance()->setDisplayedPoints(mMinigameResultPoints);
|
|
sInstance->field_0x340 = 1;
|
|
}
|
|
break;
|
|
case 2:
|
|
case 3:
|
|
case 6:
|
|
case 7:
|
|
if (dLytMiniGame_c::GetInstance() != nullptr) {
|
|
dLytMiniGame_c::GetInstance()->timeRelatedExecute();
|
|
dLytMiniGame_c::GetInstance()->setDisplayedTime(mMinigameTime);
|
|
sInstance->field_0x340 = 1;
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
void dMessage_c::init() {
|
|
clearLightPillarRelatedArgs();
|
|
// Probably inlines
|
|
field_0x328 = 0;
|
|
field_0x329 = 0;
|
|
field_0x32A = 0;
|
|
sInstance->setField_0x32C(12);
|
|
field_0x330 = 0;
|
|
}
|
|
|
|
void dMessage_c::reset() {
|
|
init();
|
|
mMiniGameVariant = 8;
|
|
field_0x340 = 0;
|
|
mMinigameResultPoints = 0;
|
|
mMinigameTime = 0;
|
|
}
|
|
|
|
extern "C" u8 fn_80054F30();
|
|
static SizedString<8> sCurrentLanguage;
|
|
const char *dMessage_c::getLanguageIdentifier() {
|
|
u8 lang = fn_80054F30();
|
|
if (lang == 3) {
|
|
sCurrentLanguage = "fr_US";
|
|
} else if (lang == 4) {
|
|
sCurrentLanguage = "es_US";
|
|
} else {
|
|
sCurrentLanguage = "en_US";
|
|
}
|
|
return sCurrentLanguage;
|
|
}
|
|
|
|
const char *sLytMsbts_Unused[] = {
|
|
"basic/remoConBtn_00.msbt",
|
|
"basic/remoConBtn_01.msbt",
|
|
"basic/remoConBtn_03.msbt",
|
|
"basic/remoConBtn_04.msbt",
|
|
"basic/remoConBtn_05.msbt",
|
|
"basic/nunBtn_03.msbt",
|
|
"common/commonTitle_00.msbt",
|
|
"endroll/endScroll_00.msbt",
|
|
"fileSelect/fileSelect_00.msbt",
|
|
"information/skip_00.msbt",
|
|
"map/map_00.msbt",
|
|
"messageWindow/messageBtn_00.msbt",
|
|
"miniGame/start_00.msbt",
|
|
"miniGameScore/miniGameScore_00.msbt",
|
|
"miniGameTime/miniGameTime_00.msbt",
|
|
"pause/pauseInfo_00.msbt",
|
|
"pause/pause_00.msbt",
|
|
"shop/depositBox_00.msbt",
|
|
"shop/itemSelect_00.msbt",
|
|
"shop/materialCheck_00.msbt",
|
|
"softwareKeyboard/toolbarBtn_00.msbt",
|
|
"systemWindow/systemWindow_00.msbt",
|
|
"title/titleBG_00.msbt",
|
|
};
|
|
|
|
const char *dMessage_c::getArcNameByIndex(s32 idx, bool global) {
|
|
return getArcNameByIndexInternal(idx, global);
|
|
}
|
|
|
|
static char *sArcNames[] = {
|
|
"0-Common", "1-Town", "2-Forest", "3-Mountain", "4-Desert", "5-CenterField",
|
|
};
|
|
|
|
const char *dMessage_c::getArcNameByIndexInternal(s32 idx, bool global) {
|
|
return sArcNames[idx];
|
|
}
|
|
|
|
void *dMessage_c::getDataFromMsbArc(s32 number, const char *fileName, bool global) {
|
|
SizedString<128> path;
|
|
path.sprintf("%s/%s", getLanguageIdentifier(), getArcNameByIndex(number, global));
|
|
return OarcManager::GetInstance()->getData(path, fileName);
|
|
}
|
|
|
|
void dMessage_c::setZevFromMsbArc() {
|
|
SizedString<128> path;
|
|
path.sprintf("%s/dat/zev.dat", getArcNameByIndex(0, false));
|
|
sZev0 = getDataFromMsbArc(0, path, false);
|
|
sZevStage = nullptr;
|
|
}
|
|
|
|
void dMessage_c::setStageZevFromMsbArc() {
|
|
SizedString<32> stage = dScGame_c::currentSpawnInfo.stageName;
|
|
char buf[2];
|
|
buf[0] = stage[1];
|
|
buf[1] = '\0';
|
|
|
|
SizedString<128> path;
|
|
|
|
int i = atoi(buf) + 1;
|
|
|
|
// TODO figure out what this is
|
|
if (stage == "t_tkm24" || stage == "t_tkm26") {
|
|
i = 2;
|
|
} else if (i < 1 || 6 <= i) {
|
|
i = 0;
|
|
}
|
|
path.sprintf("%s/dat/zev.dat", getArcNameByIndex(i, false));
|
|
sZevStage = getDataFromMsbArc(i, path, false);
|
|
}
|
|
|
|
void *dMessage_c::sZev0;
|
|
void *dMessage_c::sZevStage;
|
|
|
|
void *dMessage_c::getZev0Internal() {
|
|
UnkTextThing *thing = UnkTextThing::getInstance();
|
|
void *overrideZev = thing->getOverrideZev0();
|
|
if (overrideZev != nullptr && thing->getShouldOverrideData() == true) {
|
|
return overrideZev;
|
|
}
|
|
return sZev0;
|
|
}
|
|
|
|
void *dMessage_c::getZevStageInternal() {
|
|
UnkTextThing *thing = UnkTextThing::getInstance();
|
|
void *overrideZev = thing->getOverrideStageZev();
|
|
if (overrideZev != nullptr && thing->getShouldOverrideData() == true) {
|
|
return overrideZev;
|
|
}
|
|
return sZevStage;
|
|
}
|
|
|
|
s32 dMessage_c::getArcIndexForFile(const char *fileName) {
|
|
char buf[2];
|
|
buf[0] = fileName[0];
|
|
buf[1] = '\0';
|
|
return atoi(buf);
|
|
}
|