mirror of
https://github.com/pret/pmd-red.git
synced 2026-07-20 09:51:24 -05:00
1081 lines
31 KiB
C
1081 lines
31 KiB
C
#include "global.h"
|
|
#include "dungeon_message.h"
|
|
#include "dungeon.h"
|
|
#include "structs/dungeon_entity.h"
|
|
#include "code_803E46C.h"
|
|
#include "code_803E724.h"
|
|
#include "string_format.h"
|
|
#include "code_800E9E4.h"
|
|
#include "menu_input.h"
|
|
#include "code_803E668.h"
|
|
#include "bg_palette_buffer.h"
|
|
#include "input.h"
|
|
#include "pokemon.h"
|
|
#include "file_system.h"
|
|
#include "dungeon_util_1.h"
|
|
#include "code_800D090.h"
|
|
#include "dungeon_util.h"
|
|
#include "code_8045A00.h"
|
|
#include "exclusive_pokemon.h"
|
|
#include "dungeon_leader.h"
|
|
#include "text.h"
|
|
|
|
void sub_80526D0(s32 r0);
|
|
static void PutStringsOnMessageLog(void);
|
|
static bool8 TryScrollLogDown(s32 a0);
|
|
static bool8 TryScrollLogUp(s32 a0);
|
|
static void CopyStringToMessageLog(const u8 *src, u32 a1, u32 a2);
|
|
static void CreateMessageLogArrow(bool8 upArrow, s32 y);
|
|
static void DisplayMessageAddToLog(Entity *pokemon, const u8 *str, u8 r2);
|
|
static bool8 sub_8052DC0(Entity *);
|
|
|
|
extern bool8 sub_8045888(Entity *pokemon);
|
|
extern void sub_805E804(void);
|
|
extern void sub_803EAF0(s32, s32);
|
|
extern void sub_8040238(void);
|
|
extern void sub_8083E28(void);
|
|
extern u32 sub_8014140(s32 a0, const void *a1);
|
|
extern void sub_8083D30(void);
|
|
extern void sub_8083D08(void);
|
|
extern void sub_8007334(s32 a0);
|
|
extern void sub_80087EC(s32 a0, s32 a1, s32 a2, s32 a3, s32 a4);
|
|
extern void sub_8083CE0(u8 param_1);
|
|
|
|
extern u32 gUnknown_202EDD0;
|
|
extern u8 gUnknown_203B40C;
|
|
extern u8 gUnknown_202EE01;
|
|
extern s32 gUnknown_202EDCC;
|
|
extern Palette32 gFontPalette[];
|
|
|
|
extern const u8 gUnknown_80F7AE8[];
|
|
extern const u8 gUnknown_80F7AF8[];
|
|
extern const u8 gUnknown_80F7AFC[];
|
|
extern const u8 gUnknown_80F7B04[];
|
|
extern const u16 gUnknown_80F7AEA[];
|
|
|
|
static EWRAM_DATA Entity *sLastLogMsgEntity = NULL;
|
|
static UNUSED EWRAM_DATA u8 sUnused = 0;
|
|
static EWRAM_DATA SpriteOAM sUnknown_202F1F0 = {0};
|
|
static EWRAM_DATA s32 sMessageLogCursor = 0;
|
|
static EWRAM_DATA u8 sMessageLogFlags = 0;
|
|
static EWRAM_DATA SpriteOAM sMessageLogArrowSpriteOAM = {0};
|
|
EWRAM_INIT u8 gUnknown_203B434 = 1;
|
|
|
|
// Used for sMessageLogFlags
|
|
#define FLAG_CAN_SCROLL_UP 0x1
|
|
#define FLAG_CAN_SCROLL_DOWN 0x2
|
|
|
|
// Needed to match :shrug:
|
|
static inline void InlineStrcpy(u8 *dst, const u8 *src)
|
|
{
|
|
strcpy(dst, src);
|
|
}
|
|
|
|
static inline void InlineStrncpy(u8 *dst, const u8 *src, s32 n)
|
|
{
|
|
strncpy(dst, src, n);
|
|
}
|
|
|
|
void sub_80521D0(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < UNK_1BBD4_STR_COUNT; i++) {
|
|
gDungeon->unk1BDD4.unk1C054[i] = 0;
|
|
}
|
|
sLastLogMsgEntity = NULL;
|
|
gUnknown_203B434 = 1;
|
|
sub_8052210(FALSE);
|
|
}
|
|
|
|
void sub_8052210(bool8 a0)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < UNK_1BBD4_STR_COUNT; i++) {
|
|
InlineStrcpy(gDungeon->unk1BDD4.unk0[i], gUnknown_80F7AE8);
|
|
}
|
|
gDungeon->unk1BDD4.unk1C05F = 0;
|
|
gDungeon->unk1BDD4.unk1C060 = 0;
|
|
gDungeon->unk1BDD4.unk1C062 = 0;
|
|
gDungeon->unk1BDD4.unk1C064 = 0;
|
|
gDungeon->unk1BDD4.unk1C066 = 4;
|
|
gDungeon->unk1BDD4.unk1C06C = 0;
|
|
|
|
if (a0 && gUnknown_202EDD0 == 3) {
|
|
sub_803EAF0(0, 0);
|
|
sub_803E46C(11);
|
|
}
|
|
}
|
|
|
|
void sub_805229C(void)
|
|
{
|
|
return sub_80526D0(0x50);
|
|
}
|
|
|
|
void LogMessageByIdWithPopupCheckUser(Entity *pokemon, const u8 *str)
|
|
{
|
|
if (sub_8045888(pokemon)){
|
|
DisplayMessageAddToLog(pokemon, str, TRUE);
|
|
}
|
|
}
|
|
|
|
UNUSED void TryDisplayDungeonLoggableMessage2(Entity *pokemon, const u8 *str)
|
|
{
|
|
if (sub_8045888(pokemon)){
|
|
DisplayMessageAddToLog(pokemon, str, FALSE);
|
|
}
|
|
}
|
|
|
|
void DisplayDungeonLoggableMessageFalse(Entity *pokemon, const u8 *str)
|
|
{
|
|
DisplayMessageAddToLog(pokemon, str, FALSE);
|
|
}
|
|
|
|
void TryDisplayDungeonLoggableMessage3(Entity *attacker, Entity *target, const u8 *str)
|
|
{
|
|
u8 flag;
|
|
flag = sub_8045888(attacker) ? TRUE : FALSE;
|
|
if(sub_8052DC0(target) != 0)
|
|
{
|
|
flag = TRUE;
|
|
}
|
|
if(flag)
|
|
{
|
|
DisplayMessageAddToLog(attacker, str, TRUE);
|
|
}
|
|
}
|
|
|
|
void TryDisplayDungeonLoggableMessage4(Entity *attacker, Entity *target, const u8 *str)
|
|
{
|
|
u8 flag;
|
|
flag = sub_8045888(attacker) ? TRUE : FALSE;
|
|
if(sub_8052DC0(target) != 0)
|
|
{
|
|
flag = TRUE;
|
|
}
|
|
if(flag)
|
|
{
|
|
DisplayMessageAddToLog(attacker, str, FALSE);
|
|
}
|
|
}
|
|
|
|
void TryDisplayDungeonLoggableMessage5(Entity *pokemon, DungeonPos *pos,
|
|
const u8 *str)
|
|
{
|
|
u8 flag;
|
|
flag = sub_8045888(pokemon) ? TRUE : FALSE;
|
|
if(sub_803F428(pos))
|
|
{
|
|
flag = TRUE;
|
|
}
|
|
if(flag)
|
|
{
|
|
DisplayMessageAddToLog(pokemon, str, TRUE);
|
|
}
|
|
}
|
|
|
|
void DisplayDungeonLoggableMessageTrue(Entity *pokemon, const u8 *str)
|
|
{
|
|
DisplayMessageAddToLog(pokemon, str, TRUE);
|
|
}
|
|
|
|
static void DisplayMessageAddToLog(Entity *pokemon, const u8 *str, bool8 r2)
|
|
{
|
|
u8 txt[64];
|
|
u32 r7;
|
|
bool32 r8, r9;
|
|
|
|
if (sLastLogMsgEntity != pokemon) {
|
|
r7 = 1;
|
|
}
|
|
else {
|
|
r7 = gUnknown_203B434;
|
|
}
|
|
|
|
r8 = 1;
|
|
sLastLogMsgEntity = pokemon;
|
|
gUnknown_203B434 = 0;
|
|
r9 = FALSE;
|
|
while (1) {
|
|
while (1) {
|
|
s32 val = gDungeon->unk1BDD4.unk1C060;
|
|
if (++val == UNK_1BBD4_STR_COUNT) {
|
|
val = 0;
|
|
}
|
|
|
|
if (val != gDungeon->unk1BDD4.unk1C062) {
|
|
break;
|
|
}
|
|
sub_803E46C(0);
|
|
}
|
|
|
|
if (*str == '\0')
|
|
break;
|
|
|
|
gDungeon->unk1BDD4.unk1C054[gDungeon->unk1BDD4.unk1C060] = r7;
|
|
str = FormatString(str, txt, txt + 62, 128);
|
|
if (*str == '\r') str++;
|
|
if (*str == '\n') str++;
|
|
CopyStringToMessageLog(txt, r7, r8);
|
|
r7 = 0;
|
|
r8 = 0;
|
|
if (r2) {
|
|
r9 = TRUE;
|
|
InlineStrncpy(gDungeon->unk1BDD4.unk0[gDungeon->unk1BDD4.unk1C060], txt, 64);
|
|
if (++gDungeon->unk1BDD4.unk1C060 == UNK_1BBD4_STR_COUNT) {
|
|
gDungeon->unk1BDD4.unk1C060 = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (r9) {
|
|
gDungeon->unk1BDD4.unk1C064 = 0xF0;
|
|
if (gDungeon->unk1BDD4.unk1C06C == 0) {
|
|
gDungeon->unk1BDD4.unk1C06C = 1;
|
|
}
|
|
sub_805E804();
|
|
}
|
|
}
|
|
|
|
void xxx_draw_string_80524F0(void)
|
|
{
|
|
struct UnkStructDungeon1BDD4 *strPtr = &gDungeon->unk1BDD4;
|
|
|
|
switch (strPtr->unk1C06C) {
|
|
case 0:
|
|
break;
|
|
case 1:
|
|
if (sub_800EC74())
|
|
break;
|
|
sub_803EAF0(3, 0);
|
|
// fall through
|
|
case 2: {
|
|
struct UnkDrawStringStruct sp;
|
|
u32 currChr;
|
|
|
|
s32 id = strPtr->unk1C062;
|
|
if (id == strPtr->unk1C060) {
|
|
strPtr->unk1C06C = 0;
|
|
}
|
|
else {
|
|
const u8 *txtPtr = strPtr->unk0[id];
|
|
|
|
sp.unk0 = 4;
|
|
sp.unk2 = strPtr->unk1C066;
|
|
sp.unk10 = 7;
|
|
sub_80073B8(0);
|
|
if (strPtr->unk1C054[id] != 0 && strPtr->unk1C066 >= 8) {
|
|
sub_80078A4(0, 0, strPtr->unk1C066 - 1, 0xE0, 7);
|
|
}
|
|
|
|
while (1) {
|
|
txtPtr = xxx_handle_format_global(txtPtr, &sp);
|
|
if (*txtPtr == '\0' || *txtPtr == '\r' || *txtPtr == '\n')
|
|
break;
|
|
txtPtr = xxx_get_next_char_from_string(txtPtr, &currChr);
|
|
if (currChr == '`') {
|
|
sp.unk0 += 6;
|
|
}
|
|
else {
|
|
sp.unk0 += xxx_call_draw_char(sp.unk0, sp.unk2, currChr, sp.unk10, 0);
|
|
}
|
|
}
|
|
sub_80073E0(0);
|
|
strPtr->unk1C064 = 240;
|
|
if (++id == UNK_1BBD4_STR_COUNT) {
|
|
id = 0;
|
|
}
|
|
strPtr->unk1C062 = id;
|
|
strPtr->unk1C066 += 11;
|
|
if (strPtr->unk1C066 >= 48) {
|
|
strPtr->unk1C066 = 37;
|
|
strPtr->unk1C068 = 0;
|
|
strPtr->unk1C06C = 3;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
case 3:
|
|
strPtr->unk1C068++;
|
|
gIwramTextFunc4(0);
|
|
if (strPtr->unk1C068 > 10) {
|
|
strPtr->unk1C06C = 2;
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (strPtr->unk1C05E == 0 && strPtr->unk1C064 != 0 && --strPtr->unk1C064 == 0) {
|
|
strPtr->unk1C06C = 0;
|
|
sub_803EAF0(0, 0);
|
|
sub_8052210(FALSE);
|
|
}
|
|
}
|
|
|
|
void sub_80526D0(s32 r0)
|
|
{
|
|
struct UnkStructDungeon1BDD4 *strPtr = &gDungeon->unk1BDD4;
|
|
while (strPtr->unk1C06C != 0 || gDungeon->unk1BDD4.unk1C060 != gDungeon->unk1BDD4.unk1C062) {
|
|
sub_803E46C(r0);
|
|
}
|
|
}
|
|
|
|
void sub_8052740(s32 a0)
|
|
{
|
|
s32 i;
|
|
struct UnkStructDungeon1BDD4 *strPtr = &gDungeon->unk1BDD4;
|
|
|
|
sub_80526D0(a0);
|
|
for (i = 0; i < 240; i++) {
|
|
if (strPtr->unk1C064 < 180)
|
|
break;
|
|
if ((gRealInputs.held & AB_BUTTONS) == AB_BUTTONS)
|
|
break;
|
|
if (gRealInputs.pressed & JOY_EXCL_DPAD)
|
|
break;
|
|
sub_803E46C(a0);
|
|
}
|
|
}
|
|
|
|
// Prints string in dialogue box and waits for A/B button press
|
|
#define PRINT_STRING_WAIT_PRESS(chosenMenuIndex) \
|
|
{ \
|
|
s32 unkPrintRet; \
|
|
\
|
|
do { \
|
|
DrawDialogueBoxString(); \
|
|
sub_803E46C(9); \
|
|
unkPrintRet = sub_80144A4(chosenMenuIndex);\
|
|
} while (unkPrintRet != 0); \
|
|
}
|
|
|
|
void DisplayDungeonMessage(struct MonDialogueSpriteInfo *monSpriteInfo, const u8 *str, bool8 a2)
|
|
{
|
|
struct MonPortraitMsg monPortrait, *monPortraitPtr;
|
|
s32 chosenMenuIndex;
|
|
|
|
if (gUnknown_203B40C) {
|
|
sub_8052740(10);
|
|
}
|
|
|
|
sub_803EAF0(2, 0);
|
|
sub_8052210(FALSE);
|
|
|
|
monPortraitPtr = NULL;
|
|
monPortrait.faceFile = NULL;
|
|
monPortrait.faceData = NULL;
|
|
if (!gDungeon->unk181e8.blinded
|
|
&& !gDungeon->unk181e8.hallucinating
|
|
&& monSpriteInfo != NULL
|
|
&& IsPokemonDialogueSpriteAvail(monSpriteInfo->species, monSpriteInfo->spriteId))
|
|
{
|
|
monPortrait.faceFile = GetDialogueSpriteDataPtr(monSpriteInfo->species);
|
|
monPortrait.faceData = (struct PortraitGfx *) monPortrait.faceFile->data;
|
|
monPortrait.pos.x = 2;
|
|
monPortrait.pos.y = 9;
|
|
monPortrait.spriteId = monSpriteInfo->spriteId;
|
|
monPortrait.flip = FALSE;
|
|
monPortrait.unkE = 0;
|
|
monPortraitPtr = &monPortrait;
|
|
}
|
|
|
|
CreateMenuDialogueBoxAndPortrait(str, 0, 0, NULL, NULL, 3, 0, monPortraitPtr, (a2 != FALSE) ? 0x701 : 0x400);
|
|
gDungeon->unk1BDD4.unk1C05F = 1;
|
|
PRINT_STRING_WAIT_PRESS(&chosenMenuIndex);
|
|
gDungeon->unk1BDD4.unk1C05F = 0;
|
|
|
|
if (monPortrait.faceFile != NULL) {
|
|
CloseFile(monPortrait.faceFile);
|
|
}
|
|
|
|
if (a2) {
|
|
sub_805E804();
|
|
sub_8040238();
|
|
if (gUnknown_202EE01) {
|
|
sub_803EAF0(0, 0);
|
|
}
|
|
else {
|
|
sub_803EAF0(1, 0);
|
|
}
|
|
}
|
|
|
|
sub_803E708(8, 9);
|
|
}
|
|
|
|
void DisplayDungeonLoggableMessage(Entity *pokemon, const u8 *str)
|
|
{
|
|
DisplayDungeonMessage(NULL, str, TRUE);
|
|
DisplayDungeonLoggableMessageFalse(pokemon, str);
|
|
}
|
|
|
|
struct Struct_sub_808CDB0
|
|
{
|
|
DungeonPos pos;
|
|
bool8 flip;
|
|
};
|
|
|
|
extern const struct Struct_sub_808CDB0 *sub_808CDB0(s32 a0);
|
|
|
|
void DisplayDungeonDialogue(const struct DungeonDialogueStruct *dialogueInfo)
|
|
{
|
|
struct MonPortraitMsg monPortrait;
|
|
s32 leaderId, partnerId, dialogueMonId;
|
|
s32 chosenMenuIndex;
|
|
Entity *leader = xxx_call_GetLeader();
|
|
Entity *partner = GetPartnerEntity();
|
|
struct MonPortraitMsg *monPortraitPtr = NULL;
|
|
|
|
if (leader != NULL) {
|
|
EntityInfo *leaderInfo = GetEntInfo(leader);
|
|
PokemonStruct2 *monStruct2 = &gRecruitedPokemonRef->pokemon2[leaderInfo->teamIndex];
|
|
|
|
sub_808DA0C(gFormatBuffer_Monsters[0], monStruct2);
|
|
leaderId = leaderInfo->apparentID;
|
|
}
|
|
else {
|
|
leaderId = MONSTER_NONE;
|
|
strcpy(gFormatBuffer_Monsters[0], gUnknown_80F7AF8); // ??
|
|
}
|
|
|
|
if (partner != NULL) {
|
|
EntityInfo *partnerInfo = GetEntInfo(partner);
|
|
PokemonStruct2 *monStruct2 = &gRecruitedPokemonRef->pokemon2[partnerInfo->teamIndex];
|
|
|
|
sub_808DA0C(gFormatBuffer_Monsters[1], monStruct2);
|
|
partnerId = partnerInfo->apparentID;
|
|
}
|
|
else {
|
|
partnerId = MONSTER_NONE;
|
|
strcpy(gFormatBuffer_Monsters[1], gUnknown_80F7AF8); // ??
|
|
}
|
|
|
|
switch (dialogueInfo->unk4) {
|
|
case 425:
|
|
dialogueMonId = leaderId;
|
|
sprintfStatic(gSpeakerNameBuffer, gUnknown_80F7AFC, gFormatBuffer_Monsters);
|
|
break;
|
|
case 426:
|
|
dialogueMonId = partnerId;
|
|
sprintfStatic(gSpeakerNameBuffer, gUnknown_80F7AFC, gFormatBuffer_Monsters[1]);
|
|
break;
|
|
case 427:
|
|
dialogueMonId = MONSTER_NONE;
|
|
strcpy(gSpeakerNameBuffer, gUnknown_80F7B04);
|
|
break;
|
|
default:
|
|
dialogueMonId = dialogueInfo->unk4;
|
|
CopyYellowMonsterNametoBuffer(gSpeakerNameBuffer, dialogueMonId);
|
|
break;
|
|
}
|
|
|
|
if (dialogueInfo->unk0 == 2 || dialogueInfo->unk0 == 3) {
|
|
strcpy(gSpeakerNameBuffer, gUnknown_80F7B04);
|
|
}
|
|
|
|
while (1) {
|
|
if (dialogueInfo->unk6 == 0)
|
|
break;
|
|
if (dialogueInfo->unk6 == 7 && (dialogueMonId == MONSTER_SQUIRTLE || dialogueMonId == MONSTER_TOTODILE))
|
|
break;
|
|
if (dialogueInfo->unk6 == 1 && (dialogueMonId == MONSTER_BULBASAUR || dialogueMonId == MONSTER_CYNDAQUIL || dialogueMonId == MONSTER_MUDKIP || dialogueMonId == MONSTER_PIKACHU || dialogueMonId == MONSTER_CHARMANDER || dialogueMonId == MONSTER_TREECKO))
|
|
break;
|
|
if (dialogueInfo->unk6 == 280 && (dialogueMonId == MONSTER_TORCHIC || dialogueMonId == MONSTER_CHIKORITA))
|
|
break;
|
|
dialogueInfo++;
|
|
}
|
|
|
|
if (!gDungeon->unk181e8.blinded
|
|
&& !gDungeon->unk181e8.hallucinating
|
|
&& dialogueInfo->unk0 != 4
|
|
&& dialogueInfo->unk2 != 0x80
|
|
&& dialogueMonId != MONSTER_NONE)
|
|
{
|
|
const struct Struct_sub_808CDB0 *strPtr = sub_808CDB0(dialogueInfo->unk3);
|
|
|
|
monPortraitPtr = &monPortrait;
|
|
monPortraitPtr->faceFile = GetDialogueSpriteDataPtr(dialogueMonId);
|
|
if (monPortraitPtr->faceFile != NULL) {
|
|
monPortraitPtr->faceData = (struct PortraitGfx *) monPortraitPtr->faceFile->data;
|
|
monPortraitPtr->unkE = 0;
|
|
monPortraitPtr->spriteId = dialogueInfo->unk2;
|
|
monPortraitPtr->flip = strPtr->flip;
|
|
monPortraitPtr->pos.x = strPtr->pos.x;
|
|
monPortraitPtr->pos.y = strPtr->pos.y;
|
|
if (monPortraitPtr->pos.y < 2) {
|
|
monPortraitPtr->pos.y = 2;
|
|
}
|
|
}
|
|
else {
|
|
monPortraitPtr = NULL;
|
|
}
|
|
}
|
|
|
|
sub_8052740(10);
|
|
sub_803EAF0(2, 0);
|
|
sub_8052210(FALSE);
|
|
CreateDialogueBoxAndPortrait(dialogueInfo->str, 0, monPortraitPtr, gUnknown_80F7AEA[dialogueInfo->unk0]);
|
|
PRINT_STRING_WAIT_PRESS(&chosenMenuIndex);
|
|
|
|
if (monPortraitPtr != NULL) {
|
|
CloseFile(monPortraitPtr->faceFile);
|
|
}
|
|
|
|
if (dialogueInfo->unk0 != 1 && dialogueInfo->unk0 != 3) {
|
|
sub_8040238();
|
|
sub_803EAF0(0, 0);
|
|
}
|
|
sub_803E708(8, 9);
|
|
}
|
|
|
|
bool32 DisplayDungeonYesNoMessage(struct MonDialogueSpriteInfo *monSpriteInfo, const u8 *str, bool32 defaultYes)
|
|
{
|
|
struct MonPortraitMsg monPortrait, *monPortraitPtr;
|
|
s32 chosenMenuIndex;
|
|
|
|
sub_8052740(10);
|
|
sub_803EAF0(2, 0);
|
|
sub_8052210(FALSE);
|
|
|
|
monPortraitPtr = NULL;
|
|
monPortrait.faceFile = NULL;
|
|
monPortrait.faceData = NULL;
|
|
if (!gDungeon->unk181e8.blinded
|
|
&& !gDungeon->unk181e8.hallucinating
|
|
&& monSpriteInfo != NULL
|
|
&& IsPokemonDialogueSpriteAvail(monSpriteInfo->species, monSpriteInfo->spriteId))
|
|
{
|
|
monPortrait.faceFile = GetDialogueSpriteDataPtr(monSpriteInfo->species);
|
|
monPortrait.faceData = (struct PortraitGfx *) monPortrait.faceFile->data;
|
|
monPortrait.pos.x = 2;
|
|
monPortrait.pos.y = 9;
|
|
monPortrait.spriteId = monSpriteInfo->spriteId;
|
|
monPortrait.flip = FALSE;
|
|
monPortrait.unkE = 0;
|
|
monPortraitPtr = &monPortrait;
|
|
}
|
|
|
|
if (defaultYes == TRUE) {
|
|
CreateYesNoDialogueBoxAndPortrait_DefaultYes(str, monPortraitPtr, 0x300); // Yes/No - cursor starts at Yes
|
|
}
|
|
else {
|
|
CreateYesNoDialogueBoxAndPortrait_DefaultNo(str, monPortraitPtr, 0x300); // Yes/No - cursor starts at NO
|
|
}
|
|
|
|
PRINT_STRING_WAIT_PRESS(&chosenMenuIndex);
|
|
|
|
if (monPortrait.faceFile != NULL) {
|
|
CloseFile(monPortrait.faceFile);
|
|
}
|
|
|
|
sub_8040238();
|
|
sub_803EAF0(0, 0);
|
|
|
|
if (chosenMenuIndex == 1)
|
|
return TRUE;
|
|
else
|
|
return FALSE;
|
|
}
|
|
|
|
s32 DisplayDungeonMenuMessage(struct MonDialogueSpriteInfo *monSpriteInfo, const u8 *str, const MenuItem *menuItems, u16 unkArg)
|
|
{
|
|
struct MonPortraitMsg monPortrait, *monPortraitPtr;
|
|
s32 chosenMenuIndex;
|
|
|
|
sub_8052740(10);
|
|
sub_803EAF0(2, 0);
|
|
sub_8052210(FALSE);
|
|
|
|
monPortraitPtr = NULL;
|
|
monPortrait.faceFile = NULL;
|
|
monPortrait.faceData = NULL;
|
|
if (!gDungeon->unk181e8.blinded
|
|
&& !gDungeon->unk181e8.hallucinating
|
|
&& monSpriteInfo != NULL
|
|
&& IsPokemonDialogueSpriteAvail(monSpriteInfo->species, monSpriteInfo->spriteId))
|
|
{
|
|
monPortrait.faceFile = GetDialogueSpriteDataPtr(monSpriteInfo->species);
|
|
monPortrait.faceData = (struct PortraitGfx *) monPortrait.faceFile->data;
|
|
monPortrait.pos.x = 2;
|
|
monPortrait.pos.y = 9;
|
|
monPortrait.spriteId = monSpriteInfo->spriteId;
|
|
monPortrait.flip = FALSE;
|
|
monPortrait.unkE = 0;
|
|
monPortraitPtr = &monPortrait;
|
|
}
|
|
|
|
CreateMenuDialogueBoxAndPortrait(str, 0, -1, menuItems, NULL, 3, 0, monPortraitPtr, unkArg);
|
|
PRINT_STRING_WAIT_PRESS(&chosenMenuIndex);
|
|
|
|
if (monPortrait.faceFile != NULL) {
|
|
CloseFile(monPortrait.faceFile);
|
|
}
|
|
|
|
sub_8040238();
|
|
sub_803EAF0(0, 0);
|
|
return chosenMenuIndex;
|
|
}
|
|
|
|
void sub_8052D44(s16 *ids, Entity *leader, Entity *partner)
|
|
{
|
|
if (EntityExists(leader)) {
|
|
SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[0], leader, 0);
|
|
ids[0] = GetEntInfo(leader)->apparentID;
|
|
}
|
|
else {
|
|
strcpy(gFormatBuffer_Monsters[0], gUnknown_80F7AF8);
|
|
ids[0] = 0;
|
|
}
|
|
|
|
if (EntityExists(partner)) {
|
|
SubstitutePlaceholderStringTags(gFormatBuffer_Monsters[1], partner, 0);
|
|
ids[1] = GetEntInfo(partner)->apparentID;
|
|
}
|
|
else {
|
|
strcpy(gFormatBuffer_Monsters[1], gUnknown_80F7AF8);
|
|
ids[1] = 0;
|
|
}
|
|
}
|
|
|
|
static bool8 sub_8052DC0(Entity *entity)
|
|
{
|
|
return sub_8045888(entity);
|
|
}
|
|
|
|
struct TutorialFlagMsg
|
|
{
|
|
s32 flagId;
|
|
const u8 *str;
|
|
};
|
|
|
|
extern const struct TutorialFlagMsg gUnknown_80FF020;
|
|
extern const struct TutorialFlagMsg gUnknown_80FF080;
|
|
extern const struct TutorialFlagMsg gUnknown_80FF0D8;
|
|
extern const struct TutorialFlagMsg gUnknown_80FF13C;
|
|
extern const struct TutorialFlagMsg gUnknown_80FF1B4;
|
|
extern const struct TutorialFlagMsg gMovementTutorial;
|
|
extern const struct TutorialFlagMsg gHungerTutorial;
|
|
extern const struct TutorialFlagMsg gFoodTutorial;
|
|
extern const struct TutorialFlagMsg gOranTutorial;
|
|
extern const struct TutorialFlagMsg gCheriTutorial;
|
|
extern const struct TutorialFlagMsg gBlastSeedTutorial;
|
|
extern const struct TutorialFlagMsg gUnknown_80FF4A0;
|
|
extern const struct TutorialFlagMsg gPechaTutorial;
|
|
extern const struct TutorialFlagMsg gSleepSeedTutorial;
|
|
extern const struct TutorialFlagMsg gMoneyTutorial;
|
|
|
|
extern const u8 *const gUnknown_80FF6F8;
|
|
extern const u8 *const gUnknown_80FF6A4;
|
|
|
|
static inline bool32 DislayTutorialMsg(Entity *leader, const struct TutorialFlagMsg *tutorial, bool32 unkFunctionCall)
|
|
{
|
|
const u8 *str;
|
|
s32 flag = tutorial->flagId;
|
|
bool8 flagDone = GetTutorialFlag(flag);
|
|
|
|
if (!flagDone) {
|
|
SetTutorialFlag(flag);
|
|
sub_8083E28();
|
|
str = tutorial->str;
|
|
DisplayDungeonMessage(NULL, str, TRUE);
|
|
if (unkFunctionCall) {
|
|
DisplayDungeonLoggableMessageFalse(leader, str);
|
|
}
|
|
return TRUE;
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
void TryDisplayGeneralTutorialMessage(void)
|
|
{
|
|
Entity *leader = GetLeader();
|
|
|
|
if (DislayTutorialMsg(leader, &gUnknown_80FF020, TRUE)) return;
|
|
if (DislayTutorialMsg(leader, &gUnknown_80FF080, TRUE)) return;
|
|
if (DislayTutorialMsg(leader, &gUnknown_80FF0D8, TRUE)) return;
|
|
if (gDungeon->unk644.dungeonLocation.id == DUNGEON_THUNDERWAVE_CAVE) {
|
|
if (DislayTutorialMsg(leader, &gUnknown_80FF13C, TRUE)) return;
|
|
if (DislayTutorialMsg(leader, &gUnknown_80FF1B4, TRUE)) return;
|
|
if (DislayTutorialMsg(leader, &gMovementTutorial, TRUE)) return;
|
|
if (DislayTutorialMsg(leader, &gHungerTutorial, TRUE)) return;
|
|
}
|
|
}
|
|
|
|
void TryDisplayItemPickupTutorialMessage(u8 itemId)
|
|
{
|
|
u32 itemCategory = GetItemCategory(itemId);
|
|
|
|
if (itemCategory == CATEGORY_FOOD_GUMMIES) {
|
|
DislayTutorialMsg(NULL, &gFoodTutorial, FALSE);
|
|
}
|
|
else if (itemId == ITEM_ORAN_BERRY) {
|
|
DislayTutorialMsg(NULL, &gOranTutorial, FALSE);
|
|
}
|
|
else if (itemId == ITEM_CHERI_BERRY) {
|
|
DislayTutorialMsg(NULL, &gCheriTutorial, FALSE);
|
|
}
|
|
else if (itemId == ITEM_BLAST_SEED) {
|
|
DislayTutorialMsg(NULL, &gBlastSeedTutorial, FALSE);
|
|
}
|
|
else if (itemId == ITEM_GRAVELEROCK) {
|
|
DislayTutorialMsg(NULL, &gUnknown_80FF4A0, FALSE);
|
|
}
|
|
else if (itemId == ITEM_PECHA_BERRY) {
|
|
DislayTutorialMsg(NULL, &gPechaTutorial, FALSE);
|
|
}
|
|
else if (itemId == ITEM_SLEEP_SEED) {
|
|
DislayTutorialMsg(NULL, &gSleepSeedTutorial, FALSE);
|
|
}
|
|
else if (itemId == ITEM_POKE) {
|
|
DislayTutorialMsg(NULL, &gMoneyTutorial, FALSE);
|
|
}
|
|
}
|
|
|
|
void DisplayYouReachedDestFloorStr(void)
|
|
{
|
|
if (gDungeon->unkA != 0) {
|
|
DisplayDungeonMessage(NULL, gUnknown_80FF6F8, 1); // But the pokemon you seek isn't here...
|
|
}
|
|
else {
|
|
DisplayDungeonMessage(NULL, gUnknown_80FF6A4, 1);
|
|
}
|
|
}
|
|
|
|
// Used only for displaying Frosy Forest's text at floor 6
|
|
void sub_8052FB8(const u8 *str)
|
|
{
|
|
s32 r8 = 0, r9, j;
|
|
{
|
|
s32 i;
|
|
for (i = 1; i < 30; i++) {
|
|
gUnknown_202B038[0][0][i] = 0;
|
|
}
|
|
}
|
|
|
|
CreateMenuDialogueBoxAndPortrait(str, 0, 0, NULL, NULL, 2, 0, NULL, 0x30);
|
|
r9 = 0;
|
|
while (1) {
|
|
if (r8 < 62) {
|
|
r8++;
|
|
for (j = 0; j < 8; j++) {
|
|
SetBGPaletteBufferColorRGB(240 + j, &gFontPalette[0].pal[j], r8 / 2, NULL);
|
|
}
|
|
}
|
|
else {
|
|
r9++;
|
|
if (r9 & 8) {
|
|
SpriteSetAffine1(&sUnknown_202F1F0, 0);
|
|
SpriteSetAffine2(&sUnknown_202F1F0, 0);
|
|
SpriteSetObjMode(&sUnknown_202F1F0, 0);
|
|
SpriteSetMosaic(&sUnknown_202F1F0, 0);
|
|
SpriteSetBpp(&sUnknown_202F1F0, 0);
|
|
SpriteSetShape(&sUnknown_202F1F0, 1);
|
|
SpriteSetTileNum(&sUnknown_202F1F0, 0x3F0);
|
|
SpriteSetPriority(&sUnknown_202F1F0, 0);
|
|
SpriteSetPalNum(&sUnknown_202F1F0, 15);
|
|
SpriteSetY(&sUnknown_202F1F0, 120);
|
|
SpriteSetMatrixNum(&sUnknown_202F1F0, 0);
|
|
SpriteSetSize(&sUnknown_202F1F0, 0);
|
|
SpriteSetX(&sUnknown_202F1F0, 112);
|
|
|
|
AddSprite(&sUnknown_202F1F0, 0x100, NULL, NULL);
|
|
}
|
|
if (gRealInputs.pressed & AB_BUTTONS)
|
|
break;
|
|
}
|
|
DrawDialogueBoxString();
|
|
sub_803E46C(9);
|
|
}
|
|
|
|
while (r8 >= 0) {
|
|
for (j = 0; j < 8; j++) {
|
|
SetBGPaletteBufferColorRGB(240 + j, &gFontPalette[0].pal[j], r8 / 2, NULL);
|
|
}
|
|
DrawDialogueBoxString();
|
|
sub_803E46C(9);
|
|
r8--;
|
|
}
|
|
|
|
xxx_call_save_unk_text_struct_800641C(NULL, TRUE, TRUE);
|
|
sub_803E46C(9);
|
|
sub_8040238();
|
|
for (j = 0; j < 8; j++) {
|
|
SetBGPaletteBufferColorArray(240 + j, &gFontPalette[0].pal[j]);
|
|
}
|
|
sub_803E708(8, 9);
|
|
}
|
|
|
|
const u8 *GetCurrentDungeonName(void)
|
|
{
|
|
if (gDungeon->unk644.unk34 == 1) {
|
|
return GetDungeonName1(DUNGEON_OUT_ON_RESCUE);
|
|
}
|
|
else {
|
|
return GetDungeonName1(gDungeon->unk644.dungeonLocation.id);
|
|
}
|
|
}
|
|
|
|
void ResetMessageLog(void)
|
|
{
|
|
s32 i;
|
|
|
|
gDungeon->unk16 = 0;
|
|
gDungeon->unkB = 1;
|
|
for (i = 0; i < MESSAGE_LOG_STRINGS_COUNT; i++) {
|
|
gDungeon->messageLogStrings[i].str[0] = '\0';
|
|
gDungeon->messageLogStrings[i].unk0 = 0;
|
|
gDungeon->messageLogStrings[i].unk1 = 0;
|
|
gDungeon->messageLogStrings[i].unk2 = 0;
|
|
}
|
|
}
|
|
|
|
UNUSED void sub_8053200(void)
|
|
{
|
|
gDungeon->unkB = 1;
|
|
}
|
|
|
|
static void CopyStringToMessageLog(const u8 *src, u32 a1, u32 a2)
|
|
{
|
|
u8 *dst = &gDungeon->messageLogStrings[gDungeon->unk16].str[0];
|
|
u8 *maxDst = &gDungeon->messageLogStrings[gDungeon->unk16].str[MESSAGE_LOG_BUFFER_SIZE - 1];
|
|
gDungeon->messageLogStrings[gDungeon->unk16].unk0 = 1;
|
|
gDungeon->messageLogStrings[gDungeon->unk16].unk1 = a1;
|
|
gDungeon->messageLogStrings[gDungeon->unk16].unk2 = a2;
|
|
|
|
while (*src != '\0') {
|
|
if (*src == '\r') break;
|
|
if (dst < maxDst) {
|
|
*(dst++) = *src;
|
|
}
|
|
src++;
|
|
}
|
|
|
|
*dst = '\0';
|
|
if (++gDungeon->unk16 >= MESSAGE_LOG_STRINGS_COUNT) {
|
|
gDungeon->unk16 = 0;
|
|
}
|
|
|
|
gDungeon->unkB = 1;
|
|
}
|
|
|
|
#define MESSAGE_LOG_ROW_COUNT 8 // How many log messages are shown
|
|
|
|
UNUSED static const char sPksDirMeme[] = "pksdir0";
|
|
// Possibly something menu related?
|
|
// Unfortunately, this is passed to sub_8014140 which is a nullsub. It could be used for Blue and Nintendo DS' touch screen.
|
|
static const u8 sUnknownMessageLogData[] =
|
|
{
|
|
0x01, 0x00, 0x54, 0x00, 0xf0, 0xff, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x02, 0x00, 0x54, 0x00,
|
|
0x6a, 0x00, 0x18, 0x00, 0x18, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
|
|
0x00, 0x00, 0x00, 0x00, 0x70, 0x6b, 0x73, 0x64, 0x69, 0x72, 0x30, 0x00
|
|
};
|
|
|
|
bool32 DisplayMessageLog(void)
|
|
{
|
|
bool8 unkRet;
|
|
MenuInputStructSub menuInput;
|
|
|
|
sub_801317C(&menuInput);
|
|
sub_803EAF0(9, 0);
|
|
do {
|
|
sub_803E46C(13);
|
|
unkRet = sub_8008D8C(0);
|
|
} while (unkRet);
|
|
|
|
sMessageLogCursor = 0;
|
|
sMessageLogFlags = 0;
|
|
PutStringsOnMessageLog();
|
|
|
|
while (1) {
|
|
s32 unkVar;
|
|
bool32 scroll = FALSE;
|
|
|
|
sMessageLogFlags = 0;
|
|
nullsub_34(&menuInput, 0);
|
|
unkVar = sub_8014140(0, sUnknownMessageLogData);
|
|
|
|
if (TryScrollLogUp(unkVar))
|
|
scroll = TRUE;
|
|
if (TryScrollLogDown(unkVar))
|
|
scroll = TRUE;
|
|
|
|
if (!scroll) {
|
|
sub_803E46C(0xD);
|
|
}
|
|
|
|
if (sMessageLogFlags & FLAG_CAN_SCROLL_UP) {
|
|
CreateMessageLogArrow(TRUE, -8);
|
|
}
|
|
if (sMessageLogFlags & FLAG_CAN_SCROLL_DOWN) {
|
|
CreateMessageLogArrow(FALSE, 114);
|
|
}
|
|
|
|
if (!sub_80048C8()) {
|
|
if (gRealInputs.pressed & B_BUTTON || menuInput.b_button) {
|
|
sub_8083D30();
|
|
break;
|
|
}
|
|
else if (gRealInputs.pressed & A_BUTTON) {
|
|
sub_8083D08();
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
sub_803EAF0(0, 0);
|
|
return TRUE;
|
|
}
|
|
|
|
static void PutStringsOnMessageLog(void)
|
|
{
|
|
s32 i;
|
|
s32 arrId = gDungeon->unk16;
|
|
s32 y = 16;
|
|
|
|
arrId -= 8;
|
|
if (arrId < 0)
|
|
arrId += MESSAGE_LOG_STRINGS_COUNT;
|
|
|
|
sub_80073B8(0);
|
|
for (i = 0; i < MESSAGE_LOG_ROW_COUNT; i++) {
|
|
struct MessageLogString *msgLogString = &gDungeon->messageLogStrings[arrId];
|
|
|
|
if (msgLogString->unk0) {
|
|
if (msgLogString->unk1) {
|
|
sub_80078A4(0, 0, y, 0xE0, 7);
|
|
}
|
|
PrintStringOnWindow(8, y + 3, msgLogString->str, 0, 0xD);
|
|
y += 14;
|
|
}
|
|
if (++arrId >= MESSAGE_LOG_STRINGS_COUNT)
|
|
arrId = 0;
|
|
}
|
|
|
|
sub_80073E0(0);
|
|
sub_8007334(0);
|
|
}
|
|
|
|
static bool8 TryScrollLogUp(s32 a0)
|
|
{
|
|
s32 i;
|
|
struct MessageLogString *msgLogString;
|
|
s32 y;
|
|
s32 arrId;
|
|
|
|
while (1)
|
|
{
|
|
arrId = gDungeon->unk16 + sMessageLogCursor;
|
|
y = 2;
|
|
arrId -= 9;
|
|
while (arrId < 0) {
|
|
arrId += MESSAGE_LOG_STRINGS_COUNT;
|
|
}
|
|
while (arrId >= MESSAGE_LOG_STRINGS_COUNT) {
|
|
arrId -= MESSAGE_LOG_STRINGS_COUNT;
|
|
}
|
|
|
|
if (gDungeon->messageLogStrings[arrId].unk0 && sMessageLogCursor > -12) {
|
|
sMessageLogFlags |= FLAG_CAN_SCROLL_UP;
|
|
if (gRealInputs.repeated & DPAD_UP)
|
|
break;
|
|
if (a0 == 1)
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
sub_8083CE0(0);
|
|
sub_80073B8(0);
|
|
msgLogString = &gDungeon->messageLogStrings[arrId];
|
|
if (msgLogString->unk0) {
|
|
sub_80087EC(0, 0, 0, 0xD0, 0x10);
|
|
if (msgLogString->unk1) {
|
|
sub_80078A4(0, 0, y, 0xE0, 7);
|
|
}
|
|
PrintStringOnWindow(8, y + 3, msgLogString->str, 0, 0xD);
|
|
}
|
|
sub_80073E0(0);
|
|
sub_803E46C(0xD);
|
|
|
|
for (i = 0; i < 7; i++) {
|
|
gIwramTextFunc2(0);
|
|
sub_803E46C(0xD);
|
|
}
|
|
|
|
sMessageLogCursor--;
|
|
return TRUE;
|
|
}
|
|
|
|
static bool8 TryScrollLogDown(s32 a0)
|
|
{
|
|
s32 i;
|
|
struct MessageLogString *msgLogString;
|
|
s32 y;
|
|
s32 arrId;
|
|
|
|
while (1)
|
|
{
|
|
arrId = gDungeon->unk16 + sMessageLogCursor;
|
|
y = 128;
|
|
while (arrId < 0) {
|
|
arrId += MESSAGE_LOG_STRINGS_COUNT;
|
|
}
|
|
while (arrId >= MESSAGE_LOG_STRINGS_COUNT) {
|
|
arrId -= MESSAGE_LOG_STRINGS_COUNT;
|
|
}
|
|
|
|
if (sMessageLogCursor < 0) {
|
|
sMessageLogFlags |= FLAG_CAN_SCROLL_DOWN;
|
|
if (gRealInputs.repeated & DPAD_DOWN)
|
|
break;
|
|
if (a0 == 2)
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
sub_8083CE0(0);
|
|
sub_80073B8(0);
|
|
msgLogString = &gDungeon->messageLogStrings[arrId];
|
|
if (msgLogString->unk0) {
|
|
sub_80087EC(0, 0, y, 0x68, 0x10);
|
|
if (msgLogString->unk1) {
|
|
sub_80078A4(0, 0, y, 0xE0, 7);
|
|
}
|
|
PrintStringOnWindow(8, y + 3, msgLogString->str, 0, 0xD);
|
|
}
|
|
sub_80073E0(0);
|
|
sub_803E46C(0xD);
|
|
|
|
for (i = 0; i < 7; i++) {
|
|
gIwramTextFunc1(0);
|
|
sub_803E46C(0xD);
|
|
}
|
|
|
|
sMessageLogCursor++;
|
|
return TRUE;
|
|
}
|
|
|
|
static void CreateMessageLogArrow(bool8 upArrow, s32 y)
|
|
{
|
|
struct UnkTextStruct1 *unkStr = &gUnknown_2027370[0];
|
|
if (!(gUnknown_202EDCC & 8)) {
|
|
SpriteSetAffine1(&sMessageLogArrowSpriteOAM, 0);
|
|
SpriteSetAffine2(&sMessageLogArrowSpriteOAM, 0);
|
|
SpriteSetObjMode(&sMessageLogArrowSpriteOAM, 0);
|
|
SpriteSetMosaic(&sMessageLogArrowSpriteOAM, 0);
|
|
SpriteSetBpp(&sMessageLogArrowSpriteOAM, 0);
|
|
SpriteSetMatrixNum(&sMessageLogArrowSpriteOAM, (upArrow != FALSE) ? (16) : 0);
|
|
SpriteSetPalNum(&sMessageLogArrowSpriteOAM, 15);
|
|
SpriteSetY(&sMessageLogArrowSpriteOAM, (unkStr->unk2 * 8) + y);
|
|
SpriteSetX(&sMessageLogArrowSpriteOAM, (unkStr->unk0 * 8) + 92);
|
|
SpriteSetShape(&sMessageLogArrowSpriteOAM, 1);
|
|
SpriteSetSize(&sMessageLogArrowSpriteOAM, 0);
|
|
SpriteSetPriority(&sMessageLogArrowSpriteOAM, 0);
|
|
SpriteSetPalNum(&sMessageLogArrowSpriteOAM, 15);
|
|
SpriteSetTileNum(&sMessageLogArrowSpriteOAM, 0x3f0);
|
|
|
|
AddSprite(&sMessageLogArrowSpriteOAM, 127, NULL, NULL);
|
|
}
|
|
}
|
|
|