mirror of
https://github.com/pret/pmd-red.git
synced 2026-07-03 17:11:31 -05:00
1160 lines
33 KiB
C
1160 lines
33 KiB
C
#include "global.h"
|
|
#include "dungeon_util_1.h"
|
|
#include "memory.h"
|
|
#include "structs/rgb.h"
|
|
#include "structs/sprite_oam.h"
|
|
#include "structs/str_dungeon_8042F6C.h"
|
|
#include "code_803E46C.h"
|
|
#include "code_800E9E4.h"
|
|
#include "code_800DAC0.h"
|
|
#include "code_800E9A8.h"
|
|
#include "dungeon_util.h"
|
|
#include "dungeon_message.h"
|
|
#include "dungeon_generation.h"
|
|
#include "bg_control.h"
|
|
#include "random.h"
|
|
#include "file_system.h"
|
|
#include "dungeon_leader.h"
|
|
#include "dungeon.h"
|
|
#include "dungeon_ai.h"
|
|
#include "pokemon.h"
|
|
#include "cpu.h"
|
|
#include "dungeon_music.h"
|
|
#include "dungeon_random.h"
|
|
#include "code_8009804.h"
|
|
#include "tile_types.h"
|
|
#include "text.h"
|
|
#include "code_805D8C8.h"
|
|
#include "code_803E668.h"
|
|
#include "dungeon_engine.h"
|
|
#include "dungeon_map_access.h"
|
|
#include "pokemon.h"
|
|
#include "weather.h"
|
|
#include "moves.h"
|
|
#include "code_8094F88.h"
|
|
#include "code_8099360.h"
|
|
#include "bg_palette_buffer.h"
|
|
#include "exclusive_pokemon.h"
|
|
#include "constants/dungeon.h"
|
|
#include "constants/monster.h"
|
|
#include "constants/trap.h"
|
|
#include "dungeon_serializer.h"
|
|
#include "dungeon_config.h"
|
|
#include "dungeon_map.h"
|
|
|
|
extern void sub_800EE5C(s32);
|
|
extern void sub_800EF64(void);
|
|
extern void sub_800F15C(s32);
|
|
|
|
struct UnkStruct_203B414
|
|
{
|
|
s32 unk0;
|
|
s32 unk4;
|
|
s32 unk8;
|
|
s32 unkC[16];
|
|
s32 unk4C[16];
|
|
struct DungeonPos unk8C[16];
|
|
};
|
|
|
|
EWRAM_INIT DungeonPos gPlayerDotMapPosition = {100, 100};
|
|
static EWRAM_INIT struct UnkStruct_203B414 *sUnknown_203B414 = NULL;
|
|
EWRAM_INIT Dungeon *gDungeon = NULL;
|
|
EWRAM_INIT u8 *gSerializedData_203B41C = NULL;
|
|
EWRAM_INIT u8 gUnknown_203B420[8] = {0x15, 0x00, 0x16, 0x00, 0x15, 0x00, 0x16, 0x00}; // Could be a different file?
|
|
EWRAM_INIT u8 gUnknown_203B428[8] = {0x02, 0x03, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02}; // Could be a different file?
|
|
|
|
struct UnkStruct_80F6624
|
|
{
|
|
s16 unk0;
|
|
s32 unk4;
|
|
};
|
|
|
|
extern const struct UnkStruct_80F6624 gUnknown_80F6624[][3];
|
|
|
|
extern const unkStruct_2039DB0 gUnknown_80F683C;
|
|
|
|
void sub_8042B34(s32 a0, s32 a1, s32 a2)
|
|
{
|
|
unkStruct_80416E0 spStruct;
|
|
unkStruct_2039DB0 stack1C;
|
|
s32 i;
|
|
s32 r8 = 0;
|
|
Entity *leader = xxx_call_GetLeader();
|
|
sUnknown_203B414 = MemoryAlloc(sizeof(*sUnknown_203B414), 7);
|
|
|
|
sUnknown_203B414->unk0 = a0;
|
|
sUnknown_203B414->unk8 = (a1 + 1) * 4;
|
|
sub_800EE5C(gUnknown_80F6624[a0][0].unk0);
|
|
sub_800EF64();
|
|
DungeonRunFrameActions(0x46);
|
|
sUnknown_203B414->unk4 = a2;
|
|
for (i = 0; i < sUnknown_203B414->unk8; i++) {
|
|
s32 rnd;
|
|
|
|
spStruct.unk0 = gUnknown_80F6624[sUnknown_203B414->unk0][r8].unk0;
|
|
spStruct.unk4 = i;
|
|
spStruct.dir = 0;
|
|
spStruct.x = leader->pixelPos.x / 256;
|
|
spStruct.y = leader->pixelPos.y / 256;
|
|
|
|
rnd = RandInt(2);
|
|
sUnknown_203B414->unk4C[i] = (gUnknown_80F6624[sUnknown_203B414->unk0][r8].unk4 * 2) + rnd;
|
|
sUnknown_203B414->unk8C[i].x = RandInt(240) + 152;
|
|
sUnknown_203B414->unk8C[i].y = RandInt(8 + (i * 2)) - (((i - (i / 4 * 4)) * 40) - 24);
|
|
|
|
spStruct.unk10 = sUnknown_203B414->unk8C[i].x;
|
|
spStruct.unk12 = sUnknown_203B414->unk8C[i].y;
|
|
spStruct.unk14 = 4;
|
|
spStruct.unk18 = 0xFFFF;
|
|
stack1C = gUnknown_80F683C;
|
|
sUnknown_203B414->unkC[i] = sub_800E890(&spStruct);
|
|
|
|
r8++;
|
|
if (r8 >= 3 || gUnknown_80F6624[sUnknown_203B414->unk0][r8].unk0 == 0) {
|
|
r8 = 0;
|
|
}
|
|
|
|
sub_800F15C(sub_800ECA4(spStruct.unk0)->effectId);
|
|
}
|
|
}
|
|
|
|
bool8 sub_8042CC0(void)
|
|
{
|
|
s32 i;
|
|
bool8 ret = FALSE;
|
|
|
|
if (sUnknown_203B414->unk4 != 0) {
|
|
ret = TRUE;
|
|
sUnknown_203B414->unk4--;
|
|
}
|
|
|
|
for (i = 0; i < sUnknown_203B414->unk8; i++) {
|
|
sUnknown_203B414->unk8C[i].x -= sUnknown_203B414->unk4C[i];
|
|
if (sUnknown_203B414->unk8C[i].x <= -152) {
|
|
if (sUnknown_203B414->unk4 > 0) {
|
|
sUnknown_203B414->unk8C[i].x = 152;
|
|
}
|
|
else {
|
|
sUnknown_203B414->unk8C[i].x = -152;
|
|
}
|
|
}
|
|
else {
|
|
ret = TRUE;
|
|
}
|
|
sub_800E8AC(sUnknown_203B414->unkC[i], NULL, &sUnknown_203B414->unk8C[i], 0, NULL);
|
|
}
|
|
|
|
sub_800E90C(&gDungeon->unk181e8.cameraPixelPos);
|
|
return ret;
|
|
}
|
|
|
|
void sub_8042D7C(void)
|
|
{
|
|
s32 i;
|
|
|
|
if (sUnknown_203B414 == NULL)
|
|
return;
|
|
|
|
for (i = 0; i < sUnknown_203B414->unk8; i++) {
|
|
if (sub_800E9A8(sUnknown_203B414->unkC[i])) {
|
|
sub_800DC14(sUnknown_203B414->unkC[i]);
|
|
}
|
|
}
|
|
sub_800DBBC();
|
|
MemoryFree(sUnknown_203B414);
|
|
sUnknown_203B414 = NULL;
|
|
}
|
|
|
|
extern s32 sub_800E6D8(s32);
|
|
|
|
// TODO: Figure out if a new file should start here
|
|
void sub_8042DD4(s32 a0, Entity *a1, s32 a2)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
struct unkStruct_Dungeon5C4_sub *strPtr = &gDungeon->unk5C4[i];
|
|
if (strPtr->unk0 == -1) {
|
|
strPtr->unk0 = a0;
|
|
strPtr->unkC = a1;
|
|
strPtr->unk4 = a2;
|
|
strPtr->unk8 = sub_800E6D8(a0);
|
|
return;
|
|
}
|
|
}
|
|
}
|
|
|
|
UNUSED bool32 sub_8042E1C(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
struct unkStruct_Dungeon5C4_sub *strPtr = &gDungeon->unk5C4[i];
|
|
if (strPtr->unk0 != -1 && sub_800E9A8(strPtr->unk0)) {
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
void sub_8042E5C(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
struct unkStruct_Dungeon5C4_sub *strPtr = &gDungeon->unk5C4[i];
|
|
if (strPtr->unk0 >= 0 && !sub_800E9A8(strPtr->unk0)) {
|
|
strPtr->unk0 = -1;
|
|
strPtr->unkC = NULL;
|
|
}
|
|
}
|
|
}
|
|
|
|
void sub_8042E98(void)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
struct unkStruct_Dungeon5C4_sub *strPtr = &gDungeon->unk5C4[i];
|
|
strPtr->unk0 = -1;
|
|
strPtr->unk4 = 0;
|
|
strPtr->unkC = NULL;
|
|
}
|
|
}
|
|
|
|
extern void sub_800569C(DungeonPos *, axdata *, u8);
|
|
extern void sub_800EB24(s32 param_1, DungeonPos *param_2, DungeonPos *param_3,
|
|
s32 param_4, s32 param_5);
|
|
|
|
void sub_8042EC8(Entity *a0, s32 a1)
|
|
{
|
|
s32 i;
|
|
|
|
for (i = 0; i < 3; i++) {
|
|
struct unkStruct_Dungeon5C4_sub *strPtr = &gDungeon->unk5C4[i];
|
|
if (strPtr->unk0 >= 0 && strPtr->unkC == a0) {
|
|
DungeonPos sp8 = {a0->pixelPos.x / 256, a0->pixelPos.y / 256};
|
|
DungeonPos sp4 = {0};
|
|
EntityInfo *entInfo = GetEntInfo(a0);
|
|
|
|
if (strPtr->unk8 != -1) {
|
|
sub_800569C(&sp4,
|
|
&a0->axObj.axdata,
|
|
strPtr->unk8);
|
|
}
|
|
|
|
sub_800EB24(strPtr->unk0, &sp8, &sp4,a1, entInfo->action.direction);
|
|
}
|
|
}
|
|
}
|
|
|
|
extern u8 gUnknown_203B40C;
|
|
|
|
|
|
extern void sub_8040094(u8 r0);
|
|
extern void sub_8068BDC(u8 r0);
|
|
extern s16 GetTurnLimit(u8 dungeon);
|
|
extern void sub_8041888(u8 param_1);
|
|
extern void sub_803D4AC(void);
|
|
extern void sub_804513C(void);
|
|
extern void sub_8043CD8(void);
|
|
extern void sub_803E250(void);
|
|
extern void sub_803E830(void);
|
|
extern void sub_803E214(void);
|
|
extern void nullsub_56(void);
|
|
extern void sub_8047104(void);
|
|
extern void sub_8068F28(void);
|
|
extern void sub_806C1D8(void);
|
|
extern void sub_804700C(void);
|
|
extern void IncrementThievingSuccesses(void);
|
|
extern void sub_803E13C(void);
|
|
extern void sub_80841EC(void);
|
|
extern void sub_8084424(void);
|
|
extern void sub_8086130(void);
|
|
extern void FreeDungeonPokemonSprites(void);
|
|
extern void sub_803DF60(void);
|
|
extern void sub_803E02C(void);
|
|
extern void sub_80847D4(void);
|
|
extern void sub_8043D60(void);
|
|
extern void sub_806890C(void);
|
|
extern void sub_80840A4(void);
|
|
extern void sub_803E178(void);
|
|
extern void sub_80848F0(void);
|
|
extern void IncrementAdventureFloorsExplored(void);
|
|
extern void sub_806AB2C(void);
|
|
extern void DisplayPreFightDialogue(void);
|
|
extern void sub_8071DA4(Entity *);
|
|
extern void sub_803E748(void);
|
|
extern void sub_8083D68(void);
|
|
extern void sub_803E7C8(void);
|
|
extern void ShowWholeRevealedDungeonMap(void);
|
|
extern void sub_807E5AC(void);
|
|
extern void TriggerWeatherAbilities(void);
|
|
extern void sub_807E88C(void);
|
|
extern void InitDungeonPokemonSprites(void);
|
|
extern void nullsub_16(void);
|
|
extern void sub_80521D0(void);
|
|
extern void sub_803F27C(u8);
|
|
extern void sub_807E7FC(u8);
|
|
extern bool8 IsLevelResetTo1(u8 dungeon);
|
|
extern void sub_8068A84(PokemonStruct1 *pokemon);
|
|
extern void sub_807EAA0(u32, u32);
|
|
extern void sub_803D4D0(void);
|
|
extern void sub_80842F0(void);
|
|
extern void sub_80427AC(void);
|
|
extern void sub_806AA70(void);
|
|
extern void sub_803D8F0(void);
|
|
extern void sub_806AD3C(void);
|
|
extern void sub_806C42C(void);
|
|
extern void sub_806B678(void);
|
|
extern void sub_806C3C0(void);
|
|
extern void sub_806B168(void);
|
|
extern void sub_806B6C4(void);
|
|
extern void sub_806A338(void);
|
|
extern void sub_8051E3C(void);
|
|
extern void sub_8045CB0(void);
|
|
extern void sub_807FA18(void);
|
|
extern void sub_806A974(void);
|
|
extern void sub_806CF60(void);
|
|
extern void sub_8068F80(void);
|
|
extern bool8 sub_8044B28(void);
|
|
extern bool8 sub_8083C24(void);
|
|
extern bool8 sub_8083C88(u8 param_1);
|
|
extern bool8 sub_8043ED0(bool8);
|
|
extern void ShowDungeonNameBanner(void);
|
|
extern void sub_803EAF0(u32, u32);
|
|
extern void sub_806A914(bool8 a0, bool8 a1, bool8 showRunAwayEffect);
|
|
extern void sub_803F4A0(Entity *a0);
|
|
extern void sub_8083AB0(s16 param_0, Entity * target, Entity * entity);
|
|
extern void sub_8046F84(s32 itemFlag);
|
|
extern bool8 sub_8083C50(void);
|
|
extern void sub_8068FE0(Entity *, u32, Entity *r2);
|
|
extern void ResetMonEntityData(EntityInfo *, u32);
|
|
extern s32 GetMovesLearnedAtLevel(u16* dst, s16 species, s32 level, s32 IQPoints);
|
|
extern bool8 IsKeepMoney(u8 dungeon);
|
|
extern void sub_8042B0C(Entity *);
|
|
|
|
extern s16 gUnknown_2026E4E;
|
|
extern u8 gUnknown_202F32C;
|
|
extern u8 gUnknown_202F1A8;
|
|
extern s32 gDungeonBrightness;
|
|
extern Entity *gLeaderPointer;
|
|
|
|
void EnforceMaxItemsAndMoney(void);
|
|
static void sub_8043FD0(void);
|
|
void sub_806B404(void);
|
|
u8 GetFloorType(void);
|
|
|
|
extern const u8 *gUnknown_80FEC48;
|
|
extern const u8 *gUnknown_80FEC7C;
|
|
extern const u8 *gUnknown_81002B8;
|
|
extern const u8 *gPtrFinalChanceMessage;
|
|
extern const u8 *gPtrClientFaintedMessage;
|
|
extern const u8 *const gUnknown_80F89B4;
|
|
extern const u8 *const gUnknown_80F89D4;
|
|
extern const u8 *const gUnknown_80F89D8;
|
|
|
|
extern const s16 gUnknown_80F6850[4];
|
|
|
|
extern OpenedFile *gDungeonNameBannerPalette;
|
|
|
|
// This functions is the main 'loop' when the player is in a Dungeon. It runs from the moment the player enters a dungeon, until they leave(by completing or by fainting).
|
|
// arm9.bin::0206A848
|
|
void RunDungeon(UnkStruct_RunDungeon *r8)
|
|
{
|
|
bool8 check;
|
|
Entity *leader;
|
|
u8 *dungeonPtr;
|
|
s32 i;
|
|
bool8 r6;
|
|
bool8 r9;
|
|
bool8 r10;
|
|
u8 sp;
|
|
RGB color;
|
|
|
|
gUnknown_203B40C = 0;
|
|
r6 = r8->unk8;
|
|
r9 = r8->unk11;
|
|
r10 = r8->unk10;
|
|
gSerializedData_203B41C = r8->unk74;
|
|
gDungeon = r8->unk78;
|
|
if (!r6) {
|
|
*gSerializedData_203B41C = 0;
|
|
}
|
|
|
|
// Why not use memset?
|
|
dungeonPtr = (u8 *)(gDungeon);
|
|
for (i = 0; i < sizeof(Dungeon); i++) {
|
|
dungeonPtr[i] = 0;
|
|
}
|
|
|
|
gPlayerDotMapPosition.x = 0; // Needed to match
|
|
gPlayerDotMapPosition.x = 100;
|
|
|
|
if (!r6) {
|
|
gDungeon->unk644.unk34 = r8->unkF;
|
|
gDungeon->unk644.unk8 = r8->unk14;
|
|
gDungeon->unk644.windTurns = GetTurnLimit(r8->unk4.id);
|
|
gDungeon->unk644.unk36 = 0;
|
|
gDungeon->unk644.unk37 = GetRescuesAllowed(r8->unk4.id);
|
|
}
|
|
gDungeon->unk644.unk54 = 0;
|
|
gDungeon->unk644.unk55 = 0;
|
|
gDungeon->unk644.unk18 = r8->unk9;
|
|
gDungeon->unk644.unk16 = r8->unkC;
|
|
gDungeon->unk644.canRecruit = r8->unkA;
|
|
gDungeon->unk644.unk15 = r8->unkB;
|
|
gDungeon->unk644.unk17 = r8->unkD;
|
|
gDungeon->unk644.unk19 = r8->unkE;
|
|
StopDungeonBGM();
|
|
sub_803D4AC();
|
|
sub_804513C();
|
|
sub_8043CD8();
|
|
sub_80495E4();
|
|
sub_803E250();
|
|
OpenDungeonMapFile();
|
|
SetDungeonMapToNotShown();
|
|
sub_803F27C(1);
|
|
gUnknown_2026E4E = 2056;
|
|
sub_80095CC(1, 0x14);
|
|
sub_800DAC0(0);
|
|
UpdateFadeInTile(1);
|
|
sub_803DF60();
|
|
sub_803E02C();
|
|
sub_8042E98();
|
|
gUnknown_202F32C = 0;
|
|
if (r6) {
|
|
ReadDungeonState(gSerializedData_203B41C, 0x4800);
|
|
sub_8049840();
|
|
}
|
|
if (r9) {
|
|
sub_8043D60();
|
|
}
|
|
|
|
if (!r6) {
|
|
gDungeon->unk181e8.allTilesRevealed = 1;
|
|
gDungeon->unk181e8.unk1820C = 1;
|
|
if (gDungeon->unk644.unk34 == 1) {
|
|
gDungeon->unk644.dungeonLocation.id = r8->unk14.unk0;
|
|
gDungeon->unk644.dungeonLocation.floor = 1;
|
|
}
|
|
else {
|
|
gDungeon->unk644.dungeonLocation = r8->unk4;
|
|
}
|
|
|
|
gDungeon->unk644.unk30 = 0;
|
|
EnforceMaxItemsAndMoney();
|
|
}
|
|
if (!r6) {
|
|
if (gDungeon->unk644.unk34 == 1) {
|
|
gDungeon->unk644.unk38 = r8->unk14.unk4;
|
|
}
|
|
else {
|
|
gDungeon->unk644.unk38 = Rand32Bit() & 0xFFFFFF;
|
|
}
|
|
sub_808408C(gDungeon->unk644.unk38);
|
|
}
|
|
if (!r6) {
|
|
if (!sub_80980A4() && gDungeon->unk644.dungeonLocation.id == DUNGEON_TINY_WOODS) {
|
|
sub_8043FD0();
|
|
}
|
|
sub_806890C();
|
|
}
|
|
|
|
if (r9) {
|
|
gFormatArgs[0] = gDungeon->unk644.unk37;
|
|
if (gFormatArgs[0] != 0) {
|
|
DisplayDungeonMessage(0, gUnknown_80FEC48, 1);
|
|
}
|
|
else {
|
|
DisplayDungeonMessage(0, gUnknown_80FEC7C, 1);
|
|
}
|
|
}
|
|
|
|
if (r10) {
|
|
r8->unk1C.heldItem.id = 0;
|
|
if (IsLevelResetTo1(gDungeon->unk644.dungeonLocation.id)) {
|
|
sub_808D0D8(&r8->unk1C);
|
|
}
|
|
sub_8068A84(&r8->unk1C);
|
|
if (r6) {
|
|
sub_806B404();
|
|
}
|
|
}
|
|
|
|
OpenDungeonPaletteFile();
|
|
if (!r6 && gDungeon->unk644.unk34 == 1) {
|
|
if (sub_8099394(&sp)) {
|
|
unkStruct_203B480 *mailStr = GetMailatIndex(sp);
|
|
if (mailStr->rescuesAllowed) {
|
|
gFormatArgs[0] = mailStr->rescuesAllowed;
|
|
DisplayDungeonMessage(0, gUnknown_81002B8, 1);
|
|
}
|
|
else {
|
|
DisplayDungeonMessage(0, gPtrFinalChanceMessage, 1);
|
|
}
|
|
}
|
|
}
|
|
|
|
while (1) {
|
|
sub_8098080();
|
|
nullsub_16();
|
|
sub_80521D0();
|
|
ResetMessageLog();
|
|
InitDungeonPokemonSprites();
|
|
if (!r6) {
|
|
sub_804513C();
|
|
}
|
|
gLeaderPointer = NULL;
|
|
gDungeon->unk0 = 0;
|
|
if (!r6) {
|
|
gDungeon->unk644.unk3C = YetAnotherRandom24();
|
|
gDungeon->unk644.unk24 = 10;
|
|
InitDungeonRNG(gDungeon->unk644.unk3C);
|
|
}
|
|
gDungeon->unk37EC = 0;
|
|
if (!r6) {
|
|
s32 rnd;
|
|
|
|
gDungeon->decoyIsActive = FALSE;
|
|
rnd = DungeonRandInt(4);
|
|
gDungeon->unk37FD = 0;
|
|
gDungeon->deoxysDefeat = FALSE;
|
|
gDungeon->deoxysForm = gUnknown_80F6850[rnd];
|
|
gDungeon->unk37FF = 0;
|
|
gDungeon->unk644.unk31 = 0;
|
|
}
|
|
sub_803D4D0();
|
|
gDungeon->unk1 = 0;
|
|
gDungeon->unk10 = 0;
|
|
gDungeon->unk2 = 0;
|
|
gDungeon->unk4 = 0;
|
|
gDungeon->unk11 = 0;
|
|
gDungeon->unk8 = 0;
|
|
gDungeon->unk3 = 0;
|
|
gDungeon->unk6 = 0;
|
|
gDungeon->noActionInProgress = FALSE;
|
|
gDungeon->unk5C0 = -1;
|
|
gDungeon->unk7 = 0;
|
|
gDungeon->unk9 = 0;
|
|
gDungeon->unkA = 0;
|
|
gDungeon->unkB = 1;
|
|
gDungeon->unkD = 1;
|
|
gDungeon->unkE = 0;
|
|
gDungeon->unk1BDD4.unk1C05E = 0;
|
|
if (!r6) {
|
|
gDungeon->unk644.unk35 = 0;
|
|
gDungeon->unk644.unk48 = 0;
|
|
gDungeon->unk644.unk4C = 0;
|
|
gDungeon->unk644.unk50 = 0;
|
|
gDungeon->unk644.fractionalTurn = 0;
|
|
gDungeon->unk644.unk1E = 0;
|
|
gDungeon->unk644.unk2A = 0;
|
|
gDungeon->unk644.unk2B = 0;
|
|
gDungeon->unk644.unk2C = 0;
|
|
gDungeon->unk644.itemHoldersIdentified = 0;
|
|
gDungeon->unk644.monsterHouseTriggered = 0;
|
|
gDungeon->unk644.monsterHouseTriggeredEvent = 0;
|
|
gDungeon->unk644.bossSongIndex = 999;
|
|
gDungeon->unk644.unk44 = 0;
|
|
gDungeon->unk644.unk46 = 0;
|
|
gDungeon->unk644.unk40 = 99;
|
|
gDungeon->unk644.unk42 = 99;
|
|
gDungeon->weather.weather = 0;
|
|
gDungeon->tileset = gDungeon->unk1C574.unk2;
|
|
gDungeon->unk3A10 = gDungeon->unk1C574.unk3;
|
|
gDungeon->fixedRoomNumber = gDungeon->unk1C574.unk12;
|
|
sub_807E5E4(0);
|
|
sub_80842F0();
|
|
}
|
|
sub_803D8F0();
|
|
LoadDungeonPokemonSprites();
|
|
if (!r6) {
|
|
sub_80687AC();
|
|
}
|
|
else {
|
|
LoadDungeonActivePokemonSprites();
|
|
sub_8082B40();
|
|
}
|
|
sub_806C42C();
|
|
sub_806AD3C();
|
|
|
|
if (!r6) {
|
|
DungeonStartNewBGM(gDungeonMusic[gDungeon->unk3A10]);
|
|
sub_80847D4();
|
|
}
|
|
sub_8049840();
|
|
sub_803E178();
|
|
gDungeonBrightness = 0;
|
|
SetDungeonMapToNotShown();
|
|
sub_803EAF0(4, 0);
|
|
sub_8052210(0);
|
|
sub_803F27C(r6);
|
|
ShowDungeonNameBanner();
|
|
|
|
if (!r6) {
|
|
GenerateFloor();
|
|
gDungeon->unk644.windTurns = GetTurnLimit(gDungeon->unk644.dungeonLocation.id);
|
|
gDungeon->unk644.unk36 = 0;
|
|
}
|
|
sub_804AAD4();
|
|
sub_8049B8C();
|
|
LoadDungeonTilesetAssets();
|
|
if (!r6) {
|
|
sub_806B168();
|
|
sub_806C3C0();
|
|
sub_806B6C4();
|
|
}
|
|
else {
|
|
sub_806B678();
|
|
}
|
|
|
|
gDungeon->lightningRodPokemon = NULL;
|
|
gDungeon->unk17B38 = 0;
|
|
gDungeon->snatchPokemon = NULL;
|
|
gDungeon->unk17B3C = 0;
|
|
gDungeon->unk17B34 = NULL;
|
|
gDungeon->unk17B40 = 0;
|
|
if (!r6) {
|
|
sub_807FA18();
|
|
sub_8045CB0();
|
|
gDungeon->unk644.unk50 = gDungeon->unk644.unk48;
|
|
gDungeon->unk644.unk4C = 0;
|
|
sub_8051E3C();
|
|
sub_804AAAC();
|
|
}
|
|
else {
|
|
sub_806A338();
|
|
}
|
|
sub_8068F80();
|
|
sub_8049884();
|
|
sub_8049ED4();
|
|
|
|
if (!r6) {
|
|
sub_806A914(TRUE, FALSE, FALSE);
|
|
}
|
|
else {
|
|
sub_806CF60();
|
|
sub_806A974();
|
|
}
|
|
sub_8041888(1);
|
|
|
|
if (!r6) {
|
|
sub_80848F0();
|
|
IncrementAdventureFloorsExplored();
|
|
}
|
|
|
|
gUnknown_203B40C = 1;
|
|
if (r6) {
|
|
sub_807E88C();
|
|
sub_806AB2C();
|
|
}
|
|
|
|
if (gDungeon->unk7 == 0) {
|
|
sub_803E748();
|
|
}
|
|
else {
|
|
sub_803E7C8();
|
|
}
|
|
sub_8040094(0);
|
|
sub_803EAF0(0, 0);
|
|
InitDungeonMap(r6);
|
|
ShowWholeRevealedDungeonMap();
|
|
gDungeon->unkB8 = NULL;
|
|
gDungeon->unk644.unk28 = 0;
|
|
gDungeon->unk644.unk29 = 0;
|
|
gDungeon->unk12 = 99;
|
|
gDungeon->unk0 = 1;
|
|
|
|
if (!r6) {
|
|
TryDisplayGeneralTutorialMessage();
|
|
if (gDungeon->unk9 != 0) {
|
|
gDungeon->unk9 = 0;
|
|
sub_8083D68();
|
|
DisplayYouReachedDestFloorStr();
|
|
}
|
|
}
|
|
gLeaderPointer = NULL;
|
|
gDungeon->unk5 = 0;
|
|
if (!r6) {
|
|
DisplayPreFightDialogue();
|
|
if (gDungeon->unk4 != 0 || gDungeon->unk2 != 0) {
|
|
gDungeon->unk5 = 1;
|
|
}
|
|
else {
|
|
sub_803F4A0(GetLeader());
|
|
ShowWholeRevealedDungeonMap();
|
|
}
|
|
}
|
|
|
|
if (!r6) {
|
|
if (gDungeon->unk5 == 0) {
|
|
sub_807E5AC();
|
|
if (GetApparentWeather(NULL) != 0) {
|
|
sub_807E7FC(1);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
TriggerWeatherAbilities();
|
|
}
|
|
|
|
if (r6) {
|
|
r6 = FALSE;
|
|
}
|
|
else {
|
|
sub_80427AC();
|
|
sub_8075900(GetLeader(), gDungeon->forceMonsterHouse);
|
|
sub_807EAA0(1, 0);
|
|
}
|
|
|
|
nullsub_16();
|
|
if (gDungeon->unk5 == 0) {
|
|
bool8 param = TRUE;
|
|
|
|
gDungeon->unk644.unk10 = 0;
|
|
gDungeon->unk181e8.unk18218 = 0;
|
|
gDungeon->unk181e8.unk18219 = 1;
|
|
do {
|
|
RunFractionalTurn(param);
|
|
param = FALSE;
|
|
} while (!sub_8044B28());
|
|
}
|
|
|
|
leader = GetLeader();
|
|
if (EntityIsValid(leader)) {
|
|
sub_8071DA4(leader);
|
|
}
|
|
|
|
if (gDungeon->unk644.unk10 != 1) {
|
|
if (sub_8043ED0(TRUE)) {
|
|
gDungeon->unk644.unk10 = 1;
|
|
}
|
|
}
|
|
if (gDungeon->unk644.unk10 == 1 || gDungeon->unk11 != 0) {
|
|
if (gDungeon->unk6 == 0) {
|
|
sub_806AA70();
|
|
}
|
|
}
|
|
|
|
if (EntityIsValid(GetLeader())) {
|
|
sub_80526D0(0x4F);
|
|
sub_8052740(0x4F);
|
|
}
|
|
|
|
SetDungeonMapToNotShown();
|
|
sub_803EAF0(1, 0);
|
|
gDungeon->unk181e8.unk18219 = 0;
|
|
gDungeon->unk181e8.unk18218 = 1;
|
|
if (gDungeon->unk3 == 0
|
|
&& gDungeon->unk6 == 0
|
|
&& gDungeon->musPlayer.queuedSongIndex == 0x72
|
|
&& gDungeon->unk644.dungeonLocation.id == DUNGEON_BURIED_RELIC)
|
|
{
|
|
DungeonFadeOutBGM(60);
|
|
}
|
|
|
|
sub_803E708(4, 0x4F);
|
|
if (gDungeon->unk7 == 0) {
|
|
sub_803E830();
|
|
}
|
|
|
|
SetBGOBJEnableFlags(0);
|
|
color.r = 0x60;
|
|
color.g = 0x80;
|
|
color.b = 0xF8;
|
|
SetBGPaletteBufferColorRGB(253, &color, gDungeonBrightness, NULL);
|
|
sub_8040094(1);
|
|
gDungeon->unk181e8.unk18218 = 1;
|
|
if ((gDungeon->unk10 == 2 || gDungeon->unk10 == 3) && gDungeon->unk6 != 0) {
|
|
leader = GetLeader();
|
|
DisplayDungeonMessage(0, gPtrClientFaintedMessage, 1);
|
|
gDungeon->unk6 = 0;
|
|
sub_8083AB0(0x222, leader, leader);
|
|
}
|
|
CloseAllSpriteFiles();
|
|
sub_8049820();
|
|
CloseFile(gDungeonNameBannerPalette);
|
|
FreeDungeonPokemonSprites();
|
|
gUnknown_203B40C = 0;
|
|
|
|
if (gDungeon->unk3 != 0) {
|
|
SaveDungeonState(gSerializedData_203B41C, 0x4800);
|
|
r8->unk7C = 3;
|
|
r8->unk80 = gDungeon->unk644.dungeonLocation;
|
|
check = FALSE;
|
|
}
|
|
else
|
|
{
|
|
s16 var;
|
|
|
|
if (gDungeon->unk6 != 0) {
|
|
SaveDungeonState(gSerializedData_203B41C, 0x4800);
|
|
}
|
|
else {
|
|
sub_8046F84(ITEM_FLAG_IN_SHOP);
|
|
}
|
|
sub_806C1D8();
|
|
|
|
if (gDungeon->unk644.unk10 == 1) {
|
|
if (gDungeon->unk644.unk2A != 0) {
|
|
sub_804700C();
|
|
}
|
|
check = TRUE;
|
|
}
|
|
else if (gDungeon->unk11 == 1) {
|
|
sub_8083AB0(0x226, NULL, GetLeader());
|
|
check = TRUE;
|
|
}
|
|
else if (gDungeon->unk11 == 2) {
|
|
sub_8083AB0(0x229, NULL, GetLeader());
|
|
if (gDungeon->unk644.unk2A != 0) {
|
|
IncrementThievingSuccesses();
|
|
}
|
|
check = TRUE;
|
|
}
|
|
else if (gDungeon->unk11 == 3) {
|
|
sub_8083AB0(0x22A, NULL, GetLeader());
|
|
if (gDungeon->unk644.unk2A != 0) {
|
|
IncrementThievingSuccesses();
|
|
}
|
|
check = TRUE;
|
|
}
|
|
else if (gDungeon->unk11 == 4) {
|
|
var = 0x227;
|
|
sub_8083AB0(var, NULL, GetLeader());
|
|
check = TRUE;
|
|
}
|
|
else if (gDungeon->unk644.unk34 == 1 && GetFloorType() == FLOOR_TYPE_RESCUE && gDungeon->unk644.unk10 == 2) {
|
|
sub_8083AB0(0x228, NULL, GetLeader());
|
|
if (gDungeon->unk644.unk2A != 0) {
|
|
IncrementThievingSuccesses();
|
|
}
|
|
check = TRUE;
|
|
}
|
|
else {
|
|
if (gDungeon->unk644.unk2A != 0) {
|
|
IncrementThievingSuccesses();
|
|
}
|
|
if (gDungeon->unk644.dungeonLocation.floor + 1 < gDungeon->unk1CEC8) {
|
|
gDungeon->unk644.dungeonLocation.floor++;
|
|
if (gDungeon->unk644.dungeonLocation.id == DUNGEON_FROSTY_FOREST
|
|
&& gDungeon->unk644.dungeonLocation.floor == 6
|
|
&& !sub_8098100(0x1F))
|
|
{
|
|
sub_8097FA8(0x1F);
|
|
sub_8086130();
|
|
sub_8097FF8();
|
|
}
|
|
// We go back to the loop's start.
|
|
continue;
|
|
}
|
|
else {
|
|
var = 0x227;
|
|
sub_8083AB0(var, NULL, GetLeader());
|
|
check = TRUE;
|
|
// This goto is a fakematch I had to create in order to generate matching code.
|
|
// It has no real effect, because the control flow is the same without it(since check is TRUE). Unfortunately agbcc is blind and goto is needed.
|
|
// Feel free to remove it.
|
|
goto FAKEMATCH;
|
|
}
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
if (check) {
|
|
// See comment above
|
|
FAKEMATCH:
|
|
gUnknown_203B40C = 0;
|
|
r8->unk7E = 0;
|
|
sub_8097FF8();
|
|
sub_80095CC(1, 0x14);
|
|
sub_803E13C();
|
|
sub_800CDA8(4);
|
|
if (gDungeon->unk6 == 0 && sub_8083C88(gDungeon->unk644.unk34)) {
|
|
sub_80841EC();
|
|
}
|
|
|
|
if (sub_8083C24()) {
|
|
if (gDungeon->unk6 != 0) {
|
|
r8->unk7C = -2;
|
|
memset(&r8->unk84, 0, sizeof(r8->unk84));
|
|
r8->unk80 = gDungeon->unk644.dungeonLocation;
|
|
r8->unk84.dungeon = gDungeon->unk644.dungeonLocation;
|
|
r8->unk84.seed = gDungeon->unk644.unk38;
|
|
|
|
}
|
|
else {
|
|
r8->unk7C = -1;
|
|
}
|
|
}
|
|
else if (sub_8083C50()) {
|
|
if (gDungeon->unk644.unk34 == 1) {
|
|
r8->unk7C = 4;
|
|
}
|
|
else if (gDungeon->unk644.unk34 == 0) {
|
|
r8->unk7C = 1;
|
|
sub_8084424();
|
|
}
|
|
else {
|
|
r8->unk7C = 1;
|
|
sub_8084424();
|
|
}
|
|
r8->unk7E = gDungeon->unk644.unk30;
|
|
}
|
|
else {
|
|
r8->unk7C = 2;
|
|
sub_8084424();
|
|
}
|
|
}
|
|
|
|
CloseDungeonPaletteFile();
|
|
sub_803E214();
|
|
nullsub_56();
|
|
CloseDungeonMapFile();
|
|
if (r8->unk7C == 1 || r8->unk7C == 4 || r8->unk7C == 2) {
|
|
sub_8047104();
|
|
}
|
|
if (r8->unk7C == 1 || r8->unk7C == -2 || r8->unk7C == 4 || r8->unk7C == -1 || r8->unk7C == 2) {
|
|
if (r8->unk7C == 1 || r8->unk7C == 4 || r8->unk7C == 2) {
|
|
sub_8068BDC(1);
|
|
}
|
|
else if (r8->unk7C == -2) {
|
|
sub_8068BDC(0);
|
|
}
|
|
else {
|
|
sub_8068F28();
|
|
sub_8068BDC(0);
|
|
}
|
|
}
|
|
sub_800DB7C();
|
|
gDungeon = NULL;
|
|
gSerializedData_203B41C = 0;
|
|
nullsub_16();
|
|
}
|
|
|
|
void sub_8043CD8(void)
|
|
{
|
|
vram_related_8009804();
|
|
}
|
|
|
|
bool8 sub_8043CE4(s32 dungeonId)
|
|
{
|
|
if (gUnknown_202F1A8)
|
|
return TRUE;
|
|
|
|
return (gDungeonWaterType[dungeonId] == 2);
|
|
}
|
|
|
|
u8 GetFloorType(void)
|
|
{
|
|
if (gDungeon->unk644.unk34 == 1 && gDungeon->unk644.unk8.unk1 == gDungeon->unk644.dungeonLocation.floor)
|
|
return FLOOR_TYPE_RESCUE;
|
|
else if (IsBossFight())
|
|
return FLOOR_TYPE_FIXED;
|
|
else
|
|
return FLOOR_TYPE_NORMAL;
|
|
}
|
|
|
|
void sub_8043D50(s32 *a0, s32 *a1)
|
|
{
|
|
*a1 = sizeof(Dungeon);
|
|
*a0 = 0x4800; // Hmmm
|
|
}
|
|
|
|
void sub_8043D60(void)
|
|
{
|
|
s32 x, y, monId;
|
|
|
|
for (monId = 0; monId < DUNGEON_MAX_WILD_POKEMON; monId++) {
|
|
Entity *mon = gDungeon->wildPokemon[monId];
|
|
if (EntityIsValid(mon)) {
|
|
EntityInfo *monInfo = GetEntInfo(mon);
|
|
bool32 unk = TRUE;
|
|
|
|
if (monInfo->shopkeeper == TRUE)
|
|
unk = FALSE;
|
|
if (IsExperienceLocked(monInfo->joinedAt.id))
|
|
unk = FALSE;
|
|
if (monInfo->monsterBehavior == BEHAVIOR_RESCUE_TARGET)
|
|
unk = FALSE;
|
|
|
|
if (unk) {
|
|
sub_8068FE0(mon, 0x207, mon);
|
|
}
|
|
}
|
|
}
|
|
|
|
for (monId = 0; monId < MAX_TEAM_MEMBERS; monId++) {
|
|
Entity *mon = gDungeon->teamPokemon[monId];
|
|
if (EntityIsValid(mon)) {
|
|
s32 i;
|
|
EntityInfo *monInfo;
|
|
|
|
mon->unk22 = 0;
|
|
mon->isVisible = TRUE;
|
|
monInfo = GetEntInfo(mon);
|
|
monInfo->HP = monInfo->maxHPStat;
|
|
monInfo->belly = monInfo->maxBelly;
|
|
gDungeon->unk644.itemHoldersIdentified = FALSE;
|
|
ResetMonEntityData(monInfo, 0);
|
|
monInfo->apparentID = monInfo->id;
|
|
monInfo->perishSongTurns = 0;
|
|
for (i = 0; i < MAX_MON_MOVES; i++) {
|
|
Move *move = &monInfo->moves.moves[i];
|
|
if (move->moveFlags & MOVE_FLAG_EXISTS) {
|
|
move->PP = GetMoveBasePP(move);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
for (y = 0; y < 32; y++) {
|
|
for (x = 0; x < 56; x++) {
|
|
Entity *object = GetTileMut(x, y)->object;
|
|
if (EntityIsValid(object) && GetEntityType(object) == ENTITY_TRAP) {
|
|
Trap *trapData = GetTrapData(object);
|
|
if (trapData->id == 27) {
|
|
trapData->id = TRAP_PITFALL_TRAP;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
sub_8046F84(ITEM_FLAG_IN_SHOP);
|
|
}
|
|
|
|
bool8 sub_8043ED0(bool8 a0)
|
|
{
|
|
bool8 ret = FALSE;
|
|
|
|
if (!a0 && sub_8044B28())
|
|
return FALSE;
|
|
|
|
if (gDungeon->unk10 == 1) {
|
|
Entity *leader = GetLeader();
|
|
if (EntityIsValid(leader)) {
|
|
if (!a0) {
|
|
strcpy(gFormatBuffer_Monsters[0], gDungeon->faintStringBuffer);
|
|
DisplayDungeonMessage(0, gUnknown_80F89B4, 1);
|
|
}
|
|
sub_8042B0C(leader);
|
|
sub_8068FE0(leader, 0x21F, leader);
|
|
ret = TRUE;
|
|
}
|
|
}
|
|
else if (gDungeon->unk10 == 2) {
|
|
Entity *leader = GetLeader();
|
|
if (EntityIsValid(leader)) {
|
|
if (!a0) {
|
|
strcpy(gFormatBuffer_Monsters[0], gDungeon->faintStringBuffer);
|
|
DisplayDungeonMessage(0, gUnknown_80F89D4, 1);
|
|
}
|
|
sub_8042B0C(leader);
|
|
sub_8068FE0(leader, 0x222, leader);
|
|
ret = TRUE;
|
|
}
|
|
}
|
|
else if (gDungeon->unk10 == 3) {
|
|
Entity *leader = GetLeader();
|
|
if (EntityIsValid(leader)) {
|
|
if (!a0) {
|
|
strcpy(gFormatBuffer_Monsters[0], gDungeon->faintStringBuffer);
|
|
DisplayDungeonMessage(0, gUnknown_80F89D8, 1);
|
|
}
|
|
sub_8042B0C(leader);
|
|
sub_8068FE0(leader, 0x222, leader);
|
|
ret = TRUE;
|
|
}
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static void sub_8043FD0(void)
|
|
{
|
|
s32 level;
|
|
for (level = 2; level <= 5; level++) {
|
|
s32 i, monId, movesCount;
|
|
for (monId = 0; monId < NUM_MONSTERS; monId++) {
|
|
PokemonStruct1 *monStruct = &gRecruitedPokemonRef->pokemon[monId];
|
|
if (PokemonFlag1(monStruct) && PokemonFlag2(monStruct)) {
|
|
u16 learnedMoves[16];
|
|
LevelData levelData;
|
|
// I have to make the variables volatile to get matching code. I'm sure there's a solution for this, but keeping it like that for now.
|
|
#ifdef NONMATCHING
|
|
s32 atk, spAtk, def, spDef;
|
|
#else
|
|
vs32 atk, spAtk, def, spDef;
|
|
#endif // NONMATCHING
|
|
|
|
GetPokemonLevelData(&levelData, monStruct->speciesNum, level);
|
|
monStruct->level = level;
|
|
monStruct->currExp = levelData.expRequired;
|
|
monStruct->pokeHP += levelData.gainHP;
|
|
if (monStruct->pokeHP >= 999) // TODO: Make this a max hp define
|
|
monStruct->pokeHP = 999;
|
|
|
|
atk = monStruct->offense.att[0];
|
|
spAtk = monStruct->offense.att[1];
|
|
def = monStruct->offense.def[0];
|
|
spDef = monStruct->offense.def[1];
|
|
|
|
atk += levelData.gainAtt[0];
|
|
spAtk += levelData.gainAtt[1];
|
|
def += levelData.gainDef[0];
|
|
spDef += levelData.gainDef[1];
|
|
|
|
// TODO: Make 255 max define for stats
|
|
if (atk >= 255) {atk = 255;}
|
|
if (spAtk >= 255) {spAtk = 255;}
|
|
if (def >= 255) {def = 255;}
|
|
if (spDef >= 255) {spDef = 255;}
|
|
|
|
monStruct->offense.att[0] = atk;
|
|
monStruct->offense.att[1] = spAtk;
|
|
monStruct->offense.def[0] = def;
|
|
monStruct->offense.def[1] = spDef;
|
|
|
|
movesCount = GetMovesLearnedAtLevel(learnedMoves, monStruct->speciesNum, monStruct->level, 999);
|
|
if (movesCount == 0)
|
|
continue;
|
|
|
|
for (i = 0; i < movesCount; i++) {
|
|
s32 moveSlot;
|
|
for (moveSlot = 0; moveSlot < MAX_MON_MOVES; moveSlot++) {
|
|
if (!MoveFlagExists(&monStruct->moves[moveSlot])) {
|
|
InitZeroedPPPokemonMove(&monStruct->moves[moveSlot], learnedMoves[i]);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
void EnforceMaxItemsAndMoney(void)
|
|
{
|
|
s32 i;
|
|
|
|
if (GetMaxItemsAllowed(gDungeon->unk644.dungeonLocation.id) == 0)
|
|
{
|
|
for (i = 0; i < INVENTORY_SIZE; i++) {
|
|
ZeroOutItem(&gTeamInventoryRef->teamItems[i]);
|
|
}
|
|
for (i = 0; i < NUM_MONSTERS; i++) {
|
|
PokemonStruct1 *mon = (&gRecruitedPokemonRef->pokemon[i]);
|
|
if (PokemonFlag1(mon) && PokemonFlag2(mon)) {
|
|
mon->heldItem.id = 0;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (!IsKeepMoney(gDungeon->unk644.dungeonLocation.id)) {
|
|
gTeamInventoryRef->teamMoney = 0;
|
|
}
|
|
}
|