diff options
Diffstat (limited to 'src/field')
77 files changed, 74703 insertions, 0 deletions
diff --git a/src/field/bard_music.c b/src/field/bard_music.c new file mode 100644 index 000000000..daf003233 --- /dev/null +++ b/src/field/bard_music.c @@ -0,0 +1,69 @@ +#include "global.h" +#include "bard_music.h" +#include "easy_chat.h" + +struct BardSound +{ + /*0x00*/ u8 var00; + /*0x01*/ s8 var01; + /*0x02*/ u16 var02; + /*0x04*/ u16 volume; + /*0x06*/ u16 var06; +}; + +extern const struct BardSound (*const gBardMusicTable[])[][6]; +extern s16 *gUnknown_08417068[]; +extern u32 gUnknown_084170F4[]; + +static s16 CalcWordPitch(u32 arg0, u32 songPos) +{ + return gUnknown_08417068[arg0][songPos]; +} + +#if ENGLISH +const struct BardSound *GetWordSounds(u16 group, u16 word) +{ + const struct BardSound (*sounds)[][6] = gBardMusicTable[group]; + + return (*sounds)[word]; +} +#elif GERMAN +const struct BardSound *GetWordSounds(u16 group, u16 word) +{ + const struct BardSound (*sounds)[][6] = gBardMusicTable[group]; + u32 index = de_sub_80EB748(group, word); + + return (*sounds)[index]; +} +#endif + +s32 GetWordPhonemes(struct BardSong *song, const struct BardSound *src, u16 arg2) +{ + s32 i; + s32 j; + s32 thirty; + + for (i = 0; i < 6; i++) + { + song->phonemes[i].sound = src[i].var00; + if (src[i].var00 != 0xFF) + { + s32 length = src[i].var01 + gUnknown_084170F4[src[i].var00]; + + song->phonemes[i].length = length; + song->phonemes[i].volume = src[i].volume; + song->var04 += length; + } + } + + for (j = 0, thirty = 30; j < i; j++) + song->phonemes[j].pitch = CalcWordPitch(thirty + arg2, j); + + song->currWord++; + song->currPhoneme = 0; + song->phonemeTimer = 0; + song->state = 0; + song->voiceInflection = 0; + + //warning: no return statement in function returning non-void +} diff --git a/src/field/berry.c b/src/field/berry.c new file mode 100644 index 000000000..d82eab2a6 --- /dev/null +++ b/src/field/berry.c @@ -0,0 +1,1380 @@ +#include "global.h" +#include "berry.h" +#include "field_control_avatar.h" +#include "field_map_obj.h" +#include "fieldmap.h" +#include "item.h" +#include "item_menu.h" +#include "item_use.h" +#include "items.h" +#include "main.h" +#include "rng.h" +#include "text.h" + +#define BERRY_NAME_LENGTH 6 + +#define FIRST_BERRY ITEM_CHERI_BERRY +#define LAST_BERRY ITEM_ENIGMA_BERRY + +#ifdef ENGLISH +#define NAME_CHERI_BERRY _("CHERI") +#define NAME_CHESTO_BERRY _("CHESTO") +#define NAME_PECHA_BERRY _("PECHA") +#define NAME_RAWST_BERRY _("RAWST") +#define NAME_ASPEAR_BERRY _("ASPEAR") +#define NAME_LEPPA_BERRY _("LEPPA") +#define NAME_ORAN_BERRY _("ORAN") +#define NAME_PERSIM_BERRY _("PERSIM") +#define NAME_LUM_BERRY _("LUM") +#define NAME_SITRUS_BERRY _("SITRUS") +#define NAME_FIGY_BERRY _("FIGY") +#define NAME_WIKI_BERRY _("WIKI") +#define NAME_MAGO_BERRY _("MAGO") +#define NAME_AGUAV_BERRY _("AGUAV") +#define NAME_IAPAPA_BERRY _("IAPAPA") +#define NAME_RAZZ_BERRY _("RAZZ") +#define NAME_BLUK_BERRY _("BLUK") +#define NAME_NANAB_BERRY _("NANAB") +#define NAME_WEPEAR_BERRY _("WEPEAR") +#define NAME_PINAP_BERRY _("PINAP") +#define NAME_POMEG_BERRY _("POMEG") +#define NAME_KELPSY_BERRY _("KELPSY") +#define NAME_QUALOT_BERRY _("QUALOT") +#define NAME_HONDEW_BERRY _("HONDEW") +#define NAME_GREPA_BERRY _("GREPA") +#define NAME_TAMATO_BERRY _("TAMATO") +#define NAME_CORNN_BERRY _("CORNN") +#define NAME_MAGOST_BERRY _("MAGOST") +#define NAME_RABUTA_BERRY _("RABUTA") +#define NAME_NOMEL_BERRY _("NOMEL") +#define NAME_SPELON_BERRY _("SPELON") +#define NAME_PAMTRE_BERRY _("PAMTRE") +#define NAME_WATMEL_BERRY _("WATMEL") +#define NAME_DURIN_BERRY _("DURIN") +#define NAME_BELUE_BERRY _("BELUE") +#define NAME_LIECHI_BERRY _("LIECHI") +#define NAME_GANLON_BERRY _("GANLON") +#define NAME_SALAC_BERRY _("SALAC") +#define NAME_PETAYA_BERRY _("PETAYA") +#define NAME_APICOT_BERRY _("APICOT") +#define NAME_LANSAT_BERRY _("LANSAT") +#define NAME_STARF_BERRY _("STARF") +#define NAME_ENIGMA_BERRY _("ENIGMA") + +const u8 gBerryDescriptionPart1_Cheri[] = _("Blooms with delicate pretty flowers."); +const u8 gBerryDescriptionPart2_Cheri[] = _("The bright red BERRY is very spicy."); +const u8 gBerryDescriptionPart1_Chesto[] = _("The BERRY’s thick skin and fruit are"); +const u8 gBerryDescriptionPart2_Chesto[] = _("very tough. It is dry-tasting all over."); +const u8 gBerryDescriptionPart1_Pecha[] = _("Very sweet and delicious."); +const u8 gBerryDescriptionPart2_Pecha[] = _("Also very tender - handle with care."); +const u8 gBerryDescriptionPart1_Rawst[] = _("If the leaves grow long and curly,"); +const u8 gBerryDescriptionPart2_Rawst[] = _("the BERRY seems to grow very bitter."); +const u8 gBerryDescriptionPart1_Aspear[] = _("The hard BERRY is dense with a rich"); +const u8 gBerryDescriptionPart2_Aspear[] = _("juice. It is quite sour."); +const u8 gBerryDescriptionPart1_Leppa[] = _("Grows slower than CHERI and others."); +const u8 gBerryDescriptionPart2_Leppa[] = _("The smaller the BERRY, the tastier."); +const u8 gBerryDescriptionPart1_Oran[] = _("A peculiar BERRY with a mix of flavors."); +const u8 gBerryDescriptionPart2_Oran[] = _("BERRIES grow in half a day."); +const u8 gBerryDescriptionPart1_Persim[] = _("Loves sunlight. The BERRY’s color"); +const u8 gBerryDescriptionPart2_Persim[] = _("grows vivid when exposed to the sun."); +const u8 gBerryDescriptionPart1_Lum[] = _("Slow to grow. If raised with loving"); +const u8 gBerryDescriptionPart2_Lum[] = _("care, it may grow two BERRIES."); +const u8 gBerryDescriptionPart1_Sitrus[] = _("Closely related to ORAN. The large"); +const u8 gBerryDescriptionPart2_Sitrus[] = _("BERRY has a well-rounded flavor."); +const u8 gBerryDescriptionPart1_Figy[] = _("The BERRY, which looks chewed up,"); +const u8 gBerryDescriptionPart2_Figy[] = _("brims with spicy substances."); +const u8 gBerryDescriptionPart1_Wiki[] = _("The BERRY is said to have grown lumpy"); +const u8 gBerryDescriptionPart2_Wiki[] = _("to help POKéMON grip it."); +const u8 gBerryDescriptionPart1_Mago[] = _("The BERRY turns curvy as it grows."); +const u8 gBerryDescriptionPart2_Mago[] = _("The curvier, the sweeter and tastier."); +const u8 gBerryDescriptionPart1_Aguav[] = _("The flower is dainty. It is rare in its"); +const u8 gBerryDescriptionPart2_Aguav[] = _("ability to grow without light."); +const u8 gBerryDescriptionPart1_Iapapa[] = _("The BERRY is very big and sour."); +const u8 gBerryDescriptionPart2_Iapapa[] = _("It takes at least a day to grow."); +const u8 gBerryDescriptionPart1_Razz[] = _("The red BERRY tastes slightly spicy."); +const u8 gBerryDescriptionPart2_Razz[] = _("It grows quickly in just four hours."); +const u8 gBerryDescriptionPart1_Bluk[] = _("The BERRY is blue on the outside, but"); +const u8 gBerryDescriptionPart2_Bluk[] = _("it blackens the mouth when eaten."); +const u8 gBerryDescriptionPart1_Nanab[] = _("This BERRY was the seventh"); +const u8 gBerryDescriptionPart2_Nanab[] = _("discovered in the world. It is sweet."); +const u8 gBerryDescriptionPart1_Wepear[] = _("The flower is small and white. It has a"); +const u8 gBerryDescriptionPart2_Wepear[] = _("delicate balance of bitter and sour."); +const u8 gBerryDescriptionPart1_Pinap[] = _("Weak against wind and cold."); +const u8 gBerryDescriptionPart2_Pinap[] = _("The fruit is spicy and the skin, sour."); +const u8 gBerryDescriptionPart1_Pomeg[] = _("However much it is watered,"); +const u8 gBerryDescriptionPart2_Pomeg[] = _("it only grows up to six BERRIES."); +const u8 gBerryDescriptionPart1_Kelpsy[] = _("A rare variety shaped like a root."); +const u8 gBerryDescriptionPart2_Kelpsy[] = _("Grows a very large flower."); +const u8 gBerryDescriptionPart1_Qualot[] = _("Loves water. Grows strong even in"); +const u8 gBerryDescriptionPart2_Qualot[] = _("locations with constant rainfall."); +const u8 gBerryDescriptionPart1_Hondew[] = _("A BERRY that is very valuable and"); +const u8 gBerryDescriptionPart2_Hondew[] = _("rarely seen. It is very delicious."); +const u8 gBerryDescriptionPart1_Grepa[] = _("Despite its tenderness and round"); +const u8 gBerryDescriptionPart2_Grepa[] = _("shape, the BERRY is unimaginably sour."); +const u8 gBerryDescriptionPart1_Tamato[] = _("The BERRY is lip-bendingly spicy."); +const u8 gBerryDescriptionPart2_Tamato[] = _("It takes time to grow."); +const u8 gBerryDescriptionPart1_Cornn[] = _("A BERRY from an ancient era. May not"); +const u8 gBerryDescriptionPart2_Cornn[] = _("grow unless planted in quantity."); +const u8 gBerryDescriptionPart1_Magost[] = _("A BERRY that is widely said to have"); +const u8 gBerryDescriptionPart2_Magost[] = _("a finely balanced flavor."); +const u8 gBerryDescriptionPart1_Rabuta[] = _("A rare variety that is overgrown with"); +const u8 gBerryDescriptionPart2_Rabuta[] = _("hair. It is quite bitter."); +const u8 gBerryDescriptionPart1_Nomel[] = _("Quite sour. Just one bite makes it"); +const u8 gBerryDescriptionPart2_Nomel[] = _("impossible to taste for three days."); +const u8 gBerryDescriptionPart1_Spelon[] = _("The vividly red BERRY is very spicy."); +const u8 gBerryDescriptionPart2_Spelon[] = _("Its warts secrete a spicy substance."); +const u8 gBerryDescriptionPart1_Pamtre[] = _("Drifts on the sea from somewhere."); +const u8 gBerryDescriptionPart2_Pamtre[] = _("It is thought to grow elsewhere."); +const u8 gBerryDescriptionPart1_Watmel[] = _("A huge BERRY, with some over 20"); +const u8 gBerryDescriptionPart2_Watmel[] = _("inches discovered. Exceedingly sweet."); +const u8 gBerryDescriptionPart1_Durin[] = _("Bitter to even look at. It is so"); +const u8 gBerryDescriptionPart2_Durin[] = _("bitter, no one has ever eaten it as is."); +const u8 gBerryDescriptionPart1_Belue[] = _("It is glossy and looks delicious, but"); +const u8 gBerryDescriptionPart2_Belue[] = _("it is awfully sour. Takes time to grow."); +const u8 gBerryDescriptionPart1_Liechi[] = _("A mysterious BERRY. It is rumored to"); +const u8 gBerryDescriptionPart2_Liechi[] = _("contain the power of the sea."); +const u8 gBerryDescriptionPart1_Ganlon[] = _("A mysterious BERRY. It is rumored to"); +const u8 gBerryDescriptionPart2_Ganlon[] = _("contain the power of the land."); +const u8 gBerryDescriptionPart1_Salac[] = _("A mysterious BERRY. It is rumored to"); +const u8 gBerryDescriptionPart2_Salac[] = _("contain the power of the sky."); +const u8 gBerryDescriptionPart1_Petaya[] = _("A mysterious BERRY. It is rumored to"); +const u8 gBerryDescriptionPart2_Petaya[] = _("contain the power of all living things."); +const u8 gBerryDescriptionPart1_Apicot[] = _("A very mystifying BERRY. No telling"); +const u8 gBerryDescriptionPart2_Apicot[] = _("what may happen or how it can be used."); +const u8 gBerryDescriptionPart1_Lansat[] = _("Said to be a legendary BERRY."); +const u8 gBerryDescriptionPart2_Lansat[] = _("Holding it supposedly brings joy."); +const u8 gBerryDescriptionPart1_Starf[] = _("So strong, it was abandoned at the"); +const u8 gBerryDescriptionPart2_Starf[] = _("world’s edge. Considered a mirage."); +const u8 gBerryDescriptionPart1_Enigma[] = _("A completely enigmatic BERRY."); +const u8 gBerryDescriptionPart2_Enigma[] = _("Appears to have the power of stars."); +#elif defined(GERMAN) +#define NAME_CHERI_BERRY _("AMRENA") +#define NAME_CHESTO_BERRY _("MARON") +#define NAME_PECHA_BERRY _("PIRSIF") +#define NAME_RAWST_BERRY _("FRAGIA") +#define NAME_ASPEAR_BERRY _("WILBIR") +#define NAME_LEPPA_BERRY _("JONAGO") +#define NAME_ORAN_BERRY _("SINEL") +#define NAME_PERSIM_BERRY _("PERSIM") +#define NAME_LUM_BERRY _("PRUNUS") +#define NAME_SITRUS_BERRY _("TSITRU") +#define NAME_FIGY_BERRY _("GIEFE") +#define NAME_WIKI_BERRY _("WIKI") +#define NAME_MAGO_BERRY _("MAGO") +#define NAME_AGUAV_BERRY _("GAUVE") +#define NAME_IAPAPA_BERRY _("YAPA") +#define NAME_RAZZ_BERRY _("HIMMIH") +#define NAME_BLUK_BERRY _("MORB") +#define NAME_NANAB_BERRY _("NANAB") +#define NAME_WEPEAR_BERRY _("NIRBE") +#define NAME_PINAP_BERRY _("SANANA") +#define NAME_POMEG_BERRY _("GRANA") +#define NAME_KELPSY_BERRY _("SETANG") +#define NAME_QUALOT_BERRY _("QUALOT") +#define NAME_HONDEW_BERRY _("HONMEL") +#define NAME_GREPA_BERRY _("LABRUS") +#define NAME_TAMATO_BERRY _("TAMOT") +#define NAME_CORNN_BERRY _("SAIM") +#define NAME_MAGOST_BERRY _("MAGOST") +#define NAME_RABUTA_BERRY _("RABUTA") +#define NAME_NOMEL_BERRY _("TRONZI") +#define NAME_SPELON_BERRY _("KIWAN") +#define NAME_PAMTRE_BERRY _("PALLM") +#define NAME_WATMEL_BERRY _("WASMEL") +#define NAME_DURIN_BERRY _("DURIN") +#define NAME_BELUE_BERRY _("MYRTIL") +#define NAME_LIECHI_BERRY _("LYDZI") +#define NAME_GANLON_BERRY _("LINGAN") +#define NAME_SALAC_BERRY _("SALKA") +#define NAME_PETAYA_BERRY _("TAHAY") +#define NAME_APICOT_BERRY _("APIKO") +#define NAME_LANSAT_BERRY _("LANSAT") +#define NAME_STARF_BERRY _("KRAMBO") +#define NAME_ENIGMA_BERRY _("ENIGMA") + +const u8 gBerryDescriptionPart1_Cheri[] = _("Erblüht mit hübschen, zarten Blumen."); +const u8 gBerryDescriptionPart2_Cheri[] = _("Diese knallrote BEERE ist sehr scharf."); +const u8 gBerryDescriptionPart1_Chesto[] = _("Diese BEERE hat eine dicke Haut und"); +const u8 gBerryDescriptionPart2_Chesto[] = _("hartes Fruchtfleisch. Trocken!"); +const u8 gBerryDescriptionPart1_Pecha[] = _("Sehr süß und delikat."); +const u8 gBerryDescriptionPart2_Pecha[] = _("Sehr zart. Vorsichtig anfassen!"); +const u8 gBerryDescriptionPart1_Rawst[] = _("Wenn die Blätter lang und wellig sind,"); +const u8 gBerryDescriptionPart2_Rawst[] = _("wird die BEERE sehr bitter."); +const u8 gBerryDescriptionPart1_Aspear[] = _("Diese harte BEERE ist sehr"); +const u8 gBerryDescriptionPart2_Aspear[] = _("saftig und sauer im Geschmack!"); +const u8 gBerryDescriptionPart1_Leppa[] = _("Wächst langsamer als AMRENA und"); +const u8 gBerryDescriptionPart2_Leppa[] = _("andere. Je kleiner, desto delikater."); +const u8 gBerryDescriptionPart1_Oran[] = _("Eine BEERE unterschiedlichsten Ge-"); +const u8 gBerryDescriptionPart2_Oran[] = _("schmacks. Wächst an einem halben Tag."); +const u8 gBerryDescriptionPart1_Persim[] = _("Liebt Sonnenlicht. Die BEERE"); +const u8 gBerryDescriptionPart2_Persim[] = _("wächst im Sonnenlicht sehr schnell."); +const u8 gBerryDescriptionPart1_Lum[] = _("Langsamer Wuchs. Wird sie liebevoll ge-"); +const u8 gBerryDescriptionPart2_Lum[] = _("pflegt, kann sie 2 BEEREN tragen."); +const u8 gBerryDescriptionPart1_Sitrus[] = _("Eng verwandt mit SINEL. Diese große"); +const u8 gBerryDescriptionPart2_Sitrus[] = _("BEERE ist von rundem Geschmack."); +const u8 gBerryDescriptionPart1_Figy[] = _("Die BEERE sieht angekaut aus. Sie ist"); +const u8 gBerryDescriptionPart2_Figy[] = _("voller scharfer Substanzen."); +const u8 gBerryDescriptionPart1_Wiki[] = _("Die BEERE wächst unförmig,"); +const u8 gBerryDescriptionPart2_Wiki[] = _("damit PKMN sie besser greifen können."); +const u8 gBerryDescriptionPart1_Mago[] = _("Die BEERE hat Ausbeulungen. Je mehr"); +const u8 gBerryDescriptionPart2_Mago[] = _("Beulen, desto schmackhafter ist sie."); +const u8 gBerryDescriptionPart1_Aguav[] = _("Die Blume ist zart. Sie ist fähig,"); +const u8 gBerryDescriptionPart2_Aguav[] = _("ohne Licht wachsen zu können."); +const u8 gBerryDescriptionPart1_Iapapa[] = _("Die BEERE ist groß und sauer."); +const u8 gBerryDescriptionPart2_Iapapa[] = _("Sie braucht einen Tag zum Wachsen."); +const u8 gBerryDescriptionPart1_Razz[] = _("Diese rote BEERE schmeckt etwas"); +const u8 gBerryDescriptionPart2_Razz[] = _("scharf. Sie wächst in nur 4 Stunden."); +const u8 gBerryDescriptionPart1_Bluk[] = _("Die BEERE ist außen blau, verfärbt"); +const u8 gBerryDescriptionPart2_Bluk[] = _("sich im Mund aber schwarz."); +const u8 gBerryDescriptionPart1_Nanab[] = _("Diese BEERE war die 7., die auf der"); +const u8 gBerryDescriptionPart2_Nanab[] = _("Welt entdeckt wurde. Sie ist süß."); +const u8 gBerryDescriptionPart1_Wepear[] = _("Die Blume ist klein und weiß. Angenehm"); +const u8 gBerryDescriptionPart2_Wepear[] = _("bitter und sauer zugleich."); +const u8 gBerryDescriptionPart1_Pinap[] = _("Wind und Kälte verträgt sie nicht."); +const u8 gBerryDescriptionPart2_Pinap[] = _("Fruchtfleisch: Scharf. Haut: Sauer."); +const u8 gBerryDescriptionPart1_Pomeg[] = _("Egal wie viel Wasser sie bekommt, sie"); +const u8 gBerryDescriptionPart2_Pomeg[] = _("trägt immer bis zu 6 BEEREN."); +const u8 gBerryDescriptionPart1_Kelpsy[] = _("Eine Seltenheit. Geformt wie eine"); +const u8 gBerryDescriptionPart2_Kelpsy[] = _("Wurzel. Hat eine große Blume."); +const u8 gBerryDescriptionPart1_Qualot[] = _("Liebt das Wasser. Wächst besonders"); +const u8 gBerryDescriptionPart2_Qualot[] = _("gut in regenreichen Gegenden."); +const u8 gBerryDescriptionPart1_Hondew[] = _("Eine wertvolle und seltene BEERE."); +const u8 gBerryDescriptionPart2_Hondew[] = _("Sie ist sehr schmackhaft."); +const u8 gBerryDescriptionPart1_Grepa[] = _("Die BEERE ist zart und von runder"); +const u8 gBerryDescriptionPart2_Grepa[] = _("Form. Aber sie ist unglaublich sauer!"); +const u8 gBerryDescriptionPart1_Tamato[] = _("Die Schärfe der BEERE verbrennt die"); +const u8 gBerryDescriptionPart2_Tamato[] = _("Lippen. Sie braucht Zeit zum Wachsen."); +const u8 gBerryDescriptionPart1_Cornn[] = _("Eine BEERE aus alten Zeiten. Wächst"); +const u8 gBerryDescriptionPart2_Cornn[] = _("nur, wenn in großen Mengen gepflanzt."); +const u8 gBerryDescriptionPart1_Magost[] = _("Eine BEERE, die für ihren feinen, aus-"); +const u8 gBerryDescriptionPart2_Magost[] = _("gewogenen Geschmack bekannt ist."); +const u8 gBerryDescriptionPart1_Rabuta[] = _("Eine Seltenheit, die über und über mit"); +const u8 gBerryDescriptionPart2_Rabuta[] = _("Haaren bewachsen ist. Sehr bitter!"); +const u8 gBerryDescriptionPart1_Nomel[] = _("Sehr sauer. Ein Biss betäubt die"); +const u8 gBerryDescriptionPart2_Nomel[] = _("Geschmacksnerven für 3 Tage!"); +const u8 gBerryDescriptionPart1_Spelon[] = _("Die leuchtend rote BEERE ist sehr"); +const u8 gBerryDescriptionPart2_Spelon[] = _("scharf. Gibt scharfe Substanzen ab!"); +const u8 gBerryDescriptionPart1_Pamtre[] = _("Wird vom Meer angespült. Sie wächst"); +const u8 gBerryDescriptionPart2_Pamtre[] = _("an einem anderen Ort."); +const u8 gBerryDescriptionPart1_Watmel[] = _("Eine große BEERE, 25 cm groß."); +const u8 gBerryDescriptionPart2_Watmel[] = _("Außergewöhnlich süß."); +const u8 gBerryDescriptionPart1_Durin[] = _("Bitter schon ihr Anblick! Sie ist so"); +const u8 gBerryDescriptionPart2_Durin[] = _("bitter, dass niemand sie pur isst."); +const u8 gBerryDescriptionPart1_Belue[] = _("Sie glänzt, sieht zart aus, ist extrem"); +const u8 gBerryDescriptionPart2_Belue[] = _("sauer und braucht Zeit zum Wachsen."); +const u8 gBerryDescriptionPart1_Liechi[] = _("Eine geheimnisvolle BEERE. Man sagt,"); +const u8 gBerryDescriptionPart2_Liechi[] = _("sie enthalte die Kraft des Meeres."); +const u8 gBerryDescriptionPart1_Ganlon[] = _("Eine geheimnisvolle BEERE. Man sagt,"); +const u8 gBerryDescriptionPart2_Ganlon[] = _("sie enthalte die Kraft des Landes."); +const u8 gBerryDescriptionPart1_Salac[] = _("Eine geheimnisvolle BEERE. Man sagt,"); +const u8 gBerryDescriptionPart2_Salac[] = _("sie enthalte die Kraft des Himmels."); +const u8 gBerryDescriptionPart1_Petaya[] = _("Eine geheimnisvolle BEERE. Man sagt,"); +const u8 gBerryDescriptionPart2_Petaya[] = _("sie enthalte die Kraft allen Lebens."); +const u8 gBerryDescriptionPart1_Apicot[] = _("Eine rätselhafte BEERE. Man kann"); +const u8 gBerryDescriptionPart2_Apicot[] = _("nicht sagen, wie und was sie ist."); +const u8 gBerryDescriptionPart1_Lansat[] = _("Eine legendäre BEERE. Sie zu"); +const u8 gBerryDescriptionPart2_Lansat[] = _("tragen bringt Freude."); +const u8 gBerryDescriptionPart1_Starf[] = _("So stark, dass sie an den Rand der"); +const u8 gBerryDescriptionPart2_Starf[] = _("Welt verbannt wurde. Ein Märchen?"); +const u8 gBerryDescriptionPart1_Enigma[] = _("Eine enigmatische BEERE. Sie scheint"); +const u8 gBerryDescriptionPart2_Enigma[] = _("die Macht der Sterne zu besitzen."); +#endif + +const struct Berry gBerries[] = +{ + { + .name = NAME_CHERI_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 20, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Cheri, + .description2 = gBerryDescriptionPart2_Cheri, + .stageDuration = 3, + .spicy = 10, + .dry = 0, + .sweet = 0, + .bitter = 0, + .sour = 0, + .smoothness = 25, + }, + { + .name = NAME_CHESTO_BERRY, + .firmness = BERRY_FIRMNESS_SUPER_HARD, + .size = 80, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Chesto, + .description2 = gBerryDescriptionPart2_Chesto, + .stageDuration = 3, + .spicy = 0, + .dry = 10, + .sweet = 0, + .bitter = 0, + .sour = 0, + .smoothness = 25, + }, + { + .name = NAME_PECHA_BERRY, + .firmness = BERRY_FIRMNESS_VERY_SOFT, + .size = 40, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Pecha, + .description2 = gBerryDescriptionPart2_Pecha, + .stageDuration = 3, + .spicy = 0, + .dry = 0, + .sweet = 10, + .bitter = 0, + .sour = 0, + .smoothness = 25, + }, + { + .name = NAME_RAWST_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 32, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Rawst, + .description2 = gBerryDescriptionPart2_Rawst, + .stageDuration = 3, + .spicy = 0, + .dry = 0, + .sweet = 0, + .bitter = 10, + .sour = 0, + .smoothness = 25, + }, + { + .name = NAME_ASPEAR_BERRY, + .firmness = BERRY_FIRMNESS_SUPER_HARD, + .size = 50, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Aspear, + .description2 = gBerryDescriptionPart2_Aspear, + .stageDuration = 3, + .spicy = 0, + .dry = 0, + .sweet = 0, + .bitter = 0, + .sour = 10, + .smoothness = 25, + }, + { + .name = NAME_LEPPA_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 28, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Leppa, + .description2 = gBerryDescriptionPart2_Leppa, + .stageDuration = 4, + .spicy = 10, + .dry = 0, + .sweet = 10, + .bitter = 10, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_ORAN_BERRY, + .firmness = BERRY_FIRMNESS_SUPER_HARD, + .size = 35, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Oran, + .description2 = gBerryDescriptionPart2_Oran, + .stageDuration = 3, + .spicy = 10, + .dry = 10, + .sweet = 10, + .bitter = 10, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_PERSIM_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 47, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Persim, + .description2 = gBerryDescriptionPart2_Persim, + .stageDuration = 3, + .spicy = 10, + .dry = 10, + .sweet = 10, + .bitter = 10, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_LUM_BERRY, + .firmness = BERRY_FIRMNESS_SUPER_HARD, + .size = 34, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Lum, + .description2 = gBerryDescriptionPart2_Lum, + .stageDuration = 12, + .spicy = 10, + .dry = 10, + .sweet = 10, + .bitter = 10, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_SITRUS_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 95, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Sitrus, + .description2 = gBerryDescriptionPart2_Sitrus, + .stageDuration = 6, + .spicy = 10, + .dry = 10, + .sweet = 10, + .bitter = 10, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_FIGY_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 100, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Figy, + .description2 = gBerryDescriptionPart2_Figy, + .stageDuration = 6, + .spicy = 10, + .dry = 0, + .sweet = 0, + .bitter = 0, + .sour = 0, + .smoothness = 25, + }, + { + .name = NAME_WIKI_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 115, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Wiki, + .description2 = gBerryDescriptionPart2_Wiki, + .stageDuration = 6, + .spicy = 0, + .dry = 10, + .sweet = 0, + .bitter = 0, + .sour = 0, + .smoothness = 25, + }, + { + .name = NAME_MAGO_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 126, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Mago, + .description2 = gBerryDescriptionPart2_Mago, + .stageDuration = 6, + .spicy = 0, + .dry = 0, + .sweet = 10, + .bitter = 0, + .sour = 0, + .smoothness = 25, + }, + { + .name = NAME_AGUAV_BERRY, + .firmness = BERRY_FIRMNESS_SUPER_HARD, + .size = 64, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Aguav, + .description2 = gBerryDescriptionPart2_Aguav, + .stageDuration = 6, + .spicy = 0, + .dry = 0, + .sweet = 0, + .bitter = 10, + .sour = 0, + .smoothness = 25, + }, + { + .name = NAME_IAPAPA_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 223, + .maxYield = 3, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Iapapa, + .description2 = gBerryDescriptionPart2_Iapapa, + .stageDuration = 6, + .spicy = 0, + .dry = 0, + .sweet = 0, + .bitter = 0, + .sour = 10, + .smoothness = 25, + }, + { + .name = NAME_RAZZ_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 120, + .maxYield = 6, + .minYield = 3, + .description1 = gBerryDescriptionPart1_Razz, + .description2 = gBerryDescriptionPart2_Razz, + .stageDuration = 1, + .spicy = 10, + .dry = 10, + .sweet = 0, + .bitter = 0, + .sour = 0, + .smoothness = 20, + }, + { + .name = NAME_BLUK_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 108, + .maxYield = 6, + .minYield = 3, + .description1 = gBerryDescriptionPart1_Bluk, + .description2 = gBerryDescriptionPart2_Bluk, + .stageDuration = 1, + .spicy = 0, + .dry = 10, + .sweet = 10, + .bitter = 0, + .sour = 0, + .smoothness = 20, + }, + { + .name = NAME_NANAB_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 77, + .maxYield = 6, + .minYield = 3, + .description1 = gBerryDescriptionPart1_Nanab, + .description2 = gBerryDescriptionPart2_Nanab, + .stageDuration = 1, + .spicy = 0, + .dry = 0, + .sweet = 10, + .bitter = 10, + .sour = 0, + .smoothness = 20, + }, + { + .name = NAME_WEPEAR_BERRY, + .firmness = BERRY_FIRMNESS_SUPER_HARD, + .size = 74, + .maxYield = 6, + .minYield = 3, + .description1 = gBerryDescriptionPart1_Wepear, + .description2 = gBerryDescriptionPart2_Wepear, + .stageDuration = 1, + .spicy = 0, + .dry = 0, + .sweet = 0, + .bitter = 10, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_PINAP_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 80, + .maxYield = 6, + .minYield = 3, + .description1 = gBerryDescriptionPart1_Pinap, + .description2 = gBerryDescriptionPart2_Pinap, + .stageDuration = 1, + .spicy = 10, + .dry = 0, + .sweet = 0, + .bitter = 0, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_POMEG_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 135, + .maxYield = 6, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Pomeg, + .description2 = gBerryDescriptionPart2_Pomeg, + .stageDuration = 3, + .spicy = 10, + .dry = 0, + .sweet = 10, + .bitter = 10, + .sour = 0, + .smoothness = 20, + }, + { + .name = NAME_KELPSY_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 150, + .maxYield = 6, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Kelpsy, + .description2 = gBerryDescriptionPart2_Kelpsy, + .stageDuration = 3, + .spicy = 0, + .dry = 10, + .sweet = 0, + .bitter = 10, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_QUALOT_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 110, + .maxYield = 6, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Qualot, + .description2 = gBerryDescriptionPart2_Qualot, + .stageDuration = 3, + .spicy = 10, + .dry = 0, + .sweet = 10, + .bitter = 0, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_HONDEW_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 162, + .maxYield = 6, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Hondew, + .description2 = gBerryDescriptionPart2_Hondew, + .stageDuration = 3, + .spicy = 10, + .dry = 10, + .sweet = 0, + .bitter = 10, + .sour = 0, + .smoothness = 20, + }, + { + .name = NAME_GREPA_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 149, + .maxYield = 6, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Grepa, + .description2 = gBerryDescriptionPart2_Grepa, + .stageDuration = 3, + .spicy = 0, + .dry = 10, + .sweet = 10, + .bitter = 0, + .sour = 10, + .smoothness = 20, + }, + { + .name = NAME_TAMATO_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 200, + .maxYield = 4, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Tamato, + .description2 = gBerryDescriptionPart2_Tamato, + .stageDuration = 6, + .spicy = 20, + .dry = 10, + .sweet = 0, + .bitter = 0, + .sour = 0, + .smoothness = 30, + }, + { + .name = NAME_CORNN_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 75, + .maxYield = 4, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Cornn, + .description2 = gBerryDescriptionPart2_Cornn, + .stageDuration = 6, + .spicy = 0, + .dry = 20, + .sweet = 10, + .bitter = 0, + .sour = 0, + .smoothness = 30, + }, + { + .name = NAME_MAGOST_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 140, + .maxYield = 4, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Magost, + .description2 = gBerryDescriptionPart2_Magost, + .stageDuration = 6, + .spicy = 0, + .dry = 0, + .sweet = 20, + .bitter = 10, + .sour = 0, + .smoothness = 30, + }, + { + .name = NAME_RABUTA_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 226, + .maxYield = 4, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Rabuta, + .description2 = gBerryDescriptionPart2_Rabuta, + .stageDuration = 6, + .spicy = 0, + .dry = 0, + .sweet = 0, + .bitter = 20, + .sour = 10, + .smoothness = 30, + }, + { + .name = NAME_NOMEL_BERRY, + .firmness = BERRY_FIRMNESS_SUPER_HARD, + .size = 285, + .maxYield = 4, + .minYield = 2, + .description1 = gBerryDescriptionPart1_Nomel, + .description2 = gBerryDescriptionPart2_Nomel, + .stageDuration = 6, + .spicy = 10, + .dry = 0, + .sweet = 0, + .bitter = 0, + .sour = 20, + .smoothness = 30, + }, + { + .name = NAME_SPELON_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 133, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Spelon, + .description2 = gBerryDescriptionPart2_Spelon, + .stageDuration = 18, + .spicy = 40, + .dry = 10, + .sweet = 0, + .bitter = 0, + .sour = 0, + .smoothness = 70, + }, + { + .name = NAME_PAMTRE_BERRY, + .firmness = BERRY_FIRMNESS_VERY_SOFT, + .size = 244, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Pamtre, + .description2 = gBerryDescriptionPart2_Pamtre, + .stageDuration = 18, + .spicy = 0, + .dry = 40, + .sweet = 10, + .bitter = 0, + .sour = 0, + .smoothness = 70, + }, + { + .name = NAME_WATMEL_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 250, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Watmel, + .description2 = gBerryDescriptionPart2_Watmel, + .stageDuration = 18, + .spicy = 0, + .dry = 0, + .sweet = 40, + .bitter = 10, + .sour = 0, + .smoothness = 70, + }, + { + .name = NAME_DURIN_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 280, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Durin, + .description2 = gBerryDescriptionPart2_Durin, + .stageDuration = 18, + .spicy = 0, + .dry = 0, + .sweet = 0, + .bitter = 40, + .sour = 10, + .smoothness = 70, + }, + { + .name = NAME_BELUE_BERRY, + .firmness = BERRY_FIRMNESS_VERY_SOFT, + .size = 300, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Belue, + .description2 = gBerryDescriptionPart2_Belue, + .stageDuration = 18, + .spicy = 10, + .dry = 0, + .sweet = 0, + .bitter = 0, + .sour = 40, + .smoothness = 70, + }, + { + .name = NAME_LIECHI_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 111, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Liechi, + .description2 = gBerryDescriptionPart2_Liechi, + .stageDuration = 24, + .spicy = 40, + .dry = 0, + .sweet = 40, + .bitter = 0, + .sour = 10, + .smoothness = 80, + }, + { + .name = NAME_GANLON_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 33, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Ganlon, + .description2 = gBerryDescriptionPart2_Ganlon, + .stageDuration = 24, + .spicy = 0, + .dry = 40, + .sweet = 0, + .bitter = 40, + .sour = 0, + .smoothness = 80, + }, + { + .name = NAME_SALAC_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 95, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Salac, + .description2 = gBerryDescriptionPart2_Salac, + .stageDuration = 24, + .spicy = 0, + .dry = 0, + .sweet = 40, + .bitter = 0, + .sour = 40, + .smoothness = 80, + }, + { + .name = NAME_PETAYA_BERRY, + .firmness = BERRY_FIRMNESS_VERY_HARD, + .size = 237, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Petaya, + .description2 = gBerryDescriptionPart2_Petaya, + .stageDuration = 24, + .spicy = 40, + .dry = 0, + .sweet = 0, + .bitter = 40, + .sour = 0, + .smoothness = 80, + }, + { + .name = NAME_APICOT_BERRY, + .firmness = BERRY_FIRMNESS_HARD, + .size = 75, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Apicot, + .description2 = gBerryDescriptionPart2_Apicot, + .stageDuration = 24, + .spicy = 0, + .dry = 40, + .sweet = 0, + .bitter = 0, + .sour = 40, + .smoothness = 80, + }, + { + .name = NAME_LANSAT_BERRY, + .firmness = BERRY_FIRMNESS_SOFT, + .size = 97, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Lansat, + .description2 = gBerryDescriptionPart2_Lansat, + .stageDuration = 24, + .spicy = 10, + .dry = 10, + .sweet = 10, + .bitter = 10, + .sour = 10, + .smoothness = 30, + }, + { + .name = NAME_STARF_BERRY, + .firmness = BERRY_FIRMNESS_SUPER_HARD, + .size = 153, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Starf, + .description2 = gBerryDescriptionPart2_Starf, + .stageDuration = 24, + .spicy = 10, + .dry = 10, + .sweet = 10, + .bitter = 10, + .sour = 10, + .smoothness = 30, + }, + { + .name = NAME_ENIGMA_BERRY, + .firmness = BERRY_FIRMNESS_UNKNOWN, + .size = 0, + .maxYield = 2, + .minYield = 1, + .description1 = gBerryDescriptionPart1_Enigma, + .description2 = gBerryDescriptionPart2_Enigma, + .stageDuration = 24, + .spicy = 40, + .dry = 40, + .sweet = 40, + .bitter = 40, + .sour = 40, + .smoothness = 40, + }, +}; + +const struct BerryTree gBlankBerryTree = {0}; + +extern u8 S_BerryTree[]; +extern u16 gScriptLastTalked; +extern u16 gSpecialVar_0x8004; +extern u16 gSpecialVar_0x8005; +extern u16 gSpecialVar_0x8006; + +// unused +void ClearEnigmaBerries(void) +{ + CpuFill16(0, &gSaveBlock1.enigmaBerry, sizeof(gSaveBlock1.enigmaBerry)); +} + +void SetEnigmaBerry(u8 *src) +{ + u32 i; + u8 *dest = (u8*)&gSaveBlock1.enigmaBerry; + + for (i = 0; i < sizeof(gSaveBlock1.enigmaBerry); i++) + dest[i] = src[i]; + + gSaveBlock1.enigmaBerry.berry.description1 = gSaveBlock1.enigmaBerry.description1; + gSaveBlock1.enigmaBerry.berry.description2 = gSaveBlock1.enigmaBerry.description2; +} + +u32 GetEnigmaBerryChecksum(struct EnigmaBerry *enigmaBerry) +{ + const u8 *description1; + const u8 *description2; + u32 i; + u32 checksum; + u8 *dest; + + description1 = gSaveBlock1.enigmaBerry.berry.description1; + description2 = gSaveBlock1.enigmaBerry.berry.description2; + gSaveBlock1.enigmaBerry.berry.description1 = 0; + gSaveBlock1.enigmaBerry.berry.description2 = 0; + + dest = (u8*)enigmaBerry; + checksum = 0; + for (i = 0; i < ((u32)&gSaveBlock1.enigmaBerry.checksum - (u32)&gSaveBlock1.enigmaBerry); i++) + { + checksum += dest[i]; + } + + gSaveBlock1.enigmaBerry.berry.description1 = description1; + gSaveBlock1.enigmaBerry.berry.description2 = description2; + + return checksum; +} + +bool32 IsEnigmaBerryValid(void) +{ + if (!gSaveBlock1.enigmaBerry.berry.stageDuration) + return FALSE; + if (!gSaveBlock1.enigmaBerry.berry.maxYield) + return FALSE; + if (GetEnigmaBerryChecksum(&gSaveBlock1.enigmaBerry) != gSaveBlock1.enigmaBerry.checksum) + return FALSE; + return TRUE; +} + +const struct Berry *GetBerryInfo(u8 berry) +{ + if (berry == 0x2B && IsEnigmaBerryValid()) + return &gSaveBlock1.enigmaBerry.berry; + else + { + if (berry == 0 || berry > 0x2B) + berry = 1; + return &gBerries[berry - 1]; + } +} + +struct BerryTree *GetBerryTreeInfo(u8 id) +{ + return &gSaveBlock1.berryTrees[id]; +} + +bool32 FieldObjectInteractionWaterBerryTree(void) +{ + struct BerryTree *tree = GetBerryTreeInfo(FieldObjectGetBerryTreeId(gSelectedMapObject)); + + switch (tree->stage) + { + case 1: + tree->watered1 = TRUE; + break; + case 2: + tree->watered2 = TRUE; + break; + case 3: + tree->watered3 = TRUE; + break; + case 4: + tree->watered4 = TRUE; + break; + default: + return FALSE; + } + return TRUE; +} + +bool8 IsPlayerFacingPlantedBerryTree(void) +{ + if (GetFieldObjectScriptPointerForComparison() == S_BerryTree + && GetStageByBerryTreeId(FieldObjectGetBerryTreeId(gSelectedMapObject)) == 0) + return TRUE; + else + return FALSE; +} + +bool8 TryToWaterBerryTree(void) +{ + if (GetFieldObjectScriptPointerForComparison() != S_BerryTree) + return FALSE; + else + return FieldObjectInteractionWaterBerryTree(); +} + +void ClearBerryTrees(void) +{ + int i; + struct SaveBlock1 *saveBlock1 = &gSaveBlock1; + struct BerryTree berryTree = gBlankBerryTree; + + for (i = 0; i < (u8)ARRAY_COUNT(saveBlock1->berryTrees); i++) // casting to u8 fixes a mismatched signed compare. what + saveBlock1->berryTrees[i] = berryTree; +} + +bool32 BerryTreeGrow(struct BerryTree *tree) +{ + if (tree->growthSparkle) + return FALSE; + switch (tree->stage) + { + case 0: + return FALSE; + case 4: + tree->berryYield = CalcBerryYield(tree); + case 1: + case 2: + case 3: + tree->stage++; + break; + case 5: + tree->watered1 = 0; + tree->watered2 = 0; + tree->watered3 = 0; + tree->watered4 = 0; + tree->berryYield = 0; + tree->stage = 2; + if (++tree->regrowthCount == 10) + *tree = gBlankBerryTree; + break; + } + return TRUE; +} + +void BerryTreeTimeUpdate(s32 minutes) +{ + int i; + struct BerryTree *tree; + + for (i = 0; i < (u8)ARRAY_COUNT(gSaveBlock1.berryTrees); i++) + { + tree = &gSaveBlock1.berryTrees[i]; + + if (tree->berry && tree->stage && !tree->growthSparkle) + { + if (minutes >= GetStageDurationByBerryType(tree->berry) * 71) + { + *tree = gBlankBerryTree; + } + else + { + s32 time = minutes; + + while (time != 0) + { + if (tree->minutesUntilNextStage > time) + { + tree->minutesUntilNextStage -= time; + break; + } + time -= tree->minutesUntilNextStage; + tree->minutesUntilNextStage = GetStageDurationByBerryType(tree->berry); + if (!BerryTreeGrow(tree)) + break; + if (tree->stage == 5) + tree->minutesUntilNextStage *= 4; + } + } + } + } +} + +void PlantBerryTree(u8 id, u8 berry, u8 stage, bool8 sparkle) +{ + struct BerryTree *tree = GetBerryTreeInfo(id); + + *tree = gBlankBerryTree; + tree->berry = berry; + tree->minutesUntilNextStage = GetStageDurationByBerryType(berry); + tree->stage = stage; + if (stage == 5) + { + tree->berryYield = CalcBerryYield(tree); + tree->minutesUntilNextStage *= 4; + } + if (!sparkle) + { + tree->growthSparkle = TRUE; + } +} + +void RemoveBerryTree(u8 id) +{ + gSaveBlock1.berryTrees[id] = gBlankBerryTree; +} + +u8 GetBerryTypeByBerryTreeId(u8 id) +{ + return gSaveBlock1.berryTrees[id].berry; +} + +u8 GetStageByBerryTreeId(u8 id) +{ + return gSaveBlock1.berryTrees[id].stage; +} + +u8 ItemIdToBerryType(u16 item) +{ + u16 berry = item - FIRST_BERRY; + + if (berry > LAST_BERRY - FIRST_BERRY) + return 1; + else + return item - FIRST_BERRY + 1; +} + +u16 BerryTypeToItemId(u16 berry) +{ + u16 item = berry - 1; + + if (item > LAST_BERRY - FIRST_BERRY) + return FIRST_BERRY; + else + return berry + FIRST_BERRY - 1; +} + +void GetBerryNameByBerryType(u8 berry, u8 *string) +{ + memcpy(string, GetBerryInfo(berry)->name, BERRY_NAME_LENGTH); + string[BERRY_NAME_LENGTH] = EOS; +} + +void ResetBerryTreeSparkleFlag(u8 id) +{ + GetBerryTreeInfo(id)->growthSparkle = 0; +} + +u8 BerryTreeGetNumStagesWatered(struct BerryTree *tree) +{ + u8 count = 0; + + if (tree->watered1) + count++; + if (tree->watered2) + count++; + if (tree->watered3) + count++; + if (tree->watered4) + count++; + return count; +} + +u8 GetNumStagesWateredByBerryTreeId(u8 id) +{ + return BerryTreeGetNumStagesWatered(GetBerryTreeInfo(id)); +} + +u8 CalcBerryYieldInternal(u16 max, u16 min, u8 water) +{ + u32 randMin; + u32 randMax; + u32 rand; + u32 extraYield; + + if (water == 0) + return min; + else + { + randMin = (max - min) * (water - 1); + randMax = (max - min) * (water); + rand = randMin + Random() % (randMax - randMin + 1); + + if ((rand & 3) > 1) + extraYield = rand / 4 + 1; + else + extraYield = rand / 4; + return extraYield + min; + } +} + +u8 CalcBerryYield(struct BerryTree *tree) +{ + const struct Berry *berry = GetBerryInfo(tree->berry); + u8 min = berry->minYield; + u8 max = berry->maxYield; + + return CalcBerryYieldInternal(max, min, BerryTreeGetNumStagesWatered(tree)); +} + +u8 GetBerryCountByBerryTreeId(u8 id) +{ + return gSaveBlock1.berryTrees[id].berryYield; +} + +u16 GetStageDurationByBerryType(u8 berry) +{ + return GetBerryInfo(berry)->stageDuration * 60; +} + +void FieldObjectInteractionGetBerryTreeData(void) +{ + u8 id; + u8 berry; + u8 unk; + u8 group; + u8 num; + + id = FieldObjectGetBerryTreeId(gSelectedMapObject); + berry = GetBerryTypeByBerryTreeId(id); + ResetBerryTreeSparkleFlag(id); + unk = gScriptLastTalked; + num = gSaveBlock1.location.mapNum; + group = gSaveBlock1.location.mapGroup; + if (sub_8060234(unk, num, group)) + gSpecialVar_0x8004 = 0xFF; + else + gSpecialVar_0x8004 = GetStageByBerryTreeId(id); + gSpecialVar_0x8005 = GetNumStagesWateredByBerryTreeId(id); + gSpecialVar_0x8006 = GetBerryCountByBerryTreeId(id); + GetBerryNameByBerryType(berry, gStringVar1); +} + +void sub_80B4EE4(void) +{ + SetMainCallback2(sub_80A68CC); +} + +void FieldObjectInteractionPlantBerryTree(void) +{ + u8 berry = ItemIdToBerryType(gScriptItemId); + + PlantBerryTree(FieldObjectGetBerryTreeId(gSelectedMapObject), berry, 1, TRUE); + FieldObjectInteractionGetBerryTreeData(); +} + +void FieldObjectInteractionPickBerryTree(void) +{ + u8 id = FieldObjectGetBerryTreeId(gSelectedMapObject); + u8 berry = GetBerryTypeByBerryTreeId(id); + + gSpecialVar_0x8004 = AddBagItem(BerryTypeToItemId(berry), GetBerryCountByBerryTreeId(id)); +} + +void FieldObjectInteractionRemoveBerryTree(void) +{ + RemoveBerryTree(FieldObjectGetBerryTreeId(gSelectedMapObject)); + sub_8060288(gScriptLastTalked, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); +} + +u8 PlayerHasBerries(void) +{ + return IsBagPocketNonEmpty(BAG_BERRIES); +} + +void ResetBerryTreeSparkleFlags(void) +{ + s16 cam_left; + s16 cam_top; + s16 left; + s16 top; + s16 right; + s16 bottom; + int i; + + GetCameraCoords(&cam_left, &cam_top); + left = cam_left; + top = cam_top + 3; + right = cam_left + 14; + bottom = top + 8; + for (i = 0; i < (u8)ARRAY_COUNT(gSaveBlock1.mapObjects); i++) + { + if (gMapObjects[i].active && gMapObjects[i].animPattern == 12) + { + cam_left = gMapObjects[i].coords2.x; + cam_top = gMapObjects[i].coords2.y; + if (left <= cam_left && cam_left <= right && top <= cam_top && cam_top <= bottom) + ResetBerryTreeSparkleFlag(gMapObjects[i].trainerRange_berryTreeId); + } + } +} diff --git a/src/field/berry_tag_screen.c b/src/field/berry_tag_screen.c new file mode 100644 index 000000000..1413a02ca --- /dev/null +++ b/src/field/berry_tag_screen.c @@ -0,0 +1,455 @@ +#include "global.h" +#include "berry_tag_screen.h" +#include "berry.h" +#include "decompress.h" +#include "field_map_obj.h" +#include "item_menu.h" +#include "items.h" +#include "item_use.h" +#include "main.h" +#include "menu.h" +#include "menu_helpers.h" +#include "palette.h" +#include "overworld.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "text.h" + +#define OFFSET_7B (123) +#define FIRST_BERRY ITEM_CHERI_BERRY + +struct Struct2000000 +{ + /*0x00*/ u8 filler_0[0x1FFFF]; + /*0x1FFFF*/ u8 var_1FFFF; +}; + +extern struct Struct2000000 unk_2000000; +extern u16 gUnknown_030041B4; + +static EWRAM_DATA u8 gUnknown_0203932C = 0; +static EWRAM_DATA s16 gUnknown_0203932E[5] = {0}; + +extern const struct CompressedSpriteSheet gUnknown_083C1F74; +extern const struct CompressedSpritePalette gUnknown_083C1F7C; + +extern u8 gBerryCheck_Gfx[]; +extern u8 gBerryCheck_Pal[]; +extern u8 gUnknown_08E788E4[]; +extern u8 gUnknown_08E78A84[]; + +static const u8 *const gUnknown_0841192C[] = +{ + ContestStatsText_VerySoft, + ContestStatsText_Soft, + ContestStatsText_Hard, + ContestStatsText_VeryHard, + ContestStatsText_SuperHard, +}; + +static void sub_8146014(void); +static void sub_814602C(void); +static bool8 sub_8146058(void); +static void sub_8146288(void); +static bool8 sub_81462B8(void); +static void sub_814640C(u8 taskId); +static void sub_8146440(u8 taskId); +static void sub_8146480(u8 taskid); +static void sub_81464E4(void); +static void sub_8146600(u8 berry); +static void sub_81466A0(void); +static void sub_81466E8(u8 taskId, s8 direction); +static void sub_8146798(u8 berry); +static void sub_8146810(s8 berry); +static void sub_81468BC(void); + +static void sub_8146014(void) +{ + AnimateSprites(); + BuildOamBuffer(); + RunTasks(); + UpdatePaletteFade(); +} + +static void sub_814602C(void) +{ + REG_BG0VOFS = gUnknown_030041B4; + REG_BG1VOFS = gUnknown_030041B4; + + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static bool8 sub_8146058(void) +{ + u8 berry; + u16 backup; + + switch (gMain.state) + { + case 0: + sub_80F9438(); + sub_80F9368(); + sub_8146288(); + REG_BLDCNT = 0; + gMain.state += 1; + break; + case 1: + ResetPaletteFade(); + gPaletteFade.bufferTransferDisabled = 1; + gMain.state += 1; + break; + case 2: + ResetSpriteData(); + gMain.state += 1; + break; + case 3: + SetUpWindowConfig(&gWindowConfig_81E6E18); + gMain.state += 1; + break; + case 4: + MultistepInitMenuWindowBegin(&gWindowConfig_81E6E18); + gMain.state += 1; + break; + case 5: + if (!MultistepInitMenuWindowContinue()) + break; + unk_2000000.var_1FFFF = 0; + gMain.state += 1; + break; + case 6: + if (!sub_81462B8()) + break; + unk_2000000.var_1FFFF = 0; + gMain.state += 1; + break; + case 7: + sub_81464E4(); + gMain.state += 1; + break; + case 8: + berry = gScriptItemId + OFFSET_7B; + gUnknown_0203932C = CreateBerrySprite(berry, 56, 64); + gMain.state += 1; + break; + case 9: + sub_8146600(gScriptItemId + OFFSET_7B); + gMain.state += 1; + break; + case 10: + backup = REG_IME; + REG_IME = 0; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = backup; + REG_DISPSTAT |= DISPSTAT_VBLANK_INTR; + SetVBlankCallback(sub_814602C); + REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_ON | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_1D_MAP; + gMain.state += 1; + break; + case 11: + if (sub_8055870() == TRUE) + break; + gMain.state += 1; + break; + case 12: + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + gPaletteFade.bufferTransferDisabled = 0; + SetMainCallback2(sub_8146014); + return TRUE; + } + + return FALSE; +} + +void BerryTagScreen_814625C(u8 taskId) +{ + do + { + if (sub_8146058() == TRUE) + { + CreateTask(sub_8146480, 0); + return; + } + } while (sub_80F9344() != TRUE); +} + +static void sub_8146288(void) +{ + REG_BG1CNT = BGCNT_PRIORITY(2) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(5) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_BG2CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(6) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_BG3CNT = BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(7) | BGCNT_16COLOR | BGCNT_TXT256x256; + gUnknown_030041B4 = 0; +} + +bool8 sub_81462B8(void) +{ + u16 i; + void *addr; + + switch (unk_2000000.var_1FFFF) + { + case 0: + LZDecompressVram(gBerryCheck_Gfx, (void *)VRAM); + unk_2000000.var_1FFFF += 1; + break; + case 1: + LZDecompressVram(gUnknown_08E788E4, (void *)VRAM + 0x2800); + unk_2000000.var_1FFFF += 1; + break; + case 2: + LZDecompressVram(gUnknown_08E78A84, (void *)VRAM + 0x3000); + unk_2000000.var_1FFFF += 1; + break; + case 3: + for (i = 0; i < 0x400; i++) + { + if (gSaveBlock2.playerGender == MALE) + gBGTilemapBuffers[2][i] = 0x4042; + else + gBGTilemapBuffers[2][i] = 0x5042; + } + addr = (void *)(VRAM + 0x3800); + DmaCopy16(3, gBGTilemapBuffers[2], addr, 0x800); + unk_2000000.var_1FFFF += 1; + break; + case 4: + LoadCompressedPalette(gBerryCheck_Pal, 0, 96 * 2); + unk_2000000.var_1FFFF += 1; + break; + case 5: + LoadCompressedObjectPic(&gUnknown_083C1F74); + unk_2000000.var_1FFFF += 1; + break; + case 6: + LoadCompressedObjectPalette(&gUnknown_083C1F7C); + unk_2000000.var_1FFFF = 0; + return TRUE; + } + + return FALSE; +} + +static void sub_814640C(u8 taskId) +{ + if (!gPaletteFade.active) + { + SetMainCallback2(sub_80A5B40); + sub_80A7DD4(); + gpu_pal_allocator_reset__manage_upper_four(); + DestroyTask(taskId); + } +} + +static void sub_8146440(u8 taskId) +{ + PlaySE(SE_SELECT); + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gTasks[taskId].func = sub_814640C; +} + +static void sub_8146480(u8 taskid) +{ + if (!gPaletteFade.active) + { + if ((gMain.newAndRepeatedKeys & (DPAD_RIGHT | DPAD_LEFT | DPAD_UP | DPAD_DOWN)) == DPAD_UP) + sub_81466E8(taskid, -1); + if ((gMain.newAndRepeatedKeys & (DPAD_RIGHT | DPAD_LEFT | DPAD_UP | DPAD_DOWN)) == DPAD_DOWN) + sub_81466E8(taskid, 1); + if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) + sub_8146440(taskid); + } +} + +static void sub_81464E4(void) +{ + const struct Berry *berryInfo; +#ifdef UNITS_IMPERIAL + u32 size; + s32 sizeMajor; + s32 sizeMinor; +#endif +#if GERMAN + u8 buffer[16]; +#endif + + berryInfo = GetBerryInfo(gScriptItemId + OFFSET_7B + 1); + + ConvertIntToDecimalStringN(gStringVar1, gScriptItemId - FIRST_BERRY + 1, STR_CONV_MODE_LEADING_ZEROS, 2); + MenuPrint(gStringVar1, 12, 4); + +#if ENGLISH + MenuPrint(berryInfo->name, 14, 4); +#elif GERMAN + StringCopy(buffer, berryInfo->name); + StringAppend(buffer, gOtherText_Berry2); + MenuPrint(buffer, 14, 4); +#endif + + MenuPrint(berryInfo->description1, 4, 14); + MenuPrint(berryInfo->description2, 4, 16); + +#ifdef UNITS_IMPERIAL + size = (berryInfo->size * 1000) / 254; + if (size % 10 >= 5) + size += 10; + sizeMinor = (size % 100) / 10; + sizeMajor = size / 100; +#endif + + MenuPrint(gOtherText_Size, 11, 7); + if (berryInfo->size != 0) + { +#ifdef UNITS_IMPERIAL + ConvertIntToDecimalStringN(gStringVar1, sizeMajor, STR_CONV_MODE_LEFT_ALIGN, 2); + ConvertIntToDecimalStringN(gStringVar2, sizeMinor, STR_CONV_MODE_LEFT_ALIGN, 2); +#else + ConvertIntToDecimalStringN(gStringVar1, berryInfo->size / 10, STR_CONV_MODE_LEFT_ALIGN, 2); + ConvertIntToDecimalStringN(gStringVar2, berryInfo->size % 10, STR_CONV_MODE_LEFT_ALIGN, 2); +#endif + MenuPrint(gContestStatsText_Unknown1, 16, 7); + } + else + { + MenuPrint(gOtherText_ThreeQuestions2, 16, 7); + } + + MenuPrint(gOtherText_Firm, 11, 9); + if (berryInfo->firmness != 0) + MenuPrint(gUnknown_0841192C[berryInfo->firmness - 1], 16, 9); + else + MenuPrint(gOtherText_ThreeQuestions2, 16, 9); +} + +static void sub_8146600(u8 berry) +{ + const struct Berry *berryInfo; + u16 i; + + berryInfo = GetBerryInfo(berry + 1); + for (i = 0; i < 5; i++) + gUnknown_0203932E[i] = (u16)gUnknown_0203932E[i] | 0xFFFF; + + // argument is the center of the circle + if (berryInfo->spicy) + gUnknown_0203932E[0] = sub_80A7E5C(48); + if (berryInfo->dry) + gUnknown_0203932E[1] = sub_80A7E5C(88); + if (berryInfo->sweet) + gUnknown_0203932E[2] = sub_80A7E5C(128); + if (berryInfo->bitter) + gUnknown_0203932E[3] = sub_80A7E5C(168); + if (berryInfo->sour) + gUnknown_0203932E[4] = sub_80A7E5C(208); +} + +static void sub_81466A0(void) +{ + u16 i; + + for (i = 0; i < 5; i++) + { + if (gUnknown_0203932E[i] != -1) + { + DestroySprite(&gSprites[gUnknown_0203932E[i]]); + gUnknown_0203932E[i] = -1; + } + } +} + +static void sub_81466E8(u8 taskId, s8 direction) +{ + u8 berryPocket = 3; + s16 *data = gTasks[taskId].data; + + if (gBagPocketScrollStates[berryPocket].scrollTop + gBagPocketScrollStates[berryPocket].cursorPos == 0 + && direction < 0) + return; + if (gBagPocketScrollStates[berryPocket].scrollTop + gBagPocketScrollStates[berryPocket].cursorPos + 1 == gBagPocketScrollStates[berryPocket].numSlots + && direction > 0) + return; + + PlaySE(SE_SELECT); + if (gBagPocketScrollStates[berryPocket].scrollTop + gBagPocketScrollStates[berryPocket].cursorPos + direction < 0) + data[1] = -(gBagPocketScrollStates[berryPocket].scrollTop + gBagPocketScrollStates[berryPocket].cursorPos); + else if (gBagPocketScrollStates[berryPocket].scrollTop + gBagPocketScrollStates[berryPocket].cursorPos + direction >= gBagPocketScrollStates[berryPocket].numSlots) + data[1] = gBagPocketScrollStates[berryPocket].numSlots - gBagPocketScrollStates[berryPocket].scrollTop - gBagPocketScrollStates[berryPocket].cursorPos - 1; + else + data[1] = direction; + + gTasks[taskId].func = sub_8146798; + + if (direction < 0) + data[0] = -16; + else + data[0] = 16; + +} + +static void sub_8146798(u8 taskId) +{ + s16 *taskData = gTasks[taskId].data; + + gUnknown_030041B4 = (gUnknown_030041B4 + taskData[0]) & 0xFF; + if ((taskData[0] > 0 && gUnknown_030041B4 == 144) + || (taskData[0] < 0 && gUnknown_030041B4 == 112)) + { + sub_8146810(gTasks[taskId].data[1]); + sub_81468BC(); + } + if (gUnknown_030041B4 == 0) + { + gTasks[taskId].data[0] = gUnknown_030041B4; + gTasks[taskId].data[1] = gUnknown_030041B4; + gTasks[taskId].func = sub_8146480; + } +} + +static void sub_8146810(s8 berry) +{ + u8 berryPocket = 3; + + if (berry > 0) + { + if (gBagPocketScrollStates[berryPocket].cursorPos + berry > 7) + { + gBagPocketScrollStates[berryPocket].scrollTop += gBagPocketScrollStates[berryPocket].cursorPos - 7 + berry; + gBagPocketScrollStates[berryPocket].cursorPos = 7; + } + else + { + gBagPocketScrollStates[berryPocket].cursorPos += berry; + } + } + else + { + if (gBagPocketScrollStates[berryPocket].cursorPos + berry < 0) + { + gBagPocketScrollStates[berryPocket].scrollTop += gBagPocketScrollStates[berryPocket].cursorPos + berry; + gBagPocketScrollStates[berryPocket].cursorPos = 0; + } + else + { + gBagPocketScrollStates[berryPocket].cursorPos += berry; + } + } + gScriptItemId = gCurrentBagPocketItemSlots[gBagPocketScrollStates[berryPocket].scrollTop + gBagPocketScrollStates[berryPocket].cursorPos].itemId; + DestroySprite(&gSprites[gUnknown_0203932C]); + sub_81466A0(); + sub_80A7DD4(); +} + +static void sub_81468BC(void) +{ + MenuZeroFillWindowRect(0, 4, 29, 19); + sub_81464E4(); + + // center of berry sprite + gUnknown_0203932C = CreateBerrySprite(gScriptItemId + OFFSET_7B, 56, 64); + + sub_8146600(gScriptItemId + OFFSET_7B); +} diff --git a/src/field/bike.c b/src/field/bike.c new file mode 100644 index 000000000..8df901b40 --- /dev/null +++ b/src/field/bike.c @@ -0,0 +1,1011 @@ +#include "global.h" +#include "bike.h" +#include "field_map_obj.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "flags.h" +#include "global.fieldmap.h" +#include "metatile_behavior.h" +#include "overworld.h" +#include "songs.h" +#include "sound.h" + +extern u8 gUnknown_02039250; +extern u8 gUnknown_02039251; +extern u8 gUnknown_0202E854; + +static void MovePlayerOnMachBike(u8, u16, u16); +static u8 GetMachBikeTransition(u8 *); +static void MachBikeTransition_FaceDirection(u8); +static void MachBikeTransition_80E517C(u8); +static void MachBikeTransition_80E51C4(u8); +static void MachBikeTransition_80E5270(u8); +static void MovePlayerOnAcroBike(u8, u16, u16); +static u8 CheckMovementInputAcroBike(u8 *, u16, u16); +static u8 AcroBikeHandleInputNormal(u8 *, u16, u16); +static u8 AcroBikeHandleInputTurning(u8 *, u16, u16); +static u8 AcroBikeHandleInputWheelieStanding(u8 *, u16, u16); +static u8 AcroBikeHandleInputBunnyHop(u8 *, u16, u16); +static u8 AcroBikeHandleInputWheelieMoving(u8 *, u16, u16); +static u8 AcroBikeHandleInputState5(u8 *, u16, u16); +static u8 AcroBikeHandleInputState6(u8 *, u16, u16); +static void AcroBikeTransition_FaceDirection(u8); +static void AcroBikeTransition_80E5708(u8); +static void AcroBikeTransition_80E5744(u8); +static void AcroBikeTransition_NormalToWheelie(u8); +static void AcroBikeTransition_80E57F8(u8); +static void AcroBikeTransition_80E5834(u8); +static void AcroBikeTransition_80E5870(u8); +static void AcroBikeTransition_80E58AC(u8); +static void AcroBikeTransition_80E5920(u8); +static void AcroBikeTransition_80E5990(u8); +static void AcroBikeTransition_80E59A0(u8); +static void AcroBikeTransition_80E5A30(u8); +static void AcroBikeTransition_80E5AC0(u8); +static void sub_80E5B60(u16, u16); +static u8 sub_80E5C2C(void); +static void sub_80E5C7C(u8); +static void sub_80E5CB8(u8); +static u8 sub_80E5CF4(u16); +static u8 get_some_collision(u8); +static u8 sub_80E5DA0(struct MapObject *, s16, s16, u8, u8); +static bool8 IsRunningDisallowedByMetatile(u8); +static void sub_80E5E4C(); +static u8 CanBikeFaceDirOnMetatile(u8, u8); +static bool8 sub_80E5EC0(u8, u8); +static void sub_80E6024(void); + +static void (*const sMachBikeTransitions[])(u8) = +{ + MachBikeTransition_FaceDirection, + MachBikeTransition_80E517C, + MachBikeTransition_80E51C4, + MachBikeTransition_80E5270, +}; + +static void (*const gUnknown_083DB5A4[])(u8) = +{ + PlayerGoSpeed0, + sub_80593C4, + sub_80593F4, +}; + +static void (*const sAcroBikeTransitions[])(u8) = +{ + AcroBikeTransition_FaceDirection, + AcroBikeTransition_80E5708, + AcroBikeTransition_80E5744, + AcroBikeTransition_NormalToWheelie, + AcroBikeTransition_80E57F8, + AcroBikeTransition_80E5834, + AcroBikeTransition_80E5870, + AcroBikeTransition_80E58AC, + AcroBikeTransition_80E5920, + AcroBikeTransition_80E5990, + AcroBikeTransition_80E59A0, + AcroBikeTransition_80E5A30, + AcroBikeTransition_80E5AC0, +}; + +static u8 (*const sAcroBikeInputHandlers[])(u8 *, u16, u16) = +{ + AcroBikeHandleInputNormal, + AcroBikeHandleInputTurning, + AcroBikeHandleInputWheelieStanding, + AcroBikeHandleInputBunnyHop, + AcroBikeHandleInputWheelieMoving, + AcroBikeHandleInputState5, + AcroBikeHandleInputState6, +}; + +const u16 gMachBikeSpeeds[] = {SPEED_NORMAL, SPEED_FAST, SPEED_FASTEST}; +static const u8 Unknown_3DB606[] = {4, 0}; + +static const struct UnknownStruct1 gUnknown_083DB608[] = +{ + {1, 2, 15, 15, Unknown_3DB606, Unknown_3DB606, 1}, + {2, 2, 15, 15, Unknown_3DB606, Unknown_3DB606, 2}, + {3, 2, 15, 15, Unknown_3DB606, Unknown_3DB606, 3}, + {4, 2, 15, 15, Unknown_3DB606, Unknown_3DB606, 4}, +}; + +void MovePlayerOnBike(u8 direction, u16 newKeys, u16 heldKeys) +{ + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_MACH_BIKE) + MovePlayerOnMachBike(direction, newKeys, heldKeys); + else + MovePlayerOnAcroBike(direction, newKeys, heldKeys); +} + +static void MovePlayerOnMachBike(u8 direction, u16 newKeys, u16 heldKeys) +{ + sMachBikeTransitions[GetMachBikeTransition(&direction)](direction); +} + +static u8 GetMachBikeTransition(u8 *ptr) +{ + u8 direction = player_get_direction_upper_nybble(); + + if (*ptr == 0) + { + *ptr = direction; + if (gPlayerAvatar.unkB == 0) + { + gPlayerAvatar.running2 = 0; + return 0; + } + gPlayerAvatar.running2 = 2; + return 3; + } + + if (*ptr != direction && gPlayerAvatar.running2 != 2) + { + if (gPlayerAvatar.unkB != 0) + { + *ptr = direction; + gPlayerAvatar.running2 = 2; + return 3; + } + gPlayerAvatar.running2 = 1; + return 1; + } + else + { + gPlayerAvatar.running2 = 2; + return 2; + } +} + +static void MachBikeTransition_FaceDirection(u8 direction) +{ + PlayerFaceDirection(direction); + sub_80E6024(); +} + +static void MachBikeTransition_80E517C(u8 direction) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E)) + { + PlayerTurnInPlace(direction); + sub_80E6024(); + } + else + { + MachBikeTransition_FaceDirection(playerMapObj->mapobj_unk_18); + } +} + +static void MachBikeTransition_80E51C4(u8 direction) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + u8 collision; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + { + if (gPlayerAvatar.unkB) + MachBikeTransition_80E5270(playerMapObj->placeholder18); + else + MachBikeTransition_FaceDirection(playerMapObj->placeholder18); + } + else + { + collision = get_some_collision(direction); + if (collision > 0 && collision < 12) + { + if (collision == COLLISION_LEDGE_JUMP) + { + PlayerJumpLedge(direction); + } + else + { + sub_80E6024(); + if (collision < 5 || collision > 8) + PlayerOnBikeCollide(direction); + } + } + else + { + gUnknown_083DB5A4[gPlayerAvatar.bikeFrameCounter](direction); + gPlayerAvatar.unkB = gPlayerAvatar.bikeFrameCounter + (gPlayerAvatar.bikeFrameCounter >> 1); // same as dividing by 2, but compiler is insistent on >> 1 + if (gPlayerAvatar.bikeFrameCounter < 2) // do not go faster than the last element in the mach bike array + gPlayerAvatar.bikeFrameCounter++; + } + } +} + +static void MachBikeTransition_80E5270(u8 var) +{ + u8 collision; + + if (gPlayerAvatar.unkB != 0) + gPlayerAvatar.bikeFrameCounter = --gPlayerAvatar.unkB; + + collision = get_some_collision(var); + + if (collision > 0 && collision < 12) + { + if (collision == COLLISION_LEDGE_JUMP) + { + PlayerJumpLedge(var); + } + else + { + sub_80E6024(); + if (collision < 5 || collision > 8) + PlayerOnBikeCollide(var); + } + } + else + { + gUnknown_083DB5A4[gPlayerAvatar.bikeFrameCounter](var); + } +} + +static void MovePlayerOnAcroBike(u8 newDirection, u16 newKeys, u16 heldKeys) +{ + sAcroBikeTransitions[CheckMovementInputAcroBike(&newDirection, newKeys, heldKeys)](newDirection); +} + +static u8 CheckMovementInputAcroBike(u8 *newDirection, u16 newKeys, u16 heldKeys) +{ + return sAcroBikeInputHandlers[gPlayerAvatar.acroBikeState](newDirection, newKeys, heldKeys); +} + +static u8 AcroBikeHandleInputNormal(u8 *newDirection, u16 newKeys, u16 heldKeys) +{ + u8 direction = player_get_direction_upper_nybble(); + + gPlayerAvatar.bikeFrameCounter = 0; + if (*newDirection == DIR_NONE) + { + if (newKeys & B_BUTTON) + { + //We're standing still with the B button held. + //Do a wheelie. + *newDirection = direction; + gPlayerAvatar.running2 = 0; + gPlayerAvatar.acroBikeState = ACRO_STATE_WHEELIE_STANDING; + return ACRO_TRANS_NORMAL_TO_WHEELIE; + } + else + { + *newDirection = direction; + gPlayerAvatar.running2 = 0; + return ACRO_TRANS_FACE_DIRECTION; + } + } + if (*newDirection == direction && (heldKeys & B_BUTTON) && gPlayerAvatar.unkB == 0) + { + gPlayerAvatar.unkB++; + gPlayerAvatar.acroBikeState = ACRO_STATE_WHEELIE_MOVING; + return 11; + } + if (*newDirection != direction && gPlayerAvatar.running2 != 2) + { + gPlayerAvatar.acroBikeState = ACRO_STATE_TURNING; + gPlayerAvatar.unk9 = *newDirection; + gPlayerAvatar.running2 = 0; + return CheckMovementInputAcroBike(newDirection, newKeys, heldKeys); + } + gPlayerAvatar.running2 = 2; + return 2; +} + +static u8 AcroBikeHandleInputTurning(u8 *newDirection, u16 newKeys, u16 heldKeys) +{ + u8 direction; + + *newDirection = gPlayerAvatar.unk9; + gPlayerAvatar.bikeFrameCounter++; + + //Wait 6 frames before actually changing direction + if (gPlayerAvatar.bikeFrameCounter > 6) + { + gPlayerAvatar.running2 = 1; + gPlayerAvatar.acroBikeState = ACRO_STATE_NORMAL; + sub_80E6024(); + return 1; + } + direction = player_get_direction_upper_nybble(); + if (*newDirection == sub_80E5C2C()) + { + sub_80E6024(); + gPlayerAvatar.unkB = 1; + if (*newDirection == GetOppositeDirection(direction)) + { + gPlayerAvatar.acroBikeState = ACRO_STATE_6; + return 9; + } + else + { + gPlayerAvatar.running2 = 2; + gPlayerAvatar.acroBikeState = ACRO_STATE_5; + return 8; + } + } + *newDirection = direction; + return 0; +} + +static u8 AcroBikeHandleInputWheelieStanding(u8 *ptr, u16 newKeys, u16 heldKeys) +{ + u8 direction; + struct MapObject *playerMapObj; + + direction = player_get_direction_upper_nybble(); + playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + gPlayerAvatar.running2 = 0; + + if (heldKeys & B_BUTTON) + gPlayerAvatar.bikeFrameCounter++; + else + { + //B button was released. + gPlayerAvatar.bikeFrameCounter = 0; + if (!MetatileBehavior_IsBumpySlope(playerMapObj->mapobj_unk_1E)) + { + //Go back to normal on flat ground + *ptr = direction; + gPlayerAvatar.acroBikeState = ACRO_STATE_NORMAL; + sub_80E6024(); + return 4; + } + } + if (gPlayerAvatar.bikeFrameCounter >= 40) + { + *ptr = direction; + gPlayerAvatar.acroBikeState = ACRO_STATE_BUNNY_HOP; + sub_80E6024(); + return 6; + } + if (*ptr == direction) + { + gPlayerAvatar.running2 = 2; + gPlayerAvatar.acroBikeState = ACRO_STATE_WHEELIE_MOVING; + sub_80E6024(); + return 10; + } + if (*ptr == 0) + { + *ptr = direction; + return 5; + } + gPlayerAvatar.running2 = 1; + return 5; +} + +static u8 AcroBikeHandleInputBunnyHop(u8 *ptr, u16 newKeys, u16 heldKeys) +{ + u8 direction; + struct MapObject *playerMapObj; + + direction = player_get_direction_upper_nybble(); + playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!(heldKeys & B_BUTTON)) + { + //B button was released + sub_80E6024(); + if (MetatileBehavior_IsBumpySlope(playerMapObj->mapobj_unk_1E)) + { + //Do a standing wheelie on a bumpy slope + gPlayerAvatar.acroBikeState = ACRO_STATE_WHEELIE_STANDING; + return CheckMovementInputAcroBike(ptr, newKeys, heldKeys); + } + else + { + //Go back to normal on flat ground + *ptr = direction; + gPlayerAvatar.running2 = 0; + gPlayerAvatar.acroBikeState = ACRO_STATE_NORMAL; + return 4; + } + } + + //B Button is still held + + if (*ptr == DIR_NONE) + { + *ptr = direction; + gPlayerAvatar.running2 = 0; + return 6; + } + if (*ptr != direction && gPlayerAvatar.running2 != 2) + { + gPlayerAvatar.running2 = 1; + return 6; + } + gPlayerAvatar.running2 = 2; + return 7; +} + +static u8 AcroBikeHandleInputWheelieMoving(u8 *ptr, u16 newKeys, u16 heldKeys) +{ + u8 direction; + struct MapObject *playerMapObj; + + direction = player_get_direction_lower_nybble(); + playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!(heldKeys & B_BUTTON)) + { + sub_80E6024(); + if (!MetatileBehavior_IsBumpySlope(playerMapObj->mapobj_unk_1E)) + { + gPlayerAvatar.acroBikeState = ACRO_STATE_NORMAL; + if (*ptr == 0) + { + *ptr = direction; + gPlayerAvatar.running2 = 0; + return 4; + } + if (*ptr != direction && gPlayerAvatar.running2 != 2) + { + gPlayerAvatar.running2 = 0; + return 4; + } + gPlayerAvatar.running2 = 2; + return 12; + } + gPlayerAvatar.acroBikeState = ACRO_STATE_WHEELIE_STANDING; + return CheckMovementInputAcroBike(ptr, newKeys, heldKeys); + } + if (*ptr == 0) + { + *ptr = direction; + gPlayerAvatar.acroBikeState = ACRO_STATE_WHEELIE_STANDING; + gPlayerAvatar.running2 = 0; + sub_80E6024(); + return 5; + } + if (direction != *ptr && gPlayerAvatar.running2 != 2) + { + gPlayerAvatar.running2 = 0; + return 5; + } + gPlayerAvatar.running2 = 2; + return 10; +} + +static u8 AcroBikeHandleInputState5(u8 *ptr, u16 newKeys, u16 heldKeys) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + playerMapObj->mapobj_bit_9 = 0; + FieldObjectSetDirection(playerMapObj, playerMapObj->mapobj_unk_18); + gPlayerAvatar.acroBikeState = ACRO_STATE_NORMAL; + return CheckMovementInputAcroBike(ptr, newKeys, heldKeys); +} + +static u8 AcroBikeHandleInputState6(u8 *ptr, u16 newKeys, u16 heldKeys) +{ + gPlayerAvatar.acroBikeState = ACRO_STATE_NORMAL; + return CheckMovementInputAcroBike(ptr, newKeys, heldKeys); +} + +static void AcroBikeTransition_FaceDirection(u8 direction) +{ + PlayerFaceDirection(direction); +} + +static void AcroBikeTransition_80E5708(u8 direction) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + direction = playerMapObj->placeholder18; + PlayerFaceDirection(direction); +} + +static void AcroBikeTransition_80E5744(u8 direction) +{ + u8 collision; + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + { + AcroBikeTransition_FaceDirection(playerMapObj->placeholder18); + return; + } + collision = get_some_collision(direction); + if (collision > 0 && collision < 12) + { + if (collision == COLLISION_LEDGE_JUMP) + PlayerJumpLedge(direction); + else if (collision < 5 || collision > 8) + PlayerOnBikeCollide(direction); + } + else + { + npc_use_some_d2s(direction); + } +} + +static void AcroBikeTransition_NormalToWheelie(u8 direction) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + direction = playerMapObj->placeholder18; + PlayerStartWheelie(direction); +} + +static void AcroBikeTransition_80E57F8(u8 direction) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + direction = playerMapObj->placeholder18; + sub_8059534(direction); +} + +static void AcroBikeTransition_80E5834(u8 direction) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + direction = playerMapObj->placeholder18; + sub_8059504(direction); +} + +static void AcroBikeTransition_80E5870(u8 direction) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + direction = playerMapObj->placeholder18; + sub_805954C(direction); +} + +static void AcroBikeTransition_80E58AC(u8 direction) +{ + u8 var; + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + { + AcroBikeTransition_80E5870(playerMapObj->placeholder18); + return; + } + var = get_some_collision(direction); + //TODO: Try to get rid of this goto + if (var == 0 || var == 9) + { + goto derp; + } + else if (var == 6) + { + sub_8059594(direction); + } + else if (var < 5 || var > 8) + { + if (var <= 11) + { + AcroBikeTransition_80E5870(direction); + } + else + { + derp: + sub_8059570(direction); + } + } +} + +static void AcroBikeTransition_80E5920(u8 direction) +{ + u8 var; + struct MapObject *playerMapObj; + + var = get_some_collision(direction); + if (var != 0) + { + if (var == 7) + return; + if (var < 10) + { + AcroBikeTransition_80E5708(direction); + return; + } + if (sub_80E5EC0(var, direction) == 0) + { + AcroBikeTransition_80E5708(direction); + return; + } + } + playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + PlaySE(SE_JITE_PYOKO); + playerMapObj->mapobj_bit_9 = 1; + PlayerSetAnimId(sub_80608A4(direction), 2); +} + +static void AcroBikeTransition_80E5990(u8 direction) +{ + sub_80595B8(direction); +} + +static void AcroBikeTransition_80E59A0(u8 direction) +{ + u8 var; + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + { + sub_8059504(playerMapObj->placeholder18); + return; + } + var = get_some_collision(direction); + if (var > 0 && var < 12) + { + if (var == 6) + { + sub_8059594(direction); + } + else if (var == 9) + { + sub_8059504(direction); + } + else if (var <= 4) + { + if (MetatileBehavior_IsBumpySlope(playerMapObj->mapobj_unk_1E)) + sub_8059504(direction); + else + sub_80595DC(direction); //hit wall? + } + return; + } + sub_8059618(direction); + gPlayerAvatar.running2 = 2; +} + +static void AcroBikeTransition_80E5A30(u8 direction) +{ + u8 var; + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + { + PlayerStartWheelie(playerMapObj->placeholder18); + return; + } + var = get_some_collision(direction); + if (var > 0 && var < 12) + { + if (var == 6) + { + sub_8059594(direction); + } + else if (var == 9) + { + sub_8059504(direction); + } + else if (var <= 4) + { + if (MetatileBehavior_IsBumpySlope(playerMapObj->mapobj_unk_1E)) + sub_8059504(direction); + else + sub_80595DC(direction); //hit wall? + } + return; + } + sub_8059600(direction); + gPlayerAvatar.running2 = 2; +} + +static void AcroBikeTransition_80E5AC0(u8 direction) +{ + u8 var; + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (CanBikeFaceDirOnMetatile(direction, playerMapObj->mapobj_unk_1E) == 0) + { + sub_8059534(playerMapObj->placeholder18); + return; + } + var = get_some_collision(direction); + if (var > 0 && var < 12) + { + if (var == 6) + PlayerJumpLedge(direction); + else if (var < 5 || var > 8) + sub_8059534(direction); + return; + } + sub_8059630(direction); +} + +void sub_80E5B38(u16 a, u16 b) +{ + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE) + sub_80E5B60(a, b); +} + +static void sub_80E5B60(u16 unused, u16 b) +{ + u8 var; + + var = sub_80E5CF4(b); + if (var == (gPlayerAvatar.unkC & 0xF)) + { + if (gPlayerAvatar.unk14[0] < 0xFF) + gPlayerAvatar.unk14[0]++; + } + else + { + sub_80E5C7C(var); + gPlayerAvatar.unkB = 0; + } + + var = b & 0xF; + if (var == (gPlayerAvatar.unk10 & 0xF)) + { + if (gPlayerAvatar.unk1C[0] < 0xFF) + gPlayerAvatar.unk1C[0]++; + } + else + { + sub_80E5CB8(var); + gPlayerAvatar.unkB = 0; + } +} + +static bool8 sub_80E5BC8(const u8 *a, const u8 *b) +{ + u8 i; + + for (i = 0; a[i] != 0; i++) + { + if (gPlayerAvatar.unk14[i] > a[i]) + return FALSE; + } + for (i = 0; b[i] != 0; i++) + { + if (gPlayerAvatar.unk1C[i] > b[i]) + return FALSE; + } + return TRUE; +} + +static u8 sub_80E5C2C(void) +{ + u32 i; + + for (i = 0; i < 4; i++) + { + const struct UnknownStruct1 *s = &gUnknown_083DB608[i]; + u32 r1 = gPlayerAvatar.unkC; + u32 r2 = gPlayerAvatar.unk10; + + r1 &= s->unk8; + r2 &= s->unkC; + if (r1 == s->unk0 && r2 == s->unk4 && sub_80E5BC8(s->unk10, s->unk14)) + return s->unk18; + } + return 0; +} + +static void sub_80E5C7C(u8 a) +{ + u8 i; + + gPlayerAvatar.unkC = (gPlayerAvatar.unkC << 4) | (a & 0xF); + + for (i = 7; i != 0; i--) + gPlayerAvatar.unk14[i] = gPlayerAvatar.unk14[i - 1]; + gPlayerAvatar.unk14[0] = 1; +} + +static void sub_80E5CB8(u8 a) +{ + u8 i; + + gPlayerAvatar.unk10 = (gPlayerAvatar.unk10 << 4) | (a & 0xF); + + for (i = 7; i != 0; i--) + gPlayerAvatar.unk1C[i] = gPlayerAvatar.unk1C[i - 1]; + gPlayerAvatar.unk1C[0] = 1; +} + +static u8 sub_80E5CF4(u16 a) +{ + if (a & 0x40) + return 2; + if (a & 0x80) + return 1; + if (a & 0x20) + return 3; + if (a & 0x10) + return 4; + return 0; +} + +static u8 get_some_collision(u8 direction) +{ + s16 x; + s16 y; + u8 metatitleBehavior; + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + x = playerMapObj->coords2.x; + y = playerMapObj->coords2.y; + MoveCoords(direction, &x, &y); + metatitleBehavior = MapGridGetMetatileBehaviorAt(x, y); + return sub_80E5DA0(playerMapObj, x, y, direction, metatitleBehavior); +} + +static u8 sub_80E5DA0(struct MapObject *mapObject, s16 x, s16 y, u8 direction, u8 metatitleBehavior) +{ + u8 collision = CheckForFieldObjectCollision(mapObject, x, y, direction, metatitleBehavior); + + if (collision > 4) + return collision; + + if (collision == 0 && IsRunningDisallowedByMetatile(metatitleBehavior)) + collision = 2; + + if (collision) + sub_80E5E4C(); + + return collision; +} + +bool8 IsRunningDisallowed(u8 tile) +{ + if (IsRunningDisallowedByMetatile(tile) != FALSE || gMapHeader.mapType == MAP_TYPE_INDOOR) + return TRUE; + else + return FALSE; +} + +static bool8 IsRunningDisallowedByMetatile(u8 tile) +{ + if (MetatileBehavior_IsRunningDisallowed(tile)) + return TRUE; + if (MetatileBehavior_IsFortreeBridge(tile) && (PlayerGetZCoord() & 1) == 0) + return TRUE; + return FALSE; +} + +static void sub_80E5E4C(void) +{ + if (gUnknown_02039250 != 0 && gUnknown_02039251 < 100) + gUnknown_02039251++; +} + +static bool8 CanBikeFaceDirOnMetatile(u8 direction, u8 tile) +{ + if (direction == DIR_EAST || direction == DIR_WEST) + { + //Bike cannot face east or west on a vertical rail + if (MetatileBehavior_IsIsolatedVerticalRail(tile) + || MetatileBehavior_IsVerticalRail(tile)) + return FALSE; + } + else + { + //Bike cannot face north or south on a horizontal rail + if (MetatileBehavior_IsIsolatedHorizontalRail(tile) + || MetatileBehavior_IsHorizontalRail(tile)) + return FALSE; + } + return TRUE; +} + +static bool8 sub_80E5EC0(u8 var1, u8 direction) +{ + if (direction == DIR_NORTH || direction == DIR_SOUTH) + { + if (var1 == 10 || var1 == 12) + return FALSE; + } + else if (var1 == 11 || var1 == 13) + { + return FALSE; + } + + return TRUE; +} + +bool8 IsBikingDisallowedByPlayer(void) +{ + s16 x, y; + u8 tileBehavior; + + if (!(gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_SURFING | PLAYER_AVATAR_FLAG_4))) + { + PlayerGetDestCoords(&x, &y); + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + if (!IsRunningDisallowedByMetatile(tileBehavior)) + return FALSE; + } + return TRUE; +} + +bool8 player_should_look_direction_be_enforced_upon_movement(void) +{ + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_ACRO_BIKE) != FALSE && MetatileBehavior_IsBumpySlope(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E) != FALSE) + return FALSE; + else + return TRUE; +} + +void GetOnOffBike(u8 var) +{ + gUnknown_0202E854 = 0; + + if (gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) + { + SetPlayerAvatarTransitionFlags(PLAYER_AVATAR_FLAG_ON_FOOT); + Overworld_ClearSavedMusic(); + Overworld_PlaySpecialMapMusic(); + } + else + { + SetPlayerAvatarTransitionFlags(var); + Overworld_SetSavedMusic(BGM_CYCLING); + Overworld_ChangeMusicTo(BGM_CYCLING); + } +} + +void BikeClearState(int var1, int var2) +{ + u8 i; + + gPlayerAvatar.acroBikeState = ACRO_STATE_NORMAL; + gPlayerAvatar.unk9 = 0; + gPlayerAvatar.bikeFrameCounter = 0; + gPlayerAvatar.unkB = 0; + gPlayerAvatar.unkC = var1; + gPlayerAvatar.unk10 = var2; + + for (i = 0; i < 8; i++) + gPlayerAvatar.unk14[i] = 0; + + for (i = 0; i < 8; i++) + gPlayerAvatar.unk1C[i] = 0; +} + +void sub_80E6010(u8 var) +{ + gPlayerAvatar.bikeFrameCounter = var; + gPlayerAvatar.unkB = gPlayerAvatar.bikeFrameCounter + (gPlayerAvatar.bikeFrameCounter >> 1); // lazy way of multiplying by 1.5. +} + +static void sub_80E6024(void) +{ + gPlayerAvatar.bikeFrameCounter = 0; + gPlayerAvatar.unkB = 0; +} + +s16 GetPlayerSpeed(void) +{ + // because the player pressed a direction, it won't ever return a speed of 0 since this function returns the player's current speed. + s16 machSpeeds[3]; + + memcpy(machSpeeds, gMachBikeSpeeds, sizeof(machSpeeds)); + + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_MACH_BIKE) + return machSpeeds[gPlayerAvatar.bikeFrameCounter]; + else if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE) + return SPEED_FASTER; + else if (gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_SURFING | PLAYER_AVATAR_FLAG_DASH)) + return SPEED_FAST; + else + return SPEED_NORMAL; +} + +void sub_80E6084(void) +{ + s16 x, y; + u8 tileBehavior; + + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE) + { + PlayerGetDestCoords(&x, &y); + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + if (MetatileBehavior_IsBumpySlope(tileBehavior)) + { + gPlayerAvatar.acroBikeState = ACRO_STATE_WHEELIE_STANDING; + sub_8059C94(player_get_direction_upper_nybble()); + } + } +} diff --git a/src/field/birch_pc.c b/src/field/birch_pc.c new file mode 100644 index 000000000..9872dd54d --- /dev/null +++ b/src/field/birch_pc.c @@ -0,0 +1,114 @@ +#include "global.h" +#include "event_data.h" +#include "field_message_box.h" +#include "pokedex.h" +#include "species.h" + +extern u16 gSpecialVar_0x8004; +extern u16 gSpecialVar_0x8005; +extern u16 gSpecialVar_0x8006; + +extern const u8 gBirchDexRatingText_LessThan10[]; +extern const u8 gBirchDexRatingText_LessThan20[]; +extern const u8 gBirchDexRatingText_LessThan30[]; +extern const u8 gBirchDexRatingText_LessThan40[]; +extern const u8 gBirchDexRatingText_LessThan50[]; +extern const u8 gBirchDexRatingText_LessThan60[]; +extern const u8 gBirchDexRatingText_LessThan70[]; +extern const u8 gBirchDexRatingText_LessThan80[]; +extern const u8 gBirchDexRatingText_LessThan90[]; +extern const u8 gBirchDexRatingText_LessThan100[]; +extern const u8 gBirchDexRatingText_LessThan110[]; +extern const u8 gBirchDexRatingText_LessThan120[]; +extern const u8 gBirchDexRatingText_LessThan130[]; +extern const u8 gBirchDexRatingText_LessThan140[]; +extern const u8 gBirchDexRatingText_LessThan150[]; +extern const u8 gBirchDexRatingText_LessThan160[]; +extern const u8 gBirchDexRatingText_LessThan170[]; +extern const u8 gBirchDexRatingText_LessThan180[]; +extern const u8 gBirchDexRatingText_LessThan190[]; +extern const u8 gBirchDexRatingText_LessThan200[]; +extern const u8 gBirchDexRatingText_DexCompleted[]; + +bool16 ScriptGetPokedexInfo(void) +{ + if (gSpecialVar_0x8004 == 0) // is national dex not present? + { + gSpecialVar_0x8005 = GetHoennPokedexCount(0); + gSpecialVar_0x8006 = GetHoennPokedexCount(1); + } + else + { + gSpecialVar_0x8005 = GetNationalPokedexCount(0); + gSpecialVar_0x8006 = GetNationalPokedexCount(1); + } + + return IsNationalPokedexEnabled(); +} + +// This shows your Hoenn Pokedex rating and not your National Dex. +const u8 *GetPokedexRatingText(u16 count) +{ + if (count < 10) + return gBirchDexRatingText_LessThan10; + if (count < 20) + return gBirchDexRatingText_LessThan20; + if (count < 30) + return gBirchDexRatingText_LessThan30; + if (count < 40) + return gBirchDexRatingText_LessThan40; + if (count < 50) + return gBirchDexRatingText_LessThan50; + if (count < 60) + return gBirchDexRatingText_LessThan60; + if (count < 70) + return gBirchDexRatingText_LessThan70; + if (count < 80) + return gBirchDexRatingText_LessThan80; + if (count < 90) + return gBirchDexRatingText_LessThan90; + if (count < 100) + return gBirchDexRatingText_LessThan100; + if (count < 110) + return gBirchDexRatingText_LessThan110; + if (count < 120) + return gBirchDexRatingText_LessThan120; + if (count < 130) + return gBirchDexRatingText_LessThan130; + if (count < 140) + return gBirchDexRatingText_LessThan140; + if (count < 150) + return gBirchDexRatingText_LessThan150; + if (count < 160) + return gBirchDexRatingText_LessThan160; + if (count < 170) + return gBirchDexRatingText_LessThan170; + if (count < 180) + return gBirchDexRatingText_LessThan180; + if (count < 190) + return gBirchDexRatingText_LessThan190; + if (count < 200) + return gBirchDexRatingText_LessThan200; + if (count == 200) + { + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_JIRACHI), 1) + || GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_DEOXYS), 1)) // Jirachi or Deoxys is not counted towards the dex completion. If either of these flags are enabled, it means the actual count is less than 200. + return gBirchDexRatingText_LessThan200; + return gBirchDexRatingText_DexCompleted; + } + if (count == 201) + { + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_JIRACHI), 1) + && GetSetPokedexFlag(SpeciesToNationalPokedexNum(SPECIES_DEOXYS), 1)) // If both of these flags are enabled, it means the actual count is less than 200. + return gBirchDexRatingText_LessThan200; + return gBirchDexRatingText_DexCompleted; + } + if (count == 202) + return gBirchDexRatingText_DexCompleted; // Hoenn dex is considered complete, even though the hoenn dex count is 210. + return gBirchDexRatingText_LessThan10; +} + +void ShowPokedexRatingMessage(void) +{ + ShowFieldMessage(GetPokedexRatingText(gSpecialVar_0x8004)); +} diff --git a/src/field/braille_puzzles.c b/src/field/braille_puzzles.c new file mode 100644 index 000000000..b11b1ff3a --- /dev/null +++ b/src/field/braille_puzzles.c @@ -0,0 +1,262 @@ +#include "global.h" +#include "braille_puzzles.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_effect.h" +#include "fieldmap.h" +#include "flags.h" +#include "main.h" +#include "map_constants.h" +#include "map_obj_lock.h" +#include "menu.h" +#include "rom6.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "species.h" +#include "task.h" +#include "text.h" + +extern u8 gPlayerPartyCount; +extern u8 gLastFieldPokeMenuOpened; + +extern u8 S_OpenRegiceChamber[]; // regiice event script + +bool8 ShouldDoBrailleDigEffect(void) +{ + if (!FlagGet(SYS_BRAILLE_DIG) + && (gSaveBlock1.location.mapGroup == MAP_GROUP_SEALED_CHAMBER_OUTER_ROOM + && gSaveBlock1.location.mapNum == MAP_ID_SEALED_CHAMBER_OUTER_ROOM)) + { + if (gSaveBlock1.pos.x == 10 && gSaveBlock1.pos.y == 3) + return TRUE; + else if (gSaveBlock1.pos.x == 9 && gSaveBlock1.pos.y == 3) + return TRUE; + else if (gSaveBlock1.pos.x == 11 && gSaveBlock1.pos.y == 3) + return TRUE; + } + + return FALSE; +} + +void DoBrailleDigEffect(void) +{ + MapGridSetMetatileIdAt(16, 8, 554); + MapGridSetMetatileIdAt(17, 8, 555); + MapGridSetMetatileIdAt(18, 8, 556); + MapGridSetMetatileIdAt(16, 9, 3634); + MapGridSetMetatileIdAt(17, 9, 563); + MapGridSetMetatileIdAt(18, 9, 3636); + DrawWholeMapView(); + PlaySE(SE_BAN); + FlagSet(SYS_BRAILLE_DIG); + ScriptContext2_Disable(); +} + +bool8 CheckRelicanthWailord(void) +{ + // First comes Relicanth. + if (GetMonData(&gPlayerParty, MON_DATA_SPECIES2, 0) == SPECIES_RELICANTH) + { + CalculatePlayerPartyCount(); + // Last comes Wailord + if (GetMonData(&gPlayerParty[gPlayerPartyCount - 1], MON_DATA_SPECIES2, 0) == SPECIES_WAILORD) + return TRUE; + } + return FALSE; +} + +bool8 ShouldDoBrailleStrengthEffect(void) +{ + if (!FlagGet(SYS_BRAILLE_STRENGTH) && (gSaveBlock1.location.mapGroup == MAP_GROUP_DESERT_RUINS && gSaveBlock1.location.mapNum == MAP_ID_DESERT_RUINS)) + { + if (gSaveBlock1.pos.x == 10 && gSaveBlock1.pos.y == 23) + return TRUE; + else if (gSaveBlock1.pos.x == 9 && gSaveBlock1.pos.y == 23) + return TRUE; + else if (gSaveBlock1.pos.x == 11 && gSaveBlock1.pos.y == 23) + return TRUE; + } + + return FALSE; +} + +void DoBrailleStrengthEffect(void) +{ + FieldEffectActiveListRemove(0x28); + MapGridSetMetatileIdAt(14, 26, 554); + MapGridSetMetatileIdAt(15, 26, 555); + MapGridSetMetatileIdAt(16, 26, 556); + MapGridSetMetatileIdAt(14, 27, 3634); + MapGridSetMetatileIdAt(15, 27, 563); + MapGridSetMetatileIdAt(16, 27, 3636); + DrawWholeMapView(); + PlaySE(SE_BAN); + FlagSet(SYS_BRAILLE_STRENGTH); + ScriptContext2_Disable(); +} + +bool8 ShouldDoBrailleFlyEffect(void) +{ + if (!FlagGet(SYS_BRAILLE_FLY) && (gSaveBlock1.location.mapGroup == MAP_GROUP_ANCIENT_TOMB && gSaveBlock1.location.mapNum == MAP_ID_ANCIENT_TOMB)) + { + if (gSaveBlock1.pos.x == 8 && gSaveBlock1.pos.y == 25) + return TRUE; + } + + return FALSE; +} + +void DoBrailleFlyEffect(void) +{ + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; + FieldEffectStart(FLDEFF_USE_FLY_ANCIENT_TOMB); +} + +bool8 FldEff_UseFlyAncientTomb(void) +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)UseFlyAncientTomb_Callback >> 16; + gTasks[taskId].data[9] = (u32)UseFlyAncientTomb_Callback; + return FALSE; +} + +void UseFlyAncientTomb_Callback(void) +{ + FieldEffectActiveListRemove(FLDEFF_USE_FLY_ANCIENT_TOMB); + UseFlyAncientTomb_Finish(); +} + +void UseFlyAncientTomb_Finish(void) +{ + MapGridSetMetatileIdAt(14, 26, 554); + MapGridSetMetatileIdAt(15, 26, 555); + MapGridSetMetatileIdAt(16, 26, 556); + MapGridSetMetatileIdAt(14, 27, 3634); + MapGridSetMetatileIdAt(15, 27, 563); + MapGridSetMetatileIdAt(16, 27, 3636); + DrawWholeMapView(); + PlaySE(SE_BAN); + FlagSet(SYS_BRAILLE_FLY); + ScriptContext2_Disable(); +} + +void DoBrailleWait(void) +{ + if (!FlagGet(SYS_BRAILLE_WAIT)) + CreateTask(Task_BrailleWait, 0x50); +} + +void Task_BrailleWait(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (data[0]) + { + case 0: + data[1] = 7200; + data[0] = 1; + break; + case 1: + if (BrailleWait_CheckButtonPress() != FALSE) + { + MenuZeroFillScreen(); + PlaySE(SE_SELECT); + data[0] = 2; + } + else + { + data[1] = data[1] - 1; + if (data[1] == 0) + { + MenuZeroFillScreen(); + data[0] = 3; + data[1] = 30; + } + } + break; + case 2: + if (BrailleWait_CheckButtonPress() == FALSE) + { + data[1] = data[1] - 1; + if (data[1] == 0) + data[0] = 4; + break; + } + sub_8064E2C(); + DestroyTask(taskId); + ScriptContext2_Disable(); + break; + case 3: + data[1] = data[1] - 1; + if (data[1] == 0) + data[0] = 4; + break; + case 4: + sub_8064E2C(); + ScriptContext1_SetupScript(S_OpenRegiceChamber); + DestroyTask(taskId); + break; + } +} + +bool32 BrailleWait_CheckButtonPress(void) +{ + u16 keyMask = A_BUTTON | B_BUTTON | START_BUTTON | SELECT_BUTTON | DPAD_ANY; + + if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR) + keyMask |= L_BUTTON | R_BUTTON; + if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_L_EQUALS_A) + keyMask |= L_BUTTON; + + if (gMain.newKeys & keyMask) + return TRUE; + else + return FALSE; +} + +void DoSealedChamberShakingEffect1(void) +{ + u8 taskId = CreateTask(SealedChamberShakingEffect, 0x9); + + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[4] = 2; + gTasks[taskId].data[5] = 5; + gTasks[taskId].data[6] = 50; + SetCameraPanningCallback(0); +} + +void DoSealedChamberShakingEffect2(void) +{ + u8 taskId = CreateTask(SealedChamberShakingEffect, 0x9); + + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[4] = 3; + gTasks[taskId].data[5] = 5; + gTasks[taskId].data[6] = 2; + SetCameraPanningCallback(0); +} + +void SealedChamberShakingEffect(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + task->data[1]++; + + if (!(task->data[1] % task->data[5])) + { + task->data[1] = 0; + task->data[2]++; + task->data[4] = -task->data[4]; + SetCameraPanning(0, task->data[4]); + if (task->data[2] == task->data[6]) + { + DestroyTask(taskId); + EnableBothScriptContexts(); + InstallCameraPanAheadCallback(); + } + } +} diff --git a/src/field/choose_party.c b/src/field/choose_party.c new file mode 100644 index 000000000..9cdf63fc8 --- /dev/null +++ b/src/field/choose_party.c @@ -0,0 +1,987 @@ +#include "global.h" +#include "decoration.h" +#include "field_fadetransition.h" +#include "main.h" +#include "menu.h" +#include "name_string_util.h" +#include "palette.h" +#include "party_menu.h" +#include "pokemon_menu.h" +#include "pokemon.h" +#include "pokemon_summary_screen.h" +#include "overworld.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "strings.h" +#include "string_util.h" +#include "task.h" +#include "text.h" + +struct UnknownPokemonStruct2 +{ + /*0x00*/ u16 species; + /*0x02*/ u16 heldItem; + /*0x04*/ u8 nickname[11]; + /*0x0F*/ u8 level; + /*0x10*/ u16 hp; + /*0x12*/ u16 maxhp; + /*0x14*/ u32 status; + /*0x18*/ u32 personality; + /*0x1C*/ u8 gender; + /*0x1D*/ u8 language; +}; + +extern u8 gPlayerPartyCount; +extern u8 gLastFieldPokeMenuOpened; +extern u8 gUnknown_020384F0; +extern struct UnknownPokemonStruct2 gUnknown_02023A00[]; +extern u8 gUnknown_0202E8F6; +extern struct Pokemon gUnknown_030042FC[]; +extern const u16 gBattleTowerBanlist[]; + +EWRAM_DATA u8 gSelectedOrderFromParty[3] = {0}; + +extern void OpenPartyMenu(); +extern void TryCreatePartyMenuMonIcon(u8, u8, struct Pokemon *); +extern void LoadHeldItemIconGraphics(void); +extern void CreateHeldItemIcons_806DC34(); +extern u8 sub_806BD58(u8, u8); +extern void PartyMenuPrintMonsLevelOrStatus(void); +extern void PrintPartyMenuMonNicknames(void); +extern void sub_806BC3C(u8, u8); +extern u8 sub_806B58C(u8); +extern u16 sub_806BE38(); +extern u8 sub_806CA38(); +extern TaskFunc PartyMenuGetPopupMenuFunc(u8, const struct PartyPopupMenu *, const struct PartyMenuItem *, u8); +extern u8 sub_806B124(); +extern void sub_806C994(); +extern void sub_806C658(); +extern void sub_806AEDC(void); +extern void sub_806AF4C(); +extern void ShowPokemonSummaryScreen(struct Pokemon *, u8, u8, void (*)(void), int); +extern void sub_806C890(); +extern void sub_806D5A4(); +extern void sub_806B908(void); +extern void CreateMonIcon_806D99C(int, u8, int, struct UnknownPokemonStruct2 *); +extern void sub_806D50C(int, u8); +extern void CreatePartyMenuMonIcon(); +extern void CreateHeldItemIcon_806DCD4(int, u8, int); +extern u8 GetMonStatusAndPokerus(); +extern void PartyMenuPrintHP(); +extern void PartyMenuPutStatusTilemap(u8, int, u8); +extern void PartyMenuPrintLevel(); +extern void PartyMenuPutNicknameTilemap(); +extern void PrintPartyMenuMonNickname(); +extern void PartyMenuDrawHPBar(); +extern bool8 sub_80F9344(void); +extern void sub_806D4AC(); +extern void sub_806D3B4(); +extern void PartyMenuDoPrintLevel(u8, u8, u8); +extern void PartyMenuDoDrawHPBar(u8, u8, u16, u16); +extern void PartyMenuDoPutNicknameTilemap(u16, u8, u8, u8, const u8 *); +extern void box_print(u8, int, const u8 *); +extern void sub_806BCE8(void); +extern void sub_806E750(u8, const struct PartyPopupMenu *, const struct PartyMenuItem *, int); + +static void ClearPartySelection(void); +static bool8 IsMonAllowedInBattleTower(struct Pokemon *); +static void sub_812238C(u8); +static void sub_8122450(u8); +static void sub_81224A8(u8); +static void sub_8122728(u8); +static void BattleTowerEntryMenuCallback_Exit(u8); +static void sub_81228E8(u8); +static void sub_8122950(u8); +static void sub_81229B8(void); +static void sub_8122AB8(u8); +static void sub_8122B10(u8); +static void sub_8122C18(u8); +static void Task_DaycareStorageMenu8122EAC(u8); +void sub_8123138(u8); +static void sub_8123170(u8); +static void sub_81231AC(void); + +void sub_8121E10(void) +{ + ClearPartySelection(); + ewram1B000.unk263 = 0; + OpenPartyMenu(4, 0); +} + +void sub_8121E34(void) +{ + ClearPartySelection(); + ewram1B000.unk263 = 1; + OpenPartyMenu(4, 0); +} + +static void ClearPartySelection(void) +{ + u8 i; + + for (i = 0; i < 3; i++) + gSelectedOrderFromParty[i] = 0; +} + +bool8 sub_8121E78(void) +{ + u8 i; + + switch (ewram1B000_alt.unk264) + { + case 0: + if (ewram1B000_alt.unk266 < gPlayerPartyCount) + { + TryCreatePartyMenuMonIcon(ewram1B000_alt.unk260, ewram1B000_alt.unk266, &gPlayerParty[ewram1B000_alt.unk266]); + ewram1B000_alt.unk266++; + } + else + { + ewram1B000_alt.unk266 = 0; + ewram1B000_alt.unk264++; + } + break; + case 1: + LoadHeldItemIconGraphics(); + ewram1B000_alt.unk264++; + break; + case 2: + CreateHeldItemIcons_806DC34(ewram1B000_alt.unk260); + ewram1B000_alt.unk264++; + break; + case 3: + if (sub_806BD58(ewram1B000_alt.unk260, ewram1B000_alt.unk266) == 1) + { + ewram1B000_alt.unk266 = 0; + ewram1B000_alt.unk264++; + } + else + { + ewram1B000_alt.unk266++; + } + break; + case 4: + PartyMenuPrintMonsLevelOrStatus(); + ewram1B000_alt.unk264++; + break; + case 5: + PrintPartyMenuMonNicknames(); + ewram1B000_alt.unk264++; + break; + case 6: + for (i = 0; i < gPlayerPartyCount; i++) + { + u8 j; + + for (j = 0; j < 3; j++) + { + if (gSelectedOrderFromParty[j] == i + 1) + { + sub_806BC3C(i, j * 14 + 0x1C); + break; + } + } + if (j == 3) + { + if (IsMonAllowedInBattleTower(&gPlayerParty[i]) == TRUE) + sub_806BC3C(i, 0x70); + else + sub_806BC3C(i, 0x7E); + } + } + ewram1B000_alt.unk264++; + break; + case 7: + if (sub_806B58C(ewram1B000_alt.unk266) == 1) + { + ewram1B000_alt.unk266 = 0; + ewram1B000_alt.unk264 = 0; + return TRUE; + } + else + { + ewram1B000_alt.unk266++; + } + break; + } + return FALSE; +} + +static bool8 IsMonAllowedInBattleTower(struct Pokemon *pkmn) +{ + u16 species; + s32 i = 0; + + if (GetMonData(pkmn, MON_DATA_IS_EGG)) + return FALSE; + + if (ewram1B000.unk263 == 0) + { + if (GetMonData(pkmn, MON_DATA_HP) == 0) + return FALSE; + else + return TRUE; + } + + if ((gSaveBlock2.filler_A8.var_4AC & 1) == 0 + && GetMonData(pkmn, MON_DATA_LEVEL) > 50) + return FALSE; + + // Check if the pkmn is in the ban list + species = GetMonData(pkmn, MON_DATA_SPECIES); + while (gBattleTowerBanlist[i] != 0xFFFF) + { + if (gBattleTowerBanlist[i] == species) + return FALSE; + i++; + } + return TRUE; +} + +static u8 sub_81220C8(void) +{ + u8 i; + + if (ewram1B000.unk263 == 0) + return 0xFF; + if (gSelectedOrderFromParty[2] == 0) + return 0x11; + for (i = 0; i < 2; i++) + { + u8 j; + + ewram1B000.unk282 = GetMonData(&gUnknown_030042FC[gSelectedOrderFromParty[i]], MON_DATA_SPECIES); + ewram1B000.unk280 = GetMonData(&gUnknown_030042FC[gSelectedOrderFromParty[i]], MON_DATA_HELD_ITEM); + for (j = i + 1; j < 3; j++) + { + if (ewram1B000.unk282 == GetMonData(&gUnknown_030042FC[gSelectedOrderFromParty[j]], MON_DATA_SPECIES)) + return 0x12; + if (ewram1B000.unk280 != 0 && ewram1B000.unk280 == GetMonData(&gUnknown_030042FC[gSelectedOrderFromParty[j]], MON_DATA_HELD_ITEM)) + return 0x13; + } + } + return 0xFF; +} + +//------------------------------------------------------------------------------ +// Battle Tower Entry Menu +//------------------------------------------------------------------------------ + +static void BattleTowerEntryMenuCallback_Summary(u8); +static void BattleTowerEntryMenuCallback_Enter(u8); +static void BattleTowerEntryMenuCallback_NoEntry(u8); +static void BattleTowerEntryMenuCallback_Exit(u8); + +static const struct PartyMenuItem sBattleTowerEntryMenuItems[] = +{ + {OtherText_Summary, BattleTowerEntryMenuCallback_Summary}, + {OtherText_Enter2, BattleTowerEntryMenuCallback_Enter}, + {OtherText_NoEntry, BattleTowerEntryMenuCallback_NoEntry}, + {gUnknownText_Exit, BattleTowerEntryMenuCallback_Exit}, +}; + +static const u8 gUnknown_084017D0[] = {1, 0, 3}; +static const u8 gUnknown_084017D3[] = {2, 0, 3}; +static const u8 gUnknown_084017D6[] = {0, 3}; + +static const struct PartyPopupMenu sBattleTowerEntryMenu[] = +{ + {ARRAY_COUNT(gUnknown_084017D0), 9, gUnknown_084017D0}, + {ARRAY_COUNT(gUnknown_084017D3), 9, gUnknown_084017D3}, + {ARRAY_COUNT(gUnknown_084017D6), 9, gUnknown_084017D6}, +}; + + +static bool8 IsPartyMemberAlreadySelected(u8 partyMember) +{ + u8 i; + + for (i = 0; i < 3; i++) + { + if (gSelectedOrderFromParty[i] == partyMember) + return TRUE; + } + return FALSE; +} + +static void sub_81221F8(u8 taskId) +{ + sub_806D538(5, 1); + if (IsMonAllowedInBattleTower(&gPlayerParty[gLastFieldPokeMenuOpened]) == TRUE) + { + if (IsPartyMemberAlreadySelected(gLastFieldPokeMenuOpened + 1) == TRUE) + { + gTasks[taskId].data[4] = 1; + sub_806E750(1, sBattleTowerEntryMenu, sBattleTowerEntryMenuItems, 0); + } + else + { + gTasks[taskId].data[4] = 0; + sub_806E750(0, sBattleTowerEntryMenu, sBattleTowerEntryMenuItems, 0); + } + } + else + { + gTasks[taskId].data[4] = 2; + sub_806E750(2, sBattleTowerEntryMenu, sBattleTowerEntryMenuItems, 0); + } +} + +void sub_81222B0(u8 taskId) +{ + if (!gPaletteFade.active) + { + switch (sub_806BE38(taskId)) + { + case 1: + PlaySE(SE_SELECT); + gLastFieldPokeMenuOpened = sub_806CA38(taskId); + if (gLastFieldPokeMenuOpened != 6) + { + GetMonNickname(&gPlayerParty[gLastFieldPokeMenuOpened], gStringVar1); + sub_81221F8(taskId); + gTasks[taskId].func = sub_812238C; + } + else + { + gTasks[taskId].func = sub_81224A8; + } + sub_808B5B4(taskId); + break; + case 2: + PlaySE(SE_SELECT); + ClearPartySelection(); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = sub_8122450; + break; + } + } +} + +// Handle input +static void sub_812238C(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gMain.newAndRepeatedKeys & 0x40) + { + if (GetMenuCursorPos() != 0) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + } + return; + } + if (gMain.newAndRepeatedKeys & 0x80) + { + if (GetMenuCursorPos() != 3) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + } + return; + } + if (gMain.newKeys & A_BUTTON) + { + TaskFunc popupMenuFunc; + + PlaySE(SE_SELECT); + popupMenuFunc = PartyMenuGetPopupMenuFunc( + gTasks[taskId].data[4], + sBattleTowerEntryMenu, + sBattleTowerEntryMenuItems, + GetMenuCursorPos()); + popupMenuFunc(taskId); + return; + } + if (gMain.newKeys & B_BUTTON) + { + BattleTowerEntryMenuCallback_Exit(taskId); + return; + } + } +} + +// Return from menu? +static void sub_8122450(u8 taskId) +{ + if (!gPaletteFade.active) + { + SetMainCallback2(gMain.savedCallback); + DestroyTask(taskId); + } +} + +// Wait for A or B press +static void sub_8122480(u8 taskId) +{ + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + BattleTowerEntryMenuCallback_Exit(taskId); +} + +static void sub_81224A8(u8 taskId) +{ + u8 val = sub_81220C8(); + + if (val != 0xFF) + { + sub_806D538(val, 0); + gTasks[taskId].func = sub_8122480; + } + else + { + if (gSelectedOrderFromParty[0] != 0) + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = sub_8122450; + } + else + { + PlaySE(SE_HAZURE); + sub_806D538(14, 0); + gTasks[taskId].func = sub_8122480; + } + } +} + +// CB2 for menu? +static void sub_8122530(void) +{ + while (1) + { + if (sub_806B124() == 1) + { + sub_806C994(ewram1B000.unk260, gUnknown_020384F0); + sub_806C658(ewram1B000.unk260, 0); + GetMonNickname(&gPlayerParty[gUnknown_020384F0], gStringVar1); + gLastFieldPokeMenuOpened = gUnknown_020384F0; + sub_81221F8(ewram1B000.unk260); + SetMainCallback2(sub_806AEDC); + break; + } + if (sub_80F9344() == 1) + break; + } +} + +static void sub_81225A4(void) +{ + gPaletteFade.bufferTransferDisabled = TRUE; + sub_806AF4C(4, 0xFF, sub_812238C, 5); + SetMainCallback2(sub_8122530); +} + +// Wait for fade, then show summary screen +static void sub_81225D4(u8 taskId) +{ + if (!gPaletteFade.active) + { + u8 r4 = gSprites[gTasks[taskId].data[3] >> 8].data0; + + DestroyTask(taskId); + ewram1B000.unk262 = 1; + ShowPokemonSummaryScreen(gPlayerParty, r4, gPlayerPartyCount - 1, sub_81225A4, 0); + } +} + +// Summary callback? +static void BattleTowerEntryMenuCallback_Summary(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = sub_81225D4; +} + +static void BattleTowerEntryMenuCallback_Enter(u8 taskId) +{ + u8 i; + + for (i = 0; i < 3; i++) + { + if (gSelectedOrderFromParty[i] == 0) + { + gSelectedOrderFromParty[i] = gLastFieldPokeMenuOpened + 1; + sub_806BC3C(gLastFieldPokeMenuOpened, i * 14 + 0x1C); + if (i == 2) + sub_806C890(taskId); + BattleTowerEntryMenuCallback_Exit(taskId); + return; + } + } + PlaySE(SE_HAZURE); + MenuZeroFillWindowRect(20, 10, 29, 19); + HandleDestroyMenuCursors(); + sub_806D5A4(); + sub_806E834(gOtherText_NoMoreThreePoke, 1); + gTasks[taskId].func = sub_8122728; +} + +static void sub_8122728(u8 taskId) +{ + if (gUnknown_0202E8F6 == 1) + return; + + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + MenuZeroFillWindowRect(0, 14, 29, 19); + HandleDestroyMenuCursors(); + BattleTowerEntryMenuCallback_Exit(taskId); + } +} + +static void BattleTowerEntryMenuCallback_NoEntry(u8 taskId) +{ + u8 i; + + for (i = 0; i < 3; i++) + { + if (gSelectedOrderFromParty[i] == gLastFieldPokeMenuOpened + 1) + { + gSelectedOrderFromParty[i] = 0; + switch (i) + { + case 0: + gSelectedOrderFromParty[0] = gSelectedOrderFromParty[1]; + gSelectedOrderFromParty[1] = gSelectedOrderFromParty[2]; + gSelectedOrderFromParty[2] = 0; + break; + case 1: + gSelectedOrderFromParty[1] = gSelectedOrderFromParty[2]; + gSelectedOrderFromParty[2] = 0; + break; + } + break; // exit loop + } + } + sub_806BC3C(gLastFieldPokeMenuOpened, 0x70); + if (gSelectedOrderFromParty[0] != 0) + sub_806BC3C(gSelectedOrderFromParty[0] - 1, 0x1C); + if (gSelectedOrderFromParty[1] != 0) + sub_806BC3C(gSelectedOrderFromParty[1] - 1, 0x2A); + BattleTowerEntryMenuCallback_Exit(taskId); +} + +static void sub_81227FC(u8 taskId) +{ + MenuZeroFillWindowRect(20, 10, 29, 19); + HandleDestroyMenuCursors(); + sub_806D538(0, 0); + gTasks[taskId].func = sub_81222B0; +} + +static void BattleTowerEntryMenuCallback_Exit(u8 taskId) +{ + PlaySE(SE_SELECT); + sub_81227FC(taskId); +} + +bool8 sub_8122854(void) +{ + switch (ewram1B000_alt.unk264) + { + case 0: + sub_81228E8(ewram1B000_alt.unk260); + ewram1B000_alt.unk264++; + break; + case 1: + LoadHeldItemIconGraphics(); + ewram1B000_alt.unk264++; + break; + case 2: + sub_8122950(ewram1B000_alt.unk260); + ewram1B000_alt.unk264++; + break; + case 3: + sub_81229B8(); + ewram1B000_alt.unk264++; + break; + case 4: + sub_806B908(); + return TRUE; + } + return FALSE; +} + +static void sub_81228E8(u8 a) +{ + u8 i; + + for (i = 0; i < 3; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != 0) + CreatePartyMenuMonIcon(a, i, 3, &gPlayerParty[i]); + if (gUnknown_02023A00[i].species != 0) + { + CreateMonIcon_806D99C(a, i + 3, 3, &gUnknown_02023A00[i]); + sub_806D50C(a, i + 3); + } + } +} + +static void sub_8122950(u8 a) +{ + u8 i; + + for (i = 0; i < 3; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != 0) + { + u16 item = GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM); + + CreateHeldItemIcon_806DCD4(a, i, item); + } + if (gUnknown_02023A00[i].species != 0) + CreateHeldItemIcon_806DCD4(a, i + 3, gUnknown_02023A00[i].heldItem); + } +} + +static void sub_81229B8(void) +{ + u8 i; + + for (i = 0; i < 3; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != 0) + { + u8 status; + + PartyMenuPrintHP(i, 3, &gPlayerParty[i]); + status = GetMonStatusAndPokerus(&gPlayerParty[i]); + if (status != 0 && status != 6) + PartyMenuPutStatusTilemap(i, 3, status - 1); + else + PartyMenuPrintLevel(i, 3, &gPlayerParty[i]); + PartyMenuPutNicknameTilemap(i, 3, &gPlayerParty[i]); + PrintPartyMenuMonNickname(i, 3, &gPlayerParty[i]); + PartyMenuDrawHPBar(i, 3, &gPlayerParty[i]); + } + } +} + +void sub_8122A48(u8 taskId) +{ + if (!gPaletteFade.active) + { + gTasks[taskId].data[0] = 30; + sub_806D4AC(taskId, gUnknown_02023A00[0].species, 0); + sub_806D4AC(taskId, gUnknown_02023A00[1].species, 1); + sub_806D4AC(taskId, gUnknown_02023A00[2].species, 2); + gTasks[taskId].func = sub_8122AB8; + ewram1B000.unk261 = 1; + } +} + +static void sub_8122AB8(u8 taskId) +{ + sub_806D3B4(taskId, gUnknown_02023A00[1].species, gUnknown_02023A00[2].species); + if (gTasks[taskId].data[0] == 0) + { + gTasks[taskId].func = sub_8122B10; + ewram1B000.unk261 = 2; + PlaySE(SE_W231); + } +} + +static void sub_8122B10(u8 taskId) +{ + u8 i; + + for (i = 0; i < 3; i++) + { + if (gUnknown_02023A00[i].species != 0) + { + u8 r2; + + PartyMenuDoPrintHP(i + 3, 3, gUnknown_02023A00[i].hp, gUnknown_02023A00[i].maxhp); + if (gUnknown_02023A00[i].hp == 0) + r2 = 7; + else + r2 = pokemon_ailments_get_primary(gUnknown_02023A00[i].status); + if (r2 != 0) + PartyMenuPutStatusTilemap(i + 3, 3, r2 - 1); + else + PartyMenuDoPrintLevel(i + 3, 3, gUnknown_02023A00[i].level); + PartyMenuDoPutNicknameTilemap(gUnknown_02023A00[i].species, gUnknown_02023A00[i].gender, 3, i + 3, gUnknown_02023A00[i].nickname); + StringCopy(gStringVar1, gUnknown_02023A00[i].nickname); + StringGetEnd10(gStringVar1); + SanitizeNameString(gStringVar1); + box_print(i + 3, 3, gStringVar1); + PartyMenuDoDrawHPBar(i + 3, 3, gUnknown_02023A00[i].hp, gUnknown_02023A00[i].maxhp); + } + } + gTasks[taskId].func = sub_8122C18; + gTasks[taskId].data[0] = 0; +} + +static void sub_8122C18(u8 taskId) +{ + gTasks[taskId].data[0]++; + if (gTasks[taskId].data[0] == 256) + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = sub_8122450; + } +} + +// Exactly the same as sub_8121E78 except for case 6 +bool8 unref_sub_8122C60(void) +{ + switch (ewram1B000_alt.unk264) + { + case 0: + if (ewram1B000_alt.unk266 < gPlayerPartyCount) + { + TryCreatePartyMenuMonIcon(ewram1B000_alt.unk260, ewram1B000_alt.unk266, &gPlayerParty[ewram1B000_alt.unk266]); + ewram1B000_alt.unk266++; + } + else + { + ewram1B000_alt.unk266 = 0; + ewram1B000_alt.unk264++; + } + break; + case 1: + LoadHeldItemIconGraphics(); + ewram1B000_alt.unk264++; + break; + case 2: + CreateHeldItemIcons_806DC34(ewram1B000_alt.unk260); + ewram1B000_alt.unk264++; + break; + case 3: + if (sub_806BD58(ewram1B000_alt.unk260, ewram1B000_alt.unk266) == 1) + { + ewram1B000_alt.unk266 = 0; + ewram1B000_alt.unk264++; + } + else + { + ewram1B000_alt.unk266++; + } + break; + case 4: + PartyMenuPrintMonsLevelOrStatus(); + ewram1B000_alt.unk264++; + break; + case 5: + PrintPartyMenuMonNicknames(); + ewram1B000_alt.unk264++; + break; + case 6: + sub_806BCE8(); + ewram1B000_alt.unk264++; + break; + case 7: + if (sub_806B58C(ewram1B000_alt.unk266) == 1) + { + ewram1B000_alt.unk266 = 0; + ewram1B000_alt.unk264 = 0; + return TRUE; + } + else + { + ewram1B000_alt.unk266++; + } + break; + } + return FALSE; +} + +//------------------------------------------------------------------------------ +// Daycare Pokemon Storage Menu +//------------------------------------------------------------------------------ + +static void DaycareStorageMenuCallback_Store(u8); +static void DaycareStorageMenuCallback_Summary(u8); +static void DaycareStorageMenuCallback_Exit(u8); + +static const struct PartyMenuItem sDaycareStorageMenuItems[] = +{ + {OtherText_Store, DaycareStorageMenuCallback_Store}, + {OtherText_Summary, DaycareStorageMenuCallback_Summary}, + {gUnknownText_Exit, DaycareStorageMenuCallback_Exit}, +}; + +static const u8 gUnknown_08401808[] = {0, 1, 2}; +static const u8 gUnknown_0840180B[] = {1, 2}; + +static const struct PartyPopupMenu sDaycareStorageMenus[] = +{ + {ARRAY_COUNT(gUnknown_08401808), 9, gUnknown_08401808}, + {ARRAY_COUNT(gUnknown_0840180B), 9, gUnknown_0840180B}, +}; + +static void sub_8122D94(u8 taskId) +{ + if (!GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_IS_EGG)) + { + gTasks[taskId].data[4] = 0; + sub_806E750(0, sDaycareStorageMenus, sDaycareStorageMenuItems, 0); + } + else + { + gTasks[taskId].data[4] = 1; + sub_806E750(1, sDaycareStorageMenus, sDaycareStorageMenuItems, 0); + } +} + +void sub_8122E0C(u8 taskId) +{ + if (!gPaletteFade.active) + { + switch (sub_806BD80(taskId)) + { + case 1: + PlaySE(SE_SELECT); + gLastFieldPokeMenuOpened = sub_806CA38(taskId); + GetMonNickname(&gPlayerParty[gLastFieldPokeMenuOpened], gStringVar1); + sub_8122D94(taskId); + gTasks[taskId].func = Task_DaycareStorageMenu8122EAC; + break; + case 2: + PlaySE(SE_SELECT); + gLastFieldPokeMenuOpened = 0xFF; + gSpecialVar_0x8004 = 0xFF; + sub_8123138(taskId); + break; + } + } +} + +static void Task_DaycareStorageMenu8122EAC(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gMain.newAndRepeatedKeys & 0x40) + { + if (GetMenuCursorPos() != 0) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + } + return; + } + if (gMain.newAndRepeatedKeys & 0x80) + { + if (GetMenuCursorPos() != 3) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + } + return; + } + if (gMain.newKeys & A_BUTTON) + { + TaskFunc popupMenuFunc; + + PlaySE(SE_SELECT); + popupMenuFunc = PartyMenuGetPopupMenuFunc( + gTasks[taskId].data[4], + sDaycareStorageMenus, + sDaycareStorageMenuItems, + GetMenuCursorPos()); + popupMenuFunc(taskId); + return; + } + if (gMain.newKeys & B_BUTTON) + { + DaycareStorageMenuCallback_Exit(taskId); + return; + } + } +} + +static void DaycareStorageMenuCallback_Store(u8 taskId) +{ + gSpecialVar_0x8004 = gLastFieldPokeMenuOpened; + sub_8123138(taskId); +} + +static void sub_8122F90(void) +{ + while (1) + { + if (sub_806B124() == 1) + { + sub_806C994(ewram1B000.unk260, gUnknown_020384F0); + sub_806BF74(ewram1B000.unk260, 0); + GetMonNickname(&gPlayerParty[gUnknown_020384F0], gStringVar1); + gLastFieldPokeMenuOpened = gUnknown_020384F0; + sub_8122D94(ewram1B000.unk260); + SetMainCallback2(sub_806AEDC); + break; + } + if (sub_80F9344() == 1) + break; + } +} + +static void sub_8123004(void) +{ + gPaletteFade.bufferTransferDisabled = TRUE; + sub_806AF4C(6, 0xFF, Task_DaycareStorageMenu8122EAC, 5); + SetMainCallback2(sub_8122F90); +} + +static void sub_8123034(u8 taskId) +{ + if (!gPaletteFade.active) + { + u8 r4 = gSprites[gTasks[taskId].data[3] >> 8].data0; + + DestroyTask(taskId); + ewram1B000.unk262 = 1; + ShowPokemonSummaryScreen(gPlayerParty, r4, gPlayerPartyCount - 1, sub_8123004, 0); + } +} + +static void DaycareStorageMenuCallback_Summary(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = sub_8123034; +} + +static void DaycareStorageMenuCallback_Exit(u8 taskId) +{ + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(20, 10, 29, 19); + HandleDestroyMenuCursors(); + sub_806D538(15, 0); + gTasks[taskId].func = sub_8122E0C; +} + +void sub_8123138(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = sub_8123170; +} + +static void sub_8123170(u8 taskId) +{ + if (!gPaletteFade.active) + { + gFieldCallback = sub_81231AC; + SetMainCallback2(c2_exit_to_overworld_2_switch); + DestroyTask(taskId); + } +} + +// Do these last two functions really belong in here? + +static void sub_81231C4(u8); + +void sub_81231AC(void) +{ + pal_fill_black(); + CreateTask(sub_81231C4, 10); +} + +static void sub_81231C4(u8 taskId) +{ + if (sub_807D770() == TRUE) + { + DestroyTask(taskId); + ScriptContext2_Disable(); + EnableBothScriptContexts(); + } +} diff --git a/src/field/coins.c b/src/field/coins.c new file mode 100644 index 000000000..91a4b508d --- /dev/null +++ b/src/field/coins.c @@ -0,0 +1,84 @@ +#include "global.h" +#include "coins.h" +#include "menu.h" +#include "string_util.h" +#include "strings.h" + +#define MAX_COINS 9999 + +void UpdateCoinsWindow(s32 coins, u8 x, u8 y) +{ + PrintCoins(coins, 4, x + 2, y + 1); +} + +void ShowCoinsWindow(u32 coins, u8 x, u8 y) +{ + MenuDrawTextWindow(x, y, x + 9, y + 3); + UpdateCoinsWindow(coins, x, y); +} + +void HideCoinsWindow(u8 x, u8 y) +{ + MenuZeroFillWindowRect(x, y, x + 9, y + 3); +} + +void PrintCoins(s32 coins, u8 b, u8 x, u8 y) +{ + u8 string[16]; + u8 *ptr; + u8 r1; + u8 foo; + + ConvertIntToDecimalString(string, coins); + r1 = (b * 6 + 0x21 - 8 * (b + 2)); + x = x - r1 / 8; + foo = r1 % 8; + ptr = gStringVar1; + if (foo) + { + ptr[0] = EXT_CTRL_CODE_BEGIN; + ptr[1] = 0x11; + ptr[2] = 8 - (foo); + ptr += 3; + } + ptr[0] = EXT_CTRL_CODE_BEGIN; + ptr[1] = 0x11; + ptr[2] = (b - StringLength(string)) * 6; + ptr += 3; + StringCopy(ptr, string); + MenuPrint(gOtherText_Coins2, x, y); +} + +u16 GetCoins(void) +{ + return gSaveBlock1.coins; +} + +bool8 GiveCoins(u16 coins) +{ + u32 newCoins; + + if (GetCoins() >= MAX_COINS) + return FALSE; + newCoins = coins + gSaveBlock1.coins; + if (gSaveBlock1.coins > (u16)newCoins) + gSaveBlock1.coins = MAX_COINS; + else + { + gSaveBlock1.coins = newCoins; + if ((u16)newCoins > MAX_COINS) + gSaveBlock1.coins = MAX_COINS; + } + return TRUE; +} + +bool8 TakeCoins(u16 coins) +{ + if (GetCoins() >= coins) + { + gSaveBlock1.coins -= coins; + return TRUE; + } + else + return FALSE; +} diff --git a/src/field/coord_event_weather.c b/src/field/coord_event_weather.c new file mode 100644 index 000000000..9c5a1ca4d --- /dev/null +++ b/src/field/coord_event_weather.c @@ -0,0 +1,118 @@ +#include "global.h" +#include "coord_event_weather.h" +#include "field_weather.h" + +struct CoordEventWeather +{ + u8 weather; + void (*func)(void); +}; + +static void CoordEventWeather_Indoor(void); +static void CoordEventWeather_Sunny(void); +static void CoordEventWeather_Rain(void); +static void CoordEventWeather_Snowflakes(void); +static void CoordEventWeather_Thunderstorm(void); +static void CoordEventWeather_Fog(void); +static void CoordEventWeather_DiagonalFog(void); +static void CoordEventWeather_Snow(void); +static void CoordEventWeather_Sandstorm(void); +static void CoordEventWeather_Cloudy(void); +static void CoordEventWeather_Drought(void); +static void CoordEventWeather_UnderwaterFog(void); +static void CoordEventWeather_UnderwaterBubbles(void); + +static const struct CoordEventWeather sCoordEventWeatherFuncs[] = +{ + { 0x1, CoordEventWeather_Indoor }, + { 0x2, CoordEventWeather_Sunny }, + { 0x3, CoordEventWeather_Rain }, + { 0x4, CoordEventWeather_Snowflakes }, + { 0x5, CoordEventWeather_Thunderstorm }, + { 0x6, CoordEventWeather_Fog }, + { 0x7, CoordEventWeather_DiagonalFog }, + { 0x8, CoordEventWeather_Snow }, + { 0x9, CoordEventWeather_Sandstorm }, + { 0xa, CoordEventWeather_Cloudy }, + { 0xb, CoordEventWeather_Drought }, + { 0x14, CoordEventWeather_UnderwaterFog }, + { 0x15, CoordEventWeather_UnderwaterBubbles }, +}; + +static void CoordEventWeather_Indoor(void) +{ + SetWeather(1); +} + +static void CoordEventWeather_Sunny(void) +{ + SetWeather(2); +} + +static void CoordEventWeather_Rain(void) +{ + SetWeather(3); +} + +static void CoordEventWeather_Snowflakes(void) +{ + SetWeather(4); +} + +static void CoordEventWeather_Thunderstorm(void) +{ + SetWeather(5); +} + +static void CoordEventWeather_Fog(void) +{ + SetWeather(6); +} + +static void CoordEventWeather_DiagonalFog(void) +{ + SetWeather(9); +} + +static void CoordEventWeather_Snow(void) +{ + SetWeather(7); +} + +static void CoordEventWeather_Sandstorm(void) +{ + SetWeather(8); +} + +static void CoordEventWeather_Cloudy(void) +{ + SetWeather(11); +} + +static void CoordEventWeather_Drought(void) +{ + SetWeather(12); +} + +static void CoordEventWeather_UnderwaterFog(void) +{ + SetWeather(20); +} + +static void CoordEventWeather_UnderwaterBubbles(void) +{ + SetWeather(21); +} + +void DoCoordEventWeather(u8 n) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sCoordEventWeatherFuncs); i++) + { + if (sCoordEventWeatherFuncs[i].weather == n) + { + sCoordEventWeatherFuncs[i].func(); + return; + } + } +} diff --git a/src/field/daycare.c b/src/field/daycare.c new file mode 100644 index 000000000..591b5b188 --- /dev/null +++ b/src/field/daycare.c @@ -0,0 +1,1690 @@ +#include "global.h" +#include "daycare.h" +#include "pokemon.h" +#include "event_data.h" +#include "species.h" +#include "items.h" +#include "text.h" +#include "string_util.h" +#include "mail_data.h" +#include "name_string_util.h" +#include "pokemon_storage_system.h" +#include "rng.h" +#include "moves.h" +#include "trade.h" +#include "strings2.h" +#include "data/pokemon/egg_moves.h" +#include "party_menu.h" +#include "field_effect.h" +#include "main.h" +#include "menu.h" +#include "sound.h" +#include "songs.h" +#include "script.h" +#include "overworld.h" + +IWRAM_DATA u16 gUnknown_03000470[52]; +IWRAM_DATA u16 gUnknown_030004D8[4]; +IWRAM_DATA u16 gUnknown_030004E0[4]; +IWRAM_DATA u16 gUnknown_030004E8[12]; +IWRAM_DATA u16 gUnknown_03000500[4]; + +static void sub_80417F4(struct DayCareMail *); +static void sub_80420FC(struct Pokemon *, u16, struct DayCareData *); +static u8 daycare_relationship_score(struct DayCareData *); + +const u8 *const gUnknown_08209AC4[] = { + DaycareText_GetAlongVeryWell, + DaycareText_GetAlong, + DaycareText_DontLikeOther, + DaycareText_PlayOther +}; + +const u8 gUnknown_08209AD4[] = _("タマゴ"); + +u8 *GetMonNick(struct Pokemon *mon, u8 *dest) +{ + s8 nickname[POKEMON_NAME_LENGTH * 2]; + + GetMonData(mon, MON_DATA_NICKNAME, nickname); + return StringCopy10(dest, nickname); +} + +u8 *GetBoxMonNick(struct BoxPokemon *mon, u8 *dest) +{ + s8 nickname[POKEMON_NAME_LENGTH * 2]; + + GetBoxMonData(mon, MON_DATA_NICKNAME, nickname); + return StringCopy10(dest, nickname); +} + +u8 Daycare_CountPokemon(struct DayCareData *daycare_data) +{ + u8 i, count; + count = 0; + + for(i = 0;i <= 1;i++) + if(GetBoxMonData(&daycare_data->mons[i], MON_DATA_SPECIES) != 0) + count++; + + return count; +} + +void sub_8041324(struct BoxPokemon * box_pokemon, struct RecordMixingDayCareMail * daycareMailEtc) +{ + u8 i; + u8 specCount; + specCount = 0; + for (i=0; i<2; i++) + { + if (GetBoxMonData(&box_pokemon[i], MON_DATA_SPECIES) != SPECIES_NONE) + { + specCount ++; + if (GetBoxMonData(&box_pokemon[i], MON_DATA_HELD_ITEM) == ITEM_NONE) + { + daycareMailEtc->unk74[i] = 0; + } else + { + daycareMailEtc->unk74[i] = 1; + } + } else + { + daycareMailEtc->unk74[i] = 1; + } + } + daycareMailEtc->unk70 = specCount; +} + +static s8 Daycare_FindEmptySpot(struct BoxPokemon * daycare_data) +{ + u8 i; + + for(i = 0;i <= 1;i++) + if(GetBoxMonData(daycare_data + i, MON_DATA_SPECIES) == 0) + return i; + + return -1; +} + +static void Daycare_SendPokemon(struct Pokemon * mon, struct DayCareData * daycare_data) +{ + s8 empty_slot; + u8 mail; + u8 *names; + + empty_slot = Daycare_FindEmptySpot(daycare_data->mons); + if(MonHasMail(mon)) { + StringCopy((names = daycare_data->misc.mail[empty_slot].names), gSaveBlock2.playerName); + PadNameString(names, 0xFC); + names += 8; + GetMonNick(mon, names); + mail = GetMonData(mon, MON_DATA_MAIL); + daycare_data->misc.mail[empty_slot].message = gSaveBlock1.mail[mail]; + TakeMailFromMon(mon); + } + daycare_data->mons[empty_slot] = mon->box; + BoxMonRestorePP(&daycare_data->mons[empty_slot]); + daycare_data->misc.countersEtc.steps[empty_slot] = 0; + ZeroMonData(mon); + party_compaction(); + CalculatePlayerPartyCount(); +} + +void Daycare_SendPokemon_Special() +{ + Daycare_SendPokemon(gPlayerParty + gLastFieldPokeMenuOpened, &gSaveBlock1.daycareData); +} + +static void sub_80414C0(struct DayCareData * daycare_data) +{ + if((GetBoxMonData(&daycare_data->mons[1], MON_DATA_SPECIES) != 0) && GetBoxMonData(&daycare_data->mons[0], MON_DATA_SPECIES) == 0) + { + daycare_data->mons[0] = daycare_data->mons[1]; + ZeroBoxMonData(&daycare_data->mons[1]); + daycare_data->misc.mail[0] = daycare_data->misc.mail[1]; + daycare_data->misc.countersEtc.steps[0] = daycare_data->misc.countersEtc.steps[1]; + daycare_data->misc.countersEtc.steps[1] = 0; + sub_80417F4(&daycare_data->misc.mail[1]); + } +} + +u8 TryIncrementMonLevel(struct Pokemon *); +extern u16 gMoveToLearn; + +static void DayCare_LevelUpMoves(struct Pokemon * mon) +{ + s32 i; + u8 r6; + u16 temp; + + for (i = 0; i < MAX_LEVEL; i++) + { + if (TryIncrementMonLevel(mon)) + { + r6 = 1; + while ((temp = MonTryLearningNewMove(mon, r6)) != 0) + { + r6 = 0; + if (temp == 0xffff) + DeleteFirstMoveAndGiveMoveToMon(mon, gMoveToLearn); + } + } + else + break; + } + + CalculateMonStats(mon); +} + +static u16 sub_8041570(struct DayCareData * daycare_data, u8 slot) +{ + u16 species; + u32 experience; + struct Pokemon pokemon; + + GetBoxMonNick(&daycare_data->mons[slot], gStringVar1); + species = GetBoxMonData(&daycare_data->mons[slot], MON_DATA_SPECIES); + sub_803B4B4(&daycare_data->mons[slot], &pokemon); + if (GetMonData(&pokemon, MON_DATA_LEVEL) != MAX_LEVEL) + { + experience = GetMonData(&pokemon, MON_DATA_EXP) + daycare_data->misc.countersEtc.steps[slot]; + SetMonData(&pokemon, MON_DATA_EXP, (u8 *)&experience); + DayCare_LevelUpMoves(&pokemon); + } + gPlayerParty[PARTY_SIZE - 1] = pokemon; + if (daycare_data->misc.mail[slot].message.itemId) + { + GiveMailToMon2(&gPlayerParty[PARTY_SIZE - 1], &daycare_data->misc.mail[slot].message); + sub_80417F4(&daycare_data->misc.mail[slot]); + } + party_compaction(); + ZeroBoxMonData(&daycare_data->mons[slot]); + daycare_data->misc.countersEtc.steps[slot] = 0; + sub_80414C0(daycare_data); + CalculatePlayerPartyCount(); + return species; +} + +u16 sub_8041648() +{ + return sub_8041570(&gSaveBlock1.daycareData, gSpecialVar_0x8004); +} + +u8 Daycare_GetLevelAfterSteps(struct BoxPokemon * mon, u32 steps){ + struct BoxPokemon temp = *mon; + u32 new_exp = GetBoxMonData(mon, MON_DATA_EXP) + steps; + SetBoxMonData(&temp, MON_DATA_EXP, (u8 *) &new_exp); + return GetLevelFromBoxMonExp(&temp); +} + +static u8 sub_80416A0(struct DayCareData *daycareData, u8 slot) +{ + u8 levelBefore; + u8 levelAfter; + + levelBefore = GetLevelFromBoxMonExp(&daycareData->mons[slot]); + levelAfter = Daycare_GetLevelAfterSteps(&daycareData->mons[slot], daycareData->misc.countersEtc.steps[slot]); + return levelAfter - levelBefore; +} + +static u8 sub_80416E8(struct DayCareData *dayCareData, u8 slot) +{ + u8 levelDelta = sub_80416A0(dayCareData, slot); + GetBoxMonNick(&dayCareData->mons[slot], gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, levelDelta, STR_CONV_MODE_LEFT_ALIGN, 2); + return levelDelta; +} + +static u16 sub_8041728(struct DayCareData *dayCareData, u8 slot) +{ + u16 cost; + + u8 levelDelta = sub_80416A0(dayCareData, slot); + GetBoxMonNick(&dayCareData->mons[slot], gStringVar1); + cost = 100 + 100 * levelDelta; + ConvertIntToDecimalStringN(gStringVar2, cost, STR_CONV_MODE_LEFT_ALIGN, 5); + return cost; +} + +void sub_8041770(void) +{ + gSpecialVar_0x8005 = sub_8041728(&gSaveBlock1.daycareData, gSpecialVar_0x8004); +} + +void sub_8041790(u16 i) +{ + gSaveBlock1.daycareData.misc.countersEtc.steps[0] += i; + gSaveBlock1.daycareData.misc.countersEtc.steps[1] += i; +} + +u8 sub_80417B8(void) +{ + if (GetBoxMonData(&gSaveBlock1.daycareData.mons[gSpecialVar_0x8004], MON_DATA_SPECIES) != 0) + return sub_80416E8(&gSaveBlock1.daycareData, gSpecialVar_0x8004); + return 0; +} + +static void sub_80417F4(struct DayCareMail *mail) +{ + u8 zero; + u8 *names; + u8 *names2; + int i; + zero = 0; + for (i = 7, names = mail->names + 7; i >= 0; i --) + *names-- = zero; + names2 = mail->names + 8; + zero = 0; + names = mail->names + 18; + do *names-- = zero; while ((int)names >= (int)names2); + ClearMailStruct(&mail->message); +} + +void unref_sub_8041824(struct DayCareData *dayCareData) +{ + u8 slot; + for (slot = 0; slot < ARRAY_COUNT(dayCareData->mons); slot ++) + { + ZeroBoxMonData(&dayCareData->mons[slot]); + dayCareData->misc.countersEtc.steps[slot] = 0; + sub_80417F4(&dayCareData->misc.mail[slot]); + } + dayCareData->misc.countersEtc.personalityLo = 0; + dayCareData->misc.countersEtc.unk_11a = 0; +} + +u16 sub_8041870(u16 species) +{ + int i, j, k; + bool8 found; + for (i = 0; i < 5; i ++) + { + found = FALSE; + for (j = 1; j < NUM_SPECIES; j ++) + { + for (k = 0; k < 5; k ++) + { + if (gEvolutionTable[j].evolutions[k].targetSpecies == species) + { + species = j; + found = TRUE; + break; + } + } + if (found) + break; + } + if (j == 412) + break; + } + return species; +} + +static void sub_80418F0(struct DayCareData *dayCareData) +{ + dayCareData->misc.countersEtc.personalityLo = (Random() % 0xfffe) + 1; + FlagSet(0x86); +} + +static void sub_804191C(struct DayCareData *dayCareData) +{ + dayCareData->misc.countersEtc.personalityLo = Random() | 0x8000; + FlagSet(0x86); +} + +void sub_8041940(void) +{ + sub_80418F0(&gSaveBlock1.daycareData); +} + +void sub_8041950(void) +{ + sub_804191C(&gSaveBlock1.daycareData); +} + +static void sub_8041960(u8 *data, u8 idx) +{ + int i, j; + u8 temp[6]; + data[idx] = 0xff; + for (i = 0; i < 6; i ++) + temp[i] = data[i]; + j = 0; + for (i = 0; i < 6; i ++) + if (temp[i] != 0xff) + data[j++] = temp[i]; +} + +static void InheritIVs(struct Pokemon *egg, struct DayCareData *dayCareData) +{ + u8 i; + u8 selectedIvs[3]; + u8 allIvs[6]; + u8 whichParent[3]; + u8 iv; + for (i = 0; i < 6; i ++) + allIvs[i] = i; + for (i = 0; i < 3; i ++) + { + selectedIvs[i] = allIvs[Random() % (6 - i)]; + sub_8041960(allIvs, selectedIvs[i]); + } + for (i = 0; i < 3; i ++) + whichParent[i] = Random() % 2; + for (i = 0; i < 3; i ++) + { + switch (selectedIvs[i]) + { + case 0: + iv = GetBoxMonData(&dayCareData->mons[whichParent[i]], MON_DATA_HP_IV); + SetMonData(egg, MON_DATA_HP_IV, &iv); + break; + case 1: + iv = GetBoxMonData(&dayCareData->mons[whichParent[i]], MON_DATA_ATK_IV); + SetMonData(egg, MON_DATA_ATK_IV, &iv); + break; + case 2: + iv = GetBoxMonData(&dayCareData->mons[whichParent[i]], MON_DATA_DEF_IV); + SetMonData(egg, MON_DATA_DEF_IV, &iv); + break; + case 3: + iv = GetBoxMonData(&dayCareData->mons[whichParent[i]], MON_DATA_SPD_IV); + SetMonData(egg, MON_DATA_SPD_IV, &iv); + break; + case 4: + iv = GetBoxMonData(&dayCareData->mons[whichParent[i]], MON_DATA_SPATK_IV); + SetMonData(egg, MON_DATA_SPATK_IV, &iv); + break; + case 5: + iv = GetBoxMonData(&dayCareData->mons[whichParent[i]], MON_DATA_SPDEF_IV); + SetMonData(egg, MON_DATA_SPDEF_IV, &iv); + break; + } + } +} + +#ifdef NONMATCHING +static +#endif +u8 pokemon_get_eggmoves(struct Pokemon *pokemon, u16 *eggMoves) +{ + u16 eggMoveIdx; + u16 numMovesFound; + u16 species; + u16 i; + + numMovesFound = 0; + eggMoveIdx = 0; + species = GetMonData(pokemon, MON_DATA_SPECIES); + for (i = 0; i < ARRAY_COUNT(gEggMoves) - 1; i ++) + { + if (gEggMoves[i] == species + EGG_MOVES_SPECIES_OFFSET) + { + eggMoveIdx = i + 1; + break; + } + } + for (i = 0; i < 10; i ++) + { + if (gEggMoves[eggMoveIdx + i] > EGG_MOVES_SPECIES_OFFSET) + { + break; + } + eggMoves[i] = gEggMoves[eggMoveIdx + i]; + numMovesFound++; + } + return numMovesFound; +} + +#ifdef NONMATCHING + +void daycare_build_child_moveset(struct Pokemon *egg, struct BoxPokemon *dad, struct BoxPokemon *mom) +{ + u16 numSharedParentMoves; + u8 numLevelUpMoves; + u8 numEggMoves; + u16 i, j; + + numSharedParentMoves = 0; + for (i = 0; i < 4; i ++) + { + gUnknown_03000500[i] = 0; + gUnknown_030004D8[i] = 0; + gUnknown_030004E0[i] = 0; + } + for (i = 0; i < 10; i ++) + gUnknown_030004E8[i] = 0; + for (i = 0; i < 50; i ++) + gUnknown_03000470[i] = 0; + + numLevelUpMoves = GetLevelUpMovesBySpecies(GetMonData(egg, MON_DATA_SPECIES), gUnknown_03000470); + for (i = 0; i < 4; i ++) + { + gUnknown_030004D8[i] = GetBoxMonData(dad, MON_DATA_MOVE1 + i); + gUnknown_03000500[i] = GetBoxMonData(mom, MON_DATA_MOVE1 + i); + } + numEggMoves = pokemon_get_eggmoves(egg, gUnknown_030004E8); + + for (i = 0; i < 4; i ++) + { + if (gUnknown_030004D8[i] != MOVE_NONE) + { + for (j = 0; j < numEggMoves; j ++) + { + if (gUnknown_030004D8[i] == gUnknown_030004E8[j]) + { + if (GiveMoveToMon(egg, gUnknown_030004D8[i]) == 0xffff) + DeleteFirstMoveAndGiveMoveToMon(egg, gUnknown_030004D8[i]); + break; + } + } + } + else + break; + } + for (i = 0; i < 4; i ++) + { + if (gUnknown_030004D8[i] != MOVE_NONE) + { + for (j = 0; j < 50 + 8; j ++) + { + if (gUnknown_030004D8[i] == ItemIdToBattleMoveId(ITEM_TM01 + j) && CanMonLearnTMHM(egg, j)) + { + if (GiveMoveToMon(egg, gUnknown_030004D8[i]) == 0xffff) + DeleteFirstMoveAndGiveMoveToMon(egg, gUnknown_030004D8[i]); + } + } + } + } + for (i = 0; i < 4; i ++) + { + if (gUnknown_030004D8[i] == MOVE_NONE) + break; + for (j = 0; j < 4; j ++) + { + if (gUnknown_030004D8[i] == gUnknown_03000500[j] && gUnknown_030004D8[i] != MOVE_NONE) + gUnknown_030004E0[numSharedParentMoves++] = gUnknown_030004D8[i]; + } + } + for (i = 0; i < 4; i ++) + { + if (gUnknown_030004E0[i] == MOVE_NONE) + break; + for (j = 0; j < numLevelUpMoves; j ++) + { + if (gUnknown_03000470[j] != MOVE_NONE && gUnknown_030004E0[i] == gUnknown_03000470[j]) + { + if (GiveMoveToMon(egg, gUnknown_030004E0[i]) == 0xffff) + DeleteFirstMoveAndGiveMoveToMon(egg, gUnknown_030004E0[i]); + break; + } + } + } +} +#else +__attribute__((naked)) +void daycare_build_child_moveset(struct Pokemon *egg, struct BoxPokemon *dad, struct BoxPokemon *mom) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tsub sp, 0xC\n" + "\tadds r7, r0, 0\n" + "\tmov r10, r1\n" + "\tmov r9, r2\n" + "\tmovs r0, 0\n" + "\tstr r0, [sp]\n" + "\tmovs r6, 0\n" + "\tldr r5, _08041CC8 @ =gUnknown_03000500\n" + "\tmovs r2, 0\n" + "\tldr r4, _08041CCC @ =gUnknown_030004D8\n" + "\tldr r3, _08041CD0 @ =gUnknown_030004E0\n" + "_08041BE4:\n" + "\tlsls r1, r6, 1\n" + "\tadds r0, r1, r5\n" + "\tstrh r2, [r0]\n" + "\tadds r0, r1, r4\n" + "\tstrh r2, [r0]\n" + "\tadds r1, r3\n" + "\tstrh r2, [r1]\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r6, r0, 16\n" + "\tcmp r6, 0x3\n" + "\tbls _08041BE4\n" + "\tmovs r6, 0\n" + "\tldr r2, _08041CD4 @ =gUnknown_030004E8\n" + "\tmovs r1, 0\n" + "_08041C02:\n" + "\tlsls r0, r6, 1\n" + "\tadds r0, r2\n" + "\tstrh r1, [r0]\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r6, r0, 16\n" + "\tcmp r6, 0x9\n" + "\tbls _08041C02\n" + "\tmovs r6, 0\n" + "\tldr r2, _08041CD8 @ =gUnknown_03000470\n" + "\tmovs r1, 0\n" + "_08041C18:\n" + "\tlsls r0, r6, 1\n" + "\tadds r0, r2\n" + "\tstrh r1, [r0]\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r6, r0, 16\n" + "\tcmp r6, 0x31\n" + "\tbls _08041C18\n" + "\tadds r0, r7, 0\n" + "\tmovs r1, 0xB\n" + "\tbl GetMonData\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tldr r1, _08041CD8 @ =gUnknown_03000470\n" + "\tbl GetLevelUpMovesBySpecies\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tstr r0, [sp, 0x4]\n" + "\tmovs r6, 0\n" + "\tldr r1, _08041CCC @ =gUnknown_030004D8\n" + "\tmov r8, r1\n" + "_08041C46:\n" + "\tadds r5, r6, 0\n" + "\tadds r5, 0xD\n" + "\tmov r0, r10\n" + "\tadds r1, r5, 0\n" + "\tbl GetBoxMonData\n" + "\tlsls r4, r6, 1\n" + "\tmov r2, r8\n" + "\tadds r1, r4, r2\n" + "\tstrh r0, [r1]\n" + "\tmov r0, r9\n" + "\tadds r1, r5, 0\n" + "\tbl GetBoxMonData\n" + "\tldr r1, _08041CC8 @ =gUnknown_03000500\n" + "\tadds r4, r1\n" + "\tstrh r0, [r4]\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r6, r0, 16\n" + "\tcmp r6, 0x3\n" + "\tbls _08041C46\n" + "\tldr r1, _08041CD4 @ =gUnknown_030004E8\n" + "\tadds r0, r7, 0\n" + "\tbl pokemon_get_eggmoves\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tmov r8, r0\n" + "\tmovs r6, 0\n" + "_08041C82:\n" + "\tldr r0, _08041CCC @ =gUnknown_030004D8\n" + "\tlsls r1, r6, 1\n" + "\tadds r2, r1, r0\n" + "\tldrh r1, [r2]\n" + "\tmov r9, r0\n" + "\tcmp r1, 0\n" + "\tbeq _08041CF8\n" + "\tmovs r5, 0\n" + "\tcmp r5, r8\n" + "\tbcs _08041CEA\n" + "\tadds r4, r2, 0\n" + "\tldr r2, _08041CDC @ =0x0000ffff\n" + "_08041C9A:\n" + "\tldr r0, _08041CD4 @ =gUnknown_030004E8\n" + "\tlsls r1, r5, 1\n" + "\tadds r1, r0\n" + "\tldrh r0, [r4]\n" + "\tldrh r1, [r1]\n" + "\tcmp r0, r1\n" + "\tbne _08041CE0\n" + "\tadds r1, r0, 0\n" + "\tadds r0, r7, 0\n" + "\tstr r2, [sp, 0x8]\n" + "\tbl GiveMoveToMon\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tldr r2, [sp, 0x8]\n" + "\tcmp r0, r2\n" + "\tbne _08041CEA\n" + "\tldrh r1, [r4]\n" + "\tadds r0, r7, 0\n" + "\tbl DeleteFirstMoveAndGiveMoveToMon\n" + "\tb _08041CEA\n" + "\t.align 2, 0\n" + "_08041CC8: .4byte gUnknown_03000500\n" + "_08041CCC: .4byte gUnknown_030004D8\n" + "_08041CD0: .4byte gUnknown_030004E0\n" + "_08041CD4: .4byte gUnknown_030004E8\n" + "_08041CD8: .4byte gUnknown_03000470\n" + "_08041CDC: .4byte 0x0000ffff\n" + "_08041CE0:\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r5, r0, 16\n" + "\tcmp r5, r8\n" + "\tbcc _08041C9A\n" + "_08041CEA:\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r6, r0, 16\n" + "\tldr r3, _08041E14 @ =gUnknown_030004D8\n" + "\tmov r9, r3\n" + "\tcmp r6, 0x3\n" + "\tbls _08041C82\n" + "_08041CF8:\n" + "\tmovs r6, 0\n" + "_08041CFA:\n" + "\tlsls r0, r6, 1\n" + "\tmov r2, r9\n" + "\tadds r1, r0, r2\n" + "\tldrh r1, [r1]\n" + "\tadds r2, r0, 0\n" + "\tadds r6, 0x1\n" + "\tmov r8, r6\n" + "\tcmp r1, 0\n" + "\tbeq _08041D5C\n" + "\tmovs r5, 0\n" + "\tldr r0, _08041E14 @ =gUnknown_030004D8\n" + "\tadds r4, r2, r0\n" + "\tldr r6, _08041E18 @ =0x0000ffff\n" + "\tmov r9, r0\n" + "_08041D16:\n" + "\tldr r3, _08041E1C @ =0x00000121\n" + "\tadds r0, r5, r3\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tbl ItemIdToBattleMoveId\n" + "\tldrh r1, [r4]\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tcmp r1, r0\n" + "\tbne _08041D52\n" + "\tlsls r1, r5, 24\n" + "\tlsrs r1, 24\n" + "\tadds r0, r7, 0\n" + "\tbl CanMonLearnTMHM\n" + "\tcmp r0, 0\n" + "\tbeq _08041D52\n" + "\tldrh r1, [r4]\n" + "\tadds r0, r7, 0\n" + "\tbl GiveMoveToMon\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tcmp r0, r6\n" + "\tbne _08041D52\n" + "\tldrh r1, [r4]\n" + "\tadds r0, r7, 0\n" + "\tbl DeleteFirstMoveAndGiveMoveToMon\n" + "_08041D52:\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r5, r0, 16\n" + "\tcmp r5, 0x39\n" + "\tbls _08041D16\n" + "_08041D5C:\n" + "\tmov r1, r8\n" + "\tlsls r0, r1, 16\n" + "\tlsrs r6, r0, 16\n" + "\tcmp r6, 0x3\n" + "\tbls _08041CFA\n" + "\tmovs r6, 0\n" + "\tmov r2, r9\n" + "\tldrh r0, [r2]\n" + "\tldr r3, _08041E20 @ =gUnknown_030004E0\n" + "\tmov r10, r3\n" + "\tcmp r0, 0\n" + "\tbeq _08041DC6\n" + "\tmov r4, r9\n" + "\tldr r0, _08041E24 @ =gUnknown_03000500\n" + "\tmov r9, r0\n" + "\tmov r12, r10\n" + "_08041D7C:\n" + "\tmovs r5, 0\n" + "\tlsls r2, r6, 1\n" + "\tadds r6, 0x1\n" + "\tmov r8, r6\n" + "\tadds r3, r2, r4\n" + "_08041D86:\n" + "\tlsls r0, r5, 1\n" + "\tadd r0, r9\n" + "\tldrh r2, [r3]\n" + "\tadds r1, r2, 0\n" + "\tldrh r0, [r0]\n" + "\tcmp r1, r0\n" + "\tbne _08041DA8\n" + "\tcmp r1, 0\n" + "\tbeq _08041DA8\n" + "\tldr r1, [sp]\n" + "\tadds r0, r1, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tstr r0, [sp]\n" + "\tlsls r1, 1\n" + "\tadd r1, r12\n" + "\tstrh r2, [r1]\n" + "_08041DA8:\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r5, r0, 16\n" + "\tcmp r5, 0x3\n" + "\tbls _08041D86\n" + "\tmov r1, r8\n" + "\tlsls r0, r1, 16\n" + "\tlsrs r6, r0, 16\n" + "\tcmp r6, 0x3\n" + "\tbhi _08041DC6\n" + "\tlsls r0, r6, 1\n" + "\tadds r0, r4\n" + "\tldrh r0, [r0]\n" + "\tcmp r0, 0\n" + "\tbne _08041D7C\n" + "_08041DC6:\n" + "\tmovs r6, 0\n" + "\tmov r2, r10\n" + "\tldrh r0, [r2]\n" + "\tcmp r0, 0\n" + "\tbeq _08041E50\n" + "_08041DD0:\n" + "\tmovs r5, 0\n" + "\tadds r3, r6, 0x1\n" + "\tmov r8, r3\n" + "\tldr r0, [sp, 0x4]\n" + "\tcmp r5, r0\n" + "\tbcs _08041E38\n" + "\tldr r2, _08041E18 @ =0x0000ffff\n" + "_08041DDE:\n" + "\tldr r1, _08041E28 @ =gUnknown_03000470\n" + "\tlsls r0, r5, 1\n" + "\tadds r0, r1\n" + "\tldrh r1, [r0]\n" + "\tcmp r1, 0\n" + "\tbeq _08041E2C\n" + "\tlsls r0, r6, 1\n" + "\tmov r3, r10\n" + "\tadds r4, r0, r3\n" + "\tldrh r0, [r4]\n" + "\tcmp r0, r1\n" + "\tbne _08041E2C\n" + "\tadds r1, r0, 0\n" + "\tadds r0, r7, 0\n" + "\tstr r2, [sp, 0x8]\n" + "\tbl GiveMoveToMon\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tldr r2, [sp, 0x8]\n" + "\tcmp r0, r2\n" + "\tbne _08041E38\n" + "\tldrh r1, [r4]\n" + "\tadds r0, r7, 0\n" + "\tbl DeleteFirstMoveAndGiveMoveToMon\n" + "\tb _08041E38\n" + "\t.align 2, 0\n" + "_08041E14: .4byte gUnknown_030004D8\n" + "_08041E18: .4byte 0x0000ffff\n" + "_08041E1C: .4byte 0x00000121\n" + "_08041E20: .4byte gUnknown_030004E0\n" + "_08041E24: .4byte gUnknown_03000500\n" + "_08041E28: .4byte gUnknown_03000470\n" + "_08041E2C:\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r5, r0, 16\n" + "\tldr r0, [sp, 0x4]\n" + "\tcmp r5, r0\n" + "\tbcc _08041DDE\n" + "_08041E38:\n" + "\tmov r1, r8\n" + "\tlsls r0, r1, 16\n" + "\tlsrs r6, r0, 16\n" + "\tcmp r6, 0x3\n" + "\tbhi _08041E50\n" + "\tldr r0, _08041E60 @ =gUnknown_030004E0\n" + "\tlsls r1, r6, 1\n" + "\tadds r1, r0\n" + "\tldrh r1, [r1]\n" + "\tmov r10, r0\n" + "\tcmp r1, 0\n" + "\tbne _08041DD0\n" + "_08041E50:\n" + "\tadd sp, 0xC\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_08041E60: .4byte gUnknown_030004E0"); +} +#endif + +static void RemoveEggFromDayCare(struct DayCareData *dayCareData) +{ + dayCareData->misc.countersEtc.personalityLo = 0; + dayCareData->misc.countersEtc.unk_11a = 0; +} + +void sub_8041E7C(void) +{ + RemoveEggFromDayCare(&gSaveBlock1.daycareData); +} + +static void incense_effects(u16 *species, struct DayCareData *dayCareData) +{ + u16 momItem, dadItem; + if (*species == SPECIES_WYNAUT || *species == SPECIES_AZURILL) + { + momItem = GetBoxMonData(&dayCareData->mons[0], MON_DATA_HELD_ITEM); + dadItem = GetBoxMonData(&dayCareData->mons[1], MON_DATA_HELD_ITEM); + if (*species == SPECIES_WYNAUT && momItem != ITEM_LAX_INCENSE && dadItem != ITEM_LAX_INCENSE) + { + *species = SPECIES_WOBBUFFET; + } + if (*species == SPECIES_AZURILL && momItem != ITEM_SEA_INCENSE && dadItem != ITEM_SEA_INCENSE) + { + *species = SPECIES_MARILL; + } + } +} + +static u16 sub_8041EEC(struct DayCareData *dayCareData, u8 *a1) // inherit_species_from_mom +{ + u16 i; + u16 species[2]; + u16 eggSpecies; + u8 buffer; + for (i=0; i<2; i++) + { + species[i] = GetBoxMonData(&dayCareData->mons[i], MON_DATA_SPECIES); + if (species[i] == SPECIES_DITTO) + { + a1[0] = i ^ 1; + a1[1] = i; + } + else if (GetBoxMonGender(&dayCareData->mons[i]) == MON_FEMALE) + { + a1[0] = i; + a1[1] = i ^ 1; + } + } + eggSpecies = sub_8041870(species[a1[0]]); + if (eggSpecies == SPECIES_NIDORAN_F && dayCareData->misc.countersEtc.personalityLo & 0x8000) + { + eggSpecies = SPECIES_NIDORAN_M; + } + if (eggSpecies == SPECIES_ILLUMISE && dayCareData->misc.countersEtc.personalityLo & 0x8000) + { + eggSpecies = SPECIES_VOLBEAT; + } + if (species[a1[1]] == SPECIES_DITTO && GetBoxMonGender(&dayCareData->mons[a1[0]]) != MON_FEMALE) + { + buffer = a1[1]; + a1[1] = a1[0]; + a1[0] = buffer; + } + return eggSpecies; +} + +static void sub_8041FC4(struct DayCareData *dayCareData) // give_egg +{ + struct Pokemon egg; + u16 species; + u8 parents[2]; + u8 isEgg; + species = sub_8041EEC(dayCareData, parents); + incense_effects(&species, dayCareData); + sub_80420FC(&egg, species, dayCareData); + InheritIVs(&egg, dayCareData); + daycare_build_child_moveset(&egg, &dayCareData->mons[parents[1]], &dayCareData->mons[parents[0]]); + isEgg = TRUE; + SetMonData(&egg, MON_DATA_IS_EGG, &isEgg); + gPlayerParty[5] = egg; + party_compaction(); + CalculatePlayerPartyCount(); + RemoveEggFromDayCare(dayCareData); +} + + +void sub_8042044(struct Pokemon *mon, u16 species, u8 overwriteMetLocation) // scr_create_egg +{ + u8 metLevel; + u16 ball; + u8 language; + u8 metLocation; + u8 isEgg; + CreateMon(mon, species, 5, 0x20, FALSE, 0, FALSE, 0); + metLevel = 0; + ball = ITEM_POKE_BALL; + language = LANGUAGE_JAPANESE; + SetMonData(mon, MON_DATA_POKEBALL, (u8 *)&ball); + SetMonData(mon, MON_DATA_NICKNAME, gUnknown_08209AD4); + SetMonData(mon, MON_DATA_FRIENDSHIP, &gBaseStats[species].eggCycles); + SetMonData(mon, MON_DATA_MET_LEVEL, &metLevel); + SetMonData(mon, MON_DATA_LANGUAGE, &language); + if (overwriteMetLocation) + { + metLocation = 0xfd; + SetMonData(mon, MON_DATA_MET_LOCATION, &metLocation); + } + isEgg = TRUE; + SetMonData(mon, MON_DATA_IS_EGG, &isEgg); +} + +static void sub_80420FC(struct Pokemon *mon, u16 species, struct DayCareData *dayCareData) +{ + u32 personality; + u16 ball; + u8 metLevel; + u8 language; + personality = dayCareData->misc.countersEtc.personalityLo | (Random() << 16); + CreateMon(mon, species, 5, 0x20, TRUE, personality, FALSE, 0); + metLevel = 0; + ball = ITEM_POKE_BALL; + language = LANGUAGE_JAPANESE; + SetMonData(mon, MON_DATA_POKEBALL, (u8 *)&ball); + SetMonData(mon, MON_DATA_NICKNAME, gUnknown_08209AD4); + SetMonData(mon, MON_DATA_FRIENDSHIP, &gBaseStats[species].eggCycles); + SetMonData(mon, MON_DATA_MET_LEVEL, &metLevel); + SetMonData(mon, MON_DATA_LANGUAGE, &language); +} + +void sp0B8_daycare(void) +{ + sub_8041FC4(&gSaveBlock1.daycareData); +} + +#ifdef NONMATCHING +static bool8 sub_80421B0(struct DayCareData *dayCareData) +{ + struct BoxPokemon *parent; + u32 i; + int v0; + int steps; + v0 = 0; + for (i=0, parent=&dayCareData->mons[0]; i<2; parent++, i++) + { + if (GetBoxMonData(parent, MON_DATA_SANITY_BIT2, v0)) + { + dayCareData->misc.countersEtc.steps[i]++; + v0++; + } + } + if (dayCareData->misc.countersEtc.personalityLo == 0 && v0 == 2 && dayCareData->misc.extra.misc[4] == 0xff && daycare_relationship_score(dayCareData) > (u32)((u32)(Random() * 100) / 0xffff)) + { + sub_8041940(); + } + if ((++dayCareData->misc.countersEtc.unk_11a) == 0xff) + { + for (i=0; i<gPlayerPartyCount; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + { + steps = GetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP); + if (steps == 0) + { + gSpecialVar_0x8004 = i; + return TRUE; + } + steps--; + SetMonData(&gPlayerParty[i], MON_DATA_FRIENDSHIP, (u8 *)&steps); + } + } + } + return FALSE; +} +#else +__attribute__((naked)) +static bool8 sub_80421B0(struct DayCareData *dayCareData) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tsub sp, 0x8\n" + "\tadds r7, r0, 0\n" + "\tmovs r2, 0\n" + "\tmovs r6, 0\n" + "\tadds r5, r7, 0\n" + "_080421BC:\n" + "\tlsls r4, r6, 2\n" + "\tadds r0, r5, 0\n" + "\tmovs r1, 0x5\n" + "\tstr r2, [sp, 0x4]\n" + "\tbl GetBoxMonData\n" + "\tldr r2, [sp, 0x4]\n" + "\tcmp r0, 0\n" + "\tbeq _080421DE\n" + "\tmovs r0, 0x88\n" + "\tlsls r0, 1\n" + "\tadds r1, r7, r0\n" + "\tadds r1, r4\n" + "\tldr r0, [r1]\n" + "\tadds r0, 0x1\n" + "\tstr r0, [r1]\n" + "\tadds r2, 0x1\n" + "_080421DE:\n" + "\tadds r5, 0x50\n" + "\tadds r6, 0x1\n" + "\tcmp r6, 0x1\n" + "\tbls _080421BC\n" + "\tmovs r1, 0x8C\n" + "\tlsls r1, 1\n" + "\tadds r0, r7, r1\n" + "\tldrh r0, [r0]\n" + "\tcmp r0, 0\n" + "\tbne _08042226\n" + "\tcmp r2, 0x2\n" + "\tbne _08042226\n" + "\tsubs r1, 0x4\n" + "\tadds r0, r7, r1\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0xFF\n" + "\tbne _08042226\n" + "\tadds r0, r7, 0\n" + "\tbl daycare_relationship_score\n" + "\tadds r4, r0, 0\n" + "\tlsls r4, 24\n" + "\tlsrs r4, 24\n" + "\tbl Random\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmovs r1, 0x64\n" + "\tmuls r0, r1\n" + "\tldr r1, _08042240 @ =0x0000ffff\n" + "\tbl __udivsi3\n" + "\tcmp r4, r0\n" + "\tbls _08042226\n" + "\tbl sub_8041940\n" + "_08042226:\n" + "\tmovs r0, 0x8D\n" + "\tlsls r0, 1\n" + "\tadds r1, r7, r0\n" + "\tldrb r0, [r1]\n" + "\tadds r0, 0x1\n" + "\tstrb r0, [r1]\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tcmp r0, 0xFF\n" + "\tbne _08042290\n" + "\tmovs r6, 0\n" + "\tb _08042288\n" + "\t.align 2, 0\n" + "_08042240: .4byte 0x0000ffff\n" + "_08042244:\n" + "\tmovs r0, 0x64\n" + "\tadds r1, r6, 0\n" + "\tmuls r1, r0\n" + "\tldr r0, _08042270 @ =gPlayerParty\n" + "\tadds r4, r1, r0\n" + "\tadds r0, r4, 0\n" + "\tmovs r1, 0x2D\n" + "\tbl GetMonData\n" + "\tcmp r0, 0\n" + "\tbeq _08042286\n" + "\tadds r0, r4, 0\n" + "\tmovs r1, 0x20\n" + "\tbl GetMonData\n" + "\tstr r0, [sp]\n" + "\tcmp r0, 0\n" + "\tbne _08042278\n" + "\tldr r0, _08042274 @ =gSpecialVar_0x8004\n" + "\tstrh r6, [r0]\n" + "\tmovs r0, 0x1\n" + "\tb _08042292\n" + "\t.align 2, 0\n" + "_08042270: .4byte gPlayerParty\n" + "_08042274: .4byte gSpecialVar_0x8004\n" + "_08042278:\n" + "\tsubs r0, 0x1\n" + "\tstr r0, [sp]\n" + "\tadds r0, r4, 0\n" + "\tmovs r1, 0x20\n" + "\tmov r2, sp\n" + "\tbl SetMonData\n" + "_08042286:\n" + "\tadds r6, 0x1\n" + "_08042288:\n" + "\tldr r0, _0804229C @ =gPlayerPartyCount\n" + "\tldrb r0, [r0]\n" + "\tcmp r6, r0\n" + "\tbcc _08042244\n" + "_08042290:\n" + "\tmovs r0, 0\n" + "_08042292:\n" + "\tadd sp, 0x8\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1\n" + "\t.align 2, 0\n" + "_0804229C: .4byte gPlayerPartyCount"); +} +#endif + +bool8 sub_80422A0(void) +{ + return sub_80421B0(&gSaveBlock1.daycareData); +} + +static bool8 sub_80422B4(struct DayCareData *dayCareData) +{ + return (u32)((-dayCareData->misc.countersEtc.personalityLo) | dayCareData->misc.countersEtc.personalityLo) >> 31; +} + +static void sub_80422C4(struct DayCareData *dayCareData) +{ + u8 language; + if (GetBoxMonData(&dayCareData->mons[0], MON_DATA_SPECIES) != 0) + { + GetBoxMonNick(&dayCareData->mons[0], gStringVar1); + language = GetBoxMonData(&dayCareData->mons[0], MON_DATA_LANGUAGE); + GetBoxMonData(&dayCareData->mons[0], MON_DATA_OT_NAME, gStringVar3); + ConvertInternationalString(gStringVar3, language); + } + if (GetBoxMonData(&dayCareData->mons[1], MON_DATA_SPECIES) != 0) + { + GetBoxMonNick(&dayCareData->mons[1], gStringVar2); + } +} + +u16 sub_8042328(void) +{ + GetBoxMonNick(&gPlayerParty[gLastFieldPokeMenuOpened].box, gStringVar1); + return GetBoxMonData(&gPlayerParty[gLastFieldPokeMenuOpened].box, MON_DATA_SPECIES); +} + +void sp0B5_daycare(void) +{ + sub_80422C4(&gSaveBlock1.daycareData); +} + +u8 sp0B6_daycare(void) +{ + u8 monCount; + if (sub_80422B4(&gSaveBlock1.daycareData)) + { + return 1; + } + monCount = Daycare_CountPokemon(&gSaveBlock1.daycareData); + if (monCount != 0) + { + return monCount + 1; + } + return 0; +} + +#ifdef NONMATCHING +static +#endif +bool8 sub_80423A8(u16 *a, u16 *b) +{ + int i, j; + u16 *v0, *v1, v2; + for (i=0, v0=a; i<2; v0++, i++) + { + for (j=0, v2=*v0, v1=b; j<2; v1++, j++) + { + if (v2 == *v1) + { + return TRUE; + } + } + } + return FALSE; +} + +#ifdef NONMATCHING +static u8 daycare_relationship_score(struct DayCareData *dayCareData) +{ + u16 species[2]; + u32 otIds[2]; + u32 genders[2]; + u16 eggGroups[2][2]; + int i; + u16 *spc; + u32 *ids; + u32 *gnd; + u16 *egg1; + u16 *egg2; + struct BoxPokemon *parent; + for (i=0, parent=&dayCareData->mons[0], spc=species, ids=otIds, gnd=genders, egg1=&eggGroups[0][0], egg2=&eggGroups[0][1]; i<2; spc++, egg1+=2, egg2+=2, parent++, i++) + { + *spc = GetBoxMonData(parent, MON_DATA_SPECIES); + *ids++ = GetBoxMonData(parent, MON_DATA_OT_ID); + *gnd++ = GetGenderFromSpeciesAndPersonality(*spc, GetBoxMonData(parent, MON_DATA_PERSONALITY)); + *egg1 = gBaseStats[*spc].eggGroup1; + *egg2 = gBaseStats[*spc].eggGroup2; + } + if (eggGroups[0][0] == 0xf) + { + return 0; + } + if (eggGroups[1][0] == 0xf) + { + return 0; + } + if (eggGroups[0][0] == 0xd && eggGroups[1][0] == 0xd) + { + return 0; + } + else if (eggGroups[0][0] == 0xd || eggGroups[1][0] == 0xd) + { + if (otIds[0] == otIds[1]) + { + return 20; + } + return 50; + } + if (genders[0] == genders[1] || genders[0] == MON_GENDERLESS || genders[1] == MON_GENDERLESS) + { + return 0; + } + if (!sub_80423A8(eggGroups[0], eggGroups[1])) + { + return 0; + } + if (species[0] == species[1]) + { + if (otIds[0] == otIds[1]) + { + return 50; + } + return 70; + } + else + { + if (otIds[0] != otIds[1]) + { + return 50; + } + return 20; + } +} +#else +__attribute__((naked)) +static u8 daycare_relationship_score(struct DayCareData *dayCareData) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tsub sp, 0x2C\n" + "\tmovs r1, 0\n" + "\tmov r8, r1\n" + "\tmov r2, sp\n" + "\tadds r2, 0x8\n" + "\tstr r2, [sp, 0x1C]\n" + "\tadd r1, sp, 0xC\n" + "\tmov r10, r1\n" + "\tadds r2, 0xC\n" + "\tstr r2, [sp, 0x20]\n" + "\tmov r1, sp\n" + "\tadds r1, 0x2\n" + "\tldr r2, _08042488 @ =gBaseStats\n" + "\tmov r9, r2\n" + "\tldr r5, [sp, 0x1C]\n" + "\tadds r7, r1, 0\n" + "\tmov r6, sp\n" + "\tldr r1, [sp, 0x20]\n" + "\tstr r1, [sp, 0x24]\n" + "\tmov r2, r10\n" + "\tstr r2, [sp, 0x28]\n" + "\tadds r4, r0, 0\n" + "_0804240E:\n" + "\tadds r0, r4, 0\n" + "\tmovs r1, 0xB\n" + "\tbl GetBoxMonData\n" + "\tstrh r0, [r5]\n" + "\tadds r0, r4, 0\n" + "\tmovs r1, 0x1\n" + "\tbl GetBoxMonData\n" + "\tldr r1, [sp, 0x28]\n" + "\tstm r1!, {r0}\n" + "\tstr r1, [sp, 0x28]\n" + "\tadds r0, r4, 0\n" + "\tmovs r1, 0\n" + "\tbl GetBoxMonData\n" + "\tadds r1, r0, 0\n" + "\tldrh r0, [r5]\n" + "\tbl GetGenderFromSpeciesAndPersonality\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tldr r2, [sp, 0x24]\n" + "\tstm r2!, {r0}\n" + "\tstr r2, [sp, 0x24]\n" + "\tldrh r1, [r5]\n" + "\tlsls r0, r1, 3\n" + "\tsubs r0, r1\n" + "\tlsls r0, 2\n" + "\tadd r0, r9\n" + "\tldrb r0, [r0, 0x14]\n" + "\tstrh r0, [r6]\n" + "\tldrh r1, [r5]\n" + "\tlsls r0, r1, 3\n" + "\tsubs r0, r1\n" + "\tlsls r0, 2\n" + "\tadd r0, r9\n" + "\tldrb r0, [r0, 0x15]\n" + "\tstrh r0, [r7]\n" + "\tadds r5, 0x2\n" + "\tadds r7, 0x4\n" + "\tadds r6, 0x4\n" + "\tadds r4, 0x50\n" + "\tmovs r0, 0x1\n" + "\tadd r8, r0\n" + "\tmov r1, r8\n" + "\tcmp r1, 0x1\n" + "\tbls _0804240E\n" + "\tmov r0, sp\n" + "\tldrh r1, [r0]\n" + "\tcmp r1, 0xF\n" + "\tbeq _08042484\n" + "\tldrh r0, [r0, 0x4]\n" + "\tcmp r0, 0xF\n" + "\tbeq _08042484\n" + "\tcmp r1, 0xD\n" + "\tbne _0804248C\n" + "\tcmp r0, 0xD\n" + "\tbne _08042490\n" + "_08042484:\n" + "\tmovs r0, 0\n" + "\tb _080424E4\n" + "\t.align 2, 0\n" + "_08042488: .4byte gBaseStats\n" + "_0804248C:\n" + "\tcmp r0, 0xD\n" + "\tbne _0804249C\n" + "_08042490:\n" + "\tldr r1, [sp, 0xC]\n" + "\tmov r2, r10\n" + "\tldr r0, [r2, 0x4]\n" + "\tcmp r1, r0\n" + "\tbeq _080424DE\n" + "\tb _080424E2\n" + "_0804249C:\n" + "\tldr r0, [sp, 0x14]\n" + "\tldr r2, [sp, 0x20]\n" + "\tldr r1, [r2, 0x4]\n" + "\tcmp r0, r1\n" + "\tbeq _08042484\n" + "\tcmp r0, 0xFF\n" + "\tbeq _08042484\n" + "\tcmp r1, 0xFF\n" + "\tbeq _08042484\n" + "\tadd r1, sp, 0x4\n" + "\tmov r0, sp\n" + "\tbl sub_80423A8\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbeq _08042484\n" + "\tldr r0, [sp, 0x1C]\n" + "\tldrh r1, [r0, 0x2]\n" + "\tldrh r0, [r0]\n" + "\tcmp r0, r1\n" + "\tbne _080424D4\n" + "\tldr r1, [sp, 0xC]\n" + "\tmov r2, r10\n" + "\tldr r0, [r2, 0x4]\n" + "\tcmp r1, r0\n" + "\tbeq _080424E2\n" + "\tmovs r0, 0x46\n" + "\tb _080424E4\n" + "_080424D4:\n" + "\tldr r1, [sp, 0xC]\n" + "\tmov r2, r10\n" + "\tldr r0, [r2, 0x4]\n" + "\tcmp r1, r0\n" + "\tbne _080424E2\n" + "_080424DE:\n" + "\tmovs r0, 0x14\n" + "\tb _080424E4\n" + "_080424E2:\n" + "\tmovs r0, 0x32\n" + "_080424E4:\n" + "\tadd sp, 0x2C\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1"); +} +#endif + +u8 daycare_relationship_score_from_savegame(void) +{ + return daycare_relationship_score(&gSaveBlock1.daycareData); +} + +void sp0B9_daycare_relationship_comment(void) +{ + u8 whichString; + u8 relationshipScore; + + relationshipScore = daycare_relationship_score_from_savegame(); + whichString = 0; + if (relationshipScore == 0) + whichString = 3; + if (relationshipScore == 20) + whichString = 2; + if (relationshipScore == 50) + whichString = 1; + if (relationshipScore == 70) + whichString = 0; + StringCopy(gStringVar4, gUnknown_08209AC4[whichString]); +} + +#ifdef NONMATCHING +bool8 NameHasGenderSymbol(const u8 *name, u8 genderRatio) +{ + u8 i; + u8 flags[2]; + + // This portion is nonmatching + flags[1] = 0; + flags[0] = 0; + for (i = 0; name[i] != EOS; i ++) + // End nonmatching portion + + { + if (name[i] == CHAR_MALE) flags[0] ++; + if (name[i] == CHAR_FEMALE) flags[1] ++; + } + if (genderRatio == MON_MALE && flags[0] && !flags[1]) return TRUE; + if (genderRatio == MON_FEMALE && flags[1] && !flags[0]) return TRUE; + return FALSE; +} +#else +__attribute__((naked)) +bool8 NameHasGenderSymbol(const u8 *name, u8 genderRatio) +{ + asm_unified("\n" + "\tpush {r4,r5,lr}\n" + "\tsub sp, 0x4\n" + "\tadds r4, r0, 0\n" + "\tlsls r1, 24\n" + "\tlsrs r5, r1, 24\n" + "\tmov r2, sp\n" + "\tmov r1, sp\n" + "\tmovs r0, 0\n" + "\tstrb r0, [r1, 0x1]\n" + "\tstrb r0, [r2]\n" + "\tmovs r3, 0\n" + "\tldrb r0, [r4]\n" + "\tcmp r0, 0xFF\n" + "\tbeq _0804258C\n" + "_08042564:\n" + "\tadds r1, r4, r3\n" + "\tldrb r0, [r1]\n" + "\tcmp r0, 0xB5\n" + "\tbne _08042572\n" + "\tldrb r0, [r2]\n" + "\tadds r0, 0x1\n" + "\tstrb r0, [r2]\n" + "_08042572:\n" + "\tldrb r0, [r1]\n" + "\tcmp r0, 0xB6\n" + "\tbne _0804257E\n" + "\tldrb r0, [r2, 0x1]\n" + "\tadds r0, 0x1\n" + "\tstrb r0, [r2, 0x1]\n" + "_0804257E:\n" + "\tadds r0, r3, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r3, r0, 24\n" + "\tadds r0, r4, r3\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0xFF\n" + "\tbne _08042564\n" + "_0804258C:\n" + "\tcmp r5, 0\n" + "\tbne _080425A0\n" + "\tmov r0, sp\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0\n" + "\tbeq _080425A0\n" + "\tmov r0, sp\n" + "\tldrb r0, [r0, 0x1]\n" + "\tcmp r0, 0\n" + "\tbeq _080425B4\n" + "_080425A0:\n" + "\tcmp r5, 0xFE\n" + "\tbne _080425B8\n" + "\tmov r0, sp\n" + "\tldrb r0, [r0, 0x1]\n" + "\tcmp r0, 0\n" + "\tbeq _080425B8\n" + "\tmov r0, sp\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0\n" + "\tbne _080425B8\n" + "_080425B4:\n" + "\tmovs r0, 0x1\n" + "\tb _080425BA\n" + "_080425B8:\n" + "\tmovs r0, 0\n" + "_080425BA:\n" + "\tadd sp, 0x4\n" + "\tpop {r4,r5}\n" + "\tpop {r1}\n" + "\tbx r1"); +} +#endif + +static u8 *AppendGenderSymbol(u8 *name, u8 gender) +{ + if (gender == MON_MALE) + { + if (!NameHasGenderSymbol(name, MON_MALE)) + return StringAppend(name, gOtherText_MaleSymbol3); + } + + else if (gender == MON_FEMALE) + { + if (!NameHasGenderSymbol(name, MON_FEMALE)) + return StringAppend(name, gOtherText_FemaleSymbol3); + } + return StringAppend(name, gOtherText_GenderlessSymbol); +} + +static u8 *MonAppendGenderSymbol(u8 *name, struct BoxPokemon *boxMon) +{ + return AppendGenderSymbol(name, GetBoxMonGender(boxMon)); +} + +static void DaycareLevelMenuGetText(struct DayCareData *dayCareData, u8 *dest) +{ + u8 buffers[2][20]; + u8 i; + *dest = EOS; + for (i = 0; i < 2; i ++) + { + GetBoxMonNick(&dayCareData->mons[i], buffers[i]); + MonAppendGenderSymbol(buffers[i], &dayCareData->mons[i]); + } + StringCopy(dest, buffers[0]); + StringAppend(dest, gOtherText_NewLine2); + StringAppend(dest, buffers[1]); + StringAppend(dest, gOtherText_NewLine2); + StringAppend(dest, gOtherText_CancelAndLv); +} + +static void DaycareLevelMenuGetLevelText(struct DayCareData *dayCareData, u8 *dest) +{ + u8 i; + u8 level; + *dest = EOS; + for (i = 0; i < 2; i ++) + { + level = Daycare_GetLevelAfterSteps(&dayCareData->mons[i], dayCareData->misc.countersEtc.steps[i]); + dest[0] = 0x34; + dest[1] = 0xFC; + dest[2] = 0x14; + dest[3] = 0x06; + dest = ConvertIntToDecimalStringN(dest + 4, level, STR_CONV_MODE_RIGHT_ALIGN, 3); + dest[0] = 0xFC; + dest[1] = 0x14; + dest[2] = 0x00; + dest = StringCopy(dest + 3, gOtherText_NewLine2); + } + *dest = EOS; +} + +static void DaycareLevelMenuProcessKeyInput(u8 taskId) +{ + if (gMain.newKeys & DPAD_UP) + { + if (gTasks[taskId].data[0] != 0) + { + gTasks[taskId].data[0] --; + MoveMenuCursor(-1); + PlaySE(SE_SELECT); + } + } + else if (gMain.newKeys & DPAD_DOWN) + { + if (gTasks[taskId].data[0] != 2) + { + gTasks[taskId].data[0] ++; + MoveMenuCursor(+1); + PlaySE(SE_SELECT); + } + } + else if (gMain.newKeys & A_BUTTON) + { + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + gLastFieldPokeMenuOpened = gScriptResult = gTasks[taskId].data[0]; + DestroyTask(taskId); + MenuZeroFillWindowRect(15, 6, 29, 13); + EnableBothScriptContexts(); + } + else if (gMain.newKeys & B_BUTTON) + { + HandleDestroyMenuCursors(); + gLastFieldPokeMenuOpened = gScriptResult = 2; + DestroyTask(taskId); + MenuZeroFillWindowRect(15, 6, 29, 13); + EnableBothScriptContexts(); + } +} + +void ShowDaycareLevelMenu(void) +{ + u8 buffer[100]; + MenuDrawTextWindow(15, 6, 29, 13); + DaycareLevelMenuGetText(&gSaveBlock1.daycareData, buffer); + MenuPrint(buffer, 16, 7); + DaycareLevelMenuGetLevelText(&gSaveBlock1.daycareData, buffer); + MenuPrint_PixelCoords(buffer, 0xce, 0x38, TRUE); + InitMenu(0, 16, 7, 3, 0, 13); + CreateTask(DaycareLevelMenuProcessKeyInput, 3); +} + +void ChooseSendDaycareMon(void) +{ + OpenPartyMenu(6, 0); + gMain.savedCallback = c2_exit_to_overworld_2_switch; +} diff --git a/src/field/decoration.c b/src/field/decoration.c new file mode 100644 index 000000000..e067191e9 --- /dev/null +++ b/src/field/decoration.c @@ -0,0 +1,4280 @@ +#include "global.h" +#include "main.h" +#include "map_object_constants.h" +#include "overworld.h" +#include "sound.h" +#include "songs.h" +#include "string_util.h" +#include "menu.h" +#include "menu_helpers.h" +#include "strings.h" +#include "script.h" +#include "palette.h" +#include "field_player_avatar.h" +#include "field_camera.h" +#include "field_fadetransition.h" +#include "fieldmap.h" +#include "metatile_behavior.h" +#include "event_data.h" +#include "field_weather.h" +#include "decoration.h" + +EWRAM_DATA u8 *gUnknown_020388D0 = NULL; +EWRAM_DATA u8 gUnknown_020388D4 = 0; +EWRAM_DATA u8 gUnknown_020388D5 = 0; +EWRAM_DATA u8 gUnknown_020388D6[16] = {0}; +EWRAM_DATA u8 gUnknown_020388E6[12] = {0}; +EWRAM_DATA u8 gUnknown_020388F2 = 0; +EWRAM_DATA u8 gUnknown_020388F3 = 0; +EWRAM_DATA u8 gUnknown_020388F4 = 0; +EWRAM_DATA u8 gUnknown_020388F5 = 0; +EWRAM_DATA u8 gUnknown_020388F6 = 0; +EWRAM_DATA u8 gUnknown_020388F7[8] = {0}; +EWRAM_DATA struct UnkStruct_02038900 gUnknown_02038900 = {0}; +EWRAM_DATA u16 gUnknown_020391A4 = 0; +EWRAM_DATA u16 gUnknown_020391A6 = 0; +EWRAM_DATA u8 gUnknown_020391A8 = 0; +EWRAM_DATA u8 gUnknown_020391A9 = 0; +EWRAM_DATA u8 gUnknown_020391AA = 0; +EWRAM_DATA struct OamData gUnknown_020391AC = {0}; +EWRAM_DATA struct UnkStruct_020391B4 gUnknown_020391B4[16] = {0}; +EWRAM_DATA u8 gUnknown_02039234 = 0; + +#if ENGLISH +const u8 DecorDesc_SMALL_DESK[] = _( + "A small desk built\n" + "for one."); + +const u8 DecorDesc_POKEMON_DESK[] = _( + "A small desk built in\n" + "the shape of a POKé\n" + "BALL."); + +const u8 DecorDesc_HEAVY_DESK[] = _( + "A large desk made\n" + "of steel. Put some\n" + "decorations on it."); + +const u8 DecorDesc_RAGGED_DESK[] = _( + "A large desk made\n" + "of wood. Put some\n" + "decorations on it."); + +const u8 DecorDesc_COMFORT_DESK[] = _( + "A large desk made\n" + "of leaves. Put some\n" + "decorations on it."); + +const u8 DecorDesc_PRETTY_DESK[] = _( + "A huge desk made\n" + "of glass. Holds lots\n" + "of decorations."); + +const u8 DecorDesc_BRICK_DESK[] = _( + "A huge desk made\n" + "of brick. Holds lots\n" + "of decorations."); + +const u8 DecorDesc_CAMP_DESK[] = _( + "A huge desk made\n" + "of logs. Put lots of\n" + "decorations on it."); + +const u8 DecorDesc_HARD_DESK[] = _( + "A huge desk made\n" + "of rocks. Holds\n" + "many decorations."); + +const u8 DecorDesc_SMALL_CHAIR[] = _( + "A small chair made\n" + "for one."); + +const u8 DecorDesc_POKEMON_CHAIR[] = _( + "A small chair built\n" + "in the shape of a\n" + "POKé BALL."); + +const u8 DecorDesc_HEAVY_CHAIR[] = _( + "A small chair made\n" + "of steel."); + +const u8 DecorDesc_PRETTY_CHAIR[] = _( + "A small chair made\n" + "of glass."); + +const u8 DecorDesc_COMFORT_CHAIR[] = _( + "A small chair made\n" + "of leaves."); + +const u8 DecorDesc_RAGGED_CHAIR[] = _( + "A small chair made\n" + "of wood."); + +const u8 DecorDesc_BRICK_CHAIR[] = _( + "A small chair made\n" + "of brick."); + +const u8 DecorDesc_CAMP_CHAIR[] = _( + "A small chair made\n" + "of logs."); + +const u8 DecorDesc_HARD_CHAIR[] = _( + "A small chair made\n" + "of rock."); + +const u8 DecorDesc_RED_PLANT[] = _( + "A vivid red potted\n" + "plant."); + +const u8 DecorDesc_TROPICAL_PLANT[] = _( + "A flowering tropical\n" + "plant in a pot."); + +const u8 DecorDesc_PRETTY_FLOWERS[] = _( + "A pot of cute\n" + "flowers."); + +const u8 DecorDesc_COLORFUL_PLANT[] = _( + "A large pot with\n" + "many colorful\n" + "flowers."); + +const u8 DecorDesc_BIG_PLANT[] = _( + "A large, umbrella-\n" + "shaped plant in a\n" + "big pot."); + +const u8 DecorDesc_GORGEOUS_PLANT[] = _( + "A large, impressive\n" + "plant in a big pot."); + +const u8 DecorDesc_RED_BRICK[] = _( + "A red-colored brick.\n" + "Decorations can be\n" + "placed on top."); + +const u8 DecorDesc_YELLOW_BRICK[] = _( + "A yellow-colored\n" + "brick. Put some\n" + "decorations on top."); + +const u8 DecorDesc_BLUE_BRICK[] = _( + "A blue-colored\n" + "brick. Put some\n" + "decorations on top."); + +const u8 DecorDesc_RED_BALLOON[] = _( + "A red balloon filled\n" + "with water. Bursts\n" + "if stepped on."); + +const u8 DecorDesc_BLUE_BALLOON[] = _( + "A blue balloon filled\n" + "with water. Bursts\n" + "if stepped on."); + +const u8 DecorDesc_YELLOW_BALLOON[] = _( + "A yellow balloon\n" + "filled with water.\n" + "Pops if stepped on."); + +const u8 DecorDesc_RED_TENT[] = _( + "A large red tent.\n" + "You can hide inside\n" + "it."); + +const u8 DecorDesc_BLUE_TENT[] = _( + "A large blue tent.\n" + "You can hide inside\n" + "it."); + +const u8 DecorDesc_SOLID_BOARD[] = _( + "Place over a hole to\n" + "cross to the other\n" + "side."); + +const u8 DecorDesc_SLIDE[] = _( + "Use to slide down\n" + "from the platform."); + +const u8 DecorDesc_FENCE_LENGTH[] = _( + "A small fence that\n" + "blocks passage."); + +const u8 DecorDesc_FENCE_WIDTH[] = _( + "A small fence that\n" + "blocks passage."); + +const u8 DecorDesc_TIRE[] = _( + "An old large tire.\n" + "Decorations can be\n" + "placed on top."); + +const u8 DecorDesc_STAND[] = _( + "A large pedestal\n" + "with steps."); + +const u8 DecorDesc_MUD_BALL[] = _( + "A large ball of mud.\n" + "Crumbles if stepped\n" + "on."); + +const u8 DecorDesc_BREAKABLE_DOOR[] = _( + "A weird door that\n" + "people can walk\n" + "right through."); + +const u8 DecorDesc_SAND_ORNAMENT[] = _( + "An ornament made\n" + "of sand. Crumbles if\n" + "touched."); + +const u8 DecorDesc_SILVER_SHIELD[] = _( + "Awarded for 50\n" + "straight wins at\n" + "the BATTLE TOWER."); + +const u8 DecorDesc_GOLD_SHIELD[] = _( + "Awarded for 100\n" + "straight wins at\n" + "the BATTLE TOWER."); + +const u8 DecorDesc_GLASS_ORNAMENT[] = _( + "A glass replica of\n" + "a famous sculpture\n" + "at the ART MUSEUM."); + +const u8 DecorDesc_TV[] = _( + "A small, gray-\n" + "colored toy TV."); + +const u8 DecorDesc_ROUND_TV[] = _( + "A toy TV modeled\n" + "in the image of a\n" + "SEEDOT."); + +const u8 DecorDesc_CUTE_TV[] = _( + "A toy TV modeled\n" + "in the image of a\n" + "SKITTY."); + +const u8 DecorDesc_GLITTER_MAT[] = _( + "An odd mat that\n" + "glitters if stepped\n" + "on."); + +const u8 DecorDesc_JUMP_MAT[] = _( + "A trick mat that\n" + "jumps when it is\n" + "stepped on."); + +const u8 DecorDesc_SPIN_MAT[] = _( + "A trick mat that\n" + "spins around when\n" + "stepped on."); + +const u8 DecorDesc_C_LOW_NOTE_MAT[] = _( + "A mat that plays\n" + "a low C note when\n" + "stepped on."); + +const u8 DecorDesc_D_NOTE_MAT[] = _( + "A mat that plays\n" + "a D note when\n" + "stepped on."); + +const u8 DecorDesc_E_NOTE_MAT[] = _( + "A mat that plays\n" + "an E note when\n" + "stepped on."); + +const u8 DecorDesc_F_NOTE_MAT[] = _( + "A mat that plays\n" + "an F note when\n" + "stepped on."); + +const u8 DecorDesc_G_NOTE_MAT[] = _( + "A mat that plays\n" + "a G note when\n" + "stepped on."); + +const u8 DecorDesc_A_NOTE_MAT[] = _( + "A mat that plays\n" + "an A note when\n" + "stepped on."); + +const u8 DecorDesc_B_NOTE_MAT[] = _( + "A mat that plays\n" + "a B note when\n" + "stepped on."); + +const u8 DecorDesc_C_HIGH_NOTE_MAT[] = _( + "A mat that plays\n" + "a high C note when\n" + "stepped on."); + +const u8 DecorDesc_SURF_MAT[] = _( + "A mat designed with\n" + "a SURF image.\n" + "Put items on top."); + +const u8 DecorDesc_THUNDER_MAT[] = _( + "A mat designed with\n" + "a THUNDER image.\n" + "Put items on top."); + +const u8 DecorDesc_FIRE_BLAST_MAT[] = _( + "A mat designed with\n" + "a FIRE BLAST image.\n" + "Put items on top."); + +const u8 DecorDesc_POWDER_SNOW_MAT[] = _( + "A mat with a POWDER\n" + "SNOW image design.\n" + "Put items on top."); + +const u8 DecorDesc_ATTRACT_MAT[] = _( + "A mat designed with\n" + "an ATTRACT image.\n" + "Put items on top."); + +const u8 DecorDesc_FISSURE_MAT[] = _( + "A mat designed with\n" + "a FISSURE image.\n" + "Put items on top."); + +const u8 DecorDesc_SPIKES_MAT[] = _( + "A mat designed with\n" + "a SPIKES image.\n" + "Put items on top."); + +const u8 DecorDesc_BALL_POSTER[] = _( + "A small poster\n" + "printed with POKé\n" + "BALLS."); + +const u8 DecorDesc_GREEN_POSTER[] = _( + "A small poster with\n" + "a TREECKO print."); + +const u8 DecorDesc_RED_POSTER[] = _( + "A small poster with\n" + "a TORCHIC print."); + +const u8 DecorDesc_BLUE_POSTER[] = _( + "A small poster with\n" + "a MUDKIP print."); + +const u8 DecorDesc_CUTE_POSTER[] = _( + "A small poster with\n" + "an AZURILL print."); + +const u8 DecorDesc_PIKA_POSTER[] = _( + "A large poster with\n" + "a PIKACHU and\n" + "PICHU print."); + +const u8 DecorDesc_LONG_POSTER[] = _( + "A large poster with\n" + "a SEVIPER print."); + +const u8 DecorDesc_SEA_POSTER[] = _( + "A large poster with\n" + "a RELICANTH print."); + +const u8 DecorDesc_SKY_POSTER[] = _( + "A large poster with\n" + "a WINGULL print."); + +const u8 DecorDesc_KISS_POSTER[] = _( + "A large poster with\n" + "a SMOOCHUM print."); + +const u8 DecorDesc_PICHU_DOLL[] = _( + "A PICHU doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_PIKACHU_DOLL[] = _( + "A PIKACHU doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_MARILL_DOLL[] = _( + "A MARILL doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_TOGEPI_DOLL[] = _( +#if REVISION >= 1 + "A TOGEPI doll.\n" +#else + "A TOPGEPI doll.\n" +#endif + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_CYNDAQUIL_DOLL[] = _( + "A CYNDAQUIL doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_CHIKORITA_DOLL[] = _( + "A CHIKORITA doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_TOTODILE_DOLL[] = _( + "A TOTODILE doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_JIGGLYPUFF_DOLL[] = _( + "A JIGGLYPUFF doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_MEOWTH_DOLL[] = _( + "A MEOWTH doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_CLEFAIRY_DOLL[] = _( + "A CLEFAIRY doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_DITTO_DOLL[] = _( + "A DITTO doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_SMOOCHUM_DOLL[] = _( + "A SMOOCHUM doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_TREECKO_DOLL[] = _( + "A TREECKO doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_TORCHIC_DOLL[] = _( + "A TORCHIC doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_MUDKIP_DOLL[] = _( + "A MUDKIP doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_DUSKULL_DOLL[] = _( + "A DUSKULL doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_WYNAUT_DOLL[] = _( + "A WYNAUT doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_BALTOY_DOLL[] = _( + "A BALTOY doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_KECLEON_DOLL[] = _( + "A KECLEON doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_AZURILL_DOLL[] = _( + "An AZURILL doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_SKITTY_DOLL[] = _( + "A SKITTY doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_SWABLU_DOLL[] = _( + "A SWABLU doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_GULPIN_DOLL[] = _( + "A GULPIN doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_LOTAD_DOLL[] = _( + "A LOTAD doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_SEEDOT_DOLL[] = _( + "A SEEDOT doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_PIKA_CUSHION[] = _( + "A PIKACHU cushion.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_ROUND_CUSHION[] = _( + "A MARILL cushion.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_KISS_CUSHION[] = _( + "A SMOOCHUM\n" + "cushion. Place it on\n" + "a mat or a desk."); + +const u8 DecorDesc_ZIGZAG_CUSHION[] = _( + "A ZIGZAGOON\n" + "cushion. Place it on\n" + "a mat or a desk."); + +const u8 DecorDesc_SPIN_CUSHION[] = _( + "A SPINDA cushion.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_DIAMOND_CUSHION[] = _( + "A SABLEYE cushion.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_BALL_CUSHION[] = _( + "A BALL cushion.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_GRASS_CUSHION[] = _( + "A grass-mark\n" + "cushion. Place it on\n" + "a mat or a desk."); + +const u8 DecorDesc_FIRE_CUSHION[] = _( + "A fire-mark\n" + "cushion. Place it on\n" + "a mat or a desk."); + +const u8 DecorDesc_WATER_CUSHION[] = _( + "A water-mark\n" + "cushion. Place it on\n" + "a mat or a desk."); + +const u8 DecorDesc_SNORLAX_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_RHYDON_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_LAPRAS_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_VENUSAUR_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_CHARIZARD_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_BLASTOISE_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_WAILMER_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_REGIROCK_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_REGICE_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); + +const u8 DecorDesc_REGISTEEL_DOLL[] = _( + "A large doll.\n" + "Place it on a mat\n" + "or a desk."); +#elif GERMAN +#include "../data/decoration/descriptions_de.h" +#endif + +const u16 DecorGfx_SMALL_DESK[] = { + 0x87 +}; + +const u16 DecorGfx_POKEMON_DESK[] = { + 0x8F +}; + +const u16 DecorGfx_HEAVY_DESK[] = { + 0x90, + 0x91, + 0x92, + 0x98, + 0x99, + 0x9A +}; + +const u16 DecorGfx_RAGGED_DESK[] = { + 0x93, + 0x94, + 0x95, + 0x9B, + 0x9C, + 0x9D +}; + +const u16 DecorGfx_COMFORT_DESK[] = { + 0x96, + 0x97, + 0xA3, + 0x9E, + 0x9F, + 0xAB +}; + +const u16 DecorGfx_PRETTY_DESK[] = { + 0xBD, + 0xBE, + 0xBF, + 0xC5, + 0xC6, + 0xC7, + 0xCD, + 0xCE, + 0xCF +}; + +const u16 DecorGfx_BRICK_DESK[] = { + 0xA0, + 0xA1, + 0xA2, + 0xA8, + 0xA9, + 0xAA, + 0xB0, + 0xB1, + 0xB2 +}; + +const u16 DecorGfx_CAMP_DESK[] = { + 0xA4, + 0xA5, + 0xA6, + 0xAC, + 0xAD, + 0xAE, + 0xB4, + 0xB5, + 0xB6 +}; + +const u16 DecorGfx_HARD_DESK[] = { + 0xA7, + 0xBB, + 0xBC, + 0xAF, + 0xC3, + 0xC4, + 0xB7, + 0xCB, + 0xCC +}; + +const u16 DecorGfx_SMALL_CHAIR[] = { + 0xB8 +}; + +const u16 DecorGfx_POKEMON_CHAIR[] = { + 0xB9 +}; + +const u16 DecorGfx_HEAVY_CHAIR[] = { + 0xBA +}; + +const u16 DecorGfx_PRETTY_CHAIR[] = { + 0xC0 +}; + +const u16 DecorGfx_COMFORT_CHAIR[] = { + 0xC1 +}; + +const u16 DecorGfx_RAGGED_CHAIR[] = { + 0xC2 +}; + +const u16 DecorGfx_BRICK_CHAIR[] = { + 0xC8 +}; + +const u16 DecorGfx_CAMP_CHAIR[] = { + 0xC9 +}; + +const u16 DecorGfx_HARD_CHAIR[] = { + 0xCA +}; + +const u16 DecorGfx_RED_PLANT[] = { + 0xD0, + 0xD8 +}; + +const u16 DecorGfx_TROPICAL_PLANT[] = { + 0xD2, + 0xDA +}; + +const u16 DecorGfx_PRETTY_FLOWERS[] = { + 0xD4, + 0xDC +}; + +const u16 DecorGfx_COLORFUL_PLANT[] = { + 0xE0, + 0xE2, + 0xE8, + 0xE9 +}; + +const u16 DecorGfx_BIG_PLANT[] = { + 0xE4, + 0xE6, + 0xEC, + 0xED +}; + +const u16 DecorGfx_GORGEOUS_PLANT[] = { + 0xF0, + 0xF2, + 0xF8, + 0xF9 +}; + +const u16 DecorGfx_RED_BRICK[] = { + 0x25, + 0x2D +}; + +const u16 DecorGfx_YELLOW_BRICK[] = { + 0x26, + 0x2E +}; + +const u16 DecorGfx_BLUE_BRICK[] = { + 0x27, + 0x2F +}; + +const u16 DecorGfx_RED_BALLOON[] = { + 0x138 +}; + +const u16 DecorGfx_BLUE_BALLOON[] = { + 0x13C +}; + +const u16 DecorGfx_YELLOW_BALLOON[] = { + 0x140 +}; + +const u16 DecorGfx_RED_TENT[] = { + 0x30, + 0x31, + 0x32, + 0x38, + 0x39, + 0x3A, + 0x40, + 0x41, + 0x3B +}; + +const u16 DecorGfx_BLUE_TENT[] = { + 0x48, + 0x49, + 0x68, + 0x50, + 0x51, + 0x70, + 0x58, + 0x59, + 0x69 +}; + +const u16 DecorGfx_SOLID_BOARD[] = { + 0x34, + 0x3C +}; + +const u16 DecorGfx_SLIDE[] = { + 0x35, + 0x36, + 0x3D, + 0x3E, + 0x63, + 0x64, + 0x6F, + 0x77 +}; + +const u16 DecorGfx_FENCE_LENGTH[] = { + 0x33 +}; + +const u16 DecorGfx_FENCE_WIDTH[] = { + 0x2C +}; + +const u16 DecorGfx_TIRE[] = { + 0x80, + 0x81, + 0x88, + 0x89 +}; + +const u16 DecorGfx_STAND[] = { + 0x6A, + 0x6B, + 0x6C, + 0x6D, + 0x72, + 0x73, + 0x74, + 0x75 +}; + +const u16 DecorGfx_MUD_BALL[] = { + 0x28 +}; + +const u16 DecorGfx_BREAKABLE_DOOR[] = { + 0x37, + 0x3F +}; + +const u16 DecorGfx_SAND_ORNAMENT[] = { + 0x85, + 0x8D +}; + +const u16 DecorGfx_SILVER_SHIELD[] = { + 0xD6, + 0xDE +}; + +const u16 DecorGfx_GOLD_SHIELD[] = { + 0x12E, + 0x136 +}; + +const u16 DecorGfx_GLASS_ORNAMENT[] = { + 0x82, + 0x8A +}; + +const u16 DecorGfx_TV[] = { + 0xF4 +}; + +const u16 DecorGfx_ROUND_TV[] = { + 0xF5 +}; + +const u16 DecorGfx_CUTE_TV[] = { + 0xF6 +}; + +const u16 DecorGfx_GLITTER_MAT[] = { + 0x60 +}; + +const u16 DecorGfx_JUMP_MAT[] = { + 0x61 +}; + +const u16 DecorGfx_SPIN_MAT[] = { + 0x62 +}; + +const u16 DecorGfx_C_LOW_NOTE_MAT[] = { + 0x78 +}; + +const u16 DecorGfx_D_NOTE_MAT[] = { + 0x79 +}; + +const u16 DecorGfx_E_NOTE_MAT[] = { + 0x7A +}; + +const u16 DecorGfx_F_NOTE_MAT[] = { + 0x7B +}; + +const u16 DecorGfx_G_NOTE_MAT[] = { + 0x7C +}; + +const u16 DecorGfx_A_NOTE_MAT[] = { + 0x7D +}; + +const u16 DecorGfx_B_NOTE_MAT[] = { + 0x7E +}; + +const u16 DecorGfx_C_HIGH_NOTE_MAT[] = { + 0xB3 +}; + +const u16 DecorGfx_SURF_MAT[] = { + 0x42, + 0x43, + 0x44, + 0x4A, + 0x4B, + 0x4C, + 0x52, + 0x53, + 0x54 +}; + +const u16 DecorGfx_THUNDER_MAT[] = { + 0x45, + 0x46, + 0x47, + 0x4D, + 0x4E, + 0x4F, + 0x55, + 0x56, + 0x57 +}; + +const u16 DecorGfx_FIRE_BLAST_MAT[] = { + 0x5A, + 0x5B, + 0x5C, + 0x5D, + 0x5E, + 0x5F, + 0x65, + 0x66, + 0x67 +}; + +const u16 DecorGfx_POWDER_SNOW_MAT[] = { + 0x100, + 0x101, + 0x102, + 0x108, + 0x109, + 0x10A, + 0x110, + 0x111, + 0x112 +}; + +const u16 DecorGfx_ATTRACT_MAT[] = { + 0x103, + 0x104, + 0x105, + 0x10B, + 0x10C, + 0x10D, + 0x113, + 0x114, + 0x115 +}; + +const u16 DecorGfx_FISSURE_MAT[] = { + 0x106, + 0x107, + 0x118, + 0x10E, + 0x10F, + 0x120, + 0x116, + 0x117, + 0x128 +}; + +const u16 DecorGfx_SPIKES_MAT[] = { + 0x119, + 0x11A, + 0x11B, + 0x121, + 0x122, + 0x123, + 0x129, + 0x12A, + 0x12B +}; + +const u16 DecorGfx_BALL_POSTER[] = { + 0x130 +}; + +const u16 DecorGfx_GREEN_POSTER[] = { + 0x131 +}; + +const u16 DecorGfx_RED_POSTER[] = { + 0x132 +}; + +const u16 DecorGfx_BLUE_POSTER[] = { + 0x133 +}; + +const u16 DecorGfx_CUTE_POSTER[] = { + 0x134 +}; + +const u16 DecorGfx_PIKA_POSTER[] = { + 0x11C, + 0x11D +}; + +const u16 DecorGfx_LONG_POSTER[] = { + 0x11E, + 0x11F +}; + +const u16 DecorGfx_SEA_POSTER[] = { + 0x124, + 0x125 +}; + +const u16 DecorGfx_SKY_POSTER[] = { + 0x126, + 0x127 +}; + +const u16 DecorGfx_KISS_POSTER[] = { + 0x12C, + 0x12D +}; + +const u16 DecorGfx_PICHU_DOLL[] = { + MAP_OBJ_GFX_PICHU_DOLL +}; + +const u16 DecorGfx_PIKACHU_DOLL[] = { + MAP_OBJ_GFX_PIKACHU_DOLL +}; + +const u16 DecorGfx_MARILL_DOLL[] = { + MAP_OBJ_GFX_MARILL_DOLL +}; + +const u16 DecorGfx_TOGEPI_DOLL[] = { + MAP_OBJ_GFX_TOGEPI_DOLL +}; + +const u16 DecorGfx_CYNDAQUIL_DOLL[] = { + MAP_OBJ_GFX_CYNDAQUIL_DOLL +}; + +const u16 DecorGfx_CHIKORITA_DOLL[] = { + MAP_OBJ_GFX_CHIKORITA_DOLL +}; + +const u16 DecorGfx_TOTODILE_DOLL[] = { + MAP_OBJ_GFX_TOTODILE_DOLL +}; + +const u16 DecorGfx_JIGGLYPUFF_DOLL[] = { + MAP_OBJ_GFX_JIGGLYPUFF_DOLL +}; + +const u16 DecorGfx_MEOWTH_DOLL[] = { + MAP_OBJ_GFX_MEOWTH_DOLL +}; + +const u16 DecorGfx_CLEFAIRY_DOLL[] = { + MAP_OBJ_GFX_CLEFAIRY_DOLL +}; + +const u16 DecorGfx_DITTO_DOLL[] = { + MAP_OBJ_GFX_DITTO_DOLL +}; + +const u16 DecorGfx_SMOOCHUM_DOLL[] = { + MAP_OBJ_GFX_SMOOCHUM_DOLL +}; + +const u16 DecorGfx_TREECKO_DOLL[] = { + MAP_OBJ_GFX_TREECKO_DOLL +}; + +const u16 DecorGfx_TORCHIC_DOLL[] = { + MAP_OBJ_GFX_TORCHIC_DOLL +}; + +const u16 DecorGfx_MUDKIP_DOLL[] = { + MAP_OBJ_GFX_MUDKIP_DOLL +}; + +const u16 DecorGfx_DUSKULL_DOLL[] = { + MAP_OBJ_GFX_DUSKULL_DOLL +}; + +const u16 DecorGfx_WYNAUT_DOLL[] = { + MAP_OBJ_GFX_WYNAUT_DOLL +}; + +const u16 DecorGfx_BALTOY_DOLL[] = { + MAP_OBJ_GFX_BALTOY_DOLL +}; + +const u16 DecorGfx_KECLEON_DOLL[] = { + MAP_OBJ_GFX_KECLEON_DOLL +}; + +const u16 DecorGfx_AZURILL_DOLL[] = { + MAP_OBJ_GFX_AZURILL_DOLL +}; + +const u16 DecorGfx_SKITTY_DOLL[] = { + MAP_OBJ_GFX_SKITTY_DOLL +}; + +const u16 DecorGfx_SWABLU_DOLL[] = { + MAP_OBJ_GFX_SWABLU_DOLL +}; + +const u16 DecorGfx_GULPIN_DOLL[] = { + MAP_OBJ_GFX_GULPIN_DOLL +}; + +const u16 DecorGfx_LOTAD_DOLL[] = { + MAP_OBJ_GFX_LOTAD_DOLL +}; + +const u16 DecorGfx_SEEDOT_DOLL[] = { + MAP_OBJ_GFX_SEEDOT_DOLL +}; + +const u16 DecorGfx_PIKA_CUSHION[] = { + MAP_OBJ_GFX_PIKA_CUSHION +}; + +const u16 DecorGfx_ROUND_CUSHION[] = { + MAP_OBJ_GFX_ROUND_CUSHION +}; + +const u16 DecorGfx_KISS_CUSHION[] = { + MAP_OBJ_GFX_KISS_CUSHION +}; + +const u16 DecorGfx_ZIGZAG_CUSHION[] = { + MAP_OBJ_GFX_ZIGZAG_CUSHION +}; + +const u16 DecorGfx_SPIN_CUSHION[] = { + MAP_OBJ_GFX_SPIN_CUSHION +}; + +const u16 DecorGfx_DIAMOND_CUSHION[] = { + MAP_OBJ_GFX_DIAMOND_CUSHION +}; + +const u16 DecorGfx_BALL_CUSHION[] = { + MAP_OBJ_GFX_BALL_CUSHION +}; + +const u16 DecorGfx_GRASS_CUSHION[] = { + MAP_OBJ_GFX_GRASS_CUSHION +}; + +const u16 DecorGfx_FIRE_CUSHION[] = { + MAP_OBJ_GFX_FIRE_CUSHION +}; + +const u16 DecorGfx_WATER_CUSHION[] = { + MAP_OBJ_GFX_WATER_CUSHION +}; + +const u16 DecorGfx_SNORLAX_DOLL[] = { + MAP_OBJ_GFX_BIG_SNORLAX_DOLL +}; + +const u16 DecorGfx_RHYDON_DOLL[] = { + MAP_OBJ_GFX_BIG_RHYDON_DOLL +}; + +const u16 DecorGfx_LAPRAS_DOLL[] = { + MAP_OBJ_GFX_BIG_LAPRAS_DOLL +}; + +const u16 DecorGfx_VENUSAUR_DOLL[] = { + MAP_OBJ_GFX_BIG_VENUSAUR_DOLL +}; + +const u16 DecorGfx_CHARIZARD_DOLL[] = { + MAP_OBJ_GFX_BIG_CHARIZARD_DOLL +}; + +const u16 DecorGfx_BLASTOISE_DOLL[] = { + MAP_OBJ_GFX_BIG_BLASTOISE_DOLL +}; + +const u16 DecorGfx_WAILMER_DOLL[] = { + MAP_OBJ_GFX_BIG_WAILMER_DOLL +}; + +const u16 DecorGfx_REGIROCK_DOLL[] = { + MAP_OBJ_GFX_BIG_REGIROCK_DOLL +}; + +const u16 DecorGfx_REGICE_DOLL[] = { + MAP_OBJ_GFX_BIG_REGICE_DOLL +}; + +const u16 DecorGfx_REGISTEEL_DOLL[] = { + MAP_OBJ_GFX_BIG_REGISTEEL_DOLL +}; + +#if ENGLISH +const struct Decoration gDecorations[] = { + {DECOR_NONE, _("SMALL DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x1, DECORCAT_DESK, 0, DecorDesc_SMALL_DESK, DecorGfx_SMALL_DESK}, + {DECOR_SMALL_DESK, _("SMALL DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x1, DECORCAT_DESK, 3000, DecorDesc_SMALL_DESK, DecorGfx_SMALL_DESK}, + {DECOR_POKEMON_DESK, _("POKéMON DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x1, DECORCAT_DESK, 3000, DecorDesc_POKEMON_DESK, DecorGfx_POKEMON_DESK}, + {DECOR_HEAVY_DESK, _("HEAVY DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_3x2, DECORCAT_DESK, 6000, DecorDesc_HEAVY_DESK, DecorGfx_HEAVY_DESK}, + {DECOR_RAGGED_DESK, _("RAGGED DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_3x2, DECORCAT_DESK, 6000, DecorDesc_RAGGED_DESK, DecorGfx_RAGGED_DESK}, + {DECOR_COMFORT_DESK, _("COMFORT DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_3x2, DECORCAT_DESK, 6000, DecorDesc_COMFORT_DESK, DecorGfx_COMFORT_DESK}, + {DECOR_PRETTY_DESK, _("PRETTY DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_3x3, DECORCAT_DESK, 9000, DecorDesc_PRETTY_DESK, DecorGfx_PRETTY_DESK}, + {DECOR_BRICK_DESK, _("BRICK DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_3x3, DECORCAT_DESK, 9000, DecorDesc_BRICK_DESK, DecorGfx_BRICK_DESK}, + {DECOR_CAMP_DESK, _("CAMP DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_3x3, DECORCAT_DESK, 9000, DecorDesc_CAMP_DESK, DecorGfx_CAMP_DESK}, + {DECOR_HARD_DESK, _("HARD DESK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_3x3, DECORCAT_DESK, 9000, DecorDesc_HARD_DESK, DecorGfx_HARD_DESK}, + {DECOR_SMALL_CHAIR, _("SMALL CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_SMALL_CHAIR, DecorGfx_SMALL_CHAIR}, + {DECOR_POKEMON_CHAIR, _("POKéMON CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_POKEMON_CHAIR, DecorGfx_POKEMON_CHAIR}, + {DECOR_HEAVY_CHAIR, _("HEAVY CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_HEAVY_CHAIR, DecorGfx_HEAVY_CHAIR}, + {DECOR_PRETTY_CHAIR, _("PRETTY CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_PRETTY_CHAIR, DecorGfx_PRETTY_CHAIR}, + {DECOR_COMFORT_CHAIR, _("COMFORT CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_COMFORT_CHAIR, DecorGfx_COMFORT_CHAIR}, + {DECOR_RAGGED_CHAIR, _("RAGGED CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_RAGGED_CHAIR, DecorGfx_RAGGED_CHAIR}, + {DECOR_BRICK_CHAIR, _("BRICK CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_BRICK_CHAIR, DecorGfx_BRICK_CHAIR}, + {DECOR_CAMP_CHAIR, _("CAMP CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_CAMP_CHAIR, DecorGfx_CAMP_CHAIR}, + {DECOR_HARD_CHAIR, _("HARD CHAIR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_CHAIR, 2000, DecorDesc_HARD_CHAIR, DecorGfx_HARD_CHAIR}, + {DECOR_RED_PLANT, _("RED PLANT"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_1x2, DECORCAT_PLANT, 3000, DecorDesc_RED_PLANT, DecorGfx_RED_PLANT}, + {DECOR_TROPICAL_PLANT, _("TROPICAL PLANT"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_1x2, DECORCAT_PLANT, 3000, DecorDesc_TROPICAL_PLANT, DecorGfx_TROPICAL_PLANT}, + {DECOR_PRETTY_FLOWERS, _("PRETTY FLOWERS"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_1x2, DECORCAT_PLANT, 3000, DecorDesc_PRETTY_FLOWERS, DecorGfx_PRETTY_FLOWERS}, + {DECOR_COLORFUL_PLANT, _("COLORFUL PLANT"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_2x2, DECORCAT_PLANT, 5000, DecorDesc_COLORFUL_PLANT, DecorGfx_COLORFUL_PLANT}, + {DECOR_BIG_PLANT, _("BIG PLANT"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_2x2, DECORCAT_PLANT, 5000, DecorDesc_BIG_PLANT, DecorGfx_BIG_PLANT}, + {DECOR_GORGEOUS_PLANT, _("GORGEOUS PLANT"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_2x2, DECORCAT_PLANT, 5000, DecorDesc_GORGEOUS_PLANT, DecorGfx_GORGEOUS_PLANT}, + {DECOR_RED_BRICK, _("RED BRICK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 500, DecorDesc_RED_BRICK, DecorGfx_RED_BRICK}, + {DECOR_YELLOW_BRICK, _("YELLOW BRICK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 500, DecorDesc_YELLOW_BRICK, DecorGfx_YELLOW_BRICK}, + {DECOR_BLUE_BRICK, _("BLUE BRICK"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 500, DecorDesc_BLUE_BRICK, DecorGfx_BLUE_BRICK}, + {DECOR_RED_BALLOON, _("RED BALLOON"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 500, DecorDesc_RED_BALLOON, DecorGfx_RED_BALLOON}, + {DECOR_BLUE_BALLOON, _("BLUE BALLOON"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 500, DecorDesc_BLUE_BALLOON, DecorGfx_BLUE_BALLOON}, + {DECOR_YELLOW_BALLOON, _("YELLOW BALLOON"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 500, DecorDesc_YELLOW_BALLOON, DecorGfx_YELLOW_BALLOON}, + {DECOR_RED_TENT, _("RED TENT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_ORNAMENT, 10000, DecorDesc_RED_TENT, DecorGfx_RED_TENT}, + {DECOR_BLUE_TENT, _("BLUE TENT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_ORNAMENT, 10000, DecorDesc_BLUE_TENT, DecorGfx_BLUE_TENT}, + {DECOR_SOLID_BOARD, _("SOLID BOARD"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 3000, DecorDesc_SOLID_BOARD, DecorGfx_SOLID_BOARD}, + {DECOR_SLIDE, _("SLIDE"), DECORPERM_PASS_FLOOR, DECORSHAPE_2x4, DECORCAT_ORNAMENT, 8000, DecorDesc_SLIDE, DecorGfx_SLIDE}, + {DECOR_FENCE_LENGTH, _("FENCE LENGTH"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 500, DecorDesc_FENCE_LENGTH, DecorGfx_FENCE_LENGTH}, + {DECOR_FENCE_WIDTH, _("FENCE WIDTH"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 500, DecorDesc_FENCE_WIDTH, DecorGfx_FENCE_WIDTH}, + {DECOR_TIRE, _("TIRE"), DECORPERM_SOLID_FLOOR, DECORSHAPE_2x2, DECORCAT_ORNAMENT, 800, DecorDesc_TIRE, DecorGfx_TIRE}, + {DECOR_STAND, _("STAND"), DECORPERM_PASS_FLOOR, DECORSHAPE_4x2, DECORCAT_ORNAMENT, 7000, DecorDesc_STAND, DecorGfx_STAND}, + {DECOR_MUD_BALL, _("MUD BALL"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 200, DecorDesc_MUD_BALL, DecorGfx_MUD_BALL}, + {DECOR_BREAKABLE_DOOR, _("BREAKABLE DOOR"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 3000, DecorDesc_BREAKABLE_DOOR, DecorGfx_BREAKABLE_DOOR}, + {DECOR_SAND_ORNAMENT, _("SAND ORNAMENT"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 3000, DecorDesc_SAND_ORNAMENT, DecorGfx_SAND_ORNAMENT}, + {DECOR_SILVER_SHIELD, _("SILVER SHIELD"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 0, DecorDesc_SILVER_SHIELD, DecorGfx_SILVER_SHIELD}, + {DECOR_GOLD_SHIELD, _("GOLD SHIELD"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 0, DecorDesc_GOLD_SHIELD, DecorGfx_GOLD_SHIELD}, + {DECOR_GLASS_ORNAMENT, _("GLASS ORNAMENT"), DECORPERM_BEHIND_FLOOR, DECORSHAPE_1x2, DECORCAT_ORNAMENT, 0, DecorDesc_GLASS_ORNAMENT, DecorGfx_GLASS_ORNAMENT}, + {DECOR_TV, _("TV"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 3000, DecorDesc_TV, DecorGfx_TV}, + {DECOR_ROUND_TV, _("ROUND TV"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 4000, DecorDesc_ROUND_TV, DecorGfx_ROUND_TV}, + {DECOR_CUTE_TV, _("CUTE TV"), DECORPERM_SOLID_FLOOR, DECORSHAPE_1x1, DECORCAT_ORNAMENT, 4000, DecorDesc_CUTE_TV, DecorGfx_CUTE_TV}, + {DECOR_GLITTER_MAT, _("GLITTER MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 2000, DecorDesc_GLITTER_MAT, DecorGfx_GLITTER_MAT}, + {DECOR_JUMP_MAT, _("JUMP MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 2000, DecorDesc_JUMP_MAT, DecorGfx_JUMP_MAT}, + {DECOR_SPIN_MAT, _("SPIN MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 2000, DecorDesc_SPIN_MAT, DecorGfx_SPIN_MAT}, + {DECOR_C_LOW_NOTE_MAT, _("C Low NOTE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 500, DecorDesc_C_LOW_NOTE_MAT, DecorGfx_C_LOW_NOTE_MAT}, + {DECOR_D_NOTE_MAT, _("D NOTE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 500, DecorDesc_D_NOTE_MAT, DecorGfx_D_NOTE_MAT}, + {DECOR_E_NOTE_MAT, _("E NOTE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 500, DecorDesc_E_NOTE_MAT, DecorGfx_E_NOTE_MAT}, + {DECOR_F_NOTE_MAT, _("F NOTE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 500, DecorDesc_F_NOTE_MAT, DecorGfx_F_NOTE_MAT}, + {DECOR_G_NOTE_MAT, _("G NOTE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 500, DecorDesc_G_NOTE_MAT, DecorGfx_G_NOTE_MAT}, + {DECOR_A_NOTE_MAT, _("A NOTE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 500, DecorDesc_A_NOTE_MAT, DecorGfx_A_NOTE_MAT}, + {DECOR_B_NOTE_MAT, _("B NOTE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 500, DecorDesc_B_NOTE_MAT, DecorGfx_B_NOTE_MAT}, + {DECOR_C_HIGH_NOTE_MAT, _("C High NOTE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_1x1, DECORCAT_MAT, 500, DecorDesc_C_HIGH_NOTE_MAT, DecorGfx_C_HIGH_NOTE_MAT}, + {DECOR_SURF_MAT, _("SURF MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_MAT, 4000, DecorDesc_SURF_MAT, DecorGfx_SURF_MAT}, + {DECOR_THUNDER_MAT, _("THUNDER MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_MAT, 4000, DecorDesc_THUNDER_MAT, DecorGfx_THUNDER_MAT}, + {DECOR_FIRE_BLAST_MAT, _("FIRE BLAST MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_MAT, 4000, DecorDesc_FIRE_BLAST_MAT, DecorGfx_FIRE_BLAST_MAT}, + {DECOR_POWDER_SNOW_MAT, _("POWDER SNOW MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_MAT, 4000, DecorDesc_POWDER_SNOW_MAT, DecorGfx_POWDER_SNOW_MAT}, + {DECOR_ATTRACT_MAT, _("ATTRACT MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_MAT, 4000, DecorDesc_ATTRACT_MAT, DecorGfx_ATTRACT_MAT}, + {DECOR_FISSURE_MAT, _("FISSURE MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_MAT, 4000, DecorDesc_FISSURE_MAT, DecorGfx_FISSURE_MAT}, + {DECOR_SPIKES_MAT, _("SPIKES MAT"), DECORPERM_PASS_FLOOR, DECORSHAPE_3x3, DECORCAT_MAT, 4000, DecorDesc_SPIKES_MAT, DecorGfx_SPIKES_MAT}, + {DECOR_BALL_POSTER, _("BALL POSTER"), DECORPERM_NA_WALL, DECORSHAPE_1x1, DECORCAT_POSTER, 1000, DecorDesc_BALL_POSTER, DecorGfx_BALL_POSTER}, + {DECOR_GREEN_POSTER, _("GREEN POSTER"), DECORPERM_NA_WALL, DECORSHAPE_1x1, DECORCAT_POSTER, 1000, DecorDesc_GREEN_POSTER, DecorGfx_GREEN_POSTER}, + {DECOR_RED_POSTER, _("RED POSTER"), DECORPERM_NA_WALL, DECORSHAPE_1x1, DECORCAT_POSTER, 1000, DecorDesc_RED_POSTER, DecorGfx_RED_POSTER}, + {DECOR_BLUE_POSTER, _("BLUE POSTER"), DECORPERM_NA_WALL, DECORSHAPE_1x1, DECORCAT_POSTER, 1000, DecorDesc_BLUE_POSTER, DecorGfx_BLUE_POSTER}, + {DECOR_CUTE_POSTER, _("CUTE POSTER"), DECORPERM_NA_WALL, DECORSHAPE_1x1, DECORCAT_POSTER, 1000, DecorDesc_CUTE_POSTER, DecorGfx_CUTE_POSTER}, + {DECOR_PIKA_POSTER, _("PIKA POSTER"), DECORPERM_NA_WALL, DECORSHAPE_2x1, DECORCAT_POSTER, 1500, DecorDesc_PIKA_POSTER, DecorGfx_PIKA_POSTER}, + {DECOR_LONG_POSTER, _("LONG POSTER"), DECORPERM_NA_WALL, DECORSHAPE_2x1, DECORCAT_POSTER, 1500, DecorDesc_LONG_POSTER, DecorGfx_LONG_POSTER}, + {DECOR_SEA_POSTER, _("SEA POSTER"), DECORPERM_NA_WALL, DECORSHAPE_2x1, DECORCAT_POSTER, 1500, DecorDesc_SEA_POSTER, DecorGfx_SEA_POSTER}, + {DECOR_SKY_POSTER, _("SKY POSTER"), DECORPERM_NA_WALL, DECORSHAPE_2x1, DECORCAT_POSTER, 1500, DecorDesc_SKY_POSTER, DecorGfx_SKY_POSTER}, + {DECOR_KISS_POSTER, _("KISS POSTER"), DECORPERM_NA_WALL, DECORSHAPE_2x1, DECORCAT_POSTER, 1500, DecorDesc_KISS_POSTER, DecorGfx_KISS_POSTER}, + {DECOR_PICHU_DOLL, _("PICHU DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_PICHU_DOLL, DecorGfx_PICHU_DOLL}, + {DECOR_PIKACHU_DOLL, _("PIKACHU DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_PIKACHU_DOLL, DecorGfx_PIKACHU_DOLL}, + {DECOR_MARILL_DOLL, _("MARILL DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_MARILL_DOLL, DecorGfx_MARILL_DOLL}, + {DECOR_TOGEPI_DOLL, _("TOGEPI DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_TOGEPI_DOLL, DecorGfx_TOGEPI_DOLL}, + {DECOR_CYNDAQUIL_DOLL, _("CYNDAQUIL DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_CYNDAQUIL_DOLL, DecorGfx_CYNDAQUIL_DOLL}, + {DECOR_CHIKORITA_DOLL, _("CHIKORITA DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_CHIKORITA_DOLL, DecorGfx_CHIKORITA_DOLL}, + {DECOR_TOTODILE_DOLL, _("TOTODILE DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_TOTODILE_DOLL, DecorGfx_TOTODILE_DOLL}, + {DECOR_JIGGLYPUFF_DOLL, _("JIGGLYPUFF DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_JIGGLYPUFF_DOLL, DecorGfx_JIGGLYPUFF_DOLL}, + {DECOR_MEOWTH_DOLL, _("MEOWTH DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_MEOWTH_DOLL, DecorGfx_MEOWTH_DOLL}, + {DECOR_CLEFAIRY_DOLL, _("CLEFAIRY DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_CLEFAIRY_DOLL, DecorGfx_CLEFAIRY_DOLL}, + {DECOR_DITTO_DOLL, _("DITTO DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_DITTO_DOLL, DecorGfx_DITTO_DOLL}, + {DECOR_SMOOCHUM_DOLL, _("SMOOCHUM DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_SMOOCHUM_DOLL, DecorGfx_SMOOCHUM_DOLL}, + {DECOR_TREECKO_DOLL, _("TREECKO DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_TREECKO_DOLL, DecorGfx_TREECKO_DOLL}, + {DECOR_TORCHIC_DOLL, _("TORCHIC DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_TORCHIC_DOLL, DecorGfx_TORCHIC_DOLL}, + {DECOR_MUDKIP_DOLL, _("MUDKIP DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_MUDKIP_DOLL, DecorGfx_MUDKIP_DOLL}, + {DECOR_DUSKULL_DOLL, _("DUSKULL DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_DUSKULL_DOLL, DecorGfx_DUSKULL_DOLL}, + {DECOR_WYNAUT_DOLL, _("WYNAUT DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_WYNAUT_DOLL, DecorGfx_WYNAUT_DOLL}, + {DECOR_BALTOY_DOLL, _("BALTOY DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_BALTOY_DOLL, DecorGfx_BALTOY_DOLL}, + {DECOR_KECLEON_DOLL, _("KECLEON DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_KECLEON_DOLL, DecorGfx_KECLEON_DOLL}, + {DECOR_AZURILL_DOLL, _("AZURILL DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_AZURILL_DOLL, DecorGfx_AZURILL_DOLL}, + {DECOR_SKITTY_DOLL, _("SKITTY DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_SKITTY_DOLL, DecorGfx_SKITTY_DOLL}, + {DECOR_SWABLU_DOLL, _("SWABLU DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_SWABLU_DOLL, DecorGfx_SWABLU_DOLL}, + {DECOR_GULPIN_DOLL, _("GULPIN DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_GULPIN_DOLL, DecorGfx_GULPIN_DOLL}, + {DECOR_LOTAD_DOLL, _("LOTAD DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_LOTAD_DOLL, DecorGfx_LOTAD_DOLL}, + {DECOR_SEEDOT_DOLL, _("SEEDOT DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_DOLL, 3000, DecorDesc_SEEDOT_DOLL, DecorGfx_SEEDOT_DOLL}, + {DECOR_PIKA_CUSHION, _("PIKA CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_PIKA_CUSHION, DecorGfx_PIKA_CUSHION}, + {DECOR_ROUND_CUSHION, _("ROUND CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_ROUND_CUSHION, DecorGfx_ROUND_CUSHION}, + {DECOR_KISS_CUSHION, _("KISS CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_KISS_CUSHION, DecorGfx_KISS_CUSHION}, + {DECOR_ZIGZAG_CUSHION, _("ZIGZAG CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_ZIGZAG_CUSHION, DecorGfx_ZIGZAG_CUSHION}, + {DECOR_SPIN_CUSHION, _("SPIN CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_SPIN_CUSHION, DecorGfx_SPIN_CUSHION}, + {DECOR_DIAMOND_CUSHION, _("DIAMOND CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_DIAMOND_CUSHION, DecorGfx_DIAMOND_CUSHION}, + {DECOR_BALL_CUSHION, _("BALL CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_BALL_CUSHION, DecorGfx_BALL_CUSHION}, + {DECOR_GRASS_CUSHION, _("GRASS CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_GRASS_CUSHION, DecorGfx_GRASS_CUSHION}, + {DECOR_FIRE_CUSHION, _("FIRE CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_FIRE_CUSHION, DecorGfx_FIRE_CUSHION}, + {DECOR_WATER_CUSHION, _("WATER CUSHION"), DECORPERM_SOLID_MAT, DECORSHAPE_1x1, DECORCAT_CUSHION, 2000, DecorDesc_WATER_CUSHION, DecorGfx_WATER_CUSHION}, + {DECOR_SNORLAX_DOLL, _("SNORLAX DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_SNORLAX_DOLL, DecorGfx_SNORLAX_DOLL}, + {DECOR_RHYDON_DOLL, _("RHYDON DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_RHYDON_DOLL, DecorGfx_RHYDON_DOLL}, + {DECOR_LAPRAS_DOLL, _("LAPRAS DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_LAPRAS_DOLL, DecorGfx_LAPRAS_DOLL}, + {DECOR_VENUSAUR_DOLL, _("VENUSAUR DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_VENUSAUR_DOLL, DecorGfx_VENUSAUR_DOLL}, + {DECOR_CHARIZARD_DOLL, _("CHARIZARD DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_CHARIZARD_DOLL, DecorGfx_CHARIZARD_DOLL}, + {DECOR_BLASTOISE_DOLL, _("BLASTOISE DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_BLASTOISE_DOLL, DecorGfx_BLASTOISE_DOLL}, + {DECOR_WAILMER_DOLL, _("WAILMER DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_WAILMER_DOLL, DecorGfx_WAILMER_DOLL}, + {DECOR_REGIROCK_DOLL, _("REGIROCK DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_REGIROCK_DOLL, DecorGfx_REGIROCK_DOLL}, + {DECOR_REGICE_DOLL, _("REGICE DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_REGICE_DOLL, DecorGfx_REGICE_DOLL}, + {DECOR_REGISTEEL_DOLL, _("REGISTEEL DOLL"), DECORPERM_SOLID_MAT, DECORSHAPE_1x2, DECORCAT_DOLL, 10000, DecorDesc_REGISTEEL_DOLL, DecorGfx_REGISTEEL_DOLL} +}; +#elif GERMAN +#include "../data/decoration/decorations.h" +#endif + +const u8 *const gUnknown_083EC5E4[] = { + SecretBaseText_Desk, + SecretBaseText_Chair, + SecretBaseText_Plant, + SecretBaseText_Ornament, + SecretBaseText_Mat, + SecretBaseText_Poster, + SecretBaseText_Doll, + SecretBaseText_Cushion +}; + +const struct MenuAction2 gUnknown_083EC604[] = { + {SecretBaseText_Decorate, sub_80FF160}, + {SecretBaseText_PutAway, sub_8100A0C}, + {SecretBaseText_Toss, sub_8101700}, + {gUnknownText_Exit, gpu_pal_decompress_alloc_tag_and_upload} +}; + +const u8 *const gUnknown_083EC624[] = { + SecretBaseText_PutOutDecor, + SecretBaseText_StoreChosenDecor, + SecretBaseText_ThrowAwayDecor, + gMenuText_GoBackToPrev +}; + +const struct YesNoFuncTable gUnknown_083EC634[] = { + {sub_80FF5BC, sub_80FF058}, + {sub_81017A0, sub_80FF058}, + {sub_81017A0, sub_80FF058}, + {sub_8109D04, sub_80FF058} +}; + +const u16 gUnknown_083EC654[] = {0x6318, 0x739C, 0x7FFF}; +const u8 gUnknown_083EC65A[] = _("{PALETTE 13}{STR_VAR_1}"); + +const u8 Unknown_3EC660[] = {0, 1, 2, 3}; +const u8 Unknown_3EC664[] = {0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13}; +const u8 Unknown_3EC670[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; +const u8 Unknown_3EC680[] = {0, 1, 4, 5, 8, 9, 12, 13, 16, 17, 20, 21}; +const u8 Unknown_3EC68C[] = {0, 1, 2, 3, 4, 5, 6, 7}; +const u8 Unknown_3EC694[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31}; +const u8 Unknown_3EC6B4[] = {0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29, 32, 33, 34, 35, 36, 37, 40, 41, 42, 43, 44, 45}; +const u8 Unknown_3EC6D8[] = {0, 1, 2, 3, 4, 5, 8, 9, 10, 11, 12, 13, 16, 17, 18, 19, 20, 21, 24, 25, 26, 27, 28, 29}; + +const u8 Unknown_3EC6F0[] = {0, 0, 0, 0}; +const u8 Unknown_3EC6F4[] = {0, 0, 1, 1, 0, 0, 1, 1}; +const u8 Unknown_3EC6FC[] = {0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2}; +const u8 Unknown_3EC708[] = {0, 0, 1, 1, 2, 2, 3, 3, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 4, 4, 5, 5, 6, 6, 7, 7}; +const u8 Unknown_3EC728[] = {0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3}; +const u8 Unknown_3EC738[] = {0, 0, 0, 0, 1, 1, 1, 1}; +const u8 Unknown_3EC740[] = {0, 0, 0, 0, 1, 1, 1, 1, 2, 2, 2, 2}; +const u8 Unknown_3EC74C[] = {0, 0, 1, 1, 0, 0, 1, 1, 2, 2, 3, 3, 2, 2, 3, 3, 4, 4, 5, 5, 4, 4, 5, 5, 6, 6, 7, 7, 6, 6, 7, 7}; +const u8 Unknown_3EC76C[] = {0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 8, 8, 6, 6, 7, 7, 8, 8}; +const u8 Unknown_3EC790[] = {0, 0, 1, 1, 2, 2, 0, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 3, 3, 4, 4, 5, 5}; + +const u8 Unknown_3EC7A8[] = {4, 5, 6, 7}; +const u8 Unknown_3EC7AC[] = {4, 5, 4, 5, 6, 7, 6, 7}; +const u8 Unknown_3EC7B4[] = {4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7}; +const u8 Unknown_3EC7C0[] = {4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7, 4, 5, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 6, 7}; +const u8 Unknown_3EC7E0[] = {4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7}; +const u8 Unknown_3EC7F0[] = {4, 5, 6, 7, 4, 5, 6, 7}; +const u8 Unknown_3EC7F8[] = {4, 5, 6, 7, 4, 5, 6, 7, 4, 5, 6, 7}; +const u8 Unknown_3EC804[] = {4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7, 4, 5, 4, 5, 6, 7, 6, 7}; +const u8 Unknown_3EC824[] = {4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7}; +const u8 Unknown_3EC848[] = {4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7, 4, 5, 4, 5, 4, 5, 6, 7, 6, 7, 6, 7}; + +const struct UnkStruct_803EC860 gUnknown_083EC860[] = { + {Unknown_3EC660, Unknown_3EC6F0, Unknown_3EC7A8, 0x4}, + {Unknown_3EC68C, Unknown_3EC6F4, Unknown_3EC7AC, 0x8}, + {Unknown_3EC664, Unknown_3EC6FC, Unknown_3EC7B4, 0xc}, + {Unknown_3EC694, Unknown_3EC708, Unknown_3EC7C0, 0x20}, + {Unknown_3EC670, Unknown_3EC728, Unknown_3EC7E0, 0x10}, + {Unknown_3EC68C, Unknown_3EC738, Unknown_3EC7F0, 0x8}, + {Unknown_3EC680, Unknown_3EC740, Unknown_3EC7F8, 0xc}, + {Unknown_3EC694, Unknown_3EC74C, Unknown_3EC804, 0x20}, + {Unknown_3EC6B4, Unknown_3EC76C, Unknown_3EC824, 0x24}, + {Unknown_3EC6D8, Unknown_3EC790, Unknown_3EC848, 0x18} +}; + +const struct UnkStruct_083EC900 gUnknown_083EC900[] = { + {0, 1, 0x78, 0x4e}, + {1, 2, 0x80, 0x4e}, + {1, 3, 0x90, 0x56}, + {1, 3, 0x90, 0x46}, + {0, 2, 0x80, 0x46}, + {2, 2, 0x78, 0x46}, + {2, 3, 0x80, 0x56}, + {2, 3, 0x80, 0x36}, + {0, 3, 0x90, 0x46}, + {1, 3, 0x90, 0x46} +}; + +const union AnimCmd gSpriteAnim_83EC928[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 0), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_83EC930[] = { + gSpriteAnim_83EC928 +}; + +const struct SpriteFrameImage gSpriteImageTable_83EC934[] = { + {.data = (u8 *)&gUnknown_02038900.image, .size = sizeof gUnknown_02038900.image} +}; + +const struct SpriteTemplate gSpriteTemplate_83EC93C = { + .tileTag = 0xffff, + .paletteTag = 3000, + .oam = &gUnknown_020391AC, + .anims = gSpriteAnimTable_83EC930, + .images = gSpriteImageTable_83EC934, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_81009A8 +}; + +const struct SpritePalette gUnknown_083EC954 = {.data = (u16 *)&gUnknown_02038900.palette, .tag = 3000}; + +const struct YesNoFuncTable gUnknown_083EC95C = {.yesFunc = sub_81000C4, .noFunc = sub_810065C}; +const struct YesNoFuncTable gUnknown_083EC964 = {.yesFunc = sub_810026C, .noFunc = sub_810065C}; +const struct YesNoFuncTable gUnknown_083EC96C[] = { + {.yesFunc = sub_80FFAB0, .noFunc = sub_80FFB08}, + {.yesFunc = sub_8100F88, .noFunc = sub_8100FB4} +}; + +const u8 gUnknown_083EC97C[] = {4, 4, 4, 4, 0, 3, 3, 0}; +const u8 gUnknown_083EC984[] = {4, 4, 4, 4, 0, 4, 3, 0}; + +const u16 gUnknown_083EC98C[] = INCBIN_U16("graphics/unknown/83EC98C.gbapal"); +const u16 Unknown_3EC9AC[] = INCBIN_U16("graphics/unknown/83EC9AC.gbapal"); +const struct YesNoFuncTable gUnknown_083EC9CC = {.yesFunc = sub_810153C, .noFunc = sub_8100EEC}; +const struct YesNoFuncTable gUnknown_083EC9D4 = {.yesFunc = sub_8101590, .noFunc = sub_8100EEC}; +const u32 gSpriteImage_83EC9DC[] = INCBIN_U32("graphics/unknown_sprites/83EC9DC.4bpp"); +const struct SpritePalette gUnknown_083ECA5C = {.data = gUnknown_083EC98C, .tag = 8}; +const struct SpritePalette gUnknown_083ECA64 = {.data = Unknown_3EC9AC, .tag = 8}; +const struct OamData gOamData_83ECA6C = { + .size = 1, .priority = 1 +}; + +const union AnimCmd gSpriteAnim_83ECA74[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 0), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_83ECA7C[] = { + gSpriteAnim_83ECA74 +}; + +const struct SpriteFrameImage gSpriteImageTable_83ECA80[] = { + obj_frame_tiles(gSpriteImage_83EC9DC) +}; + +const struct SpriteTemplate gSpriteTemplate_83ECA88 = { + .tileTag = 0xffff, + .paletteTag = 8, + .oam = &gOamData_83ECA6C, + .anims = gSpriteAnimTable_83ECA7C, + .images = gSpriteImageTable_83ECA80, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_8101698 +}; + +const struct YesNoFuncTable gUnknown_083ECAA0 = {.yesFunc = sub_8101848, .noFunc = sub_80FED3C}; + +u8 *const unref_label_083ECAA8[] = {ewram}; + +// text + +extern u8 gUnknown_0815F399[]; + +void sub_80FE1DC(void) +{ + sub_80FE2B4(); + MenuDrawTextWindow(0, 0, 10, 9); + PrintMenuItems(1, 1, 4, (const struct MenuAction *)gUnknown_083EC604); + InitMenu(0, 1, 1, 4, gUnknown_020388D4, 9); +} + +void sub_80FE220(void) +{ + gUnknown_020388D4 = 0; + ScriptContext2_Enable(); + sub_80FE1DC(); + sub_80FE394(); +} + +void DecorationPC(u8 taskId) +{ + sub_80FE220(); + gTasks[taskId].func = Task_DecorationPCProcessMenuInput; +} + +void Task_SecretBasePC_Decoration(u8 taskId) +{ + DecorationPC(taskId); + ewram_1f000.items = gSaveBlock1.secretBases[0].decorations; + ewram_1f000.pos = gSaveBlock1.secretBases[0].decorationPos; + ewram_1f000.size = sizeof gSaveBlock1.secretBases[0].decorations; + ewram_1f000.isPlayerRoom = 0; +} + +void DoPlayerPCDecoration(u8 taskId) +{ + DecorationPC(taskId); + ewram_1f000.items = gSaveBlock1.playerRoomDecor; + ewram_1f000.pos = gSaveBlock1.playerRoomDecorPos; + ewram_1f000.size = sizeof gSaveBlock1.playerRoomDecor; + ewram_1f000.isPlayerRoom = 1; +} + +void sub_80FE2B4(void) +{ + u16 palettes[3]; + memcpy(palettes, gUnknown_083EC654, sizeof gUnknown_083EC654); + LoadPalette(&palettes[2], 0xdf, 2); + LoadPalette(&palettes[1], 0xd1, 2); + LoadPalette(&palettes[0], 0xd8, 2); +} + +void Task_DecorationPCProcessMenuInput(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gMain.newKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + gUnknown_020388D4 = MoveMenuCursor(-1); + sub_80FE394(); + } + if (gMain.newKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + gUnknown_020388D4 = MoveMenuCursor(1); + sub_80FE394(); + } + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + gUnknown_083EC604[gUnknown_020388D4].func(taskId); + } else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gpu_pal_decompress_alloc_tag_and_upload(taskId); + } + } +} + +void sub_80FE394(void) +{ + MenuFillWindowRectWithBlankTile(2, 15, 27, 18); + MenuPrint(gUnknown_083EC624[gUnknown_020388D4], 2, 15); +} + +void gpu_pal_decompress_alloc_tag_and_upload(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 10, 9); + MenuFillWindowRectWithBlankTile(2, 15, 27, 18); + FreeSpritePaletteByTag(6); + if (ewram_1f000.isPlayerRoom == 0) + { + ScriptContext1_SetupScript(gUnknown_0815F399); + DestroyTask(taskId); + } else + { + ReshowPlayerPC(taskId); + } +} + +void sub_80FE418(u8 taskId) +{ + sub_80FE5AC(taskId); +} + +void sub_80FE428(u8 taskId) +{ + InitMenu(0, 1, 1, 4, gUnknown_020388D4, 9); + sub_80FE394(); + gTasks[taskId].func = Task_DecorationPCProcessMenuInput; +} + +void sub_80FE470(u8 decoCat, u8 left, u8 top, u8 palIdx) // PrintDecorationCategorySelectionMenuString +{ + u8 *strptr; + u8 v0; + v0 = sub_8072CBC(); + // PALETTE {palIdx} + strptr = gStringVar4; + strptr[0] = EXT_CTRL_CODE_BEGIN; + strptr[1] = 5; + strptr[2] = palIdx; + strptr += 3; + strptr = StringCopy(strptr, gUnknown_083EC5E4[decoCat]); + strptr = sub_8072C14(strptr, sub_8134194(decoCat), 0x56, 1); + *strptr++ = 0xba; + strptr = sub_8072C14(strptr, gDecorationInventories[decoCat].size, 0x68, 1); + strptr[0] = EXT_CTRL_CODE_BEGIN; + strptr[1] = 5; + strptr[2] = v0; + strptr[3] = EOS; + MenuPrint(gStringVar4, left, top); +} + +void sub_80FE528(u8 taskId) // PrintDecorationCategorySelectionMenuStrings +{ + u8 decoCat; + MenuDrawTextWindow(0, 0, 14, 19); + for (decoCat=0; decoCat<8; decoCat++) + { + if (ewram_1f000.isPlayerRoom == 1 && gTasks[taskId].data[11] == 0 && decoCat != DECORCAT_DOLL && decoCat != DECORCAT_CUSHION) + { + sub_80FE470(decoCat, 1, 2 * decoCat + 1, 13); // Selectable + } else + { + sub_80FE470(decoCat, 1, 2 * decoCat + 1, 255); // Unselectable + } + } + MenuPrint(gUnknownText_Exit, 1, 17); +} + +void sub_80FE5AC(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 29, 19); + sub_80FE528(taskId); + InitMenu(0, 1, 1, 9, gUnknown_020388F6, 13); + gTasks[taskId].func = sub_80FE604; +} + +void sub_80FE604(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + } else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + } else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + gUnknown_020388F6 = GetMenuCursorPos(); + if (gUnknown_020388F6 != 8) + { + gUnknown_020388D5 = sub_8134194(gUnknown_020388F6); + if (gUnknown_020388D5) + { + sub_8134104(gUnknown_020388F6); + gUnknown_020388D0 = gDecorationInventories[gUnknown_020388F6].items; + sub_80FEF50(taskId); + sub_80F944C(); + sub_80F9480(gUnknown_020388F7, 8); + LoadScrollIndicatorPalette(); + gTasks[taskId].func = sub_80FE868; + } else + { + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 14, 19); + DisplayItemMessageOnField(taskId, gSecretBaseText_NoDecors, sub_80FE418, 0); + } + } else + { + sub_80FE728(taskId); + } + } else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + sub_80FE728(taskId); + } + } +} + +void sub_80FE728(u8 taskId) +{ + if (gTasks[taskId].data[11] != 3) + { + sub_80FE758(taskId); + } else + { + sub_8109DAC(taskId); + } +} + +void sub_80FE758(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 14, 19); + if (gTasks[taskId].data[11] != 2) + { + sub_80FE1DC(); + MenuDisplayMessageBox(); + sub_80FE394(); + gTasks[taskId].func = Task_DecorationPCProcessMenuInput; + } else + { + sub_80B3068(taskId); + } +} + +void sub_80FE7A8(u8 taskId) +{ + gTasks[taskId].data[11] = 3; + gUnknown_020388F6 = 0; + sub_80FE5AC(taskId); +} + +void sub_80FE7D4(u8 *dest, u8 decClass) +{ + StringCopy(dest, gUnknown_083EC5E4[decClass]); +} + +void sub_80FE7EC(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 29, 19); + + sub_80FEC94(taskId); + sub_80FECB8(gUnknown_020388F6); + +#if ENGLISH + MenuDrawTextWindow(15, 12, 29, 19); +#elif GERMAN + if ((gUnknown_020388F2 + gUnknown_020388F4) != gUnknown_020388D5) + { + MenuDrawTextWindow(15, 12, 29, 19); + } +#endif + + sub_80FECE0(gUnknown_020388F2 + gUnknown_020388F4); + InitMenu(0, 1, 2, gUnknown_020388F3 + 1, gUnknown_020388F2, 13); +} + +void sub_80FE868(u8 taskId) +{ + sub_80FE7EC(taskId); + gTasks[taskId].func = sub_80FE948; +} + +void sub_80FE894(u8 taskId /*r8*/, s8 cursorVector /*r5*/, s8 bgVector /*r7*/) +{ + int v0 /*r10*/; + u8 v1; + v0 = gUnknown_020388F2 + gUnknown_020388F4 == gUnknown_020388D5; + PlaySE(SE_SELECT); + if (cursorVector != 0) + { + gUnknown_020388F2 = MoveMenuCursor(cursorVector); + } + if (bgVector != 0) + { + v1 = gUnknown_020388F4; + gUnknown_020388F4 = v1 + bgVector; + sub_80FEABC(taskId, 1); + } + if (gUnknown_020388F2 + gUnknown_020388F4 != gUnknown_020388D5) + { + if (v0) + { + MenuDrawTextWindow(15, 12, 29, 19); + } + sub_80FECE0(gUnknown_020388F2 + gUnknown_020388F4); + } else + { + MenuZeroFillWindowRect(15, 12, 29, 19); + } +} + +void sub_80FE948(u8 taskId) +{ + if (!gPaletteFade.active) + { + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP) + { + if (gUnknown_020388F2 != 0) + { + sub_80FE894(taskId, -1, 0); + } else if (gUnknown_020388F4 != 0) + { + sub_80FE894(taskId, 0, -1); + } + } + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN) + { + if (gUnknown_020388F2 != gUnknown_020388F3) + { + sub_80FE894(taskId, 1, 0); + } else if (gUnknown_020388F4 + gUnknown_020388F2 != gUnknown_020388D5) + { + sub_80FE894(taskId, 0, 1); + } + } + if (gMain.newKeys & A_BUTTON) + { + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + gUnknown_020388F5 = gUnknown_020388F2 + gUnknown_020388F4; + if (gUnknown_020388F5 == gUnknown_020388D5) + { + gUnknown_083EC634[gTasks[taskId].data[11]].noFunc(taskId); + } else + { + gUnknown_083EC634[gTasks[taskId].data[11]].yesFunc(taskId); + } + } else if (gMain.newKeys & B_BUTTON) + { + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + gUnknown_083EC634[gTasks[taskId].data[11]].noFunc(taskId); + } + } +} + +void sub_80FEABC(u8 taskId, u8 dummy1) +{ + u16 i; + u16 j; + u8 ni; + if (gUnknown_020388F4 != 0 || (DestroyVerticalScrollIndicator(0), gUnknown_020388F4 != 0)) + { + CreateVerticalScrollIndicators(0, 0x3c, 0x08); + } + if (gUnknown_020388F4 + 7 == gUnknown_020388D5) + { + DestroyVerticalScrollIndicator(1); + } + if (gUnknown_020388F4 + 7 < gUnknown_020388D5) + { + CreateVerticalScrollIndicators(1, 0x3c, 0x98); + } + for (i=gUnknown_020388F4; i<gUnknown_020388F4+8; i++) + { + ni = 2 * (i - gUnknown_020388F4) + 2; + if (gUnknown_020388F7[i - gUnknown_020388F4]) + { + sub_80F94F8(&gUnknown_020388F7[i - gUnknown_020388F4]); + } + if (i == gUnknown_020388D5) + { + sub_8072A18(gUnknownText_Exit, 0x08, 8 * ni, 0x68, 1); + break; + } + if (gUnknown_020388D0[i]) + { + if (ewram_1f000.isPlayerRoom == 1 && gUnknown_020388F6 != DECORCAT_DOLL && gUnknown_020388F6 != DECORCAT_CUSHION && gTasks[taskId].data[11] == 0) + { + StringCopy(gStringVar1, gDecorations[gUnknown_020388D0[i]].name); + sub_8072A18(gUnknown_083EC65A, 0x08, 8 * ni, 0x68, 1); + } else + { + sub_8072A18(gDecorations[gUnknown_020388D0[i]].name, 0x08, 8 * ni, 0x68, 1); + } + for (j=0; j<16; j++) + { + if (gUnknown_020388D6[j] - 1 == i) + { + sub_80F94A4(4, &gUnknown_020388F7[i - gUnknown_020388F4], 0x6c, (i - gUnknown_020388F4) * 16 + 24); + break; + } + } + for (j=0; j<12; j++) + { + if (gUnknown_020388E6[j] - 1 == i) + { + sub_80F94A4(5, &gUnknown_020388F7[i - gUnknown_020388F4], 0x6c, (i - gUnknown_020388F4) * 16 + 24); + break; + } + } + } + } +} + +void sub_80FEC94(u8 taskId) +{ + MenuDrawTextWindow(0, 0, 14, 19); + sub_80FEABC(taskId, 0); +} + +void sub_80FECB8(u8 decoCat) +{ + MenuDrawTextWindow(15, 0, 29, 3); + sub_80FE470(decoCat, 16, 1, 0xff); +} + +#if ENGLISH +void sub_80FECE0(u8 decoCat) +{ + sub_8072AB0(gDecorations[gUnknown_020388D0[decoCat]].description, 0x80, 0x68, 0x68, 0x30, 0x1); +} +#elif GERMAN +__attribute__((naked)) +void sub_80FECE0(u8 decoCat) +{ + asm(".syntax unified\n\ + push {lr}\n\ + sub sp, 0x8\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + ldr r0, _080FED18 @ =gUnknown_020388D5\n\ + ldrb r0, [r0]\n\ + cmp r2, r0\n\ + beq _080FED24\n\ + ldr r1, _080FED1C @ =gDecorations\n\ + ldr r0, _080FED20 @ =gUnknown_020388D0\n\ + ldr r0, [r0]\n\ + adds r0, r2\n\ + ldrb r0, [r0]\n\ + lsls r0, 5\n\ + adds r1, 0x18\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + movs r1, 0x30\n\ + str r1, [sp]\n\ + movs r1, 0x1\n\ + str r1, [sp, 0x4]\n\ + movs r1, 0x80\n\ + movs r2, 0x68\n\ + movs r3, 0x68\n\ + bl sub_8072AB0\n\ + movs r0, 0x1\n\ + b _080FED26\n\ + .align 2, 0\n\ +_080FED18: .4byte gUnknown_020388D5\n\ +_080FED1C: .4byte gDecorations\n\ +_080FED20: .4byte gUnknown_020388D0\n\ +_080FED24:\n\ + movs r0, 0\n\ +_080FED26:\n\ + add sp, 0x8\n\ + pop {r1}\n\ + bx r1\n\ + .syntax divided\n"); +} +#endif + +void sub_80FED1C(void) +{ + MenuZeroFillWindowRect(15, 0, 29, 3); + MenuZeroFillWindowRect(15, 12, 29, 19); +} + +void sub_80FED3C(u8 taskId) +{ + LoadScrollIndicatorPalette(); + gTasks[taskId].func = sub_80FE868; +} + +bool8 sub_80FED64(u8 a0) +{ + u8 i; + for (i=0; i<16; i++) + { + if (gUnknown_020388D6[i] == a0) + { + return TRUE; + } + } + return FALSE; +} + +void sub_80FED90(u8 taskId) +{ + u16 i; + u16 j; + u16 k; + u16 cnt; + cnt = 0; + for (i=0; i<16; i++) + { + gUnknown_020388D6[i] = 0; + if (i < 12) + { + gUnknown_020388E6[i] = 0; + } + } + for (i=0; i<16; i++) + { + if (gSaveBlock1.secretBases[0].decorations[i] != 0) + { + for (j=0; j<gDecorationInventories[gUnknown_020388F6].size; j++) + { + if (gUnknown_020388D0[j] == gSaveBlock1.secretBases[0].decorations[i]) + { + for (k=0; k<cnt && gUnknown_020388D6[k]!=j+1; k++); + if (k == cnt) + { + gUnknown_020388D6[cnt] = j+1; + cnt++; + break; + } + } + } + } + } + cnt = 0; + for (i=0; i<12; i++) + { + if (gSaveBlock1.playerRoomDecor[i] != 0) + { + for (j=0; j<gDecorationInventories[gUnknown_020388F6].size; j++) + { + if (gUnknown_020388D0[j] == gSaveBlock1.playerRoomDecor[i] && !sub_80FED64(j + 1)) + { + for (k=0; k<cnt && gUnknown_020388E6[k]!=j+1; k++); + if (k == cnt) + { + gUnknown_020388E6[cnt] = j+1; + cnt++; + break; + } + } + } + } + } +} + +void sub_80FEF28(void) +{ + if (gUnknown_020388D5 <= 7) + { + gUnknown_020388F3 = gUnknown_020388D5; + } else + { + gUnknown_020388F3 = 7; + } +} + +void sub_80FEF50(u8 taskId) +{ + sub_80FED90(taskId); + sub_80FEF28(); + gUnknown_020388F2 = 0; + gUnknown_020388F4 = 0; +} + +void sub_80FEF74(void) +{ + sub_80F9520(gUnknown_020388F7, 8); + DestroyVerticalScrollIndicator(0); + DestroyVerticalScrollIndicator(1); + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 14, 19); +} + +bool8 sub_80FEFA4(void) +{ + u16 i; + int v0; + for (i=0; i<16; i++) + { + v0 = gUnknown_020388F4 + gUnknown_020388F2 + 1; + if (gUnknown_020388D6[i] == v0 || (i < 12 && gUnknown_020388E6[i] == v0)) + { + return FALSE; + } + } + return TRUE; +} + +void sub_80FEFF4(u8 taskId) +{ + if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) + { + LoadScrollIndicatorPalette(); + gTasks[taskId].func = sub_80FE868; + } +} + +void sub_80FF034(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 14, 19); + sub_80FE5AC(taskId); +} + +void sub_80FF058(u8 taskId) +{ + sub_80F9520(gUnknown_020388F7, 8); + DestroyVerticalScrollIndicator(0); + DestroyVerticalScrollIndicator(1); + BuyMenuFreeMemory(); + gTasks[taskId].func = sub_80FF034; +} + +void sub_80FF098(u8 taskId) +{ + gUnknown_020388D5--; + if (gUnknown_020388F4 + 7 > gUnknown_020388D5 && gUnknown_020388F4 != 0) + { + gUnknown_020388F4--; + } + sub_8134104(gUnknown_020388F6); + sub_80FED90(taskId); + sub_80FEF28(); +} + +void sub_80FF0E0(u8 taskId) +{ + gTasks[taskId].data[3] = gSaveBlock1.pos.x; + gTasks[taskId].data[4] = gSaveBlock1.pos.y; + PlayerGetDestCoords(&gTasks[taskId].data[0], &gTasks[taskId].data[1]); +} + +void sub_80FF114(u8 taskId) +{ + DrawWholeMapView(); + Overworld_SetWarpDestination(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum, -1, gTasks[taskId].data[3], gTasks[taskId].data[4]); + warp_in(); +} +void sub_80FF160(u8 taskId) +{ + if (!sub_81341D4()) + { + DisplayItemMessageOnField(taskId, gSecretBaseText_NoDecors, sub_80FE428, 0); + } else + { + gTasks[taskId].data[11] = 0; + gUnknown_020388F6 = 0; + sub_80FE5AC(taskId); + } +} + +u16 sub_80FF1B0(u8 decoId, u8 a1) +{ + u16 retval; + retval = 0xffff; + + switch (decoId) + { + case DECOR_STAND: + retval = gUnknown_083EC97C[a1] << 12; + return retval; + case DECOR_SLIDE: + retval = gUnknown_083EC984[a1] << 12; + return retval; + default: + return retval; + } +} + +void sub_80FF1EC(u16 mapX, u16 mapY, u8 decWidth, u8 decHeight, u16 decIdx) +{ + u16 i; + u16 j; // r10 + u16 behavior; + u16 flags; // r8 + u16 v0; + u16 v1; + s16 x; + s16 decBottom; + + for (i=0; i<decHeight; i++) + { + decBottom = mapY - decHeight + 1 + i; + for (j=0; j<decWidth; j++) + { + x = mapX + j; + behavior = GetBehaviorByMetatileId(0x200 + gDecorations[decIdx].tiles[i * decWidth + j]); + if (sub_8057288(behavior) == 1 || (gDecorations[decIdx].permission != DECORPERM_PASS_FLOOR && (behavior >> 12))) + { + flags = 0xc00; + } else + { + flags = 0x000; + } + if (gDecorations[decIdx].permission != DECORPERM_NA_WALL && sub_80572B0(MapGridGetMetatileBehaviorAt(x, decBottom)) == 1) + { + v0 = 1; + } else + { + v0 = 0; + } + v1 = sub_80FF1B0(gDecorations[decIdx].id, i * decWidth + j); + if (v1 != 0xffff) + { + MapGridSetMetatileEntryAt(x, decBottom, (gDecorations[decIdx].tiles[i * decWidth + j] + (0x200 | v0)) | flags | v1); + } else + { + MapGridSetMetatileIdAt(x, decBottom, (gDecorations[decIdx].tiles[i * decWidth + j] + (0x200 | v0)) | flags); + } + } + } +} + +void sub_80FF394(u16 mapX, u16 mapY, u16 decIdx) +{ + switch (gDecorations[decIdx].shape) + { + case DECORSHAPE_1x1: + sub_80FF1EC(mapX, mapY, 1, 1, decIdx); + break; + case DECORSHAPE_2x1: + sub_80FF1EC(mapX, mapY, 2, 1, decIdx); + break; + case DECORSHAPE_3x1: // unused + sub_80FF1EC(mapX, mapY, 3, 1, decIdx); + break; + case DECORSHAPE_4x2: + sub_80FF1EC(mapX, mapY, 4, 2, decIdx); + break; + case DECORSHAPE_2x2: + sub_80FF1EC(mapX, mapY, 2, 2, decIdx); + break; + case DECORSHAPE_1x2: + sub_80FF1EC(mapX, mapY, 1, 2, decIdx); + break; + case DECORSHAPE_1x3: // unused + sub_80FF1EC(mapX, mapY, 1, 3, decIdx); + break; + case DECORSHAPE_2x4: + sub_80FF1EC(mapX, mapY, 2, 4, decIdx); + break; + case DECORSHAPE_3x3: + sub_80FF1EC(mapX, mapY, 3, 3, decIdx); + break; + case DECORSHAPE_3x2: + sub_80FF1EC(mapX, mapY, 3, 2, decIdx); + break; + } +} + +void sub_80FF474(void) +{ + u8 i; + u8 j; + for (i=0; i<14; i++) + { + if (FlagGet(i + 0xae) == 1) + { + FlagClear(i + 0xae); + for (j=0; j<gMapHeader.events->mapObjectCount; j++) + { + if (gMapHeader.events->mapObjects[j].flagId == i + 0xae) + { + break; + } + } + VarSet(0x3f20 + gMapHeader.events->mapObjects[j].graphicsId, gUnknown_02038900.decoration->tiles[0]); + gSpecialVar_0x8005 = gMapHeader.events->mapObjects[j].localId; + gSpecialVar_0x8006 = gUnknown_020391A4; + gSpecialVar_0x8007 = gUnknown_020391A6; + show_sprite(gSpecialVar_0x8005, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + sub_805C0F8(gSpecialVar_0x8005, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, gSpecialVar_0x8006, gSpecialVar_0x8007); + sub_805C78C(gSpecialVar_0x8005, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + break; + } + } +} + +bool8 sub_80FF58C/*IsThereRoomForMoreDecorations*/(void) +{ + u16 i; + for (i=0; i<ewram_1f000.size; i++) + { + if (ewram_1f000.items[i] == 0) + { + return TRUE; + } + } + return FALSE; +} + +void sub_80FF5BC(u8 taskId) +{ + if (ewram_1f000.isPlayerRoom == 1 && gUnknown_020388F6 != DECORCAT_DOLL && gUnknown_020388F6 != DECORCAT_CUSHION) + { + sub_80FEF74(); + sub_80FED1C(); + DisplayItemMessageOnField(taskId, gSecretBaseText_DecorCantPlace, sub_80FEFF4, 0); + } else if (sub_80FEFA4() == TRUE) + { + if (sub_80FF58C() == TRUE) + { + fade_screen(1, 0); + gTasks[taskId].data[2] = 0; + gTasks[taskId].func = sub_80FF6AC; + } else + { + sub_80FEF74(); + sub_80FED1C(); + ConvertIntToDecimalStringN(gStringVar1, ewram_1f000.size, STR_CONV_MODE_RIGHT_ALIGN, 2); + if (!ewram_1f000.isPlayerRoom) + { + StringExpandPlaceholders(gStringVar4, gSecretBaseText_NoMoreDecor); + } else + { + StringExpandPlaceholders(gStringVar4, gSecretBaseText_NoMoreDecor2); + } + DisplayItemMessageOnField(taskId, gStringVar4, sub_80FEFF4, 0); + } + } else + { + sub_80FEF74(); + sub_80FED1C(); + DisplayItemMessageOnField(taskId, gSecretBaseText_InUseAlready, sub_80FEFF4, 0); + } +} + +void sub_80FF6AC(u8 taskId) +{ + switch (gTasks[taskId].data[2]) + { + case 0: + if (!gPaletteFade.active) + { + sub_80FF0E0(taskId); + DestroyVerticalScrollIndicator(0); + DestroyVerticalScrollIndicator(1); + sub_80F9520(gUnknown_020388F7, 8); + BuyMenuFreeMemory(); + gTasks[taskId].data[2] = 1; + } + break; + case 1: + gPaletteFade.bufferTransferDisabled = 1; + AddDecorationIconObjectFromFieldObject(&gUnknown_02038900, gUnknown_020388D0[gUnknown_020388F5]); + sub_80FF960(taskId); + SetUpPlacingDecorationPlayerAvatar(taskId, &gUnknown_02038900); + pal_fill_black(); + gPaletteFade.bufferTransferDisabled = 0; + gTasks[taskId].data[2] = 2; + break; + case 2: + if (sub_807D770() == 1) + { + gTasks[taskId].data[12] = 0; + sub_810065C(taskId); + } + break; + } +} + +void AddDecorationIconObjectFromFieldObject(struct UnkStruct_02038900 * unk_02038900, u8 decoIdx) +{ + sub_80FEF74(); + sub_80FED1C(); + sub_81006D0(unk_02038900); + unk_02038900->decoration = &gDecorations[decoIdx]; + if (gDecorations[decoIdx].permission != DECORPERM_SOLID_MAT) + { + sub_81008BC(unk_02038900); + sub_8100930(unk_02038900->decoration->shape); + sub_8100874(unk_02038900); + sub_810070C(unk_02038900->palette, ((u16 *)gMapHeader.mapData->secondaryTileset->metatiles + 8 * unk_02038900->decoration->tiles[0])[7] >> 12); + LoadSpritePalette(&gUnknown_083EC954); + gUnknown_020391A8 = gSprites[gUnknown_03004880.unk4].data0; + gUnknown_03004880.unk4 = CreateSprite(&gSpriteTemplate_83EC93C, gUnknown_083EC900[unk_02038900->decoration->shape].x, gUnknown_083EC900[unk_02038900->decoration->shape].y, 0); + } else + { + gUnknown_020391A8 = gSprites[gUnknown_03004880.unk4].data0; + gUnknown_03004880.unk4 = AddPseudoFieldObject(unk_02038900->decoration->tiles[0], sub_81009A8, gUnknown_083EC900[unk_02038900->decoration->shape].x, gUnknown_083EC900[unk_02038900->decoration->shape].y, 1); + gSprites[gUnknown_03004880.unk4].oam.priority = 1; + } +} + +void SetUpPlacingDecorationPlayerAvatar(u8 taskId, struct UnkStruct_02038900 *unk_02038900) +{ + u8 v0; + v0 = 16 * (u8)gTasks[taskId].data[5] + gUnknown_083EC900[unk_02038900->decoration->shape].x - 8 * ((u8)gTasks[taskId].data[5] - 1); + if (unk_02038900->decoration->shape == DECORSHAPE_3x1 || unk_02038900->decoration->shape == DECORSHAPE_3x3 || unk_02038900->decoration->shape == DECORSHAPE_3x2) + { + v0 -= 8; + } + if (gSaveBlock2.playerGender == MALE) + { + gUnknown_020391A9 = AddPseudoFieldObject(0xc1, SpriteCallbackDummy, v0, 0x48, 0); + } else + { + gUnknown_020391A9 = AddPseudoFieldObject(0xc2, SpriteCallbackDummy, v0, 0x48, 0); + } + gSprites[gUnknown_020391A9].oam.priority = 1; + DestroySprite(&gSprites[gUnknown_020391A8]); + gUnknown_020391A8 = gUnknown_03004880.unk4; +} + +void sub_80FF960(u8 taskId) +{ + switch (gDecorations[gUnknown_020388D0[gUnknown_020388F5]].shape) + { + case DECORSHAPE_1x1: + gTasks[taskId].data[5] = 1; + gTasks[taskId].data[6] = 1; + break; + case DECORSHAPE_2x1: + gTasks[taskId].data[5] = 2; + gTasks[taskId].data[6] = 1; + break; + case DECORSHAPE_3x1: + gTasks[taskId].data[5] = 3; + gTasks[taskId].data[6] = 1; + break; + case DECORSHAPE_4x2: + gTasks[taskId].data[5] = 4; + gTasks[taskId].data[6] = 2; + break; + case DECORSHAPE_2x2: + gTasks[taskId].data[5] = 2; + gTasks[taskId].data[6] = 2; + break; + case DECORSHAPE_1x2: + gTasks[taskId].data[5] = 1; + gTasks[taskId].data[6] = 2; + break; + case DECORSHAPE_1x3: + gTasks[taskId].data[5] = 1; + gTasks[taskId].data[6] = 3; + gTasks[taskId].data[1]++; + break; + case DECORSHAPE_2x4: + gTasks[taskId].data[5] = 2; + gTasks[taskId].data[6] = 4; + break; + case DECORSHAPE_3x3: + gTasks[taskId].data[5] = 3; + gTasks[taskId].data[6] = 3; + break; + case DECORSHAPE_3x2: + gTasks[taskId].data[5] = 3; + gTasks[taskId].data[6] = 2; + break; + } +} + +void sub_80FFAB0(u8 taskId) +{ + gTasks[taskId].data[10] = 0; + gSprites[gUnknown_020391A8].data7 = 1; + gSprites[gUnknown_020391A9].data7 = 1; + sub_810045C(); + sub_8100038(taskId); +} + +void sub_80FFB08(u8 taskId) +{ + gTasks[taskId].data[10] = 0; + gSprites[gUnknown_020391A8].data7 = 1; + gSprites[gUnknown_020391A9].data7 = 1; + sub_810045C(); + DisplayItemMessageOnField(taskId, gSecretBaseText_CancelDecorating, sub_8100248, 0); +} + +bool8 sub_80FFB6C(u8 a0, u16 a1) +{ + if (sub_8057274(a0) != 1 || a1 != 0) + { + return FALSE; + } + return TRUE; +} + +bool8 sub_80FFB94(u8 taskId, s16 x, s16 y, u16 decoId) +{ + if (x == gTasks[taskId].data[3] + 7 && y == gTasks[taskId].data[4] + 7 && decoId != 0) + { + return FALSE; + } + return TRUE; +} + +bool8 sub_80FFBDC(u16 a0, const struct Decoration *decoration) +{ + if (sub_8057274(a0) != 1) + { + if (decoration->id == DECOR_SOLID_BOARD && sub_8057300(a0) == 1) + { + return TRUE; + } + if (sub_805729C(a0)) + { + return TRUE; + } + } + return FALSE; +} + +// When behaviorBy is set, it is masked by 0xf000. This is the step that fails to match when built. +#ifdef NONMATCHING +bool8 sub_80FFC24(u8 taskId, const struct Decoration *decoration) +{ + u8 i; + u8 j; + u8 behaviorAt; + u16 behaviorBy; + u8 mapY; + u8 mapX; + s16 curY; + s16 curX; + mapY = gTasks[taskId].data[6]; + mapX = gTasks[taskId].data[5]; + switch (decoration->permission) + { + case DECORPERM_SOLID_FLOOR: + case DECORPERM_PASS_FLOOR: + for (i=0; i<mapY; i++) + { + curY = gTasks[taskId].data[1] - i; + for (j=0; j<mapX; j++) + { + curX = gTasks[taskId].data[0] + j; + behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); + behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[(mapY - 1 - i) * mapX + j]) & 0xf000; + if (!sub_80FFBDC(behaviorAt, decoration)) + { + return FALSE; + } + if (!sub_80FFB94(taskId, curX, curY, behaviorBy)) + { + return FALSE; + } + behaviorAt = GetFieldObjectIdByXYZ(curX, curY, 0); + if (behaviorAt != 0 && behaviorAt != 16) + { + return FALSE; + } + } + } + break; + case DECORPERM_BEHIND_FLOOR: + for (i=0; i<mapY-1; i++) + { + curY = gTasks[taskId].data[1] - i; + for (j=0; j<mapX; j++) + { + curX = gTasks[taskId].data[0] + j; + behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); + behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[(mapY - 1 - i) * mapX + j]) & 0xf000; + if (!sub_805729C(behaviorAt) && !sub_80FFB6C(behaviorAt, behaviorBy)) + { + return FALSE; + } + if (!sub_80FFB94(taskId, curX, curY, behaviorBy)) + { + return FALSE; + } + if (GetFieldObjectIdByXYZ(curX, curY, 0) != 16) + { + return FALSE; + } + } + } + curY = gTasks[taskId].data[1] - mapY + 1; + for (j=0; j<mapX; j++) + { + curX = gTasks[taskId].data[0] + j; + behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); + behaviorBy = GetBehaviorByMetatileId(0x200 + decoration->tiles[j]) & 0xf000; + if (!sub_805729C(behaviorAt) && !sub_80572B0(behaviorAt)) + { + return FALSE; + } + if (!sub_80FFB94(taskId, curX, curY, behaviorBy)) + { + return FALSE; + } + behaviorAt = GetFieldObjectIdByXYZ(curX, curY, 0); + if (behaviorAt != 0 && behaviorAt != 16) + { + return FALSE; + } + } + break; + case DECORPERM_NA_WALL: + for (i=0; i<mapY; i++) + { + curY = gTasks[taskId].data[1] - i; + for (j=0; j<mapX; j++) + { + curX = gTasks[taskId].data[0] + j; + if (!sub_80572B0(MapGridGetMetatileBehaviorAt(curX, curY))) + { + return FALSE; + } + if (MapGridGetMetatileIdAt(curX, curY + 1) == 0x28c) + { + return FALSE; + } + } + } + break; + case DECORPERM_SOLID_MAT: + curY = gTasks[taskId].data[1]; + for (j=0; j<mapX; j++) + { + curX = gTasks[taskId].data[0] + j; + behaviorAt = MapGridGetMetatileBehaviorAt(curX, curY); + if (decoration->shape == DECORSHAPE_1x2) + { + if (!sub_80572EC(behaviorAt)) + { + return FALSE; + } + } + else if (!sub_80572D8(behaviorAt)) + { + if (!sub_80572EC(behaviorAt)) + { + return FALSE; + } + } + if (GetFieldObjectIdByXYZ(curX, curY, 0) != 16) + { + return FALSE; + } + } + break; + } + return TRUE; +} +#else +__attribute__((naked)) +bool8 sub_80FFC24(u8 taskId, const struct Decoration *decoration) +{ + asm(".syntax unified\n" + "\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tsub sp, 0x24\n" + "\tstr r1, [sp]\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tmov r10, r0\n" + "\tldr r1, _080FFC60 @ =gTasks\n" + "\tlsls r0, 2\n" + "\tadd r0, r10\n" + "\tlsls r0, 3\n" + "\tadds r0, r1\n" + "\tldrb r2, [r0, 0x14]\n" + "\tstr r2, [sp, 0x4]\n" + "\tldrb r0, [r0, 0x12]\n" + "\tstr r0, [sp, 0x8]\n" + "\tldr r3, [sp]\n" + "\tldrb r0, [r3, 0x11]\n" + "\tadds r2, r1, 0\n" + "\tcmp r0, 0x4\n" + "\tbls _080FFC56\n" + "\tb _08100024\n" + "_080FFC56:\n" + "\tlsls r0, 2\n" + "\tldr r1, _080FFC64 @ =_080FFC68\n" + "\tadds r0, r1\n" + "\tldr r0, [r0]\n" + "\tmov pc, r0\n" + "\t.align 2, 0\n" + "_080FFC60: .4byte gTasks\n" + "_080FFC64: .4byte _080FFC68\n" + "\t.align 2, 0\n" + "_080FFC68:\n" + "\t.4byte _080FFC7C\n" + "\t.4byte _080FFC7C\n" + "\t.4byte _080FFD68\n" + "\t.4byte _080FFF1C\n" + "\t.4byte _080FFFA0\n" + "_080FFC7C:\n" + "\tmovs r6, 0\n" + "\tldr r0, [sp, 0x4]\n" + "\tcmp r6, r0\n" + "\tbcc _080FFC86\n" + "\tb _08100024\n" + "_080FFC86:\n" + "\tmov r1, r10\n" + "\tlsls r1, 2\n" + "\tstr r1, [sp, 0x1C]\n" + "_080FFC8C:\n" + "\tmov r2, r10\n" + "\tlsls r0, r2, 2\n" + "\tadd r0, r10\n" + "\tlsls r0, 3\n" + "\tldr r3, _080FFD64 @ =gTasks\n" + "\tadds r0, r3\n" + "\tldrh r0, [r0, 0xA]\n" + "\tsubs r0, r6\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmov r9, r0\n" + "\tmovs r7, 0\n" + "\tadds r6, 0x1\n" + "\tstr r6, [sp, 0x14]\n" + "\tldr r0, [sp, 0x8]\n" + "\tcmp r7, r0\n" + "\tbcs _080FFD56\n" + "\tmov r1, r9\n" + "\tlsls r1, 16\n" + "\tstr r1, [sp, 0xC]\n" + "\tasrs r1, 16\n" + "\tmov r9, r1\n" + "_080FFCB8:\n" + "\tldr r0, [sp, 0x1C]\n" + "\tadd r0, r10\n" + "\tlsls r0, 3\n" + "\tldr r2, _080FFD64 @ =gTasks\n" + "\tadds r0, r2\n" + "\tldrh r0, [r0, 0x8]\n" + "\tadds r0, r7\n" + "\tlsls r0, 16\n" + "\tmov r8, r0\n" + "\tasrs r6, r0, 16\n" + "\tadds r0, r6, 0\n" + "\tmov r1, r9\n" + "\tbl MapGridGetMetatileBehaviorAt\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tldr r3, [sp, 0x4]\n" + "\tldr r1, [sp, 0x14]\n" + "\tsubs r0, r3, r1\n" + "\tldr r2, [sp, 0x8]\n" + "\tadds r1, r0, 0\n" + "\tmuls r1, r2\n" + "\tadds r1, r7\n" + "\tldr r3, [sp]\n" + "\tldr r0, [r3, 0x1C]\n" + "\tlsls r1, 1\n" + "\tadds r1, r0\n" + "\tmovs r2, 0x80\n" + "\tlsls r2, 2\n" + "\tadds r0, r2, 0\n" + "\tldrh r1, [r1]\n" + "\tadds r0, r1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tbl GetBehaviorByMetatileId\n" + "\tmovs r3, 0xF0\n" + "\tlsls r3, 8\n" + "\tadds r1, r3, 0\n" + "\tadds r5, r1, 0\n" + "\tands r5, r0\n" + "\tadds r0, r4, 0\n" + "\tldr r1, [sp]\n" + "\tbl sub_80FFBDC\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _080FFD1A\n" + "\tb _080FFFF4\n" + "_080FFD1A:\n" + "\tmov r0, r10\n" + "\tadds r1, r6, 0\n" + "\tmov r2, r9\n" + "\tadds r3, r5, 0\n" + "\tbl sub_80FFB94\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _080FFD2E\n" + "\tb _080FFFF4\n" + "_080FFD2E:\n" + "\tmov r1, r8\n" + "\tlsrs r0, r1, 16\n" + "\tldr r2, [sp, 0xC]\n" + "\tlsrs r1, r2, 16\n" + "\tmovs r2, 0\n" + "\tbl GetFieldObjectIdByXYZ\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tcmp r4, 0\n" + "\tbeq _080FFD4A\n" + "\tcmp r4, 0x10\n" + "\tbeq _080FFD4A\n" + "\tb _080FFFF4\n" + "_080FFD4A:\n" + "\tadds r0, r7, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r7, r0, 24\n" + "\tldr r3, [sp, 0x8]\n" + "\tcmp r7, r3\n" + "\tbcc _080FFCB8\n" + "_080FFD56:\n" + "\tldr r1, [sp, 0x14]\n" + "\tlsls r0, r1, 24\n" + "\tlsrs r6, r0, 24\n" + "\tldr r2, [sp, 0x4]\n" + "\tcmp r6, r2\n" + "\tbcc _080FFC8C\n" + "\tb _08100024\n" + "\t.align 2, 0\n" + "_080FFD64: .4byte gTasks\n" + "_080FFD68:\n" + "\tmovs r6, 0\n" + "\tmov r3, r10\n" + "\tlsls r3, 2\n" + "\tstr r3, [sp, 0x1C]\n" + "\tldr r0, [sp, 0x4]\n" + "\tsubs r0, 0x1\n" + "\tstr r0, [sp, 0x18]\n" + "\tcmp r6, r0\n" + "\tbge _080FFE54\n" + "\tadds r0, r3, 0\n" + "\tadd r0, r10\n" + "\tlsls r0, 3\n" + "\tstr r0, [sp, 0x10]\n" + "_080FFD82:\n" + "\tldr r1, [sp, 0x10]\n" + "\tadds r0, r1, r2\n" + "\tldrh r0, [r0, 0xA]\n" + "\tsubs r0, r6\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmov r9, r0\n" + "\tmovs r7, 0\n" + "\tadds r6, 0x1\n" + "\tstr r6, [sp, 0x14]\n" + "\tldr r3, [sp, 0x8]\n" + "\tcmp r7, r3\n" + "\tbcs _080FFE48\n" + "\tlsls r0, 16\n" + "\tstr r0, [sp, 0x20]\n" + "_080FFDA0:\n" + "\tldr r1, [sp, 0x10]\n" + "\tadds r0, r1, r2\n" + "\tldrh r0, [r0, 0x8]\n" + "\tadds r0, r7\n" + "\tlsls r0, 16\n" + "\tmov r8, r0\n" + "\tasrs r6, r0, 16\n" + "\tmov r2, r9\n" + "\tlsls r1, r2, 16\n" + "\tadds r0, r6, 0\n" + "\tasrs r1, 16\n" + "\tbl MapGridGetMetatileBehaviorAt\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tldr r3, [sp, 0x4]\n" + "\tldr r1, [sp, 0x14]\n" + "\tsubs r0, r3, r1\n" + "\tldr r2, [sp, 0x8]\n" + "\tadds r1, r0, 0\n" + "\tmuls r1, r2\n" + "\tadds r1, r7\n" + "\tldr r3, [sp]\n" + "\tldr r0, [r3, 0x1C]\n" + "\tlsls r1, 1\n" + "\tadds r1, r0\n" + "\tmovs r2, 0x80\n" + "\tlsls r2, 2\n" + "\tadds r0, r2, 0\n" + "\tldrh r1, [r1]\n" + "\tadds r0, r1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tbl GetBehaviorByMetatileId\n" + "\tmovs r3, 0xF0\n" + "\tlsls r3, 8\n" + "\tadds r1, r3, 0\n" + "\tadds r5, r1, 0\n" + "\tands r5, r0\n" + "\tadds r0, r4, 0\n" + "\tbl sub_805729C\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _080FFE0C\n" + "\tadds r0, r4, 0\n" + "\tadds r1, r5, 0\n" + "\tbl sub_80FFB6C\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _080FFE0C\n" + "\tb _080FFFF4\n" + "_080FFE0C:\n" + "\tmov r0, r10\n" + "\tadds r1, r6, 0\n" + "\tldr r3, [sp, 0x20]\n" + "\tasrs r2, r3, 16\n" + "\tadds r3, r5, 0\n" + "\tbl sub_80FFB94\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _080FFE22\n" + "\tb _080FFFF4\n" + "_080FFE22:\n" + "\tmov r1, r8\n" + "\tlsrs r0, r1, 16\n" + "\tldr r2, [sp, 0x20]\n" + "\tlsrs r1, r2, 16\n" + "\tmovs r2, 0\n" + "\tbl GetFieldObjectIdByXYZ\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tcmp r0, 0x10\n" + "\tbeq _080FFE3A\n" + "\tb _080FFFF4\n" + "_080FFE3A:\n" + "\tadds r0, r7, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r7, r0, 24\n" + "\tldr r2, _080FFF18 @ =gTasks\n" + "\tldr r3, [sp, 0x8]\n" + "\tcmp r7, r3\n" + "\tbcc _080FFDA0\n" + "_080FFE48:\n" + "\tldr r1, [sp, 0x14]\n" + "\tlsls r0, r1, 24\n" + "\tlsrs r6, r0, 24\n" + "\tldr r3, [sp, 0x18]\n" + "\tcmp r6, r3\n" + "\tblt _080FFD82\n" + "_080FFE54:\n" + "\tldr r0, [sp, 0x1C]\n" + "\tadd r0, r10\n" + "\tlsls r0, 3\n" + "\tadds r0, r2\n" + "\tldrh r0, [r0, 0xA]\n" + "\tldr r1, [sp, 0x4]\n" + "\tsubs r0, r1\n" + "\tadds r0, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmov r9, r0\n" + "\tmovs r7, 0\n" + "\tldr r3, [sp, 0x8]\n" + "\tcmp r7, r3\n" + "\tbcc _080FFE74\n" + "\tb _08100024\n" + "_080FFE74:\n" + "\tlsls r0, 16\n" + "\tstr r0, [sp, 0x20]\n" + "_080FFE78:\n" + "\tldr r0, [sp, 0x1C]\n" + "\tadd r0, r10\n" + "\tlsls r0, 3\n" + "\tldr r1, _080FFF18 @ =gTasks\n" + "\tadds r0, r1\n" + "\tldrh r0, [r0, 0x8]\n" + "\tadds r0, r7\n" + "\tlsls r0, 16\n" + "\tmov r8, r0\n" + "\tasrs r6, r0, 16\n" + "\tmov r2, r9\n" + "\tlsls r1, r2, 16\n" + "\tadds r0, r6, 0\n" + "\tasrs r1, 16\n" + "\tbl MapGridGetMetatileBehaviorAt\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tldr r3, [sp]\n" + "\tldr r0, [r3, 0x1C]\n" + "\tlsls r1, r7, 1\n" + "\tadds r1, r0\n" + "\tmovs r2, 0x80\n" + "\tlsls r2, 2\n" + "\tadds r0, r2, 0\n" + "\tldrh r1, [r1]\n" + "\tadds r0, r1\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tbl GetBehaviorByMetatileId\n" + "\tmovs r3, 0xF0\n" + "\tlsls r3, 8\n" + "\tadds r1, r3, 0\n" + "\tadds r5, r1, 0\n" + "\tands r5, r0\n" + "\tadds r0, r4, 0\n" + "\tbl sub_805729C\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _080FFEDA\n" + "\tadds r0, r4, 0\n" + "\tbl sub_80572B0\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _080FFEDA\n" + "\tb _080FFFF4\n" + "_080FFEDA:\n" + "\tmov r0, r10\n" + "\tadds r1, r6, 0\n" + "\tldr r3, [sp, 0x20]\n" + "\tasrs r2, r3, 16\n" + "\tadds r3, r5, 0\n" + "\tbl sub_80FFB94\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _080FFEF0\n" + "\tb _080FFFF4\n" + "_080FFEF0:\n" + "\tmov r1, r8\n" + "\tlsrs r0, r1, 16\n" + "\tldr r2, [sp, 0x20]\n" + "\tlsrs r1, r2, 16\n" + "\tmovs r2, 0\n" + "\tbl GetFieldObjectIdByXYZ\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tcmp r4, 0\n" + "\tbeq _080FFF0A\n" + "\tcmp r4, 0x10\n" + "\tbne _080FFFF4\n" + "_080FFF0A:\n" + "\tadds r0, r7, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r7, r0, 24\n" + "\tldr r3, [sp, 0x8]\n" + "\tcmp r7, r3\n" + "\tbcc _080FFE78\n" + "\tb _08100024\n" + "\t.align 2, 0\n" + "_080FFF18: .4byte gTasks\n" + "_080FFF1C:\n" + "\tmovs r6, 0\n" + "\tldr r0, [sp, 0x4]\n" + "\tcmp r6, r0\n" + "\tbcc _080FFF26\n" + "\tb _08100024\n" + "_080FFF26:\n" + "\tmov r1, r10\n" + "\tlsls r0, r1, 2\n" + "\tadd r0, r10\n" + "\tlsls r1, r0, 3\n" + "\tldr r2, _080FFF9C @ =gTasks\n" + "\tadds r0, r1, r2\n" + "\tldrh r0, [r0, 0xA]\n" + "\tsubs r0, r6\n" + "\tlsls r0, 16\n" + "\tlsrs r0, 16\n" + "\tmov r9, r0\n" + "\tmovs r7, 0\n" + "\tldr r3, [sp, 0x8]\n" + "\tcmp r7, r3\n" + "\tbcs _080FFF8C\n" + "\tadds r0, r2, 0\n" + "\tadds r1, r0\n" + "\tmov r8, r1\n" + "\tmov r1, r9\n" + "\tlsls r0, r1, 16\n" + "\tasrs r5, r0, 16\n" + "_080FFF50:\n" + "\tmov r2, r8\n" + "\tldrh r0, [r2, 0x8]\n" + "\tadds r0, r7\n" + "\tlsls r0, 16\n" + "\tasrs r4, r0, 16\n" + "\tadds r0, r4, 0\n" + "\tadds r1, r5, 0\n" + "\tbl MapGridGetMetatileBehaviorAt\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tbl sub_80572B0\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbeq _080FFFF4\n" + "\tadds r0, r4, 0\n" + "\tadds r1, r5, 0x1\n" + "\tbl MapGridGetMetatileIdAt\n" + "\tmovs r1, 0xA3\n" + "\tlsls r1, 2\n" + "\tcmp r0, r1\n" + "\tbeq _080FFFF4\n" + "\tadds r0, r7, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r7, r0, 24\n" + "\tldr r3, [sp, 0x8]\n" + "\tcmp r7, r3\n" + "\tbcc _080FFF50\n" + "_080FFF8C:\n" + "\tadds r0, r6, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r6, r0, 24\n" + "\tldr r0, [sp, 0x4]\n" + "\tcmp r6, r0\n" + "\tbcc _080FFF26\n" + "\tb _08100024\n" + "\t.align 2, 0\n" + "_080FFF9C: .4byte gTasks\n" + "_080FFFA0:\n" + "\tmov r3, r10\n" + "\tlsls r1, r3, 2\n" + "\tadds r0, r1, r3\n" + "\tlsls r0, 3\n" + "\tadds r0, r2\n" + "\tldrh r0, [r0, 0xA]\n" + "\tmov r9, r0\n" + "\tmovs r7, 0\n" + "\tstr r1, [sp, 0x1C]\n" + "\tldr r0, [sp, 0x8]\n" + "\tcmp r7, r0\n" + "\tbcs _08100024\n" + "\tadds r6, r2, 0\n" + "\tmov r1, r9\n" + "\tlsls r1, 16\n" + "\tstr r1, [sp, 0x20]\n" + "_080FFFC0:\n" + "\tldr r0, [sp, 0x1C]\n" + "\tadd r0, r10\n" + "\tlsls r0, 3\n" + "\tadds r0, r6\n" + "\tldrh r0, [r0, 0x8]\n" + "\tadds r0, r7\n" + "\tlsls r0, 16\n" + "\tlsrs r5, r0, 16\n" + "\tasrs r0, 16\n" + "\tmov r2, r9\n" + "\tlsls r1, r2, 16\n" + "\tasrs r1, 16\n" + "\tbl MapGridGetMetatileBehaviorAt\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tldr r3, [sp]\n" + "\tldrb r0, [r3, 0x12]\n" + "\tcmp r0, 0x5\n" + "\tbne _080FFFF8\n" + "_080FFFE8:\n" + "\tadds r0, r4, 0\n" + "\tbl sub_80572EC\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbne _08100004\n" + "_080FFFF4:\n" + "\tmovs r0, 0\n" + "\tb _08100026\n" + "_080FFFF8:\n" + "\tadds r0, r4, 0\n" + "\tbl sub_80572D8\n" + "\tlsls r0, 24\n" + "\tcmp r0, 0\n" + "\tbeq _080FFFE8\n" + "_08100004:\n" + "\tadds r0, r5, 0\n" + "\tldr r2, [sp, 0x20]\n" + "\tlsrs r1, r2, 16\n" + "\tmovs r2, 0\n" + "\tbl GetFieldObjectIdByXYZ\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tcmp r0, 0x10\n" + "\tbne _080FFFF4\n" + "\tadds r0, r7, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r7, r0, 24\n" + "\tldr r3, [sp, 0x8]\n" + "\tcmp r7, r3\n" + "\tbcc _080FFFC0\n" + "_08100024:\n" + "\tmovs r0, 0x1\n" + "_08100026:\n" + "\tadd sp, 0x24\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1\n" + ".syntax divided\n"); +} +#endif + +void sub_8100038(u8 taskId) +{ + if (sub_80FFC24(taskId, &gDecorations[gUnknown_020388D0[gUnknown_020388F5]]) == 1) + { + DisplayItemMessageOnField(taskId, gSecretBaseText_PlaceItHere, sub_81000A0, 0); + } else + { + PlaySE(SE_HAZURE); + DisplayItemMessageOnField(taskId, gSecretBaseText_CantBePlacedHere, sub_81006A8, 0); + } +} + +void sub_81000A0(u8 taskId) +{ + DisplayYesNoMenu(20, 8, 1); + DoYesNoFuncWithChoice(taskId, &gUnknown_083EC95C); +} + +void sub_81000C4(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0, 29, 19); + sub_8100174(taskId); + if (gDecorations[gUnknown_020388D0[gUnknown_020388F5]].permission != DECORPERM_SOLID_MAT) + { + sub_80FF394(gTasks[taskId].data[0], gTasks[taskId].data[1], gUnknown_020388D0[gUnknown_020388F5]); + } else + { + gUnknown_020391A4 = gTasks[taskId].data[0] - 7; + gUnknown_020391A6 = gTasks[taskId].data[1] - 7; + ScriptContext1_SetupScript(gUnknown_081A2F7B); + } + gSprites[gUnknown_020391A8].pos1.y += 2; + sub_810028C(taskId); +} + +void sub_8100174(u8 taskId) +{ + u16 i; + for (i=0; i<ewram_1f000.size; i++) + { + if (ewram_1f000.items[i] == 0) + { + ewram_1f000.items[i] = gUnknown_020388D0[gUnknown_020388F5]; + ewram_1f000.pos[i] = ((gTasks[taskId].data[0] - 7) << 4) + (gTasks[taskId].data[1] - 7); + break; + } + } + if (!ewram_1f000.isPlayerRoom) + { + for (i=0; i<16; i++) + { + if (gUnknown_020388D6[i] == 0) + { + gUnknown_020388D6[i] = gUnknown_020388F5 + 1; + break; + } + } + } else + { + for (i=0; i<12; i++) + { + if (gUnknown_020388E6[i] == 0) + { + gUnknown_020388E6[i] = gUnknown_020388F5 + 1; + break; + } + } + } +} + +void sub_8100248(u8 taskId) +{ + DisplayYesNoMenu(20, 8, 1); + DoYesNoFuncWithChoice(taskId, &gUnknown_083EC964); +} + +void sub_810026C(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0, 29, 19); + sub_810028C(taskId); +} + +void sub_810028C(u8 taskId) +{ + fade_screen(1, 0); + gTasks[taskId].data[2] = 0; + gTasks[taskId].func = c1_overworld_prev_quest; +} + +void c1_overworld_prev_quest(u8 taskId) +{ + switch (gTasks[taskId].data[2]) + { + case 0: + ScriptContext2_Enable(); + if (!gPaletteFade.active) + { + sub_80FF114(taskId); + gTasks[taskId].data[2] = 1; + } + break; + case 1: + sub_81016F4(); + FreeSpritePaletteByTag(0xbb8); + gFieldCallback = &sub_8100364; + SetMainCallback2(c2_exit_to_overworld_2_switch); + DestroyTask(taskId); + break; + } +} + +void sub_8100334(u8 taskId) +{ + if (sub_807D770() == 1) + { + gTasks[taskId].func = sub_80FE948; + } +} + +void sub_8100364(void) +{ + ScriptContext2_Enable(); + LoadScrollIndicatorPalette(); + pal_fill_black(); + sub_80FE7EC(CreateTask(sub_8100334, 8)); +} + +bool8 sub_810038C(u8 taskId) +{ + s16 *data; + data = gTasks[taskId].data; + if (gUnknown_020391AA == DIR_SOUTH && data[1] - data[6] - 6 < 0) + { + data[1]++; + return FALSE; + } else if (gUnknown_020391AA == DIR_NORTH && data[1] - 7 >= gMapHeader.mapData->height) + { + data[1]--; + return FALSE; + } else if (gUnknown_020391AA == DIR_WEST && data[0] - 7 < 0) + { + data[0]++; + return FALSE; + } else if (gUnknown_020391AA == DIR_EAST && data[0] + data[5] - 8 >= gMapHeader.mapData->width) + { + data[0]--; + return FALSE; + } + return TRUE; +} + +bool8 sub_8100430(void) +{ + if ((gMain.heldKeys & DPAD_ANY) != DPAD_UP && (gMain.heldKeys & DPAD_ANY) != DPAD_DOWN && (gMain.heldKeys & DPAD_ANY) != DPAD_LEFT && (gMain.heldKeys & DPAD_ANY) != DPAD_RIGHT) + { + return FALSE; + } + return TRUE; +} + +void sub_810045C(void) +{ + gUnknown_020391AA = 0; + gSprites[gUnknown_020391A8].data2 = 0; + gSprites[gUnknown_020391A8].data3 = 0; +} + +void sub_8100494(u8 taskId) +{ + if (!gSprites[gUnknown_020391A8].data4) + { + if (gTasks[taskId].data[10] == 1) + { + gUnknown_083EC96C[gTasks[taskId].data[12]].yesFunc(taskId); + return; + } else if (gTasks[taskId].data[10] == 2) + { + gUnknown_083EC96C[gTasks[taskId].data[12]].noFunc(taskId); + return; + } + if ((gMain.heldKeys & DPAD_ANY) == DPAD_UP) + { + gUnknown_020391AA = DIR_SOUTH; + gSprites[gUnknown_020391A8].data2 = 0; + gSprites[gUnknown_020391A8].data3 = -2; + gTasks[taskId].data[1]--; + } + if ((gMain.heldKeys & DPAD_ANY) == DPAD_DOWN) + { + gUnknown_020391AA = DIR_NORTH; + gSprites[gUnknown_020391A8].data2 = 0; + gSprites[gUnknown_020391A8].data3 = 2; + gTasks[taskId].data[1]++; + } + if ((gMain.heldKeys & DPAD_ANY) == DPAD_LEFT) + { + gUnknown_020391AA = DIR_WEST; + gSprites[gUnknown_020391A8].data2 = -2; + gSprites[gUnknown_020391A8].data3 = 0; + gTasks[taskId].data[0]--; + } + if ((gMain.heldKeys & DPAD_ANY) == DPAD_RIGHT) + { + gUnknown_020391AA = DIR_EAST; + gSprites[gUnknown_020391A8].data2 = 2; + gSprites[gUnknown_020391A8].data3 = 0; + gTasks[taskId].data[0]++; + } + if (!sub_8100430() || !sub_810038C(taskId)) + { + sub_810045C(); + } + } + if (gUnknown_020391AA) + { + gSprites[gUnknown_020391A8].data4++; + gSprites[gUnknown_020391A8].data4 &= 7; + } + if (!gTasks[taskId].data[10]) + { + if (gMain.newKeys & A_BUTTON) + { + gTasks[taskId].data[10] = A_BUTTON; + } + if (gMain.newKeys & B_BUTTON) + { + gTasks[taskId].data[10] = B_BUTTON; + } + } +} + +void sub_810065C(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0, 29, 19); + gSprites[gUnknown_020391A8].data7 = 0; + gTasks[taskId].data[10] = 0; + gTasks[taskId].func = sub_8100494; +} + +void sub_81006A8(u8 taskId) +{ + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + sub_810065C(taskId); + } +} + +void sub_81006D0(struct UnkStruct_02038900 *unk_02038900) +{ + u16 i; + for (i=0; i<0x800; i++) + { + unk_02038900->image[i] = 0; + } + for (i=0; i<0x40; i++) + { + unk_02038900->tiles[i] = 0; + } +} + +void sub_810070C(u16 *a0, u16 a1) +{ + u16 i; + for (i=0; i<16; i++) + { + a0[i] = ((u16 *)gMapHeader.mapData->primaryTileset->palettes)[16 * a1 + i]; + } +} + +void sub_8100740(u8 *dest, u16 flags) +{ + u8 buffer[32]; + u16 mode; + u16 i; + mode = flags >> 10; + if (flags != 0) + { + flags &= 0x3ff; + } + for (i=0; i<32; i++) + { + buffer[i] = ((u8 *)gMapHeader.mapData->primaryTileset->tiles)[flags * 32 + i]; + } + switch (mode) + { + case 0: + for (i=0; i<32; i++) + { + dest[i] = buffer[i]; + } + break; + case 1: + for (i=0; i<8; i++) + { + dest[4*i] = (buffer[4*(i+1) - 1] >> 4) + ((buffer[4*(i+1) - 1] & 0xf) << 4); + dest[4*i + 1] = (buffer[4*(i+1) - 2] >> 4) + ((buffer[4*(i+1) - 2] & 0xf) << 4); + dest[4*i + 2] = (buffer[4*(i+1) - 3] >> 4) + ((buffer[4*(i+1) - 3] & 0xf) << 4); + dest[4*i + 3] = (buffer[4*(i+1) - 4] >> 4) + ((buffer[4*(i+1) - 4] & 0xf) << 4); + } + break; + case 2: + for (i=0; i<8; i++) + { + dest[4*i] = buffer[4*(7-i)]; + dest[4*i + 1] = buffer[4*(7-i) + 1]; + dest[4*i + 2] = buffer[4*(7-i) + 2]; + dest[4*i + 3] = buffer[4*(7-i) + 3]; + } + break; + case 3: + for (i=0; i<32; i++) + { + dest[i] = (buffer[31-i] >> 4) + ((buffer[31-i] & 0xf) << 4); + } + break; + } +} + +void sub_8100874(struct UnkStruct_02038900 *unk_02038900) +{ + u16 i; + for (i=0; i<0x40; i++) + sub_8100740(&unk_02038900->image[i * 32], unk_02038900->tiles[i]); +} + +u16 sub_810089C(u16 a0) +{ + return ((u16 *)gMapHeader.mapData->secondaryTileset->metatiles)[a0] & 0xfff; +} + +void sub_81008BC(struct UnkStruct_02038900 *unk_02038900) +{ + u8 i; + u8 shape; + shape = unk_02038900->decoration->shape; + for (i=0; i<gUnknown_083EC860[shape].size; i++) + { + unk_02038900->tiles[gUnknown_083EC860[shape].tiles[i]] = sub_810089C(unk_02038900->decoration->tiles[gUnknown_083EC860[shape].y[i]] * 8 + gUnknown_083EC860[shape].x[i]); + } +} + +void sub_8100930(u8 decoShape) +{ + gUnknown_020391AC.y = 0; + gUnknown_020391AC.affineMode = 0; + gUnknown_020391AC.objMode = 0; + gUnknown_020391AC.mosaic = 0; + gUnknown_020391AC.bpp = 0; + gUnknown_020391AC.shape = gUnknown_083EC900[decoShape].shape; + gUnknown_020391AC.x = 0; + gUnknown_020391AC.matrixNum = 0; + gUnknown_020391AC.size = gUnknown_083EC900[decoShape].size; + gUnknown_020391AC.tileNum = 0; + gUnknown_020391AC.priority = 1; + gUnknown_020391AC.paletteNum = 0; +} + +void sub_81009A8(struct Sprite *sprite) +{ + sprite->data2 = 0; + sprite->data3 = 0; + sprite->data4 = 0; + sprite->data5 = 0; + sprite->data6 = 0; + sprite->data7 = 0; + sprite->callback = sub_81009C0; +} + +void sub_81009C0(struct Sprite *sprite) +{ + if (sprite->data7 == 0) + { + if (sprite->data6 < 15) + { + sprite->invisible = 0; + } else + { + sprite->invisible = 1; + } + sprite->data6 = (sprite->data6 + 1) & 0x1f; + } else + { + sprite->invisible = 0; + } +} + +void sub_8100A0C(u8 taskId) +{ + if (sub_8100D38(taskId) == 1) + { + fade_screen(1, 0); + gTasks[taskId].data[2] = 0; + gTasks[taskId].func = sub_8100E70; + } else + { + DisplayItemMessageOnField(taskId, gSecretBaseText_NoDecorInUse, sub_80FE428, 0); + } +} + +void sub_8100A60(u8 a0) +{ + ewram_1f000.items[a0] = 0; + ewram_1f000.pos[a0] = 0; +} + +void sub_8100A7C(void) +{ + u16 i; + gSpecialVar_0x8005 = 0; + gScriptResult = 0; + if (gSpecialVar_0x8004 == gUnknown_02039234) + { + gScriptResult = 1; + } else if (gDecorations[ewram_1f000.items[gUnknown_020391B4[gSpecialVar_0x8004].decorId]].permission == DECORPERM_SOLID_MAT) + { + gSpecialVar_0x8005 = gUnknown_020391B4[gSpecialVar_0x8004].flagId; + sub_8100A60(gUnknown_020391B4[gSpecialVar_0x8004].decorId); + for (i=0; i<gMapHeader.events->mapObjectCount; i++) + { + if (gMapHeader.events->mapObjects[i].flagId == gSpecialVar_0x8005) + { + gSpecialVar_0x8006 = gMapHeader.events->mapObjects[i].localId; + break; + } + } + } +} + +void sub_8100B20(void) +{ + u8 i; + for (i=0; i<gMapHeader.events->mapObjectCount; i++) + { + if (gMapHeader.events->mapObjects[i].flagId == gSpecialVar_0x8004) + { + gSpecialVar_0x8005 = gMapHeader.events->mapObjects[i].localId; + break; + } + } +} + +void sub_8100B6C(void) +{ + u8 i; + u8 j; + u8 k; + u8 x; + u8 y; + u8 permission; + for (i=0; i<gUnknown_02039234; i++) + { + permission = gDecorations[ewram_1f000.items[gUnknown_020391B4[i].decorId]].permission; + x = ewram_1f000.pos[gUnknown_020391B4[i].decorId] >> 4; + y = ewram_1f000.pos[gUnknown_020391B4[i].decorId] & 0xf; + if (permission != DECORPERM_SOLID_MAT) + { + if (ewram_1f000.items[gUnknown_020391B4[i].decorId] == DECOR_SAND_ORNAMENT && MapGridGetMetatileIdAt(x + 7, y + 7) == 0x28c) + { + gUnknown_020391B4[i].height++; + } + for (j=0; j<gUnknown_020391B4[i].height; j++) + { + for (k=0; k<gUnknown_020391B4[i].width; k++) + { + MapGridSetMetatileEntryAt(x + 7 + k, y + 7 - j, ((u16 *)gMapHeader.mapData->map)[(x + k) + gMapHeader.mapData->width * (y - j)] | 0x3000); + } + } + sub_8100A60(gUnknown_020391B4[i].decorId); + } + } +} + +void sub_8100C88(u8 taskId) +{ + switch (gTasks[taskId].data[2]) + { + case 0: + sub_8100B6C(); + gTasks[taskId].data[2] = 1; + break; + case 1: + if (!gPaletteFade.active) + { + DrawWholeMapView(); + ScriptContext1_SetupScript(gUnknown_081A2F8A); + MenuZeroFillWindowRect(0, 0, 29, 19); + gTasks[taskId].data[2] = 2; + } + break; + case 2: + ScriptContext2_Enable(); + sub_80FED90(taskId); + pal_fill_black(); + gTasks[taskId].data[2] = 3; + break; + case 3: + if (sub_807D770() == 1) + { + gTasks[taskId].data[13] = -1; + DisplayItemMessageOnField(taskId, gSecretBaseText_DecorReturned, sub_81010F0, 0); + } + break; + } +} + +bool8 sub_8100D38(u8 taskId) +{ + u16 i; + for (i=0; i<ewram_1f000.size; i++) + { + if (ewram_1f000.items[i] != 0) + { + gTasks[taskId].data[13] = i; + return TRUE; + } + } + return FALSE; +} + +void SetUpPuttingAwayDecorationPlayerAvatar(void) +{ + player_get_direction_lower_nybble(); + MenuZeroFillWindowRect(0, 0, 29, 19); + gUnknown_020391A8 = gSprites[gUnknown_03004880.unk4].data0; + sub_81016C8(); + gUnknown_03004880.unk4 = CreateSprite(&gSpriteTemplate_83ECA88, 0x78, 0x50, 0); + if (gSaveBlock2.playerGender == MALE) + { + gUnknown_020391A9 = AddPseudoFieldObject(0xc1, SpriteCallbackDummy, 0x88, 0x48, 0); + } else + { + gUnknown_020391A9 = AddPseudoFieldObject(0xc2, SpriteCallbackDummy, 0x88, 0x48, 0); + } + gSprites[gUnknown_020391A9].oam.priority = 1; + DestroySprite(&gSprites[gUnknown_020391A8]); + gUnknown_020391A8 = gUnknown_03004880.unk4; + gSprites[gUnknown_020391A8].oam.priority = 1; +} + +void sub_8100E70(u8 taskId) +{ + s16 *data; + data = gTasks[taskId].data; + switch (data[2]) + { + case 0: + if (!gPaletteFade.active) + { + sub_80FF0E0(taskId); + data[2] = 1; + data[6] = 1; + data[5] = 1; + HandleDestroyMenuCursors(); + } + break; + case 1: + SetUpPuttingAwayDecorationPlayerAvatar(); + pal_fill_black(); + data[2] = 2; + break; + case 2: + if (sub_807D770() == TRUE) + { + data[12] = 1; + sub_8100EEC(taskId); + } + break; + } +} + +void sub_8100EEC(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0, 29, 19); + gSprites[gUnknown_020391A8].data7 = 0; + gSprites[gUnknown_020391A8].invisible = 0; + gSprites[gUnknown_020391A8].callback = sub_8101698; + gSprites[gUnknown_020391A9].pos1.x = 0x88; + gSprites[gUnknown_020391A9].pos1.y = 0x48; + gTasks[taskId].data[10] = 0; + gTasks[taskId].func = sub_8100494; +} + +void sub_8100F88(u8 taskId) +{ + gTasks[taskId].data[10] = 0; + sub_810045C(); + sub_8101024(taskId); +} + +void sub_8100FB4(u8 taskId) +{ + gTasks[taskId].data[10] = 0; + sub_810045C(); + gSprites[gUnknown_020391A8].invisible = 0; + gSprites[gUnknown_020391A8].callback = SpriteCallbackDummy; + DisplayItemMessageOnField(taskId, gSecretBaseText_StopPuttingAwayDecor, sub_810156C, 0); +} + +void sub_8101024(u8 taskId) +{ + u8 mtBehavior; + s16 *data; + sub_8101460(taskId); + if (gUnknown_02039234 != 0) + { + DisplayItemMessageOnField(taskId, gSecretBaseText_ReturnDecor, sub_8101518, 0); + } else + { + data = gTasks[taskId].data; + mtBehavior = MapGridGetMetatileBehaviorAt(data[0], data[1]); + if (MetatileBehavior_IsSecretBasePC(mtBehavior) == TRUE || sub_805738C(mtBehavior) == TRUE) + { + gSprites[gUnknown_020391A8].invisible = 0; + gSprites[gUnknown_020391A8].callback = SpriteCallbackDummy; + DisplayItemMessageOnField(taskId, gSecretBaseText_StopPuttingAwayDecor, sub_810156C, 0); + } else + { + DisplayItemMessageOnField(taskId, gSecretBaseText_NoDecor, sub_81010F0, 0); + } + } +} + +void sub_81010F0(u8 taskId) +{ + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + sub_8100EEC(taskId); + } +} + +void sub_8101118(u8 decorIdx, struct UnkStruct_020391B4 *unk_020391B4) +{ + if (gDecorations[decorIdx].shape == DECORSHAPE_1x1) + { + unk_020391B4->width = 1; + unk_020391B4->height = 1; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_2x1) + { + unk_020391B4->width = 2; + unk_020391B4->height = 1; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_3x1) + { + unk_020391B4->width = 3; + unk_020391B4->height = 1; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_4x2) + { + unk_020391B4->width = 4; + unk_020391B4->height = 2; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_2x2) + { + unk_020391B4->width = 2; + unk_020391B4->height = 2; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_1x2) + { + unk_020391B4->width = 1; + unk_020391B4->height = 2; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_1x3) + { + unk_020391B4->width = 1; + unk_020391B4->height = 3; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_2x4) + { + unk_020391B4->width = 2; + unk_020391B4->height = 4; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_3x3) + { + unk_020391B4->width = 3; + unk_020391B4->height = 3; + } else if (gDecorations[decorIdx].shape == DECORSHAPE_3x2) + { + unk_020391B4->width = 3; + unk_020391B4->height = 2; + } +} + +void sub_8101198(u8 x, u8 y) +{ + gSprites[gUnknown_020391A8].invisible = 1; + gSprites[gUnknown_020391A8].callback = SpriteCallbackDummy; + gSprites[gUnknown_020391A9].pos1.x = 0x88 + x * 16; + gSprites[gUnknown_020391A9].pos1.y = 0x48 + y * 16; +} + +bool8 sub_8101200(u8 taskId, u8 decorIdx, struct UnkStruct_020391B4 *unk_020391B4) +{ + u8 x; + u8 y; + u8 xOff; + u8 yOff; + x = gTasks[taskId].data[0] - 7; + y = gTasks[taskId].data[1] - 7; + xOff = ewram_1f000.pos[decorIdx] >> 4; + yOff = ewram_1f000.pos[decorIdx] & 0xf; + if (ewram_1f000.items[decorIdx] == DECOR_SAND_ORNAMENT && MapGridGetMetatileIdAt(xOff + 7, yOff + 7) == 0x28c) + { + unk_020391B4->height--; + } + if (x >= xOff && x < xOff + unk_020391B4->width && y > yOff - unk_020391B4->height && y <= yOff) + { + sub_8101198(unk_020391B4->width - (x - xOff + 1), yOff - y); + return TRUE; + } + return FALSE; +} + +void sub_81012A0(void) +{ + u8 xOff; + u8 yOff; + u16 i; + xOff = ewram_1f000.pos[gUnknown_020391B4[gUnknown_02039234].decorId] >> 4; + yOff = ewram_1f000.pos[gUnknown_020391B4[gUnknown_02039234].decorId] & 0xf; + for (i=0; i<0x40; i++) + { + if (gSaveBlock1.mapObjectTemplates[i].x == xOff && gSaveBlock1.mapObjectTemplates[i].y == yOff && !FlagGet(gSaveBlock1.mapObjectTemplates[i].flagId)) + { + gUnknown_020391B4[gUnknown_02039234].flagId = gSaveBlock1.mapObjectTemplates[i].flagId; + break; + } + } +} + +bool8 sub_8101340(u8 taskId) +{ + u16 i; + for (i=0; i<ewram_1f000.size; i++) + { + if (ewram_1f000.items[i] != 0) + { + if (gDecorations[ewram_1f000.items[i]].permission == DECORPERM_SOLID_MAT) + { + sub_8101118(ewram_1f000.items[i], gUnknown_020391B4); + if (sub_8101200(taskId, i, gUnknown_020391B4) == TRUE) + { + gUnknown_020391B4->decorId = i; + sub_81012A0(); + gUnknown_02039234 = 1; + return TRUE; + } + } + } + } + return FALSE; +} + +void sub_81013B8(u8 a0, u8 a1, u8 a2, u8 a3) +{ + u8 i; + u8 xOff; + u8 yOff; + u8 decorIdx; + for (i=0; i<ewram_1f000.size; i++) + { + decorIdx = ewram_1f000.items[i]; + xOff = ewram_1f000.pos[i] >> 4; + yOff = ewram_1f000.pos[i] & 0xf; + if (decorIdx != 0 && gDecorations[decorIdx].permission == DECORPERM_SOLID_MAT && a0 <= xOff && a1 <= yOff && a2 >= xOff && a3 >= yOff) + { + gUnknown_020391B4[gUnknown_02039234].decorId = i; + sub_81012A0(); + gUnknown_02039234++; + } + } +} + +#ifdef NONMATCHING +void sub_8101460(u8 taskId) +{ + u8 i; + u8 xOff; + u8 yOff; + gUnknown_02039234 = 0; + if (sub_8101340(taskId) != TRUE) + { + for (i=0; i<ewram_1f000.size; i++) + { + if (ewram_1f000.items[i] == 0) // This is using the wrong register! + { + continue; + } + sub_8101118(ewram_1f000.items[i], gUnknown_020391B4); + if (sub_8101200(taskId, i, gUnknown_020391B4) == TRUE) + { + gUnknown_020391B4[0].decorId = i; + gUnknown_02039234++; + break; + } + } + if (gUnknown_02039234 != 0) + { + xOff = ewram_1f000.pos[gUnknown_020391B4[0].decorId] >> 4; + yOff = ewram_1f000.pos[gUnknown_020391B4[0].decorId] & 0xf; + sub_81013B8(xOff, yOff - gUnknown_020391B4[0].height + 1, xOff + gUnknown_020391B4[0].width - 1, yOff); + } + } +} +#else +__attribute__((naked)) +void sub_8101460(u8 taskId) +{ + asm(".syntax unified\n" + "\tpush {r4-r7,lr}\n" + "\tlsls r0, 24\n" + "\tlsrs r6, r0, 24\n" + "\tldr r4, _081014B8 @ =gUnknown_02039234\n" + "\tmovs r0, 0\n" + "\tstrb r0, [r4]\n" + "\tadds r0, r6, 0\n" + "\tbl sub_8101340\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tcmp r0, 0x1\n" + "\tbeq _08101504\n" + "\tmovs r5, 0\n" + "\tldr r0, _081014BC @ =ewram_1f000\n" + "\tldrb r1, [r0, 0x8]\n" + "\tcmp r5, r1\n" + "\tbcs _081014D2\n" + "\tadds r7, r4, 0\n" + "_08101486:\n" + "\tldr r0, [r0]\n" + "\tadds r0, r5\n" + "\tldrb r1, [r0] @ compiler incorrectly uses r0 for this and the next instruction\n" + "\tcmp r1, 0\n" + "\tbeq _081014C4\n" + "\tldr r4, _081014C0 @ =gUnknown_020391B4\n" + "\tadds r0, r1, 0\n" + "\tadds r1, r4, 0\n" + "\tbl sub_8101118\n" + "\tadds r0, r6, 0\n" + "\tadds r1, r5, 0\n" + "\tadds r2, r4, 0\n" + "\tbl sub_8101200\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tcmp r0, 0x1\n" + "\tbne _081014C4\n" + "\tstrb r5, [r4]\n" + "\tldrb r0, [r7]\n" + "\tadds r0, 0x1\n" + "\tstrb r0, [r7]\n" + "\tb _081014D2\n" + "\t.align 2, 0\n" + "_081014B8: .4byte gUnknown_02039234\n" + "_081014BC: .4byte 0x201f000\n" + "_081014C0: .4byte gUnknown_020391B4\n" + "_081014C4:\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r5, r0, 24\n" + "\tldr r0, _0810150C @ =ewram_1f000\n" + "\tldrb r1, [r0, 0x8]\n" + "\tcmp r5, r1\n" + "\tbcc _08101486\n" + "_081014D2:\n" + "\tldr r0, _08101510 @ =gUnknown_02039234\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0\n" + "\tbeq _08101504\n" + "\tldr r0, _0810150C @ =ewram_1f000\n" + "\tldr r2, _08101514 @ =gUnknown_020391B4\n" + "\tldrb r1, [r2]\n" + "\tldr r0, [r0, 0x4]\n" + "\tadds r0, r1\n" + "\tldrb r1, [r0]\n" + "\tlsrs r0, r1, 4\n" + "\tmovs r3, 0xF\n" + "\tands r3, r1\n" + "\tldrb r1, [r2, 0x2]\n" + "\tsubs r1, r3, r1\n" + "\tadds r1, 0x1\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tldrb r2, [r2, 0x1]\n" + "\tadds r2, r0\n" + "\tsubs r2, 0x1\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tbl sub_81013B8\n" + "_08101504:\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_0810150C: .4byte 0x201f000\n" + "_08101510: .4byte gUnknown_02039234\n" + "_08101514: .4byte gUnknown_020391B4\n" + ".syntax divided\n"); +} +#endif + +void sub_8101518(u8 taskId) +{ + DisplayYesNoMenu(20, 8, 1); + DoYesNoFuncWithChoice(taskId, &gUnknown_083EC9CC); +} + +void sub_810153C(u8 taskId) +{ + fade_screen(1, 0); + gTasks[taskId].data[2] = 0; + gTasks[taskId].func = sub_8100C88; +} + +void sub_810156C(u8 taskId) +{ + DisplayYesNoMenu(20, 8, 1); + DoYesNoFuncWithChoice(taskId, &gUnknown_083EC9D4); +} + +void sub_8101590(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0, 29, 19); + sub_81015B0(taskId); +} + +void sub_81015B0(u8 taskId) +{ + fade_screen(1, 0); + gTasks[taskId].data[2] = 0; + gTasks[taskId].func = sub_81015E0; +} + +void sub_81015E0(u8 taskId) +{ + switch (gTasks[taskId].data[2]) + { + case 0: + if (!gPaletteFade.active) + { + sub_80FF114(taskId); + gTasks[taskId].data[2] = 1; + } + break; + case 1: + sub_81016F4(); + gFieldCallback = sub_8101678; + SetMainCallback2(c2_exit_to_overworld_2_switch); + DestroyTask(taskId); + break; + } +} + +void sub_8101648(u8 taskId) +{ + if (sub_807D770() == TRUE) + { + gTasks[taskId].func = Task_DecorationPCProcessMenuInput; + } +} + +void sub_8101678(void) +{ + pal_fill_black(); + MenuDisplayMessageBox(); + sub_80FE220(); + CreateTask(sub_8101648, 8); +} + +void sub_8101698(struct Sprite *sprite) +{ + sprite->data0 = (sprite->data0 + 1) & 0x1f; + if (sprite->data0 >= 16) + { + sprite->invisible = TRUE; + } else + { + sprite->invisible = FALSE; + } +} + +void sub_81016C8(void) +{ + if (gSaveBlock2.playerGender == MALE) + { + LoadSpritePalette(&gUnknown_083ECA5C); + } else + { + LoadSpritePalette(&gUnknown_083ECA64); + } +} + +void sub_81016F4(void) +{ + FreeSpritePaletteByTag(8); +} + +void sub_8101700(u8 taskId) +{ + if (!sub_81341D4()) + { + DisplayItemMessageOnField(taskId, gSecretBaseText_NoDecors, sub_80FE428, 0); + } else + { + gTasks[taskId].data[11] = 1; + gUnknown_020388F6 = 0; + sub_80FE5AC(taskId); + } +} + +void sub_8101750(u8 taskId) +{ + if (!sub_81341D4()) + { + DisplayItemMessageOnField(taskId, gSecretBaseText_NoDecors, sub_80FE428, 0); + } else + { + gTasks[taskId].data[11] = 2; + gUnknown_020388F6 = 0; + sub_80FE5AC(taskId); + } +} + +void sub_81017A0(u8 taskId) +{ + sub_80FEF74(); + sub_80FED1C(); + if (sub_80FEFA4() == TRUE) + { + StringCopy(gStringVar1, gDecorations[gUnknown_020388D0[gUnknown_020388F5]].name); + StringExpandPlaceholders(gStringVar4, gSecretBaseText_WillBeDiscarded); + DisplayItemMessageOnField(taskId, gStringVar4, sub_8101824, 0); + } else + { + DisplayItemMessageOnField(taskId, gSecretBaseText_DecorInUse, sub_80FEFF4, 0); + } +} + +void sub_8101824(u8 taskId) +{ + DisplayYesNoMenu(20, 8, 1); + DoYesNoFuncWithChoice(taskId, &gUnknown_083ECAA0); +} + +void sub_8101848(u8 taskId) +{ + MenuZeroFillWindowRect(20, 8, 26, 14); + sub_8109A30(gUnknown_020388D0[gUnknown_020388F5]); + gUnknown_020388D0[gUnknown_020388F5] = DECOR_NONE; + sub_80FF098(taskId); + DisplayItemMessageOnField(taskId, gSecretBaseText_DecorThrownAway, sub_80FEFF4, 0); +} diff --git a/src/field/decoration_inventory.c b/src/field/decoration_inventory.c new file mode 100644 index 000000000..083cb260c --- /dev/null +++ b/src/field/decoration_inventory.c @@ -0,0 +1,169 @@ +// + +// + +#include "global.h" +#include "sprite.h" +#include "task.h" +#include "decoration.h" +#include "decoration_inventory.h" + +#define DECOR_INV(ptr) {.items = (u8 *)&ptr, .size = sizeof ptr} + +struct DecorationInventory const gDecorationInventories[] = { + DECOR_INV(gSaveBlock1.decorDesk), + DECOR_INV(gSaveBlock1.decorChair), + DECOR_INV(gSaveBlock1.decorPlant), + DECOR_INV(gSaveBlock1.decorOrnament), + DECOR_INV(gSaveBlock1.decorMat), + DECOR_INV(gSaveBlock1.decorPoster), + DECOR_INV(gSaveBlock1.decorDoll), + DECOR_INV(gSaveBlock1.decorCushion) +}; + +void ClearDecorationInventory(u8 invIdx) +{ + u8 i; + for (i=0; i<gDecorationInventories[invIdx].size; i++) + { + gDecorationInventories[invIdx].items[i] = DECOR_NONE; + } +} + +void ClearDecorationInventories(void) +{ + u8 i; + for (i=0; i<8; i++) + { + ClearDecorationInventory(i); + } +} + +s8 sub_8133F9C(u8 invIdx) +{ + s8 i; + for (i=0; i<(s8)gDecorationInventories[invIdx].size; i++) + { + if (gDecorationInventories[invIdx].items[i] == DECOR_NONE) + { + return i; + } + } + return -1; +} + +bool8 sub_8133FE4(u8 decorIdx) +{ + u8 invIdx; + u8 i; + invIdx = gDecorations[decorIdx].category; + for (i=0; i<gDecorationInventories[invIdx].size; i++) + { + if (gDecorationInventories[invIdx].items[i] == decorIdx) + { + return TRUE; + } + } + return FALSE; +} + +bool8 IsThereStorageSpaceForDecoration(u8 decorIdx) +{ + u8 invIdx; + s8 invSlot; + if (decorIdx == DECOR_NONE) + { + return FALSE; + } + invIdx = gDecorations[decorIdx].category; + invSlot = sub_8133F9C(invIdx); + if (invSlot == -1) + { + return FALSE; + } + gDecorationInventories[invIdx].items[invSlot] = decorIdx; + return TRUE; +} + +bool8 sub_8134074(u8 decorIdx) +{ + u8 invIdx; + if (decorIdx == DECOR_NONE) + { + return FALSE; + } + invIdx = gDecorations[decorIdx].category; + if (sub_8133F9C(invIdx) == -1) + { + return FALSE; + } + return TRUE; +} + +s8 sub_81340A8(u8 decorIdx) +{ + u8 i; + u8 invIdx; + i = 0; + if (decorIdx == DECOR_NONE) + { + return FALSE; + } + for (i=0; i<gDecorationInventories[gDecorations[decorIdx].category].size; i++) + { + invIdx = gDecorations[decorIdx].category; + if (gDecorationInventories[invIdx].items[i] == decorIdx) + { + gDecorationInventories[invIdx].items[i] = DECOR_NONE; + sub_8134104(invIdx); + return TRUE; + } + } + return FALSE; +} + +void sub_8134104(u8 invIdx) +{ + u8 i; + u8 j; + u8 tmp; + for (i=0; i<gDecorationInventories[invIdx].size; i++) + { + for (j=i+1; j<gDecorationInventories[invIdx].size; j++) + { + if (gDecorationInventories[invIdx].items[j] != 0 && (gDecorationInventories[invIdx].items[i] == DECOR_NONE || gDecorationInventories[invIdx].items[i] > gDecorationInventories[invIdx].items[j])) + { + tmp = gDecorationInventories[invIdx].items[i]; + gDecorationInventories[invIdx].items[i] = gDecorationInventories[invIdx].items[j]; + gDecorationInventories[invIdx].items[j] = tmp; + } + } + } +} + +u8 sub_8134194(u8 invIdx) +{ + u8 i; + u8 count; + count = 0; + for (i=0; i<gDecorationInventories[invIdx].size; i++) + { + if (gDecorationInventories[invIdx].items[i] != 0) + { + count++; + } + } + return count; +} + +u8 sub_81341D4(void) +{ + u8 i; + u8 count; + count = 0; + for (i=0; i<8; i++) + { + count += sub_8134194(i); + } + return count; +} diff --git a/src/field/dewford_trend.c b/src/field/dewford_trend.c new file mode 100644 index 000000000..aaf4dd66a --- /dev/null +++ b/src/field/dewford_trend.c @@ -0,0 +1,332 @@ +#include "global.h" +#include "dewford_trend.h" +#include "easy_chat.h" +#include "event_data.h" +#include "link.h" +#include "rng.h" +#include "text.h" + +extern u8 unk_2000000[]; + +extern u16 gScriptResult; +extern u16 gSpecialVar_0x8004; + +static void sub_80FA46C(struct EasyChatPair *s, u16 b, u8 c); +static bool8 sub_80FA670(struct EasyChatPair *a, struct EasyChatPair *b, u8 c); +static void sub_80FA740(struct EasyChatPair *s); +static bool8 SB1ContainsWords(u16 *a); +static bool8 IsEasyChatPairEqual(u16 *words1, u16 *words2); +static s16 sub_80FA828(struct EasyChatPair *a, u16 b); + +void InitDewfordTrend(void) +{ + u16 i; + + for (i = 0; i < 5; i++) + { + gSaveBlock1.easyChatPairs[i].words[0] = sub_80EB72C(EC_GROUP_CONDITIONS); + + if (Random() & 1) + gSaveBlock1.easyChatPairs[i].words[1] = sub_80EB72C(EC_GROUP_LIFESTYLE); + else + gSaveBlock1.easyChatPairs[i].words[1] = sub_80EB72C(EC_GROUP_HOBBIES); + + gSaveBlock1.easyChatPairs[i].unk1_6 = Random() & 1; + sub_80FA740(&gSaveBlock1.easyChatPairs[i]); + } + sub_80FA46C(gSaveBlock1.easyChatPairs, 5, 0); +} + +void UpdateDewfordTrendPerDay(u16 a) +{ + u16 i; + + if (a != 0) + { + u32 sp0 = a * 5; + + for (i = 0; i < 5; i++) + { + //_080FA24A + u32 r4; + u32 r2 = sp0; + struct EasyChatPair *r5 = &gSaveBlock1.easyChatPairs[i]; + + if (r5->unk1_6 == 0) + { + if (r5->unk0_0 >= (u16)r2) + { + r5->unk0_0 -= r2; + if (r5->unk0_0 == 0) + r5->unk1_6 = 1; + continue; + } + //_080FA290 + r2 -= r5->unk0_0; + r5->unk0_0 = 0; + r5->unk1_6 = 1; + } + //_080FA2A0 + r4 = r5->unk0_0 + r2; + if ((u16)r4 > r5->unk0_7) + { + u32 sp4 = r4 % r5->unk0_7; + r4 = r4 / r5->unk0_7; + + r5->unk1_6 = r4 ^ 1; + if (r5->unk1_6) + r5->unk0_0 = sp4; + else + //_080FA2FA + r5->unk0_0 = r5->unk0_7 - sp4; + } + else + { + //_080FA310 + r5->unk0_0 = r4; + + if (r5->unk0_0 == r5->unk0_7) + r5->unk1_6 = 0; + } + } + sub_80FA46C(gSaveBlock1.easyChatPairs, 5, 0); + } + //_080FA34E +} + +bool8 sub_80FA364(u16 *a) +{ + struct EasyChatPair s = {0}; + u16 i; + + if (!SB1ContainsWords(a)) + { + if (!FlagGet(SYS_POPWORD_INPUT)) + { + FlagSet(SYS_POPWORD_INPUT); + if (!FlagGet(SYS_MIX_RECORD)) + { + gSaveBlock1.easyChatPairs[0].words[0] = a[0]; + gSaveBlock1.easyChatPairs[0].words[1] = a[1]; + return 1; + } + } + + //_080FA3C8 + s.words[0] = a[0]; + s.words[1] = a[1]; + s.unk1_6 = 1; + sub_80FA740(&s); + + for (i = 0; i < 5; i++) + { + if (sub_80FA670(&s, &gSaveBlock1.easyChatPairs[i], 0)) + { + u16 r3 = 4; + + while (r3 > i) + { + gSaveBlock1.easyChatPairs[r3] = gSaveBlock1.easyChatPairs[r3 - 1]; + r3--; + } + gSaveBlock1.easyChatPairs[i] = s; + return (i == 0); + } + //_080FA450 + } + gSaveBlock1.easyChatPairs[4] = s; + } + return 0; +} + +static void sub_80FA46C(struct EasyChatPair *s, u16 b, u8 c) +{ + u16 h; + + for (h = 0; h < b; h++) + { + u16 i; + + for (i = h + 1; i < b; i++) + { + if (sub_80FA670(&s[i], &s[h], c)) + { + struct EasyChatPair temp; + + temp = s[i]; + s[i] = s[h]; + s[h] = temp; + } + } + } +} + +void sub_80FA4E4(void *a, u32 b, u8 unused) +{ + u16 i; + u16 j; + u16 r7; + struct EasyChatPair *src; + struct EasyChatPair *dst; + u16 players = GetLinkPlayerCount(); + + for (i = 0; i < players; i++) + memcpy(&ARRAY_2007800[i * 5], (u8 *)a + i * b, 40); + src = ARRAY_2007800; + dst = ARRAY_2007900; + r7 = 0; + for (i = 0; i < players; i++) + { + for (j = 0; j < 5; j++) + { + s16 foo = sub_80FA828(src, r7); + if (foo < 0) + { + *(dst++) = *src; + r7++; + } + else + { + if (ARRAY_2007900[foo].unk0_0 < src->unk0_0) + { + ARRAY_2007900[foo] = *src; + } + } + src++; + } + } + sub_80FA46C(ARRAY_2007900, r7, 2); + src = ARRAY_2007900; + dst = gSaveBlock1.easyChatPairs; + for (i = 0; i < 5; i++) + *(dst++) = *(src++); +} + +void sub_80FA5BC(void) +{ + struct EasyChatPair *s = &gSaveBlock1.easyChatPairs[gSpecialVar_0x8004]; + + ConvertEasyChatWordsToString(gStringVar1, s->words, 2, 1); +} + +void sub_80FA5E4(void) +{ + u16 result = 0; + + if (gSaveBlock1.easyChatPairs[0].unk0_0 - gSaveBlock1.easyChatPairs[1].unk0_0 < 2) + { + asm("":::"r2"); //Force the compiler to store address of gSaveBlock1 in r3 instead of r2 + if (!gSaveBlock1.easyChatPairs[0].unk1_6 && gSaveBlock1.easyChatPairs[1].unk1_6) + result = 1; + } + gScriptResult = result; +} + +void sub_80FA648(void) +{ + gScriptResult = (gSaveBlock1.easyChatPairs[0].words[0] + gSaveBlock1.easyChatPairs[0].words[1]) & 7; +} + +static bool8 sub_80FA670(struct EasyChatPair *a, struct EasyChatPair *b, u8 c) +{ + switch (c) + { + case 0: + if (a->unk0_0 > b->unk0_0) + return 1; + if (a->unk0_0 < b->unk0_0) + return 0; + if (a->unk0_7 > b->unk0_7) + return 1; + if (a->unk0_7 < b->unk0_7) + return 0; + break; + case 1: + if (a->unk0_7 > b->unk0_7) + return 1; + if (a->unk0_7 < b->unk0_7) + return 0; + if (a->unk0_0 > b->unk0_0) + return 1; + if (a->unk0_0 < b->unk0_0) + return 0; + break; + case 2: + if (a->unk0_0 > b->unk0_0) + return 1; + if (a->unk0_0 < b->unk0_0) + return 0; + if (a->unk0_7 > b->unk0_7) + return 1; + if (a->unk0_7 < b->unk0_7) + return 0; + if (a->unk2 > b->unk2) + return 1; + if (a->unk2 < b->unk2) + return 0; + if (a->words[0] > b->words[0]) + return 1; + if (a->words[0] < b->words[0]) + return 0; + if (a->words[1] > b->words[1]) + return 1; + if (a->words[1] < b->words[1]) + return 0; + return 1; + } + return Random() & 1; +} + +static void sub_80FA740(struct EasyChatPair *s) +{ + u16 r4; + + r4 = Random() % 98; + if (r4 > 50) + { + r4 = Random() % 98; + if (r4 > 80) + r4 = Random() % 98; + } + s->unk0_7 = r4 + 30; + s->unk0_0 = (Random() % (r4 + 1)) + 30; + s->unk2 = Random(); +} + +static bool8 SB1ContainsWords(u16 *a) +{ + u16 i; + + for (i = 0; i < 5; i++) + { + if (IsEasyChatPairEqual(a, gSaveBlock1.easyChatPairs[i].words) != 0) + return TRUE; + } + return FALSE; +} + +static bool8 IsEasyChatPairEqual(u16 *words1, u16 *words2) +{ + u16 i; + + for (i = 0; i < 2; i++) + { + if (*(words1++) != *(words2++)) + return FALSE; + } + return TRUE; +} + +static s16 sub_80FA828(struct EasyChatPair *a, u16 b) +{ + s16 i; + struct EasyChatPair *s = ARRAY_2007900; + + for (i = 0; i < b; i++) + { + if (IsEasyChatPairEqual(a->words, s->words)) + return i; + s++; + } + return -1; +} diff --git a/src/field/diploma.c b/src/field/diploma.c new file mode 100644 index 000000000..27601404c --- /dev/null +++ b/src/field/diploma.c @@ -0,0 +1,139 @@ +#include "global.h" +#include "diploma.h" +#include "main.h" +#include "menu.h" +#include "palette.h" +#include "pokedex.h" +#include "overworld.h" +#include "sprite.h" +#include "string_util.h" +#include "strings2.h" +#include "task.h" +#include "text.h" +#include "unknown_task.h" + +static void VBlankCB(void); +static void MainCB2(void); +static void Task_DiplomaFadeIn(u8); +static void Task_DiplomaWaitForKeyPress(u8); +static void Task_DiplomaFadeOut(u8); +static void DisplayDiplomaText(void); + +static const u16 gDiplomaPalettes[][16] = +{ + INCBIN_U16("graphics/misc/diploma_national.gbapal"), + INCBIN_U16("graphics/misc/diploma_hoenn.gbapal"), +}; + +static const u8 gDiplomaTilemap[] = INCBIN_U8("graphics/misc/diploma_map.bin.lz"); +static const u8 gDiplomaTiles[] = INCBIN_U8("graphics/misc/diploma.4bpp.lz"); + +static void VBlankCB(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void CB2_ShowDiploma(void) +{ + u32 savedIme; + + SetVBlankCallback(NULL); + + REG_DISPCNT = 0; + REG_BG3CNT = 0; + REG_BG2CNT = 0; + REG_BG1CNT = 0; + REG_BG0CNT = 0; + REG_BG3HOFS = 0; + REG_BG3VOFS = 0; + REG_BG2HOFS = 0; + REG_BG2VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + + DmaFill16(3, 0, VRAM, VRAM_SIZE); + DmaFill32(3, 0, OAM, OAM_SIZE); + DmaFill16(3, 0, PLTT, PLTT_SIZE); + + LZ77UnCompVram(gDiplomaTiles, (void *)VRAM); + LZ77UnCompVram(gDiplomaTilemap, (void *)(VRAM + 0x3000)); + + remove_some_task(); + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + FreeAllSpritePalettes(); + LoadPalette(gDiplomaPalettes, 0, 64); + SetUpWindowConfig(&gWindowConfig_81E6C3C); + InitMenuWindow(&gWindowConfig_81E6CE4); + DisplayDiplomaText(); + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + + savedIme = REG_IME; + REG_IME = 0; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = savedIme; + REG_DISPSTAT |= DISPSTAT_VBLANK_INTR; + + SetVBlankCallback(VBlankCB); + SetMainCallback2(MainCB2); + + REG_BLDCNT = 0; + REG_BLDALPHA = 0; + REG_BLDY = 0; + REG_BG3CNT = BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(6) | BGCNT_16COLOR | BGCNT_TXT512x256; + REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON; + + CreateTask(Task_DiplomaFadeIn, 0); +} + +static void MainCB2(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void Task_DiplomaFadeIn(u8 taskId) +{ + if (!gPaletteFade.active) + gTasks[taskId].func = Task_DiplomaWaitForKeyPress; +} + +static void Task_DiplomaWaitForKeyPress(u8 taskId) +{ + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gTasks[taskId].func = Task_DiplomaFadeOut; + } +} + +static void Task_DiplomaFadeOut(u8 taskId) +{ + if (!gPaletteFade.active) + { + DestroyTask(taskId); + SetMainCallback2(sub_80546F0); + } +} + +static void DisplayDiplomaText(void) +{ + if (sub_8090FF4()) + { + REG_BG3HOFS = 256; + StringCopy(gStringVar1, gOtherText_NationalDex); + } + else + { + REG_BG3HOFS = 0; + StringCopy(gStringVar1, gOtherText_HoennDex); + } + MenuPrint(gOtherText_DiplomaCertificationGameFreak, 6, 2); +}
\ No newline at end of file diff --git a/src/field/easy_chat.c b/src/field/easy_chat.c new file mode 100644 index 000000000..6014b3d14 --- /dev/null +++ b/src/field/easy_chat.c @@ -0,0 +1,444 @@ +#include "global.h" +#include "easy_chat.h" +#include "data2.h" +#include "event_data.h" +#include "field_message_box.h" +#include "pokedex.h" +#include "rng.h" +#include "string_util.h" +#include "strings.h" +#include "strings2.h" +#include "text.h" + +static bool8 sub_80EB680(u16 *, u16, u16, u16); +static u16 sub_80EB9D8(void); +static u16 sub_80EB960(void); + +extern void *gEasyChatGroupWords[]; +extern const u8 gEasyChatGroupSizes[]; + +extern u16 gSpecialVar_0x8004; + +IWRAM_DATA u8 gUnknown_03000740; + +// returns the end of the destination buffer text +u8 *EasyChat_GetWordText(u8 *dst, u16 word) +{ + u16 group; + u16 wordIndex; + u8 *src; + u16 i; + + if (sub_80EB37C(word)) + return StringCopy(dst, gOtherText_ThreeQuestions); + + if (word == 0xFFFF) + { + *dst = EOS; + return dst; + } + else + { + group = EC_GROUP(word); + wordIndex = EC_INDEX(word); + switch (group) + { + case EC_GROUP_POKEMON: // 0 + case EC_GROUP_POKEMON_2: // 21 + dst = StringCopy(dst, gSpeciesNames[wordIndex]); + break; + case EC_GROUP_MOVE_1: // 18 + case EC_GROUP_MOVE_2: // 19 + dst = StringCopy(dst, gMoveNames[wordIndex]); + break; + default: + src = gEasyChatGroupWords[group]; + for (i = wordIndex - 1; i != 0xFFFF; i--) + { + while (*src++ != EOS) + ; + } + dst = StringCopy(dst, src); + break; + } + *dst = EOS; + return dst; + } +} + +u8 *ConvertEasyChatWordsToString(u8 *dst, u16 *words, u16 arg2, u16 arg3) +{ + u16 i; + u16 n; + + const u16 i1 = arg2 - 1; + + for (i = 0; i < arg3; i++) + { + u16 word; + + for (n = 0; n < i1; n++) + { + dst = EasyChat_GetWordText(dst, words[0]); + + if (words[0] != 0xFFFF) + { + dst[0] = CHAR_SPACE; + dst++; + } + + words++; + } + + word = words[0]; + words++; + dst = EasyChat_GetWordText(dst, word); + + dst[0] = CHAR_NEWLINE; + dst++; + } + + dst--; + dst[0] = EOS; + + return dst; +} + +u8 *sub_80EB544(u8 *dst, u16 *words, u16 arg2, u16 arg3) +{ + u16 i; + u16 n; + + const u16 i1 = arg2 - 1; + + for (i = 0; i < arg3; i++) + { + u16 word; + + for (n = 0; n < i1; n++) + { + dst = EasyChat_GetWordText(dst, words[0]); + + if (words[0] != 0xFFFF) + { + dst[0] = CHAR_SPACE; + dst++; + } + + words++; + } + + word = words[0]; + words++; + dst = EasyChat_GetWordText(dst, word); + + // Only difference with ConvertEasyChatWordsToString + dst[0] = (i == 0) ? CHAR_NEWLINE : CHAR_PROMPT_SCROLL; + dst++; + } + + dst--; + dst[0] = EOS; + + return dst; +} + + +u16 unref_sub_80EB5E0(u16 arg0) +{ + const u8 *chars; + u16 i; + u16 length; + int group, word; + + + if (arg0 == 0xFFFF) + return 0; + + group = EC_GROUP(arg0); + word = EC_INDEX(arg0); + switch (group) + { + case EC_GROUP_POKEMON: // 0 + case EC_GROUP_POKEMON_2: // 21 + chars = (u8 *) gSpeciesNames[word]; + break; + case EC_GROUP_MOVE_1: // 18 + case EC_GROUP_MOVE_2: // 19 + chars = gMoveNames[word]; + break; + default: + chars = gEasyChatGroupWords[group]; + for (i = word - 1; i != 0xFFFF; i--) + { + while (*chars++ != EOS) + ; + } + break; + } + + length = 0; + while (*chars != EOS) + { + chars++; + length++; + } + + return length; +} + +static bool8 sub_80EB680(u16 *arg0, u16 arg1, u16 arg2, u16 arg3) +{ + return FALSE; +} + +void unref_sub_80EB684(u8 arg0, u16 arg1) +{ + u16 *ptr; + u16 c; + + // FIXME: find actual tv shows used + switch (arg0) + { + case 5: + c = 6; + ptr = (u16*)((void *)&gSaveBlock1.tvShows[arg1] + 0x04); + break; + case 7: + c = 2; + ptr = (u16*)((void *)&gSaveBlock1.tvShows[arg1] + 0x1C); + break; + case 8: + c = 1; + ptr = (u16*)((void *)&gSaveBlock1.tvShows[arg1] + 0x02); + break; + default: + return; + } + + c -= 1; + while (c != 0xFFFF) + { + *ptr = -1; + ptr++; + c -= 1; + } +} + +void sub_80EB6FC(u16 *arg0, u16 arg1) +{ + u16 i; + + for (i = arg1 - 1; i != 0xFFFF; i--) + { + *arg0 = 0xFFFF; + arg0++; + } + +} + +u16 sub_80EB72C(u16 group) +{ + u16 local1 = Random() % gEasyChatGroupSizes[group]; + + if (group == EC_GROUP_POKEMON + || group == EC_GROUP_POKEMON_2 + || group == EC_GROUP_MOVE_1 + || group == EC_GROUP_MOVE_2) + { + local1 = ((u16 *) gEasyChatGroupWords[group])[local1]; + } + + return ((group & 0x7F) << 9) | (local1 & 0x1FF); +} + +u16 sub_80EB784(u16 group) +{ + if (!sub_80EAD7C(group)) + return -1; + + if (group != EC_GROUP_POKEMON) + { + if (group == EC_GROUP_TRENDY_SAYING) + return sub_80EB960(); + } + else + { + return sub_80EB9D8(); + } + + return sub_80EB72C(group); +} + +void sub_80EB7C4(void) +{ + u16 *words; + u16 arg1, arg2; + + switch (gSpecialVar_0x8004) + { + case 0: + words = gSaveBlock1.unk2B1C; + arg1 = 2; + arg2 = 2; + break; + case 1: + words = gSaveBlock1.unk2B28; + if (sub_80EB680(gSaveBlock1.unk2B28, 3, 2, 20)) + { + arg1 = 2; + arg2 = 3; + } + else + { + arg1 = 3; + arg2 = 2; + } + break; + case 2: + words = gSaveBlock1.unk2B34; + arg1 = 3; + arg2 = 2; + break; + case 3: + words = gSaveBlock1.unk2B40; + arg1 = 3; + arg2 = 2; + break; + default: + return; + } + + ConvertEasyChatWordsToString(gStringVar4, words, arg1, arg2); + ShowFieldAutoScrollMessage(gStringVar4); +} + +void sub_80EB83C(void) +{ + u16 group, local2; + + if (Random() & 1) + group = EC_GROUP_HOBBIES; + else + group = EC_GROUP_LIFESTYLE; + + local2 = sub_80EB784(group); + EasyChat_GetWordText(gStringVar2, local2); +} + +u8 sub_80EB868(u8 arg0) +{ + int offset; + int index; + + index = arg0 / 8; + offset = arg0 % 8; + return (gSaveBlock1.unk2D8C[index] >> offset) & 1; +} + +void sub_80EB890(u8 arg0) +{ + int offset; + int index; + + if (arg0 < 33) + { + index = arg0 / 8; + offset = arg0 % 8; + gSaveBlock1.unk2D8C[index] |= 1 << offset; + } +} + +u8 sub_80EB8C0(void) +{ + u8 i, count; + + for (i = 0, count = 0; i < 33; i++) + { + if (sub_80EB868(i)) + count++; + } + return count; +} + +u16 sub_80EB8EC(void) +{ + u16 i; + u16 local1, local2; + + local1 = sub_80EB8C0(); + if (local1 == 33) + return -1; + + local2 = Random() % (33 - local1); + for (i = 0; i < 33; i++) + { + if (sub_80EB868(i) == 0) + { + if (local2 == 0) + { + sub_80EB890(i); + return (i & 0x1FF) | 0x2800; + } + local2--; + } + } + return -1; +} + +static u16 sub_80EB960(void) +{ + u16 i; + u16 local1; + + local1 = sub_80EB8C0(); + if (local1 == 0) + return -1; + + local1 = Random() % local1; + for (i = 0; i < 33; i++) + { + if (sub_80EB868(i)) + { + if (local1 == 0) + return (i & 0x1FF) | 0x2800; + local1--; + } + } + + return -1; +} + +u8 sub_80EB9C8(void) +{ + return IsNationalPokedexEnabled(); +} + +static u16 sub_80EB9D8(void) +{ + u16 *speciesList; + u16 local1; + u16 i; + + local1 = sub_80EAE88(0); + + if (local1 == 0) + return -1; + + local1 = Random() % local1; + speciesList = (u16 *) gEasyChatGroupWords[EC_GROUP_POKEMON]; + for (i = 0; i < gEasyChatGroupSizes[EC_GROUP_POKEMON]; i++) + { + const u16 dexNum = SpeciesToNationalPokedexNum(*speciesList); + const u8 local2 = GetSetPokedexFlag(dexNum, 0); + + if (local2) + { + if (local1 == 0) + return *speciesList & 0x1FF; + local1--; + } + speciesList++; + } + return -1; +} diff --git a/src/field/event_data.c b/src/field/event_data.c new file mode 100644 index 000000000..43d49c417 --- /dev/null +++ b/src/field/event_data.c @@ -0,0 +1,182 @@ +#include "global.h" +#include "event_data.h" +#include "pokedex.h" + +#define TEMP_FLAGS_SIZE 0x4 +#define TEMP_UPPER_FLAGS_SIZE 0x8 +#define TEMP_VARS_SIZE 0x20 + +EWRAM_DATA u16 gSpecialVar_0x8000 = 0; +EWRAM_DATA u16 gSpecialVar_0x8001 = 0; +EWRAM_DATA u16 gSpecialVar_0x8002 = 0; +EWRAM_DATA u16 gSpecialVar_0x8003 = 0; +EWRAM_DATA u16 gSpecialVar_0x8004 = 0; +EWRAM_DATA u16 gSpecialVar_0x8005 = 0; +EWRAM_DATA u16 gSpecialVar_0x8006 = 0; +EWRAM_DATA u16 gSpecialVar_0x8007 = 0; +EWRAM_DATA u16 gSpecialVar_0x8008 = 0; +EWRAM_DATA u16 gSpecialVar_0x8009 = 0; +EWRAM_DATA u16 gSpecialVar_0x800A = 0; +EWRAM_DATA u16 gSpecialVar_0x800B = 0; +EWRAM_DATA u16 gScriptResult = 0; +EWRAM_DATA u16 gScriptLastTalked = 0; +EWRAM_DATA u16 gScriptFacing = 0; +EWRAM_DATA u8 gUnknown_0202E8E2[16] = {0}; + +extern u16 *gSpecialVars[]; + +void InitEventData(void) +{ + memset(gSaveBlock1.flags, 0, sizeof(gSaveBlock1.flags)); + memset(gSaveBlock1.vars, 0, sizeof(gSaveBlock1.vars)); + memset(gUnknown_0202E8E2, 0, sizeof(gUnknown_0202E8E2)); +} + +void ClearTempFieldEventData(void) +{ + memset(gSaveBlock1.flags, 0, TEMP_FLAGS_SIZE); + memset(gSaveBlock1.vars, 0, TEMP_VARS_SIZE); + FlagClear(SYS_ENC_UP_ITEM); + FlagClear(SYS_ENC_DOWN_ITEM); + FlagClear(SYS_USE_STRENGTH); + FlagClear(SYS_CTRL_OBJ_DELETE); +} + +// probably had different flag splits at one point. +void ClearUpperFlags(void) +{ + memset(gSaveBlock1.flags + 0x118, 0, TEMP_UPPER_FLAGS_SIZE); +} + +void DisableNationalPokedex(void) +{ + u16 *nationalDexVar = GetVarPointer(VAR_NATIONAL_DEX); + gSaveBlock2.pokedex.nationalMagic = 0; + *nationalDexVar = 0; + FlagClear(SYS_NATIONAL_DEX); +} + +void EnableNationalPokedex(void) +{ + u16 *nationalDexVar = GetVarPointer(VAR_NATIONAL_DEX); + gSaveBlock2.pokedex.nationalMagic = 0xDA; + *nationalDexVar = 0x302; + FlagSet(SYS_NATIONAL_DEX); + gSaveBlock2.pokedex.unknown1 = 1; + gSaveBlock2.pokedex.order = 0; + sub_808C0A0(); +} + +bool32 IsNationalPokedexEnabled(void) +{ + if (gSaveBlock2.pokedex.nationalMagic == 0xDA && VarGet(VAR_NATIONAL_DEX) == 0x302 && FlagGet(SYS_NATIONAL_DEX)) + return TRUE; + else + return FALSE; +} + +void DisableMysteryGift(void) +{ + FlagClear(SYS_EXDATA_ENABLE); +} + +void EnableMysteryGift(void) +{ + FlagSet(SYS_EXDATA_ENABLE); +} + +bool32 IsMysteryGiftEnabled(void) +{ + return FlagGet(SYS_EXDATA_ENABLE); +} + +void DisableResetRTC(void) +{ + VarSet(VAR_RESET_RTC_ENABLE, 0); + FlagClear(SYS_RESET_RTC_ENABLE); +} + +void EnableResetRTC(void) +{ + VarSet(VAR_RESET_RTC_ENABLE, 0x920); + FlagSet(SYS_RESET_RTC_ENABLE); +} + +bool32 CanResetRTC(void) +{ + if (FlagGet(SYS_RESET_RTC_ENABLE) && VarGet(VAR_RESET_RTC_ENABLE) == 0x920) + return TRUE; + else + return FALSE; +} + +u16 *GetVarPointer(u16 id) +{ + if (id < 0x4000) + return NULL; + if (id < 0x8000) + return &gSaveBlock1.vars[id - 0x4000]; + return gSpecialVars[id - 0x8000]; +} + +u16 VarGet(u16 id) +{ + u16 *ptr = GetVarPointer(id); + if (!ptr) + return id; + return *ptr; +} + +bool8 VarSet(u16 id, u16 value) +{ + u16 *ptr = GetVarPointer(id); + if (!ptr) + return FALSE; + *ptr = value; + return TRUE; +} + +u8 VarGetFieldObjectGraphicsId(u8 id) +{ + return VarGet(0x4010 + id); +} + +u8 *GetFlagPointer(u16 id) +{ + if (id == 0) + return 0; + + if (id < 0x4000) + return &gSaveBlock1.flags[id / 8]; + + return &gUnknown_0202E8E2[(id - 0x4000) / 8]; +} + +u8 FlagSet(u16 id) +{ + u8 *ptr = GetFlagPointer(id); + if (ptr) + *ptr |= 1 << (id & 7); + return 0; +} + +u8 FlagClear(u16 id) +{ + u8 *ptr = GetFlagPointer(id); + if (ptr) + *ptr &= ~(1 << (id & 7)); + return 0; +} + +bool8 FlagGet(u16 id) +{ + u8 *ptr = GetFlagPointer(id); + + if (!ptr) + return FALSE; + + if (!(((*ptr) >> (id & 7)) & 1)) + return FALSE; + + return TRUE; +} diff --git a/src/field/field_camera.c b/src/field/field_camera.c new file mode 100644 index 000000000..db51cf054 --- /dev/null +++ b/src/field/field_camera.c @@ -0,0 +1,495 @@ +#include "global.h" +#include "field_camera.h" +#include "berry.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "rotating_gate.h" +#include "sprite.h" +#include "text.h" + +EWRAM_DATA u8 gUnknown_0202E854 = 0; + +struct UnknownStruct +{ + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; + bool8 unk4; +}; + +static struct UnknownStruct gUnknown_03000590; +static u16 gUnknown_03000598; +static s16 gUnknown_0300059A; +static u8 gUnknown_0300059C; +static void (*gUnknown_030005A0)(void); + +struct CameraSomething gUnknown_03004880; +u16 gUnknown_03004898; +u16 gUnknown_0300489C; + +static void RedrawMapSliceNorth(struct UnknownStruct *a, struct MapData *mapData); +static void RedrawMapSliceSouth(struct UnknownStruct *a, struct MapData *mapData); +static void RedrawMapSliceEast(struct UnknownStruct *a, struct MapData *mapData); +static void RedrawMapSliceWest(struct UnknownStruct *a, struct MapData *mapData); +static s32 MapPosToBgTilemapOffset(struct UnknownStruct *a, s32 x, s32 y); + +static void DrawWholeMapViewInternal(int x, int y, struct MapData *mapData); +static void DrawMetatileAt(struct MapData *mapData, u16, int, int); +static void DrawMetatile(s32 a, u16 *b, u16 c); +static void CameraPanningCB_PanAhead(void); + +static void move_tilemap_camera_to_upper_left_corner_(struct UnknownStruct *a) +{ + a->unk2 = 0; + a->unk3 = 0; + a->unk0 = 0; + a->unk1 = 0; + a->unk4 = TRUE; +} + +static void tilemap_move_something(struct UnknownStruct *a, u32 b, u32 c) +{ + a->unk2 += b; + a->unk2 %= 32; + a->unk3 += c; + a->unk3 %= 32; +} + +static void coords8_add(struct UnknownStruct *a, u32 b, u32 c) +{ + a->unk0 += b; + a->unk1 += c; +} + +void move_tilemap_camera_to_upper_left_corner(void) +{ + move_tilemap_camera_to_upper_left_corner_(&gUnknown_03000590); + CpuFill16(0, gBGTilemapBuffers[2], 0x800); + CpuFill16(0, gBGTilemapBuffers[1], 0x800); + CpuFill16(0x3014, gBGTilemapBuffers[3], 0x800); +} + +void sub_8057A58(void) +{ + *gBGHOffsetRegs[1] = gUnknown_03000590.unk0 + gUnknown_03000598; + *gBGVOffsetRegs[1] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8; + *gBGHOffsetRegs[2] = gUnknown_03000590.unk0 + gUnknown_03000598; + *gBGVOffsetRegs[2] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8; + *gBGHOffsetRegs[3] = gUnknown_03000590.unk0 + gUnknown_03000598; + *gBGVOffsetRegs[3] = gUnknown_03000590.unk1 + gUnknown_0300059A + 8; + + if (gUnknown_03000590.unk4) + { + DmaCopy16(3, gBGTilemapBuffers[1], (void *)(VRAM + 0xE800), 0x800); + DmaCopy16(3, gBGTilemapBuffers[2], (void *)(VRAM + 0xE000), 0x800); + DmaCopy16(3, gBGTilemapBuffers[3], (void *)(VRAM + 0xF000), 0x800); + gUnknown_03000590.unk4 = FALSE; + } +} + +void sub_8057B14(u16 *a, u16 *b) +{ + *a = gUnknown_03000590.unk0 + gUnknown_03000598; + *b = gUnknown_03000590.unk1 + gUnknown_0300059A + 8; +} + +void DrawWholeMapView(void) +{ + DrawWholeMapViewInternal(gSaveBlock1.pos.x, gSaveBlock1.pos.y, gMapHeader.mapData); + gUnknown_03000590.unk4 = TRUE; +} + +static void DrawWholeMapViewInternal(int x, int y, struct MapData *mapData) +{ + u8 i; + u8 j; + u32 r6; + u8 temp; + + for (i = 0; i < 32; i += 2) + { + temp = gUnknown_03000590.unk3 + i; + if (temp >= 32) + temp -= 32; + r6 = temp * 32; + for (j = 0; j < 32; j += 2) + { + temp = gUnknown_03000590.unk2 + j; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r6 + temp, x + j / 2, y + i / 2); + } + } +} + +static void RedrawMapSlicesForCameraUpdate(struct UnknownStruct *a, int x, int y) +{ + struct MapData *mapData = gMapHeader.mapData; + + if (x > 0) + RedrawMapSliceWest(a, mapData); + if (x < 0) + RedrawMapSliceEast(a, mapData); + if (y > 0) + RedrawMapSliceNorth(a, mapData); + if (y < 0) + RedrawMapSliceSouth(a, mapData); + a->unk4 = TRUE; +} + +static void RedrawMapSliceNorth(struct UnknownStruct *a, struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r7; + + temp = a->unk3 + 28; + if (temp >= 32) + temp -= 32; + r7 = temp * 32; + for (i = 0; i < 32; i += 2) + { + temp = a->unk2 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r7 + temp, gSaveBlock1.pos.x + i / 2, gSaveBlock1.pos.y + 14); + } +} + +static void RedrawMapSliceSouth(struct UnknownStruct *a, struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r7 = a->unk3 * 32; + + for (i = 0; i < 32; i += 2) + { + temp = a->unk2 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, r7 + temp, gSaveBlock1.pos.x + i / 2, gSaveBlock1.pos.y); + } +} + +static void RedrawMapSliceEast(struct UnknownStruct *a, struct MapData *mapData) +{ + u8 i; + u8 temp; + u32 r6 = a->unk2; + + for (i = 0; i < 32; i += 2) + { + temp = a->unk3 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, temp * 32 + r6, gSaveBlock1.pos.x, gSaveBlock1.pos.y + i / 2); + } +} + +static void RedrawMapSliceWest(struct UnknownStruct *a, struct MapData *mapData) +{ + u8 i; + u8 temp; + u8 r5 = a->unk2 + 28; + + if (r5 >= 32) + r5 -= 32; + for (i = 0; i < 32; i += 2) + { + temp = a->unk3 + i; + if (temp >= 32) + temp -= 32; + DrawMetatileAt(mapData, temp * 32 + r5, gSaveBlock1.pos.x + 14, gSaveBlock1.pos.y + i / 2); + } +} + +void CurrentMapDrawMetatileAt(int a, int b) +{ + int offset = MapPosToBgTilemapOffset(&gUnknown_03000590, a, b); + + if (offset >= 0) + { + DrawMetatileAt(gMapHeader.mapData, offset, a, b); + gUnknown_03000590.unk4 = TRUE; + } +} + +void DrawDoorMetatileAt(int x, int y, u16 *arr) +{ + int offset = MapPosToBgTilemapOffset(&gUnknown_03000590, x, y); + + if (offset >= 0) + { + DrawMetatile(1, arr, offset); + gUnknown_03000590.unk4 = TRUE; + } +} + +static void DrawMetatileAt(struct MapData *mapData, u16 b, int c, int d) +{ + u16 metatileId = MapGridGetMetatileIdAt(c, d); + u16 *metatiles; + + if (metatileId > 1024) + metatileId = 0; + if (metatileId < 512) + metatiles = mapData->primaryTileset->metatiles; + else + { + metatiles = mapData->secondaryTileset->metatiles; + metatileId -= 512; + } + DrawMetatile(MapGridGetMetatileLayerTypeAt(c, d), metatiles + metatileId * 8, b); +} + +static void DrawMetatile(s32 a, u16 *b, u16 c) +{ + switch (a) + { + case 2: + gBGTilemapBuffers[3][c] = b[0]; + gBGTilemapBuffers[3][c + 1] = b[1]; + gBGTilemapBuffers[3][c + 0x20] = b[2]; + gBGTilemapBuffers[3][c + 0x21] = b[3]; + + gBGTilemapBuffers[2][c] = 0; + gBGTilemapBuffers[2][c + 1] = 0; + gBGTilemapBuffers[2][c + 0x20] = 0; + gBGTilemapBuffers[2][c + 0x21] = 0; + + gBGTilemapBuffers[1][c] = b[4]; + gBGTilemapBuffers[1][c + 1] = b[5]; + gBGTilemapBuffers[1][c + 0x20] = b[6]; + gBGTilemapBuffers[1][c + 0x21] = b[7]; + break; + case 1: + gBGTilemapBuffers[3][c] = b[0]; + gBGTilemapBuffers[3][c + 1] = b[1]; + gBGTilemapBuffers[3][c + 0x20] = b[2]; + gBGTilemapBuffers[3][c + 0x21] = b[3]; + + gBGTilemapBuffers[2][c] = b[4]; + gBGTilemapBuffers[2][c + 1] = b[5]; + gBGTilemapBuffers[2][c + 0x20] = b[6]; + gBGTilemapBuffers[2][c + 0x21] = b[7]; + + gBGTilemapBuffers[1][c] = 0; + gBGTilemapBuffers[1][c + 1] = 0; + gBGTilemapBuffers[1][c + 0x20] = 0; + gBGTilemapBuffers[1][c + 0x21] = 0; + break; + case 0: + gBGTilemapBuffers[3][c] = 0x3014; + gBGTilemapBuffers[3][c + 1] = 0x3014; + gBGTilemapBuffers[3][c + 0x20] = 0x3014; + gBGTilemapBuffers[3][c + 0x21] = 0x3014; + + gBGTilemapBuffers[2][c] = b[0]; + gBGTilemapBuffers[2][c + 1] = b[1]; + gBGTilemapBuffers[2][c + 0x20] = b[2]; + gBGTilemapBuffers[2][c + 0x21] = b[3]; + + gBGTilemapBuffers[1][c] = b[4]; + gBGTilemapBuffers[1][c + 1] = b[5]; + gBGTilemapBuffers[1][c + 0x20] = b[6]; + gBGTilemapBuffers[1][c + 0x21] = b[7]; + break; + } +} + +static s32 MapPosToBgTilemapOffset(struct UnknownStruct *a, s32 x, s32 y) +{ + x -= gSaveBlock1.pos.x; + x *= 2; + if (x >= 32 || x < 0) + return -1; + x = x + a->unk2; + if (x >= 32) + x -= 32; + + y = (y - gSaveBlock1.pos.y) * 2; + if (y >= 32 || y < 0) + return -1; + y = y + a->unk3; + if (y >= 32) + y -= 32; + + return y * 32 + x; +} + +static void CameraUpdateCallback(struct CameraSomething *a) +{ + if (a->unk4 != 0) + { + a->unk8 = gSprites[a->unk4].data2; + a->unkC = gSprites[a->unk4].data3; + } +} + +void ResetCameraUpdateInfo(void) +{ + gUnknown_03004880.unk8 = 0; + gUnknown_03004880.unkC = 0; + gUnknown_03004880.unk10 = 0; + gUnknown_03004880.unk14 = 0; + gUnknown_03004880.unk4 = 0; + gUnknown_03004880.callback = NULL; +} + +u32 InitCameraUpdateCallback(u8 a) +{ + if (gUnknown_03004880.unk4 != 0) + DestroySprite(&gSprites[gUnknown_03004880.unk4]); + gUnknown_03004880.unk4 = AddCameraObject(a); + gUnknown_03004880.callback = CameraUpdateCallback; + return 0; +} + +void CameraUpdate(void) +{ + int deltaX; + int deltaY; + int r0; + int r1; + int r7; + int r8; + + if (gUnknown_03004880.callback != NULL) + gUnknown_03004880.callback(&gUnknown_03004880); + r7 = gUnknown_03004880.unk8; + r8 = gUnknown_03004880.unkC; + deltaX = 0; + deltaY = 0; + r1 = gUnknown_03004880.unk10; + r0 = gUnknown_03004880.unk14; + + + if (r1 == 0 && r7 != 0) + { + if (r7 > 0) + deltaX = 1; + else + deltaX = -1; + } + if (r0 == 0 && r8 != 0) + { + if (r8 > 0) + deltaY = 1; + else + deltaY = -1; + } + if (r1 != 0 && r1 == -r7) + { + if (r7 > 0) + deltaX = 1; + else + deltaX = -1; + } + if (r0 != 0 && r0 == -r8) + { + if (r8 > 0) + deltaX = 1; + else + deltaX = -1; + } + + gUnknown_03004880.unk10 += r7; + gUnknown_03004880.unk10 = gUnknown_03004880.unk10 - 16 * (gUnknown_03004880.unk10 / 16); + gUnknown_03004880.unk14 += r8; + gUnknown_03004880.unk14 = gUnknown_03004880.unk14 - 16 * (gUnknown_03004880.unk14 / 16); + + if (deltaX != 0 || deltaY != 0) + { + CameraMove(deltaX, deltaY); + UpdateFieldObjectsForCameraUpdate(deltaX, deltaY); + RotatingGatePuzzleCameraUpdate(deltaX, deltaY); + ResetBerryTreeSparkleFlags(); + tilemap_move_something(&gUnknown_03000590, deltaX * 2, deltaY * 2); + RedrawMapSlicesForCameraUpdate(&gUnknown_03000590, deltaX * 2, deltaY * 2); + } + + coords8_add(&gUnknown_03000590, r7, r8); + gUnknown_0300489C -= r7; + gUnknown_03004898 -= r8; +} + +void camera_move_and_redraw(int a, int b) +{ + CameraMove(a, b); + UpdateFieldObjectsForCameraUpdate(a, b); + DrawWholeMapView(); + gUnknown_0300489C -= a * 16; + gUnknown_03004898 -= b * 16; +} + +void SetCameraPanningCallback(void (*a)(void)) +{ + gUnknown_030005A0 = a; +} + +void SetCameraPanning(s16 a, s16 b) +{ + gUnknown_03000598 = a; + gUnknown_0300059A = b + 32; +} + +void InstallCameraPanAheadCallback(void) +{ + gUnknown_030005A0 = CameraPanningCB_PanAhead; + gUnknown_0300059C = 0; + gUnknown_03000598 = 0; + gUnknown_0300059A = 32; +} + +void UpdateCameraPanning(void) +{ + if (gUnknown_030005A0 != NULL) + gUnknown_030005A0(); + //Update sprite offset of overworld objects + gSpriteCoordOffsetX = gUnknown_0300489C - gUnknown_03000598; + gSpriteCoordOffsetY = gUnknown_03004898 - gUnknown_0300059A - 8; +} + +static void CameraPanningCB_PanAhead(void) +{ + u8 var; + + if (gUnknown_0202E854 == 0) + { + InstallCameraPanAheadCallback(); + } + else + { + if (gPlayerAvatar.running1 == 1) + { + gUnknown_0300059C ^= 1; + if (gUnknown_0300059C == 0) + return; + } + else + { + gUnknown_0300059C = 0; + } + + var = player_get_direction_upper_nybble(); + if (var == 2) + { + if (gUnknown_0300059A > -8) + gUnknown_0300059A -= 2; + } + else if (var == 1) + { + if (gUnknown_0300059A < 72) + gUnknown_0300059A += 2; + } + else if (gUnknown_0300059A < 32) + { + gUnknown_0300059A += 2; + } + else if (gUnknown_0300059A > 32) + { + gUnknown_0300059A -= 2; + } + } +} diff --git a/src/field/field_control_avatar.c b/src/field/field_control_avatar.c new file mode 100644 index 000000000..ff8e8504c --- /dev/null +++ b/src/field/field_control_avatar.c @@ -0,0 +1,878 @@ +#include "global.h" +#include "field_control_avatar.h" +#include "battle_setup.h" +#include "bike.h" +#include "coord_event_weather.h" +#include "daycare.h" +#include "event_data.h" +#include "field_fadetransition.h" +#include "field_player_avatar.h" +#include "field_poison.h" +#include "field_specials.h" +#include "fieldmap.h" +#include "flags.h" +#include "item_menu.h" +#include "metatile_behavior.h" +#include "overworld.h" +#include "safari_zone.h" +#include "script.h" +#include "secret_base.h" +#include "songs.h" +#include "sound.h" +#include "start_menu.h" +#include "trainer_see.h" +#include "vars.h" +#include "wild_encounter.h" + +struct Coords32 +{ + s32 x; + s32 y; +}; + +extern u16 gScriptLastTalked; +extern u16 gScriptFacing; +extern struct LinkPlayerMapObject gLinkPlayerMapObjects[]; +extern u16 gSpecialVar_0x8004; +extern u16 gSpecialVar_0x8005; + +static EWRAM_DATA u8 gUnknown_0202E8C0 = 0; +static EWRAM_DATA u16 gUnknown_0202E8C2 = 0; + +u8 gSelectedMapObject; + +//scripts +extern u8 gUnknown_081A2C51[]; +extern u8 gUnknown_0815281E[]; +extern u8 gUnknown_08152C39[]; +extern u8 gUnknown_0815F36C[]; +extern u8 gUnknown_0815F43A[]; +extern u8 gUnknown_081A0009[]; +extern u8 gUnknown_081C6C02[]; +extern u8 HiddenItemScript[]; +extern u8 Event_TV[]; +extern u8 gUnknown_081A0009[]; +extern u8 ClosedSootopolisGymDoorScript[]; +extern u8 gUnknown_081A4363[]; +extern u8 gUnknown_081C346A[]; +extern u8 gUnknown_081616E1[]; +extern u8 Event_WorldMap[]; +extern u8 S_RunningShoesManual[]; +extern u8 PictureBookShelfScript[]; +extern u8 BookshelfScript[]; +extern u8 PokemonCenterBookshelfScript[]; +extern u8 VaseScript[]; +extern u8 TrashCanScript[]; +extern u8 ShopShelfScript[]; +extern u8 BlueprintScript[]; +extern u8 gUnknown_0815F36C[]; +extern u8 gUnknown_0815F43A[]; +extern u8 gUnknown_0815F523[]; +extern u8 gUnknown_0815F528[]; +extern u8 UseSurfScript[]; +extern u8 S_UseWaterfall[]; +extern u8 S_CannotUseWaterfall[]; +extern u8 UseDiveScript[]; +extern u8 S_UseDiveUnderwater[]; +extern u8 S_FallDownHole[]; +extern u8 gUnknown_081A14B8[]; +extern u8 S_EggHatch[]; +extern u8 gUnknown_0815FD0D[]; +extern u8 gUnknown_081C6BDE[]; + +static void player_get_pos_to_and_height(struct MapPosition *); +static void player_get_next_pos_and_height(struct MapPosition *); +static u16 cur_mapdata_block_role_at_player_pos(int); +static bool8 sub_80681F0(struct MapPosition *position, u16 b, u8 c); +static u8 *TryGetScriptOnPressingA(struct MapPosition *position, u8 b, u8 c); +static u8 *sub_8068364(struct MapPosition *, u8, u8); +static u8 *TryGetInvisibleMapObjectScript(struct MapPosition *, u8, u8 c); +static u8 *sub_8068500(struct MapPosition *, u8, u8); +static u8 *TryGetFieldMoveScript(struct MapPosition *, u8, u8); +static bool32 sub_8068770(void); +static bool32 sub_80687A4(void); +static bool8 sub_80687E4(struct MapPosition *, u16, u16); +static void happiness_algorithm_step(void); +static bool8 overworld_poison_step(void); +static bool8 is_it_battle_time_3(u16); +static bool8 mapheader_run_first_tag2_script_list_match_conditionally(struct MapPosition *, u16, u8); +static bool8 sub_8068B30(u16); +static bool8 is_non_stair_warp_tile(u16, u8); +static s8 map_warp_check_packed(struct MapHeader *, struct MapPosition *); +static void sub_8068C30(struct MapHeader *, s8, struct MapPosition *); +static bool8 map_warp_consider_2_to_inside(struct MapPosition *, u16, u8); +static s8 map_warp_check(struct MapHeader *, u16, u16, u8); +static u8 *mapheader_trigger_activate_at(struct MapHeader *, u16, u16, u8); +static struct BgEvent *FindInvisibleMapObjectByPosition(struct MapHeader *, u16, u16, u8); + +void FieldClearPlayerInput(struct FieldInput *input) +{ + input->pressedAButton = 0; + input->input_field_0_1 = 0; + input->pressedStartButton = 0; + input->pressedSelectButton = 0; + input->input_field_0_4 = 0; + input->input_field_0_5 = 0; + input->input_field_0_6 = 0; + input->pressedBButton = 0; + input->input_field_1_0 = 0; + input->input_field_1_1 = 0; + input->input_field_1_2 = 0; + input->input_field_1_3 = 0; + input->dpadDirection = 0; +} + +void FieldGetPlayerInput(struct FieldInput *input, u16 newKeys, u16 heldKeys) +{ + u8 r6 = gPlayerAvatar.running1; + u8 r9 = gPlayerAvatar.running2; + bool8 forcedMove = MetatileBehavior_IsMoveTile(cur_mapdata_block_role_at_player_pos(r9)); + + if ((r6 == 2 && forcedMove == FALSE) || r6 == 0) + { + if (GetPlayerSpeed() != 4) + { + if (newKeys & START_BUTTON) + input->pressedStartButton = TRUE; + if (newKeys & SELECT_BUTTON) + input->pressedSelectButton = TRUE; + if (newKeys & A_BUTTON) + input->pressedAButton = TRUE; + if (newKeys & B_BUTTON) + input->pressedBButton = TRUE; + } + if (heldKeys & (DPAD_UP | DPAD_DOWN | DPAD_LEFT | DPAD_RIGHT)) + { + input->input_field_0_4 = TRUE; + input->input_field_0_5 = TRUE; + } + } + if (forcedMove == FALSE) + { + if (r6 == 2 && r9 == 2) + input->input_field_0_6 = TRUE; + if (forcedMove == FALSE && r6 == 2) + input->input_field_0_1 = TRUE; + } + if (heldKeys & DPAD_UP) + input->dpadDirection = DIR_NORTH; + else if (heldKeys & DPAD_DOWN) + input->dpadDirection = DIR_SOUTH; + else if (heldKeys & DPAD_LEFT) + input->dpadDirection = DIR_WEST; + else if (heldKeys & DPAD_RIGHT) + input->dpadDirection = DIR_EAST; +} + +int sub_8068024(struct FieldInput *input) +{ + struct MapPosition position; + u8 r6; + u16 r4; + + r6 = player_get_direction_lower_nybble(); + player_get_pos_to_and_height(&position); + r4 = MapGridGetMetatileBehaviorAt(position.x, position.y); + if (CheckTrainers() == TRUE) + return TRUE; + if (mapheader_run_first_tag2_script_list_match() == 1) + return TRUE; + if (input->pressedBButton && sub_80687A4() == 1) + return TRUE; + if (input->input_field_0_6) + { + IncrementGameStat(5); + if (sub_80687E4(&position, r4, r6) == 1) + return TRUE; + } + if (input->input_field_0_1 && is_it_battle_time_3(r4) == 1) + return TRUE; + if (input->input_field_0_4 && input->dpadDirection == r6) + { + if (mapheader_run_first_tag2_script_list_match_conditionally(&position, r4, r6) == 1) + return TRUE; + } + player_get_next_pos_and_height(&position); + r4 = MapGridGetMetatileBehaviorAt(position.x, position.y); + if (input->pressedAButton && sub_80681F0(&position, r4, r6) == 1) + return TRUE; + if (input->input_field_0_5 && input->dpadDirection == r6) + { + if (map_warp_consider_2_to_inside(&position, r4, r6) == 1) + return TRUE; + } + if (input->pressedAButton && sub_8068770() == 1) + return TRUE; + if (input->pressedStartButton) + { + PlaySE(SE_WIN_OPEN); + sub_8071310(); + return TRUE; + } + if (input->pressedSelectButton && sub_80A6D1C() == TRUE) + return TRUE; + return FALSE; +} + +static void player_get_pos_to_and_height(struct MapPosition *position) +{ + PlayerGetDestCoords(&position->x, &position->y); + position->height = PlayerGetZCoord(); +} + +static void player_get_next_pos_and_height(struct MapPosition *position) +{ + s16 x, y; + + GetXYCoordsOneStepInFrontOfPlayer(&position->x, &position->y); + PlayerGetDestCoords(&x, &y); + if (MapGridGetZCoordAt(x, y) != 0) + position->height = PlayerGetZCoord(); + else + position->height = 0; +} + +static u16 cur_mapdata_block_role_at_player_pos(int unused) +{ + s16 x, y; + + PlayerGetDestCoords(&x, &y); + return MapGridGetMetatileBehaviorAt(x, y); +} + +static bool8 sub_80681F0(struct MapPosition *position, u16 b, u8 c) +{ + u8 *script = TryGetScriptOnPressingA(position, b, c); + + if (script == NULL) + return FALSE; + + if (script != gUnknown_0815281E + && script != gUnknown_08152C39 + && script != gUnknown_0815F36C + && script != gUnknown_0815F43A + && script != gUnknown_081A0009) + PlaySE(5); + + ScriptContext1_SetupScript(script); + return TRUE; +} + +static u8 *TryGetScriptOnPressingA(struct MapPosition *position, u8 b, u8 c) +{ + u8 *script; + + script = sub_8068364(position, b, c); + if (script != NULL) + return script; + script = TryGetInvisibleMapObjectScript(position, b, c); + if (script != NULL) + return script; + script = sub_8068500(position, b, c); + if (script != NULL) + return script; + script = TryGetFieldMoveScript(position, b, c); + if (script != NULL) + return script; + + return NULL; +} + +u8 *sub_80682A8(struct MapPosition *position, u8 unused, u8 c) +{ + u8 r3; + s32 i; + + if (!MetatileBehavior_IsCounter(MapGridGetMetatileBehaviorAt(position->x, position->y))) + r3 = GetFieldObjectIdByXYZ(position->x, position->y, position->height); + else + r3 = GetFieldObjectIdByXYZ(position->x + gUnknown_0821664C[c].x, position->y + gUnknown_0821664C[c].y, position->height); + if (r3 == 16 || gMapObjects[r3].localId == 0xFF) + return NULL; + for (i = 0; i < 4; i++) + { + if (gLinkPlayerMapObjects[i].active == TRUE && gLinkPlayerMapObjects[i].mapObjId == r3) + return NULL; + } + gSelectedMapObject = r3; + gScriptLastTalked = gMapObjects[r3].localId; + gScriptFacing = c; + return GetFieldObjectScriptPointerByFieldObjectId(r3); +} + +static u8 *sub_8068364(struct MapPosition *position, u8 b, u8 c) +{ + u8 r3; + u8 *script; + + r3 = GetFieldObjectIdByXYZ(position->x, position->y, position->height); + if (r3 == 16 || gMapObjects[r3].localId == 0xFF) + { + if (MetatileBehavior_IsCounter(b) != TRUE) + return NULL; + r3 = GetFieldObjectIdByXYZ(position->x + gUnknown_0821664C[c].x, position->y + gUnknown_0821664C[c].y, position->height); + if (r3 == 16 || gMapObjects[r3].localId == 0xFF) + return NULL; + } + //_080683E8 + gSelectedMapObject = r3; + gScriptLastTalked = gMapObjects[r3].localId; + gScriptFacing = c; + script = GetFieldObjectScriptPointerByFieldObjectId(r3); + script = GetRamScript(gScriptLastTalked, script); + return script; +} + +static u8 *TryGetInvisibleMapObjectScript(struct MapPosition *position, u8 unused, u8 c) +{ + struct BgEvent *bgEvent = FindInvisibleMapObjectByPosition(&gMapHeader, position->x - 7, position->y - 7, position->height); + + if (bgEvent == NULL) + return NULL; + if (bgEvent->bgUnion.script == NULL) + return gUnknown_081C6C02; + switch (bgEvent->kind) + { + case 0: + default: + return bgEvent->bgUnion.script; + case 1: + if (c != 2) + return NULL; + break; + case 2: + if (c != 1) + return NULL; + break; + case 3: + if (c != 4) + return NULL; + break; + case 4: + if (c != 3) + return NULL; + break; + case 5: + case 6: + case 7: + gSpecialVar_0x8004 = ((u32)bgEvent->bgUnion.script >> 16) + 0x258; + gSpecialVar_0x8005 = (u32)bgEvent->bgUnion.script; + if (FlagGet(gSpecialVar_0x8004) == TRUE) + return NULL; + return HiddenItemScript; + case 8: + if (c == 2) + { + gSpecialVar_0x8004 = (u32)bgEvent->bgUnion.script; + if (sub_80BC050()) + return gUnknown_081A2C51; + } + return NULL; + } + return bgEvent->bgUnion.script; +} + +static u8 *sub_8068500(struct MapPosition *position, u8 b, u8 c) +{ + s8 height; + + if (MetatileBehavior_IsPlayerFacingTVScreen(b, c) == TRUE) + return Event_TV; + if (MetatileBehavior_IsPC(b) == TRUE) + return gUnknown_081A0009; + if (MetatileBehavior_IsClosedSootopolisGymDoor(b) == TRUE) + return ClosedSootopolisGymDoorScript; + if (is_tile_x84(b) == TRUE) + return gUnknown_081A4363; + if (MetatileBehavior_IsPokeblockFeeder(b) == TRUE) + return gUnknown_081C346A; + if (MetatileBehavior_IsTrickHousePuzzleDoor(b) == TRUE) + return gUnknown_081616E1; + if (MetatileBehavior_IsRegionMap(b) == TRUE) + return Event_WorldMap; + if (sub_805791C(b) == TRUE) + return S_RunningShoesManual; + if (MetatileBehavior_IsPictureBookShelf(b) == TRUE) + return PictureBookShelfScript; + if (MetatileBehavior_IsBookShelf(b) == TRUE) + return BookshelfScript; + if (MetatileBehavior_IsPokeCenterBookShelf(b) == TRUE) + return PokemonCenterBookshelfScript; + if (MetatileBehavior_IsVase(b) == TRUE) + return VaseScript; + if (MetatileBehavior_IsTrashCan(b) == TRUE) + return TrashCanScript; + if (MetatileBehavior_IsShopShelf(b) == TRUE) + return ShopShelfScript; + if (MetatileBehavior_IsBlueprint(b) == TRUE) + return BlueprintScript; + height = position->height; + if (height == MapGridGetZCoordAt(position->x, position->y)) + { + if (MetatileBehavior_IsSecretBasePC(b) == TRUE) + return gUnknown_0815F36C; + if (sub_805724C(b) == TRUE) + return gUnknown_0815F43A; + if (sub_8057364(b) == TRUE) + return gUnknown_0815F523; + if (sub_8057378(b) == TRUE) + return gUnknown_0815F528; + } + return NULL; +} + +static u8 *TryGetFieldMoveScript(struct MapPosition *unused1, u8 b, u8 unused2) +{ + if (FlagGet(BADGE05_GET) == TRUE && PartyHasMonWithSurf() == TRUE && IsPlayerFacingSurfableFishableWater() == TRUE) + return UseSurfScript; + if (MetatileBehavior_IsWaterfall(b) == TRUE) + { + if (FlagGet(BADGE08_GET) == TRUE && IsPlayerSurfingNorth() == TRUE) + return S_UseWaterfall; + else + return S_CannotUseWaterfall; + } + return NULL; +} + +static bool32 sub_8068770(void) +{ + if (FlagGet(BADGE07_GET) && sub_8068F18() == 2) + { + ScriptContext1_SetupScript(UseDiveScript); + return TRUE; + } + return FALSE; +} + +static bool32 sub_80687A4(void) +{ + if (FlagGet(BADGE07_GET) && gMapHeader.mapType == MAP_TYPE_UNDERWATER && sub_8068F18() == 1) + { + ScriptContext1_SetupScript(S_UseDiveUnderwater); + return TRUE; + } + return FALSE; +} + +static bool8 sub_80687E4(struct MapPosition *position, u16 b, u16 unused) +{ + if (mapheader_trigger_activate_at__run_now(position) == TRUE) + return TRUE; + if (sub_8068A64(position, b) == TRUE) + return TRUE; + if (sub_8068870(b) == TRUE) + return TRUE; + if (sub_8068894() == TRUE) + return TRUE; + if (UpdateRepelCounter() == TRUE) + return TRUE; + return FALSE; +} + +bool8 mapheader_trigger_activate_at__run_now(struct MapPosition *position) +{ + u8 *script = mapheader_trigger_activate_at(&gMapHeader, position->x - 7, position->y - 7, position->height); + + if (script == NULL) + return FALSE; + ScriptContext1_SetupScript(script); + return TRUE; +} + +//can be u8, u16, or u32 +bool8 sub_8068870(u16 a) +{ + if (MetatileBehavior_IsCrackedFloorHole(a)) + { + ScriptContext1_SetupScript(S_FallDownHole); + return TRUE; + } + return FALSE; +} + +bool8 sub_8068894(void) +{ + sub_8082B78(); + happiness_algorithm_step(); + if (overworld_poison_step() == TRUE) + { + ScriptContext1_SetupScript(gUnknown_081A14B8); + return TRUE; + } + if (sub_80422A0()) + { + IncrementGameStat(13); + ScriptContext1_SetupScript(S_EggHatch); + return TRUE; + } + if (SafariZoneTakeStep() == TRUE) + return TRUE; + if (CountSSTidalStep(1) == TRUE) + { + ScriptContext1_SetupScript(gUnknown_0815FD0D); + return TRUE; + } + return FALSE; +} + +void unref_sub_80688F8(void) +{ + VarSet(VAR_HAPPINESS_STEP_COUNTER, 0); +} + +static void happiness_algorithm_step(void) +{ + u16 *ptr = GetVarPointer(VAR_HAPPINESS_STEP_COUNTER); + int i; + + (*ptr)++; + (*ptr) %= 128; + if (*ptr == 0) + { + struct Pokemon *pkmn = gPlayerParty; + + for (i = 5; i >= 0; i--) + { + AdjustFriendship(pkmn, 5); + pkmn++; + } + } +} + +void overworld_poison_timer_set(void) +{ + VarSet(VAR_POISON_STEP_COUNTER, 0); +} + +static bool8 overworld_poison_step(void) +{ + u16 *ptr; + + if (gMapHeader.mapType != MAP_TYPE_SECRET_BASE) + { + ptr = GetVarPointer(VAR_POISON_STEP_COUNTER); + (*ptr)++; + (*ptr) %= 4; + if (*ptr == 0) + { + switch (DoPoisonFieldEffect()) + { + case 0: + return FALSE; + case 1: + return FALSE; + case 2: + return TRUE; + } + } + } + return FALSE; +} + +void prev_quest_postbuffer_cursor_backup_reset(void) +{ + gUnknown_0202E8C0 = 0; +} + +static bool8 is_it_battle_time_3(u16 a) +{ + if (gUnknown_0202E8C0 < 4) + { + gUnknown_0202E8C0++; + gUnknown_0202E8C2 = a; + return FALSE; + } + if (StandardWildEncounter(a, gUnknown_0202E8C2) == TRUE) + { + gUnknown_0202E8C0 = 0; + gUnknown_0202E8C2 = a; + return TRUE; + } + else + { + gUnknown_0202E8C2 = a; + return FALSE; + } +} + +static bool8 mapheader_run_first_tag2_script_list_match_conditionally(struct MapPosition *position, u16 b, u8 c) +{ + s8 r6 = map_warp_check_packed(&gMapHeader, position); + + if (is_non_stair_warp_tile(b, c) == TRUE && r6 != -1) + { + walkrun_find_lowest_active_bit_in_bitfield(); + sub_8068C30(&gMapHeader, r6, position); + sub_8080E88(); + return TRUE; + } + return FALSE; +} + +bool8 sub_8068A64(struct MapPosition *position, u16 b) +{ + s8 r4 = map_warp_check_packed(&gMapHeader, position); + + if (r4 != -1 && sub_8068B30(b) == TRUE) + { + walkrun_find_lowest_active_bit_in_bitfield(); + sub_8068C30(&gMapHeader, r4, position); + if (MetatileBehavior_IsEscalator(b) == TRUE) + { + sub_8080F2C(b); + return TRUE; + } + if (MetatileBehavior_IsLavaridgeB1FWarp(b) == TRUE) + { + sub_8080F48(); + return TRUE; + } + if (MetatileBehavior_IsLavaridge1FWarp(b) == TRUE) + { + sub_8080F58(); + return TRUE; + } + if (MetatileBehavior_IsAquaHideoutWarp(b) == TRUE) + { + sub_8080F68(); + return TRUE; + } + if (MetatileBehavior_IsMtPyreHole(b) == TRUE) + { + ScriptContext1_SetupScript(gUnknown_081C6BDE); + return TRUE; + } + sub_8080E88(); + return TRUE; + } + return FALSE; +} + +static bool8 sub_8068B30(u16 a) +{ + if (MetatileBehavior_IsWarpDoor(a) != TRUE + && MetatileBehavior_IsLadder(a) != TRUE + && MetatileBehavior_IsEscalator(a) != TRUE + && MetatileBehavior_IsNonAnimDoor(a) != TRUE + && MetatileBehavior_IsLavaridgeB1FWarp(a) != TRUE + && MetatileBehavior_IsLavaridge1FWarp(a) != TRUE + && MetatileBehavior_IsAquaHideoutWarp(a) != TRUE + && MetatileBehavior_IsMtPyreHole(a) != TRUE) + return FALSE; + return TRUE; +} + +static bool8 is_non_stair_warp_tile(u16 a, u8 b) +{ + switch (b) + { + case 2: + return MetatileBehavior_IsNorthArrowWarp(a); + case 1: + return MetatileBehavior_IsSouthArrowWarp(a); + case 3: + return MetatileBehavior_IsWestArrowWarp(a); + case 4: + return MetatileBehavior_IsEastArrowWarp(a); + } + return FALSE; +} + +static s8 map_warp_check_packed(struct MapHeader *mapHeader, struct MapPosition *position) +{ + return map_warp_check(mapHeader, position->x - 7, position->y - 7, position->height); +} + +static void sub_8068C30(struct MapHeader *unused, s8 b, struct MapPosition *position) +{ + struct WarpEvent *warpEvent = &gMapHeader.events->warps[b]; + + if (warpEvent->mapNum == 0x7F) + { + copy_saved_warp2_bank_and_enter_x_to_warp1(warpEvent->mapGroup); + } + else + { + struct MapHeader *mapHeader; + + warp1_set_2(warpEvent->unk7, warpEvent->mapNum, warpEvent->mapGroup); + sub_80535C4(position->x, position->y); + mapHeader = Overworld_GetMapHeaderByGroupAndId(warpEvent->unk7, warpEvent->mapNum); + if (mapHeader->events->warps[warpEvent->mapGroup].mapNum == 0x7F) + saved_warp2_set(mapHeader->events->warps[b].mapGroup, gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum, b); + } +} + +static bool8 map_warp_consider_2_to_inside(struct MapPosition *position, u16 b, u8 c) +{ + s8 r4; + + if (c == 2) + { + if (sub_80571C0(b) == TRUE) + { + sub_80BC038(position, gMapHeader.events); + return TRUE; + } + if (MetatileBehavior_IsWarpDoor(b) == TRUE) + { + r4 = map_warp_check_packed(&gMapHeader, position); + if (r4 != -1 && sub_8068B30(b) == TRUE) + { + walkrun_find_lowest_active_bit_in_bitfield(); + sub_8068C30(&gMapHeader, r4, position); + sub_8080EF0(); + return TRUE; + } + } + } + return FALSE; +} + +static s8 map_warp_check(struct MapHeader *mapHeader, u16 x, u16 y, u8 warpId) +{ + s32 i; + struct WarpEvent *warpEvent = mapHeader->events->warps; + u8 warpCount = mapHeader->events->warpCount; + + for (i = 0; i < warpCount; i++, warpEvent++) + { + if ((u16)warpEvent->x == x && (u16)warpEvent->y == y) + { + if ((u8)warpEvent->warpId == warpId || (u8)warpEvent->warpId == 0) + return i; + } + } + return -1; +} + +static u8 *trigger_activate(struct CoordEvent *coordEvent) +{ + if (coordEvent != NULL) + { + if (coordEvent->script == NULL) + { + DoCoordEventWeather(coordEvent->trigger); + return NULL; + } + if (coordEvent->trigger == 0) + { + ScriptContext2_RunNewScript(coordEvent->script); + return NULL; + } + if (VarGet(coordEvent->trigger) == (u8)coordEvent->index) + return coordEvent->script; + } + return NULL; +} + +static u8 *mapheader_trigger_activate_at(struct MapHeader *mapHeader, u16 x, u16 y, u8 d) +{ + s32 i; + struct CoordEvent *coordEvents = mapHeader->events->coordEvents; + u8 coordEventCount = mapHeader->events->coordEventCount; + u8 *script; + + for (i = 0; i < coordEventCount; i++) + { + if ((u16)coordEvents[i].x == x && (u16)coordEvents[i].y == y) + { + if (coordEvents[i].unk4 == d || coordEvents[i].unk4 == 0) + { + script = trigger_activate(&coordEvents[i]); + if (script != NULL) + return script; + } + } + } + return NULL; +} + +u8 *sub_8068E24(struct MapPosition *position) +{ + return mapheader_trigger_activate_at(&gMapHeader, position->x - 7, position->y - 7, position->height); +} + +static struct BgEvent *FindInvisibleMapObjectByPosition(struct MapHeader *mapHeader, u16 b, u16 c, u8 d) +{ + u8 i; + struct BgEvent *bgEvents = mapHeader->events->bgEvents; + u8 bgEventCount = mapHeader->events->bgEventCount; + + for (i = 0; i < bgEventCount; i++) + { + if ((u16)bgEvents[i].x == b && (u16)bgEvents[i].y == c) + { + if (bgEvents[i].unk4 == d || bgEvents[i].unk4 == 0) + return &bgEvents[i]; + } + } + return NULL; +} + +int dive_warp(struct MapPosition *position, u16 b) +{ + if (gMapHeader.mapType == MAP_TYPE_UNDERWATER && sub_805750C(b) == 0) + { + if (sub_80538B0(position->x - 7, position->y - 7)) + { + walkrun_find_lowest_active_bit_in_bitfield(); + sp13E_warp_to_last_warp(); + PlaySE(SE_W291); + return TRUE; + } + } + else if (sub_80574EC(b) == TRUE) + { + if (sub_80538D0(position->x - 7, position->y - 7)) + { + walkrun_find_lowest_active_bit_in_bitfield(); + sp13E_warp_to_last_warp(); + PlaySE(SE_W291); + return TRUE; + } + } + return FALSE; +} + +u8 sub_8068F18(void) +{ + s16 x, y; + u8 r5; + + PlayerGetDestCoords(&x, &y); + r5 = MapGridGetMetatileBehaviorAt(x, y); + if (gMapHeader.mapType == MAP_TYPE_UNDERWATER && sub_805750C(r5) == 0) + { + if (sub_80538B0(x - 7, y - 7) == TRUE) + return 1; + } + else if (sub_80574EC(r5) == TRUE) + { + if (sub_80538D0(x - 7, y - 7) == TRUE) + return 2; + } + return 0; +} + +u8 *GetFieldObjectScriptPointerForComparison(void) +{ + u8 r4; + struct MapPosition position; + + r4 = player_get_direction_upper_nybble(); + player_get_next_pos_and_height(&position); + return sub_8068364(&position, MapGridGetMetatileBehaviorAt(position.x, position.y), r4); +} + +int SetCableClubWarp(void) +{ + struct MapPosition position; + + player_get_direction_upper_nybble(); //unnecessary + player_get_pos_to_and_height(&position); + MapGridGetMetatileBehaviorAt(position.x, position.y); //unnecessary + sub_8068C30(&gMapHeader, map_warp_check_packed(&gMapHeader, &position), &position); + return 0; +} diff --git a/src/field/field_door.c b/src/field/field_door.c new file mode 100644 index 000000000..ab46f0696 --- /dev/null +++ b/src/field/field_door.c @@ -0,0 +1,222 @@ +#include "global.h" +#include "field_door.h" +#include "field_camera.h" +#include "fieldmap.h" +#include "metatile_behavior.h" +#include "songs.h" +#include "task.h" + +extern struct DoorAnimFrame gDoorOpenAnimFrames[]; +extern struct DoorAnimFrame gDoorCloseAnimFrames[]; +extern struct DoorGraphics gDoorAnimGraphicsTable[]; + +static void CopyDoorTilesToVram(void *src) +{ + CpuFastSet(src, (void *)(VRAM + 0x7F00), 0x40); +} + +static void door_build_blockdef(u16 *a, u16 b, u8 *c) +{ + int i; + u16 unk; + + for (i = 0; i < 4; i++) + { + unk = *(c++) << 12; + a[i] = unk | (b + i); + } + for (; i < 8; i++) + { + unk = *(c++) << 12; + a[i] = unk; + } +} + +static void DrawCurrentDoorAnimFrame(u32 x, u32 y, u8 *c) +{ + u16 arr[8]; + + door_build_blockdef(arr, 0x3F8, c); + DrawDoorMetatileAt(x, y - 1, arr); + door_build_blockdef(arr, 0x3FC, c + 4); + DrawDoorMetatileAt(x, y, arr); +} + +static void DrawClosedDoorTiles(u32 x, u32 y) +{ + CurrentMapDrawMetatileAt(x, y - 1); + CurrentMapDrawMetatileAt(x, y); +} + +static void DrawDoor(struct DoorGraphics *gfx, struct DoorAnimFrame *frame, u32 x, u32 y) +{ + if (frame->offset == 0xFFFF) + DrawClosedDoorTiles(x, y); + else + { + CopyDoorTilesToVram(gfx->tiles + frame->offset); + DrawCurrentDoorAnimFrame(x, y, gfx->palette); + } +} + +enum +{ + TD_FRAMELIST = 0, + TD_GFX = 2, + TD_FRAME = 4, + TD_COUNTER, + TD_X, + TD_Y +}; + +static bool32 sub_8058464(struct DoorGraphics *gfx, struct DoorAnimFrame *frames, s16 *taskData) +{ + if (taskData[TD_COUNTER] == 0) + DrawDoor(gfx, &frames[taskData[TD_FRAME]], taskData[TD_X], taskData[TD_Y]); + if (taskData[TD_COUNTER] == frames[taskData[TD_FRAME]].time) + { + taskData[TD_COUNTER] = 0; + taskData[TD_FRAME]++; + if (frames[taskData[TD_FRAME]].time == 0) + return FALSE; + else + return TRUE; + } + taskData[TD_COUNTER]++; + return TRUE; +} + +static void Task_AnimateDoor(u8 taskId) +{ + u16 *taskData = gTasks[taskId].data; + struct DoorAnimFrame *frames = (struct DoorAnimFrame *)(taskData[TD_FRAMELIST] << 16 | taskData[TD_FRAMELIST + 1]); + struct DoorGraphics *gfx = (struct DoorGraphics *)(taskData[TD_GFX] << 16 | taskData[TD_GFX + 1]); + + if (sub_8058464(gfx, frames, taskData) == FALSE) + DestroyTask(taskId); +} + +static struct DoorAnimFrame *GetLastDoorFrame(struct DoorAnimFrame *frame, void *unused) +{ + while (frame->time != 0) + frame++; + return frame - 1; +} + +static struct DoorGraphics *GetDoorGraphics(struct DoorGraphics *gfx, u16 metatileNum) +{ + while (gfx->tiles != NULL) + { + if (gfx->metatileNum == metatileNum) + return gfx; + gfx++; + } + return NULL; +} + +static s8 StartDoorAnimationTask(struct DoorGraphics *gfx, struct DoorAnimFrame *frames, u32 x, u32 y) +{ + if (FuncIsActiveTask(Task_AnimateDoor) == TRUE) + return -1; + else + { + u8 taskId = CreateTask(Task_AnimateDoor, 0x50); + s16 *taskData = gTasks[taskId].data; + + taskData[TD_X] = x; + taskData[TD_Y] = y; + + taskData[TD_FRAMELIST + 1] = (u32)frames; + taskData[TD_FRAMELIST] = (u32)frames >> 16; + + taskData[TD_GFX + 1] = (u32)gfx; + taskData[TD_GFX] = (u32)gfx >> 16; + + return taskId; + } +} + +static void DrawClosedDoor(struct DoorGraphics *unused, u32 x, u32 y) +{ + DrawClosedDoorTiles(x, y); +} + +static void DrawOpenedDoor(struct DoorGraphics *gfx, u32 x, u32 y) +{ + gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y)); + if (gfx != NULL) + DrawDoor(gfx, GetLastDoorFrame(gDoorOpenAnimFrames, gDoorOpenAnimFrames), x, y); +} + +static s8 StartDoorOpenAnimation(struct DoorGraphics *gfx, u32 x, u32 y) +{ + gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y)); + if (gfx == NULL) + return -1; + else + return StartDoorAnimationTask(gfx, gDoorOpenAnimFrames, x, y); +} + +static s8 StartDoorCloseAnimation(struct DoorGraphics *gfx, u32 x, u32 y) +{ + gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y)); + if (gfx == NULL) + return -1; + else + return StartDoorAnimationTask(gfx, gDoorCloseAnimFrames, x, y); +} + +static s8 cur_mapdata_get_door_x2_at(struct DoorGraphics *gfx, u32 x, u32 y) +{ + gfx = GetDoorGraphics(gfx, MapGridGetMetatileIdAt(x, y)); + if (gfx == NULL) + return -1; + else + return gfx->unk2; +} + +void unref_sub_805869C(u32 x, u32 y) +{ + StartDoorOpenAnimation(gDoorAnimGraphicsTable, x, y); +} + +void FieldSetDoorOpened(u32 x, u32 y) +{ + if (MetatileBehavior_IsDoor(MapGridGetMetatileBehaviorAt(x, y))) + DrawOpenedDoor(gDoorAnimGraphicsTable, x, y); +} + +void FieldSetDoorClosed(u32 x, u32 y) +{ + if (MetatileBehavior_IsDoor(MapGridGetMetatileBehaviorAt(x, y))) + DrawClosedDoor(gDoorAnimGraphicsTable, x, y); +} + +s8 FieldAnimateDoorClose(u32 x, u32 y) +{ + if (!MetatileBehavior_IsDoor(MapGridGetMetatileBehaviorAt(x, y))) + return -1; + else + return StartDoorCloseAnimation(gDoorAnimGraphicsTable, x, y); +} + +s8 FieldAnimateDoorOpen(u32 x, u32 y) +{ + if (!MetatileBehavior_IsDoor(MapGridGetMetatileBehaviorAt(x, y))) + return -1; + else + return StartDoorOpenAnimation(gDoorAnimGraphicsTable, x, y); +} + +bool8 FieldIsDoorAnimationRunning(void) +{ + return FuncIsActiveTask(Task_AnimateDoor); +} + +u32 GetDoorSoundEffect(u32 x, u32 y) +{ + if (cur_mapdata_get_door_x2_at(gDoorAnimGraphicsTable, x, y) == 0) + return SE_DOOR; + else + return SE_JIDO_DOA; +} diff --git a/src/field/field_effect.c b/src/field/field_effect.c new file mode 100644 index 000000000..afe020ac7 --- /dev/null +++ b/src/field/field_effect.c @@ -0,0 +1,3405 @@ +#include "global.h" +#include "data2.h" +#include "script.h" +#include "trig.h" +#include "main.h" +#include "field_weather.h" +#include "decompress.h" +#include "sprite.h" +#include "menu.h" +#include "palette.h" +#include "text.h" +#include "overworld.h" +#include "task.h" +#include "sound.h" +#include "songs.h" +#include "decoration.h" +#include "field_player_avatar.h" +#include "field_map_obj_helpers.h" +#include "field_map_obj.h" +#include "metatile_behavior.h" +#include "field_camera.h" +#include "field_effect.h" +#include "field_fadetransition.h" +#include "fieldmap.h" +#include "field_map_obj.h" +#include "util.h" +#include "field_effect_helpers.h" + +#define subsprite_table(ptr) {.subsprites = ptr, .subspriteCount = (sizeof ptr) / (sizeof(struct Subsprite))} + +EWRAM_DATA u32 gFieldEffectArguments[8] = {0}; + +const u32 gSpriteImage_839DC14[] = INCBIN_U32("graphics/birch_speech/birch.4bpp"); +const u16 gBirchPalette[16] = INCBIN_U16("graphics/birch_speech/birch.gbapal"); +const u32 gSpriteImage_839E434[] = INCBIN_U32("graphics/misc/pokeball_glow.4bpp"); +const u16 gFieldEffectObjectPalette4[16] = INCBIN_U16("graphics/field_effect_objects/palettes/04.gbapal"); +const u32 gSpriteImage_839E474[] = INCBIN_U32("graphics/misc/pokecenter_monitor/0.4bpp"); +const u32 gSpriteImage_839E534[] = INCBIN_U32("graphics/misc/pokecenter_monitor/1.4bpp"); +const u32 gSpriteImage_839E5F4[] = INCBIN_U32("graphics/misc/big_hof_monitor.4bpp"); +const u32 gSpriteImage_839E7F4[] = INCBIN_U32("graphics/misc/small_hof_monitor.4bpp"); +const u16 gFieldEffectObjectPalette5[16] = INCBIN_U16("graphics/field_effect_objects/palettes/05.gbapal"); + +// Graphics for the lights streaking past your Pokemon when it uses a field move. +const u32 gFieldMoveStreaksTiles[] = INCBIN_U32("graphics/misc/field_move_streaks.4bpp"); +const u16 gFieldMoveStreaksPalette[16] = INCBIN_U16("graphics/misc/field_move_streaks.gbapal"); +const u16 gFieldMoveStreaksTilemap[] = INCBIN_U16("graphics/misc/field_move_streaks_map.bin"); + +// The following light streaks effect is used when the map is dark (e.g. a cave). +const u32 gDarknessFieldMoveStreaksTiles[] = INCBIN_U32("graphics/misc/darkness_field_move_streaks.4bpp"); +const u16 gDarknessFieldMoveStreaksPalette[16] = INCBIN_U16("graphics/misc/darkness_field_move_streaks.gbapal"); +const u16 gDarknessFieldMoveStreaksTilemap[] = INCBIN_U16("graphics/misc/darkness_field_move_streaks_map.bin"); + +bool8 (*const gFieldEffectScriptFuncs[])(u8 **, u32 *) = { + FieldEffectCmd_loadtiles, + FieldEffectCmd_loadfadedpal, + FieldEffectCmd_loadpal, + FieldEffectCmd_callnative, + FieldEffectCmd_end, + FieldEffectCmd_loadgfx_callnative, + FieldEffectCmd_loadtiles_callnative, + FieldEffectCmd_loadfadedpal_callnative, +}; + +const struct OamData gOamData_839F0F4 = {.size = 3}; +const struct OamData gOamData_839F0FC = {.size = 0}; +const struct OamData gOamData_839F104 = {.size = 1}; + +const struct SpriteFrameImage gSpriteImageTable_839F10C[] = { + obj_frame_tiles(gSpriteImage_839DC14) +}; +const struct SpritePalette gUnknown_0839F114 = {.data = gBirchPalette, .tag = 0x1006}; + +const union AnimCmd gSpriteAnim_839F11C[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 1), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_839F124[] = { + gSpriteAnim_839F11C +}; + +const struct SpriteTemplate gSpriteTemplate_839F128 = { + .tileTag = 0xffff, + .paletteTag = 4102, + .oam = &gOamData_839F0F4, + .anims = (const union AnimCmd *const *)&gSpriteAnimTable_839F124, + .images = gSpriteImageTable_839F10C, + .affineAnims = (const union AffineAnimCmd *const *)&gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy +}; + +const struct SpritePalette gFieldEffectObjectPaletteInfo4 = {.data = gFieldEffectObjectPalette4, .tag = 0x1007}; +const struct SpritePalette gFieldEffectObjectPaletteInfo5 = {.data = gFieldEffectObjectPalette5, .tag = 0x1010}; +const struct OamData gOamData_839F150 = { + .shape = 1, + .size = 2 +}; + +const struct SpriteFrameImage gSpriteImageTable_839F158[] = { + obj_frame_tiles(gSpriteImage_839E434) +}; + +const struct SpriteFrameImage gSpriteImageTable_839F160[] = { + obj_frame_tiles(gSpriteImage_839E474), + obj_frame_tiles(gSpriteImage_839E534) +}; + +const struct SpriteFrameImage gSpriteImageTable_839F170[] = { + obj_frame_tiles(gSpriteImage_839E5F4) +}; + +const struct SpriteFrameImage gSpriteImageTable_839F178[] = { + {.data = (u8 *)gSpriteImage_839E7F4, .size = 0x200} // the macro breaks down here +}; + +const struct Subsprite Unknown_39F180[] = { + {.x = -12, .y = -8, .priority = 2, .tileOffset = 0, .shape = 1, .size = 0}, + {.x = 4, .y = -8, .priority = 2, .tileOffset = 2, .shape = 0, .size = 0}, + {.x = -12, .y = 0, .priority = 2, .tileOffset = 3, .shape = 1, .size = 0}, + {.x = 4, .y = 0, .priority = 2, .tileOffset = 5, .shape = 0, .size = 0} +}; + +const struct SubspriteTable gUnknown_0839F1A0 = subsprite_table(Unknown_39F180); + +const struct Subsprite Unknown_39F1A8[] = { + {.x = -32, .y = -8, .priority = 2, .tileOffset = 0, .shape = 1, .size = 1}, + {.x = 0, .y = -8, .priority = 2, .tileOffset = 4, .shape = 1, .size = 1}, + {.x = -32, .y = 0, .priority = 2, .tileOffset = 8, .shape = 1, .size = 1}, + {.x = 0, .y = 0, .priority = 2, .tileOffset = 12, .shape = 1, .size = 1} +}; + +const struct SubspriteTable gUnknown_0839F1C8 = subsprite_table(Unknown_39F1A8); + +const union AnimCmd gSpriteAnim_839F1D0[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 1), + ANIMCMD_JUMP(0) +}; + +const union AnimCmd gSpriteAnim_839F1D8[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_FRAME(.imageValue = 0, .duration = 16), + ANIMCMD_FRAME(.imageValue = 1, .duration = 16), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_839F1FC[] = { + gSpriteAnim_839F1D0, + gSpriteAnim_839F1D8 +}; + +const union AnimCmd *const gSpriteAnimTable_839F204[] = { + gSpriteAnim_839F1D0 +}; + +const struct SpriteTemplate gSpriteTemplate_839F208 = { + .tileTag = 0xffff, + .paletteTag = 4103, + .oam = &gOamData_839F0FC, + .anims = gSpriteAnimTable_839F1FC, + .images = gSpriteImageTable_839F158, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_PokeballGlow +}; + + +const struct SpriteTemplate gSpriteTemplate_839F220 = { + .tileTag = 0xffff, + .paletteTag = 4100, + .oam = &gOamData_839F104, + .anims = gSpriteAnimTable_839F1FC, + .images = gSpriteImageTable_839F160, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_PokecenterMonitor +}; + + +const struct SpriteTemplate gSpriteTemplate_839F238 = { + .tileTag = 0xffff, + .paletteTag = 4112, + .oam = &gOamData_839F104, + .anims = gSpriteAnimTable_839F204, + .images = gSpriteImageTable_839F170, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_HallOfFameMonitor +}; + + +const struct SpriteTemplate gSpriteTemplate_839F250 = { + .tileTag = 0xffff, + .paletteTag = 4112, + .oam = &gOamData_839F150, + .anims = gSpriteAnimTable_839F204, + .images = gSpriteImageTable_839F178, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_HallOfFameMonitor +}; + +void (*const gUnknown_0839F268[])(struct Task *) = { + PokecenterHealEffect_0, + PokecenterHealEffect_1, + PokecenterHealEffect_2, + PokecenterHealEffect_3 +}; + +void (*const gUnknown_0839F278[])(struct Task *) = { + HallOfFameRecordEffect_0, + HallOfFameRecordEffect_1, + HallOfFameRecordEffect_2, + HallOfFameRecordEffect_3 +}; + +void (*const gUnknown_0839F288[])(struct Sprite *) = { + PokeballGlowEffect_0, + PokeballGlowEffect_1, + PokeballGlowEffect_2, + PokeballGlowEffect_3, + PokeballGlowEffect_4, + PokeballGlowEffect_5, + PokeballGlowEffect_6, + PokeballGlowEffect_7 +}; + +const struct Coords16 gUnknown_0839F2A8[] = { + {.x = 0, .y = 0}, + {.x = 6, .y = 0}, + {.x = 0, .y = 4}, + {.x = 6, .y = 4}, + {.x = 0, .y = 8}, + {.x = 6, .y = 8} +}; + +const u8 gUnknown_0839F2C0[] = {16, 12, 8, 0}; +const u8 gUnknown_0839F2C4[] = {16, 12, 8, 0}; +const u8 gUnknown_0839F2C8[] = { 0, 0, 0, 0}; + +bool8 (*const gUnknown_0839F2CC[])(struct Task *) = { + sub_80867AC, + sub_8086854, + sub_8086870, + sub_80868E4, + sub_808699C, + sub_80869B8, + sub_80869F8 +}; + +bool8 (*const gUnknown_0839F2E8[])(struct Task *) = { + sub_8086AA0, + sub_8086AC0, + sub_8086B30, + sub_8086B54, + sub_8086B64, + sub_8086B88 +}; + +bool8 (*const gUnknown_0839F300[])(struct Task *) = { + sub_8086CF4, + sub_8086D70, + sub_8086DB0, + sub_8086E10, + sub_8086E50, + sub_8086EB0, + sub_8086ED4 +}; + +bool8 (*const gUnknown_0839F31C[])(struct Task *, struct MapObject *) = { + sub_8086FB0, + waterfall_1_do_anim_probably, + waterfall_2_wait_anim_finish_probably, + sub_8087030, + sub_8087058 +}; + +bool8 (*const gUnknown_0839F330[])(struct Task *) = { + sub_8087124, + dive_2_unknown, + dive_3_unknown +}; + +bool8 (*const gUnknown_0839F33C[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_808722C, + sub_8087264, + sub_8087298, + sub_80872E4, + sub_80873D8, + sub_80873F4 +}; + +bool8 (*const gUnknown_0839F354[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_80874CC, + sub_80874FC, + sub_8087548, + sub_808759C +}; + +bool8 (*const gUnknown_0839F364[])(struct Task *, struct MapObject *, struct Sprite *) = { + sub_80876C8, + sub_80876F8, + sub_8087774, + sub_80877AC, + sub_80877D4 +}; + +void (*const gUnknown_0839F378[])(struct Task *) = { + sub_80878F4, + sub_8087914 +}; + +const u8 gUnknown_0839F380[] = {1, 3, 4, 2, 1}; + +void (*const gUnknown_0839F388[])(struct Task *) = { + sub_8087AA4, + sub_8087AC8 +}; + +void (*const gUnknown_0839F390[])(struct Task *) = { + sub_8087BEC, + sub_8087C14, + sub_8087CA4, + sub_8087D78 +}; + +void (*const gUnknown_0839F3A0[])(struct Task *) = { + sub_8087E4C, + sub_8087ED8, + sub_8087FDC +}; + +void (*const gUnknown_0839F3AC[])(struct Task *) = { + sub_8088150, + sub_80881C0, + sub_8088228, + sub_80882B4, + sub_80882E4, + sub_8088338, + sub_8088380 +}; + +void (*const gUnknown_0839F3C8[])(struct Task *) = { + sub_80884AC, + sub_80884E8, + sub_8088554, + sub_80885A8, + sub_80885D8, + sub_808860C, + sub_808862C +}; + +void (*const gUnknown_0839F3E4[])(struct Task *) = { + sub_8088984, + sub_80889E4, + sub_8088A30, + sub_8088A78, + sub_8088AF4 +}; + +void (*const gUnknown_0839F3F8[])(struct Task *) = { + sub_8088CA0, + sub_8088CF8, + sub_8088D3C, + sub_8088D94, + sub_8088DD8, + sub_8088E2C, + sub_8088EB4, + sub_8088F10, + sub_8088F30 +}; + +const union AffineAnimCmd SpriteAffineAnim_839F41C[] = { + AFFINEANIMCMD_FRAME(8, 8, -30, 0), + AFFINEANIMCMD_FRAME(28, 28, 0, 30), + AFFINEANIMCMD_END +}; + +const union AffineAnimCmd SpriteAffineAnim_839F434[] = { + AFFINEANIMCMD_FRAME(256, 256, 64, 0), + AFFINEANIMCMD_FRAME(-10, -10, 0, 22), + AFFINEANIMCMD_END +}; + +const union AffineAnimCmd *const gSpriteAffineAnimTable_0839F44C[] = { + SpriteAffineAnim_839F41C, + SpriteAffineAnim_839F434 +}; + +void (*const gUnknown_0839F454[])(struct Task *) = { + sub_80892A0, + sub_8089354, + sub_80893C0, + sub_8089414, + sub_808948C, + sub_80894C4, + fishE +}; + +const s16 gUnknown_0839F470[] = { + -2, + -4, + -5, + -6, + -7, + -8, + -8, + -8, + -7, + -7, + -6, + -5, + -3, + -2, + 0, + 2, + 4, + 8 +}; + +static u8 sActiveList[32]; + +extern u8 *gFieldEffectScriptPointers[]; + +u32 FieldEffectStart(u8 id) +{ + u8 *script; + u32 val; + + FieldEffectActiveListAdd(id); + + script = gFieldEffectScriptPointers[id]; + + while (gFieldEffectScriptFuncs[*script](&script, &val)) + ; + + return val; +} + +bool8 FieldEffectCmd_loadtiles(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + return TRUE; +} + +bool8 FieldEffectCmd_loadfadedpal(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadFadedPalette(script); + return TRUE; +} + +bool8 FieldEffectCmd_loadpal(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadPalette(script); + return TRUE; +} + +bool8 FieldEffectCmd_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_end(u8 **script, u32 *val) +{ + return FALSE; +} + +bool8 FieldEffectCmd_loadgfx_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + FieldEffectScript_LoadFadedPalette(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_loadtiles_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadTiles(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +bool8 FieldEffectCmd_loadfadedpal_callnative(u8 **script, u32 *val) +{ + (*script)++; + FieldEffectScript_LoadFadedPalette(script); + FieldEffectScript_CallNative(script, val); + return TRUE; +} + +u32 FieldEffectScript_ReadWord(u8 **script) +{ + return (*script)[0] + + ((*script)[1] << 8) + + ((*script)[2] << 16) + + ((*script)[3] << 24); +} + +void FieldEffectScript_LoadTiles(u8 **script) +{ + struct SpriteSheet *sheet = (struct SpriteSheet *)FieldEffectScript_ReadWord(script); + if (GetSpriteTileStartByTag(sheet->tag) == 0xFFFF) + LoadSpriteSheet(sheet); + (*script) += 4; +} + +void FieldEffectScript_LoadFadedPalette(u8 **script) +{ + struct SpritePalette *palette = (struct SpritePalette *)FieldEffectScript_ReadWord(script); + LoadSpritePalette(palette); + sub_807D78C(IndexOfSpritePaletteTag(palette->tag)); + (*script) += 4; +} + +void FieldEffectScript_LoadPalette(u8 **script) +{ + struct SpritePalette *palette = (struct SpritePalette *)FieldEffectScript_ReadWord(script); + LoadSpritePalette(palette); + (*script) += 4; +} + +void FieldEffectScript_CallNative(u8 **script, u32 *val) +{ + u32 (*func)(void) = (u32 (*)(void))FieldEffectScript_ReadWord(script); + *val = func(); + (*script) += 4; +} + +void FieldEffectFreeGraphicsResources(struct Sprite *sprite) +{ + u16 sheetTileStart = sprite->sheetTileStart; + u32 paletteNum = sprite->oam.paletteNum; + DestroySprite(sprite); + FieldEffectFreeTilesIfUnused(sheetTileStart); + FieldEffectFreePaletteIfUnused(paletteNum); +} + +void FieldEffectStop(struct Sprite *sprite, u8 id) +{ + FieldEffectFreeGraphicsResources(sprite); + FieldEffectActiveListRemove(id); +} + +void FieldEffectFreeTilesIfUnused(u16 tileStart) +{ + u8 i; + u16 tag = GetSpriteTileTagByTileStart(tileStart); + + if (tag != 0xFFFF) + { + for (i = 0; i < MAX_SPRITES; i++) + if (gSprites[i].inUse && gSprites[i].usingSheet && tileStart == gSprites[i].sheetTileStart) + return; + FreeSpriteTilesByTag(tag); + } +} + +void FieldEffectFreePaletteIfUnused(u8 paletteNum) +{ + u8 i; + u16 tag = GetSpritePaletteTagByPaletteNum(paletteNum); + + if (tag != 0xFFFF) + { + for (i = 0; i < MAX_SPRITES; i++) + if (gSprites[i].inUse && gSprites[i].oam.paletteNum == paletteNum) + return; + FreeSpritePaletteByTag(tag); + } +} + +void FieldEffectActiveListClear(void) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + sActiveList[i] = 0xFF; +} + +void FieldEffectActiveListAdd(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + { + if (sActiveList[i] == 0xFF) + { + sActiveList[i] = id; + return; + } + } +} + +void FieldEffectActiveListRemove(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + { + if (sActiveList[i] == id) + { + sActiveList[i] = 0xFF; + return; + } + } +} + +bool8 FieldEffectActiveListContains(u8 id) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(sActiveList); i++) + if (sActiveList[i] == id) + return TRUE; + return FALSE; +} + +u8 CreateTrainerSprite(u8 trainerSpriteID, s16 x, s16 y, u8 subpriority, u8 *buffer) +{ + struct SpriteTemplate spriteTemplate; + LoadCompressedObjectPaletteOverrideBuffer(&gTrainerFrontPicPaletteTable[trainerSpriteID], buffer); + LoadCompressedObjectPicOverrideBuffer(&gTrainerFrontPicTable[trainerSpriteID], buffer); + spriteTemplate.tileTag = gTrainerFrontPicTable[trainerSpriteID].tag; + spriteTemplate.paletteTag = gTrainerFrontPicPaletteTable[trainerSpriteID].tag; + spriteTemplate.oam = &gOamData_839F0F4; + spriteTemplate.anims = gDummySpriteAnimTable; + spriteTemplate.images = NULL; + spriteTemplate.affineAnims = gDummySpriteAffineAnimTable; + spriteTemplate.callback = SpriteCallbackDummy; + return CreateSprite(&spriteTemplate, x, y, subpriority); +} + +void LoadTrainerGfx_TrainerCard(u8 gender, u16 palOffset, u8 *dest) +{ + LZDecompressVram(gTrainerFrontPicTable[gender].data, dest); + LoadCompressedPalette(gTrainerFrontPicPaletteTable[gender].data, palOffset, 0x20); +} + +u8 CreateBirchSprite(s16 x, s16 y, u8 subpriority) +{ + LoadSpritePalette(&gUnknown_0839F114); + return CreateSprite(&gSpriteTemplate_839F128, x, y, subpriority); +} + +u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y, u8 subpriority) +{ + DecompressPicFromTable_2(&gMonFrontPicTable[species], gMonFrontPicCoords[species].coords, gMonFrontPicCoords[species].y_offset, gUnknown_081FAF4C[3], gUnknown_081FAF4C[3], species); + LoadCompressedObjectPalette(&gMonPaletteTable[species]); + GetMonSpriteTemplate_803C56C(species, 3); + gUnknown_02024E8C.paletteTag = gMonPaletteTable[0].tag; + sub_807DE38(IndexOfSpritePaletteTag(gMonPaletteTable[0].tag) + 0x10); + return CreateSprite(&gUnknown_02024E8C, x, y, subpriority); +} + +u8 CreateMonSprite_FieldMove(u16 species, u32 d, u32 g, s16 x, s16 y, u8 subpriority) +{ + const struct CompressedSpritePalette *spritePalette; + + HandleLoadSpecialPokePic(&gMonFrontPicTable[species], gMonFrontPicCoords[species].coords, gMonFrontPicCoords[species].y_offset, (u32)gUnknown_081FAF4C[3] /* this is actually u8* or something, pointing to ewram */, gUnknown_081FAF4C[3], species, g); + spritePalette = GetMonSpritePalStructFromOtIdPersonality(species, d, g); + LoadCompressedObjectPalette(spritePalette); + GetMonSpriteTemplate_803C56C(species, 3); + gUnknown_02024E8C.paletteTag = spritePalette->tag; + sub_807DE38(IndexOfSpritePaletteTag(spritePalette->tag) + 0x10); + return CreateSprite(&gUnknown_02024E8C, x, y, subpriority); +} + +void FreeResourcesAndDestroySprite(struct Sprite *sprite) +{ + sub_807DE68(); + FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(sprite->oam.paletteNum)); + if (sprite->oam.affineMode != 0) + { + FreeOamMatrix(sprite->oam.matrixNum); + } + DestroySprite(sprite); +} + +#ifdef NONMATCHING +void MultiplyInvertedPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + int curRed; + int curGreen; + int curBlue; + + curRed = gPlttBufferUnfaded[i] & 0x1f; + curGreen = (gPlttBufferUnfaded[i] & (0x1f << 5)) >> 5; + curBlue = (gPlttBufferUnfaded[i] & (0x1f << 10)) >> 10; + curRed += (((0x1f - curRed) * r) >> 4); + curGreen += (((0x1f - curGreen) * g) >> 4); + curBlue += (((0x1f - curBlue) * b) >> 4); + gPlttBufferFaded[i] = RGB(curRed, curGreen, curBlue); +} + +void MultiplyPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + int curRed; + int curGreen; + int curBlue; + + curRed = gPlttBufferUnfaded[i] & 0x1f; + curGreen = (gPlttBufferUnfaded[i] & (0x1f << 5)) >> 5; + curBlue = (gPlttBufferUnfaded[i] & (0x1f << 10)) >> 10; + curRed -= ((curRed * r) >> 4); + curGreen -= ((curGreen * g) >> 4); + curBlue -= ((curBlue * b) >> 4); + gPlttBufferFaded[i] = RGB(curRed, curGreen, curBlue); +} +#else +__attribute__((naked)) +void MultiplyInvertedPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + asm(".syntax unified\n" + "\tpush {r4-r7,lr}\n" + "\tmov r7, r9\n" + "\tmov r6, r8\n" + "\tpush {r6,r7}\n" + "\tlsls r0, 16\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tlsls r3, 24\n" + "\tlsrs r3, 24\n" + "\tldr r4, _08085D00 @ =gPlttBufferUnfaded\n" + "\tlsrs r0, 15\n" + "\tadds r4, r0, r4\n" + "\tldrh r4, [r4]\n" + "\tmovs r5, 0x1F\n" + "\tmov r9, r5\n" + "\tmov r8, r4\n" + "\tmov r6, r8\n" + "\tands r6, r5\n" + "\tmov r8, r6\n" + "\tmovs r6, 0xF8\n" + "\tlsls r6, 2\n" + "\tands r6, r4\n" + "\tlsrs r6, 5\n" + "\tmovs r5, 0xF8\n" + "\tlsls r5, 7\n" + "\tands r4, r5\n" + "\tlsrs r4, 10\n" + "\tmov r7, r9\n" + "\tmov r5, r8\n" + "\tsubs r7, r5\n" + "\tmov r12, r7\n" + "\tmov r7, r12\n" + "\tmuls r7, r1\n" + "\tadds r1, r7, 0\n" + "\tasrs r1, 4\n" + "\tadd r8, r1\n" + "\tmov r5, r9\n" + "\tsubs r1, r5, r6\n" + "\tmuls r1, r2\n" + "\tasrs r1, 4\n" + "\tadds r6, r1\n" + "\tsubs r5, r4\n" + "\tmov r9, r5\n" + "\tmov r1, r9\n" + "\tmuls r1, r3\n" + "\tasrs r1, 4\n" + "\tadds r4, r1\n" + "\tmov r7, r8\n" + "\tlsls r7, 16\n" + "\tlsls r6, 21\n" + "\torrs r6, r7\n" + "\tlsls r4, 26\n" + "\torrs r4, r6\n" + "\tlsrs r4, 16\n" + "\tldr r1, _08085D04 @ =gPlttBufferFaded\n" + "\tadds r0, r1\n" + "\tstrh r4, [r0]\n" + "\tpop {r3,r4}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_08085D00: .4byte gPlttBufferUnfaded\n" + "_08085D04: .4byte gPlttBufferFaded\n" + ".syntax divided"); +} + +__attribute__((naked)) +void MultiplyPaletteRGBComponents(u16 i, u8 r, u8 g, u8 b) +{ + asm(".syntax unified\n" + "\tpush {r4-r6,lr}\n" + "\tmov r6, r8\n" + "\tpush {r6}\n" + "\tlsls r0, 16\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tlsls r3, 24\n" + "\tlsrs r3, 24\n" + "\tldr r4, _08085D78 @ =gPlttBufferUnfaded\n" + "\tlsrs r0, 15\n" + "\tadds r4, r0, r4\n" + "\tldrh r4, [r4]\n" + "\tmovs r5, 0x1F\n" + "\tmov r8, r5\n" + "\tmov r6, r8\n" + "\tands r6, r4\n" + "\tmov r8, r6\n" + "\tmovs r5, 0xF8\n" + "\tlsls r5, 2\n" + "\tands r5, r4\n" + "\tlsrs r5, 5\n" + "\tmovs r6, 0xF8\n" + "\tlsls r6, 7\n" + "\tands r4, r6\n" + "\tlsrs r4, 10\n" + "\tmov r6, r8\n" + "\tmuls r6, r1\n" + "\tadds r1, r6, 0\n" + "\tasrs r1, 4\n" + "\tmov r6, r8\n" + "\tsubs r6, r1\n" + "\tadds r1, r5, 0\n" + "\tmuls r1, r2\n" + "\tasrs r1, 4\n" + "\tsubs r5, r1\n" + "\tadds r1, r4, 0\n" + "\tmuls r1, r3\n" + "\tasrs r1, 4\n" + "\tsubs r4, r1\n" + "\tlsls r6, 16\n" + "\tlsls r5, 21\n" + "\torrs r5, r6\n" + "\tlsls r4, 26\n" + "\torrs r4, r5\n" + "\tlsrs r4, 16\n" + "\tldr r1, _08085D7C @ =gPlttBufferFaded\n" + "\tadds r0, r1\n" + "\tstrh r4, [r0]\n" + "\tpop {r3}\n" + "\tmov r8, r3\n" + "\tpop {r4-r6}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_08085D78: .4byte gPlttBufferUnfaded\n" + "_08085D7C: .4byte gPlttBufferFaded\n" + ".syntax divided"); +} +#endif + +void Task_PokecenterHeal(u8 taskId); +u8 CreatePokeballGlowSprite(s16, s16, s16, u16); +u8 PokecenterHealEffectHelper(s16, s16); + +bool8 FldEff_PokecenterHeal(void) +{ + u8 nPokemon; + struct Task *task; + + nPokemon = CalculatePlayerPartyCount(); + task = &gTasks[CreateTask(Task_PokecenterHeal, 0xff)]; + task->data[1] = nPokemon; + task->data[2] = 0x5d; + task->data[3] = 0x24; + task->data[4] = 0x7c; + task->data[5] = 0x18; + return FALSE; +} + +void Task_PokecenterHeal(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + gUnknown_0839F268[task->data[0]](task); +} + +void PokecenterHealEffect_0(struct Task *task) +{ + task->data[0]++; + task->data[6] = CreatePokeballGlowSprite(task->data[1], task->data[2], task->data[3], 1); + task->data[7] = PokecenterHealEffectHelper(task->data[4], task->data[5]); +} + +void PokecenterHealEffect_1(struct Task *task) +{ + if (gSprites[task->data[6]].data0 > 1) + { + gSprites[task->data[7]].data0++; + task->data[0]++; + } +} + +void PokecenterHealEffect_2(struct Task *task) +{ + if (gSprites[task->data[6]].data0 > 4) + { + task->data[0]++; + } +} + +void PokecenterHealEffect_3(struct Task *task) +{ + if (gSprites[task->data[6]].data0 > 6) + { + DestroySprite(&gSprites[task->data[6]]); + FieldEffectActiveListRemove(FLDEFF_POKECENTER_HEAL); + DestroyTask(FindTaskIdByFunc(Task_PokecenterHeal)); + } +} + +void Task_HallOfFameRecord(u8 taskId); +void HallOfFameRecordEffectHelper(s16, s16, s16, u8); + +bool8 FldEff_HallOfFameRecord(void) +{ + u8 nPokemon; + struct Task *task; + + nPokemon = CalculatePlayerPartyCount(); + task = &gTasks[CreateTask(Task_HallOfFameRecord, 0xff)]; + task->data[1] = nPokemon; + task->data[2] = 0x75; + task->data[3] = 0x34; + return FALSE; +} + +void Task_HallOfFameRecord(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + gUnknown_0839F278[task->data[0]](task); +} + +void HallOfFameRecordEffect_0(struct Task *task) +{ + u8 taskId; + task->data[0]++; + task->data[6] = CreatePokeballGlowSprite(task->data[1], task->data[2], task->data[3], 0); + taskId = FindTaskIdByFunc(Task_HallOfFameRecord); + HallOfFameRecordEffectHelper(taskId, 0x78, 0x18, 0); + HallOfFameRecordEffectHelper(taskId, 0x28, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0x48, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0xa8, 0x08, 1); + HallOfFameRecordEffectHelper(taskId, 0xc8, 0x08, 1); +} + +void HallOfFameRecordEffect_1(struct Task *task) +{ + if (gSprites[task->data[6]].data0 > 1) + { + task->data[15]++; // was this ever initialized? is this ever used? + task->data[0]++; + } +} + +void HallOfFameRecordEffect_2(struct Task *task) +{ + if (gSprites[task->data[6]].data0 > 4) + { + task->data[0]++; + } +} + +void HallOfFameRecordEffect_3(struct Task *task) +{ + if (gSprites[task->data[6]].data0 > 6) + { + DestroySprite(&gSprites[task->data[6]]); + FieldEffectActiveListRemove(FLDEFF_HALL_OF_FAME_RECORD); + DestroyTask(FindTaskIdByFunc(Task_HallOfFameRecord)); + } +} + +void SpriteCB_PokeballGlowEffect(struct Sprite *); + +u8 CreatePokeballGlowSprite(s16 data6, s16 x, s16 y, u16 data5) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateInvisibleSprite(SpriteCB_PokeballGlowEffect); + sprite = &gSprites[spriteId]; + sprite->pos2.x = x; + sprite->pos2.y = y; + sprite->data5 = data5; + sprite->data6 = data6; + sprite->data7 = spriteId; + return spriteId; +} + +void SpriteCB_PokeballGlowEffect(struct Sprite *sprite) +{ + gUnknown_0839F288[sprite->data0](sprite); +} + +void PokeballGlowEffect_0(struct Sprite *sprite) +{ + u8 endSpriteId; + if (sprite->data1 == 0 || (--sprite->data1) == 0) + { + sprite->data1 = 25; + endSpriteId = CreateSpriteAtEnd(&gSpriteTemplate_839F208, gUnknown_0839F2A8[sprite->data2].x + sprite->pos2.x, gUnknown_0839F2A8[sprite->data2].y + sprite->pos2.y, 0); + gSprites[endSpriteId].oam.priority = 2; + gSprites[endSpriteId].data0 = sprite->data7; + sprite->data2++; + sprite->data6--; + PlaySE(SE_BOWA); + } + if (sprite->data6 == 0) + { + sprite->data1 = 32; + sprite->data0++; + } +} + +void PokeballGlowEffect_1(struct Sprite *sprite) +{ + if ((--sprite->data1) == 0) + { + sprite->data0++; + sprite->data1 = 8; + sprite->data2 = 0; + sprite->data3 = 0; + if (sprite->data5) + { + PlayFanfare(BGM_ME_ASA); + } + } +} + +void PokeballGlowEffect_2(struct Sprite *sprite) +{ + u8 phase; + if ((--sprite->data1) == 0) + { + sprite->data1 = 8; + sprite->data2++; + sprite->data2 &= 3; + if (sprite->data2 == 0) + { + sprite->data3++; + } + } + phase = (sprite->data2 + 3) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x108, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + phase = (sprite->data2 + 2) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x106, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + phase = (sprite->data2 + 1) & 3; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x102, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + phase = sprite->data2; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x105, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x103, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + if (sprite->data3 > 2) + { + sprite->data0++; + sprite->data1 = 8; + sprite->data2 = 0; + } +} + +void PokeballGlowEffect_3(struct Sprite *sprite) +{ + u8 phase; + if ((--sprite->data1) == 0) + { + sprite->data1 = 8; + sprite->data2++; + sprite->data2 &= 3; + if (sprite->data2 == 3) + { + sprite->data0++; + sprite->data1 = 30; + } + } + phase = sprite->data2; + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x108, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x106, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x102, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x105, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); + MultiplyInvertedPaletteRGBComponents((IndexOfSpritePaletteTag(0x1007) << 4) + 0x103, gUnknown_0839F2C0[phase], gUnknown_0839F2C4[phase], gUnknown_0839F2C8[phase]); +} + +void PokeballGlowEffect_4(struct Sprite *sprite) +{ + if ((--sprite->data1) == 0) + { + sprite->data0++; + } +} + +void PokeballGlowEffect_5(struct Sprite *sprite) +{ + sprite->data0++; +} + +void PokeballGlowEffect_6(struct Sprite *sprite) +{ + if (sprite->data5 == 0 || IsFanfareTaskInactive()) + { + sprite->data0++; + } +} + +void PokeballGlowEffect_7(struct Sprite *sprite) +{ +} + +void SpriteCB_PokeballGlow(struct Sprite *sprite) +{ + if (gSprites[sprite->data0].data0 > 4) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +u8 PokecenterHealEffectHelper(s16 x, s16 y) +{ + u8 spriteIdAtEnd; + struct Sprite *sprite; + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_839F220, x, y, 0); + sprite = &gSprites[spriteIdAtEnd]; + sprite->oam.priority = 2; + sprite->invisible = 1; + SetSubspriteTables(sprite, &gUnknown_0839F1A0); + return spriteIdAtEnd; +} + +void SpriteCB_PokecenterMonitor(struct Sprite *sprite) +{ + if (sprite->data0 != 0) + { + sprite->data0 = 0; + sprite->invisible = 0; + StartSpriteAnim(sprite, 1); + } + if (sprite->animEnded) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +void HallOfFameRecordEffectHelper(s16 a0, s16 a1, s16 a2, u8 a3) +{ + u8 spriteIdAtEnd; + if (!a3) + { + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_839F238, a1, a2, 0); + SetSubspriteTables(&gSprites[spriteIdAtEnd], &gUnknown_0839F1C8); + } else + { + spriteIdAtEnd = CreateSpriteAtEnd(&gSpriteTemplate_839F250, a1, a2, 0); + } + gSprites[spriteIdAtEnd].invisible = 1; + gSprites[spriteIdAtEnd].data0 = a0; +} + +void SpriteCB_HallOfFameMonitor(struct Sprite *sprite) +{ + if (gTasks[sprite->data0].data[15]) + { + if (sprite->data1 == 0 || (--sprite->data1) == 0) + { + sprite->data1 = 16; + sprite->invisible ^= 1; + } + sprite->data2++; + } + if (sprite->data2 > 127) + { + FieldEffectFreeGraphicsResources(sprite); + } +} + +void mapldr_080842E8(void); +void mapldr_08084390(void); +void task00_8084310(u8); +void c3_080843F8(u8); + +void sub_80865BC(void) +{ + SetMainCallback2(c2_exit_to_overworld_2_switch); + gFieldCallback = mapldr_080842E8; +} + +void mapldr_080842E8(void) +{ + pal_fill_black(); + CreateTask(task00_8084310, 0); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; +} + +void task00_8084310(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + if (!task->data[0]) + { + if (!sub_807D770()) + { + return; + } + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; + if ((int)gFieldEffectArguments[0] > 5) + { + gFieldEffectArguments[0] = 0; + } + FieldEffectStart(FLDEFF_USE_FLY); + task->data[0]++; + } + if (!FieldEffectActiveListContains(FLDEFF_USE_FLY)) + { + Overworld_ResetStateAfterFly(); + warp_in(); + SetMainCallback2(CB2_LoadMap); + gFieldCallback = mapldr_08084390; + DestroyTask(taskId); + } +} + +void mapldr_08084390(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_black(); + CreateTask(c3_080843F8, 0); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + if (gPlayerAvatar.flags & 0x08) + { + FieldObjectTurn(&gMapObjects[gPlayerAvatar.mapObjectId], DIR_WEST); + } + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; +} + +void c3_080843F8(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + if (task->data[0] == 0) + { + if (gPaletteFade.active) + { + return; + } + FieldEffectStart(FLDEFF_FLY_IN); + task->data[0]++; + } + if (!FieldEffectActiveListContains(FLDEFF_FLY_IN)) + { + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(taskId); + } +} + +extern void pal_fill_for_map_transition(void); +void sub_8086774(u8); +extern void CameraObjectReset2(void); +extern void CameraObjectReset1(void); + +void sub_8086748(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_map_transition(); + ScriptContext2_Enable(); + FreezeMapObjects(); + CreateTask(sub_8086774, 0); + gFieldCallback = NULL; +} + +void sub_8086774(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0839F2CC[task->data[0]](task)); // return code signifies whether to continue blocking here +} + +bool8 sub_80867AC(struct Task *task) // gUnknown_0839F2CC[0] +{ + struct MapObject *playerObject; + struct Sprite *playerSprite; + playerObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + playerSprite = &gSprites[gPlayerAvatar.spriteId]; + CameraObjectReset2(); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + gPlayerAvatar.unk6 = 1; + FieldObjectSetSpecialAnim(playerObject, GetFaceDirectionAnimId(player_get_direction_lower_nybble())); + task->data[4] = playerSprite->subspriteMode; + playerObject->mapobj_bit_26 = 1; + playerSprite->oam.priority = 1; + playerSprite->subspriteMode = 2; + task->data[0]++; + return TRUE; +} + +bool8 sub_8086854(struct Task *task) // gUnknown_0839F2CC[1] +{ + if (sub_807D770()) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_8086870(struct Task *task) // gUnknown_0839F2CC[2] +{ + struct Sprite *sprite; + s16 centerToCornerVecY; + sprite = &gSprites[gPlayerAvatar.spriteId]; + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + sprite->pos2.y = -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY); + task->data[1] = 1; + task->data[2] = 0; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 0; + PlaySE(SE_RU_HYUU); + task->data[0]++; + return FALSE; +} + +bool8 sub_80868E4(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.y += task->data[1]; + if (task->data[1] < 8) + { + task->data[2] += task->data[1]; + if (task->data[2] & 0xf) + { + task->data[1] <<= 1; + } + } + if (task->data[3] == 0 && sprite->pos2.y >= -16) + { + task->data[3]++; + mapObject->mapobj_bit_26 = 0; + sprite->subspriteMode = task->data[4]; + mapObject->mapobj_bit_2 = 1; + } + if (sprite->pos2.y >= 0) + { + PlaySE(SE_W070); + mapObject->mapobj_bit_3 = 1; + mapObject->mapobj_bit_5 = 1; + sprite->pos2.y = 0; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_808699C(struct Task *task) +{ + task->data[0]++; + task->data[1] = 4; + task->data[2] = 0; + SetCameraPanningCallback(NULL); + return TRUE; +} + +bool8 sub_80869B8(struct Task *task) +{ + SetCameraPanning(0, task->data[1]); + task->data[1] = -task->data[1]; + task->data[2]++; + if ((task->data[2] & 3) == 0) + { + task->data[1] >>= 1; + } + if (task->data[1] == 0) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80869F8(struct Task *task) +{ + gPlayerAvatar.unk6 = 0; + ScriptContext2_Disable(); + CameraObjectReset1(); + UnfreezeMapObjects(); + InstallCameraPanAheadCallback(); + DestroyTask(FindTaskIdByFunc(sub_8086774)); + return FALSE; +} + +void sub_8086A68(u8); +extern void sub_80B4824(u8); +extern void sub_8053FF8(void); +extern void fade_8080918(void); + +void sub_8086B98(struct Task *); +void sub_8086BE4(struct Task *); +void sub_8086C30(void); +void sub_8086C40(void); +bool8 sub_8054034(void); +void sub_8086C94(void); +void sub_80B483C(void); +void sub_8086CBC(u8); + +void sub_8086A2C(u8 a0, u8 priority) +{ + u8 taskId; + taskId = CreateTask(sub_8086A68, priority); + gTasks[taskId].data[1] = 0; + if (a0 == 0x6a) + { + gTasks[taskId].data[1] = 1; + } +} + +void sub_8086A68(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0839F2E8[task->data[0]](task)); +} + +bool8 sub_8086AA0(struct Task *task) +{ + FreezeMapObjects(); + CameraObjectReset2(); + sub_80B4824(task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_8086AC0(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(player_get_direction_lower_nybble())); + task->data[0]++; + task->data[2] = 0; + task->data[3] = 0; + if ((u8)task->data[1] == 0) + { + task->data[0] = 4; + } + PlaySE(SE_ESUKA); + } + return FALSE; +} + +bool8 sub_8086B30(struct Task *task) +{ + sub_8086B98(task); + if (task->data[2] > 3) + { + sub_8086C30(); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_8086B54(struct Task *task) +{ + sub_8086B98(task); + sub_8086C40(); + return FALSE; +} + +bool8 sub_8086B64(struct Task *task) +{ + sub_8086BE4(task); + if (task->data[2] > 3) + { + sub_8086C30(); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_8086B88(struct Task *task) +{ + sub_8086BE4(task); + sub_8086C40(); + return FALSE; +} + +void sub_8086B98(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[2]); + sprite->pos2.y = Sin(0x94, task->data[2]); + task->data[3]++; + if (task->data[3] & 1) + { + task->data[2]++; + } +} + +void sub_8086BE4(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[2]); + sprite->pos2.y = Sin(0x76, task->data[2]); + task->data[3]++; + if (task->data[3] & 1) + { + task->data[2]++; + } +} + +void sub_8086C30(void) +{ + sub_8053FF8(); + fade_8080918(); +} + +void sub_8086C40(void) +{ + if (!gPaletteFade.active && sub_8054034() == TRUE) + { + sub_80B483C(); + warp_in(); + gFieldCallback = sub_8086C94; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_8086A68)); + } +} + +void sub_8086C94(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_map_transition(); + ScriptContext2_Enable(); + CreateTask(sub_8086CBC, 0); + gFieldCallback = NULL; +} + +void sub_8086CBC(u8 taskId) +{ + struct Task *task; + task = &gTasks[taskId]; + while (gUnknown_0839F300[task->data[0]](task)); +} + +bool8 sub_8086CF4(struct Task *task) +{ + struct MapObject *mapObject; + s16 x; + s16 y; + u8 behavior; + CameraObjectReset2(); + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(DIR_EAST)); + PlayerGetDestCoords(&x, &y); + behavior = MapGridGetMetatileBehaviorAt(x, y); + task->data[0]++; + task->data[1] = 16; + if (behavior == 0x6b) + { + behavior = 1; + task->data[0] = 3; + } else + { + behavior = 0; + } + sub_80B4824(behavior); + return TRUE; +} + +bool8 sub_8086D70(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[1]); + sprite->pos2.y = Sin(0x94, task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_8086DB0(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x84, task->data[1]); + sprite->pos2.y = Sin(0x94, task->data[1]); + task->data[2]++; + if (task->data[2] & 1) + { + task->data[1]--; + } + if (task->data[1] == 0) + { + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0] = 5; + } + return FALSE; +} + +bool8 sub_8086E10(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[1]); + sprite->pos2.y = Sin(0x76, task->data[1]); + task->data[0]++; + return FALSE; +} + +bool8 sub_8086E50(struct Task *task) +{ + struct Sprite *sprite; + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.x = Cos(0x7c, task->data[1]); + sprite->pos2.y = Sin(0x76, task->data[1]); + task->data[2]++; + if (task->data[2] & 1) + { + task->data[1]--; + } + if (task->data[1] == 0) + { + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0]++; + } + return FALSE; +} + +extern bool8 sub_80B4850(void); + +bool8 sub_8086EB0(struct Task *task) +{ + if (sub_80B4850()) + { + return FALSE; + } + sub_80B483C(); + task->data[0]++; + return TRUE; +} + +bool8 sub_8086ED4(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + CameraObjectReset1(); + ScriptContext2_Disable(); + FieldObjectSetSpecialAnim(mapObject, GetGoSpeed0AnimId(DIR_EAST)); + DestroyTask(FindTaskIdByFunc(sub_8086CBC)); + } + return FALSE; +} + +void sub_8086F64(u8); + +bool8 FldEff_UseWaterfall(void) +{ + u8 taskId; + taskId = CreateTask(sub_8086F64, 0xff); + gTasks[taskId].data[1] = gFieldEffectArguments[0]; + sub_8086F64(taskId); + return FALSE; +} + +void sub_8086F64(u8 taskId) +{ + while (gUnknown_0839F31C[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId])); +} + +bool8 sub_8086FB0(struct Task *task, struct MapObject *mapObject) +{ + ScriptContext2_Enable(); + gPlayerAvatar.unk6 = 1; + task->data[0]++; + return FALSE; +} + +bool8 waterfall_1_do_anim_probably(struct Task *task, struct MapObject *mapObject) +{ + ScriptContext2_Enable(); + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject)) + { + FieldObjectClearAnimIfSpecialAnimFinished(mapObject); + gFieldEffectArguments[0] = task->data[1]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + } + return FALSE; +} + +bool8 waterfall_2_wait_anim_finish_probably(struct Task *task, struct MapObject *mapObject) +{ + if (FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + return FALSE; + } + task->data[0]++; + return TRUE; +} + +bool8 sub_8087030(struct Task *task, struct MapObject *mapObject) +{ + FieldObjectSetSpecialAnim(mapObject, GetSimpleGoAnimId(DIR_NORTH)); + task->data[0]++; + return FALSE; +} + +bool8 sub_8087058(struct Task *task, struct MapObject *mapObject) +{ + if (!FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + return FALSE; + } + if (MetatileBehavior_IsWaterfall(mapObject->mapobj_unk_1E)) + { + task->data[0] = 3; + return TRUE; + } + ScriptContext2_Disable(); + gPlayerAvatar.unk6 = 0; + DestroyTask(FindTaskIdByFunc(sub_8086F64)); + FieldEffectActiveListRemove(FLDEFF_USE_WATERFALL); + return FALSE; +} + +void Task_Dive(u8); +extern int dive_warp(struct MapPosition *, u16); + +bool8 FldEff_UseDive(void) +{ + u8 taskId; + taskId = CreateTask(Task_Dive, 0xff); + gTasks[taskId].data[15] = gFieldEffectArguments[0]; + gTasks[taskId].data[14] = gFieldEffectArguments[1]; + Task_Dive(taskId); + return FALSE; +} + +void Task_Dive(u8 taskId) +{ + while (gUnknown_0839F330[gTasks[taskId].data[0]](&gTasks[taskId])); +} + +bool8 sub_8087124(struct Task *task) +{ + gPlayerAvatar.unk6 = 1; + task->data[0]++; + return FALSE; +} + +bool8 dive_2_unknown(struct Task *task) +{ + ScriptContext2_Enable(); + gFieldEffectArguments[0] = task->data[15]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + return FALSE; +} + +bool8 dive_3_unknown(struct Task *task) +{ + struct MapPosition mapPosition; + PlayerGetDestCoords(&mapPosition.x, &mapPosition.y); + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + dive_warp(&mapPosition, gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E); + DestroyTask(FindTaskIdByFunc(Task_Dive)); + FieldEffectActiveListRemove(FLDEFF_USE_DIVE); + } + return FALSE; +} + +void sub_80871D0(u8); +void mapldr_080851BC(void); + +void sub_80871B8(u8 priority) +{ + CreateTask(sub_80871D0, priority); +} + +void sub_80871D0(u8 taskId) +{ + while (gUnknown_0839F33C[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_808722C(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + FreezeMapObjects(); + CameraObjectReset2(); + SetCameraPanningCallback(NULL); + gPlayerAvatar.unk6 = 1; + mapObject->mapobj_bit_26 = 1; + task->data[1] = 1; + task->data[0]++; + return TRUE; +} + +bool8 sub_8087264(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + SetCameraPanning(0, task->data[1]); + task->data[1] = -task->data[1]; + task->data[2]++; + if (task->data[2] > 7) + { + task->data[2] = 0; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_8087298(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->pos2.y = 0; + task->data[3] = 1; + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + FieldEffectStart(FLDEFF_LAVARIDGE_GYM_WARP); + PlaySE(SE_W153); + task->data[0]++; + return TRUE; +} + +bool8 sub_80872E4(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + s16 centerToCornerVecY; + SetCameraPanning(0, task->data[1]); + if (task->data[1] = -task->data[1], ++task->data[2] <= 17) + { + if (!(task->data[2] & 1) && (task->data[1] <= 3)) + { + task->data[1] <<= 1; + } + } else if (!(task->data[2] & 4) && (task->data[1] > 0)) + { + task->data[1] >>= 1; + } + if (task->data[2] > 6) + { + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + if (sprite->pos2.y > -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY)) + { + sprite->pos2.y -= task->data[3]; + if (task->data[3] <= 7) + { + task->data[3]++; + } + } else + { + task->data[4] = 1; + } + } + if (task->data[5] == 0 && sprite->pos2.y < -0x10) + { + task->data[5]++; + mapObject->mapobj_bit_26 = 1; + sprite->oam.priority = 1; + sprite->subspriteMode = 2; + } + if (task->data[1] == 0 && task->data[4] != 0) + { + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80873D8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8053FF8(); + fade_8080918(); + task->data[0]++; + return FALSE; +} + +bool8 sub_80873F4(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!gPaletteFade.active && sub_8054034() == TRUE) + { + warp_in(); + gFieldCallback = mapldr_080851BC; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80871D0)); + } + return FALSE; +} + +void sub_8087470(u8); + +void mapldr_080851BC(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_map_transition(); + ScriptContext2_Enable(); + gFieldCallback = NULL; + CreateTask(sub_8087470, 0); +} + +void sub_8087470(u8 taskId) +{ + while (gUnknown_0839F354[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_80874CC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + CameraObjectReset2(); + FreezeMapObjects(); + gPlayerAvatar.unk6 = 1; + mapObject->mapobj_bit_13 = 1; + task->data[0]++; + return FALSE; +} + +bool8 sub_80874FC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_807D770()) + { + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + task->data[1] = FieldEffectStart(FLDEFF_POP_OUT_OF_ASH); + task->data[0]++; + } + return FALSE; +} + +bool8 sub_8087548(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite = &gSprites[task->data[1]]; + if (sprite->animCmdIndex > 1) + { + task->data[0]++; + mapObject->mapobj_bit_13 = 0; + CameraObjectReset1(); + PlaySE(SE_W091); + FieldObjectSetSpecialAnim(mapObject, sub_80608A4(DIR_EAST)); + } + return FALSE; +} + +bool8 sub_808759C(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + gPlayerAvatar.unk6 = 0; + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_8087470)); + } + return FALSE; +} + +extern void sub_8060470(s16 *x, s16 *y, s16 dx, s16 dy); +extern const struct SpriteTemplate *const gFieldEffectObjectTemplatePointers[36]; + +u8 FldEff_LavaridgeGymWarp(void) +{ + u8 spriteId; + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[33], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + gSprites[spriteId].oam.priority = gFieldEffectArguments[3]; + gSprites[spriteId].coordOffsetEnabled = 1; + return spriteId; +} + +void sub_8087638(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_LAVARIDGE_GYM_WARP); + } +} + +void sub_808766C(u8); + +void sub_8087654(u8 priority) +{ + CreateTask(sub_808766C, priority); +} + +void sub_808766C(u8 taskId) +{ + while(gUnknown_0839F364[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId], &gSprites[gPlayerAvatar.spriteId])); +} + +bool8 sub_80876C8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + FreezeMapObjects(); + CameraObjectReset2(); + gPlayerAvatar.unk6 = 1; + mapObject->mapobj_bit_26 = 1; + task->data[0]++; + return FALSE; +} + +bool8 sub_80876F8(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + if (task->data[1] > 3) + { + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + task->data[1] = FieldEffectStart(FLDEFF_POP_OUT_OF_ASH); + task->data[0]++; + } else + { + task->data[1]++; + FieldObjectSetSpecialAnim(mapObject, GetStepInPlaceDelay4AnimId(mapObject->mapobj_unk_18)); + PlaySE(SE_FU_ZUZUZU); + } + } + return FALSE; +} + +bool8 sub_8087774(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (gSprites[task->data[1]].animCmdIndex == 2) + { + mapObject->mapobj_bit_13 = 1; + task->data[0]++; + } + return FALSE; +} + +bool8 sub_80877AC(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!FieldEffectActiveListContains(FLDEFF_POP_OUT_OF_ASH)) + { + sub_8053FF8(); + fade_8080918(); + task->data[0]++; + } + return FALSE; +} + +void sub_80878C4(u8); +void mapldr_080859D4(void); + +bool8 sub_80877D4(struct Task *task, struct MapObject *mapObject, struct Sprite *sprite) +{ + if (!gPaletteFade.active && sub_8054034() == TRUE) + { + warp_in(); + gFieldCallback = sub_8086748; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_808766C)); + } + return FALSE; +} + +u8 FldEff_PopOutOfAsh(void) +{ + u8 spriteId; + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[32], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + gSprites[spriteId].oam.priority = gFieldEffectArguments[3]; + gSprites[spriteId].coordOffsetEnabled = 1; + return spriteId; +} + +void sub_808788C(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_POP_OUT_OF_ASH); + } +} + +void sub_80878A8(void) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + CreateTask(sub_80878C4, 0x50); +} + +void sub_80878C4(u8 taskId) +{ + gUnknown_0839F378[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80878F4(struct Task *task) +{ + task->data[0]++; + task->data[14] = 64; + task->data[15] = player_get_direction_lower_nybble(); +} + +void sub_8087914(struct Task *task) +{ + struct MapObject *mapObject; + u8 unknown_0839F380[5]; + memcpy(unknown_0839F380, gUnknown_0839F380, sizeof gUnknown_0839F380); + if (task->data[14] != 0 && (--task->data[14]) == 0) + { + sub_8053FF8(); + fade_8080918(); + } + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + if (task->data[14] == 0 && !gPaletteFade.active && sub_8054034() == TRUE) + { + FieldObjectSetDirection(mapObject, task->data[15]); + sub_8053678(); + warp_in(); + gFieldCallback = mapldr_080859D4; + SetMainCallback2(CB2_LoadMap); + DestroyTask(FindTaskIdByFunc(sub_80878C4)); + } else if (task->data[1] == 0 || (--task->data[1]) == 0) + { + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(unknown_0839F380[mapObject->mapobj_unk_18])); + if (task->data[2] < 12) + { + task->data[2]++; + } + task->data[1] = 8 >> (task->data[2] >> 2); + } + } +} + +void sub_8087A74(u8); + +void mapldr_080859D4(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_map_transition(); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + CreateTask(sub_8087A74, 0); +} + +void sub_8087A74(u8 taskId) +{ + gUnknown_0839F388[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_8087AA4(struct Task *task) +{ + if (sub_807D770()) + { + task->data[0]++; + task->data[15] = player_get_direction_lower_nybble(); + } +} + +void sub_8087AC8(struct Task *task) +{ + struct MapObject *mapObject; + u8 unknown_0839F380[5]; + memcpy(unknown_0839F380, gUnknown_0839F380, sizeof gUnknown_0839F380); + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[1] == 0 || (--task->data[1]) == 0) + { + if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) && !FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + return; + } + if (task->data[2] >= 32 && task->data[15] == player_get_direction_lower_nybble()) + { + mapObject->mapobj_bit_13 = 0; + ScriptContext2_Disable(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_8087A74)); + return; + } + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(unknown_0839F380[mapObject->mapobj_unk_18])); + if (task->data[2] < 32) + { + task->data[2]++; + } + task->data[1] = task->data[2] >> 2; + } + mapObject->mapobj_bit_13 ^= 1; +} + +void sub_8087BBC(u8); +void mapldr_08085D88(void); + +void sub_8087BA8(void) +{ + CreateTask(sub_8087BBC, 0); +} + +void sub_8087BBC(u8 taskId) +{ + gUnknown_0839F390[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_8087BEC(struct Task *task) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + CameraObjectReset2(); + task->data[15] = player_get_direction_lower_nybble(); + task->data[0]++; +} + +void sub_8087C14(struct Task *task) +{ + struct MapObject *mapObject; + u8 unknown_0839F380[5]; + memcpy(unknown_0839F380, gUnknown_0839F380, sizeof gUnknown_0839F380); + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[1] == 0 || (--task->data[1]) == 0) + { + FieldObjectTurn(mapObject, unknown_0839F380[mapObject->mapobj_unk_18]); + task->data[1] = 8; + task->data[2]++; + } + if (task->data[2] > 7 && task->data[15] == mapObject->mapobj_unk_18) + { + task->data[0]++; + task->data[1] = 4; + task->data[2] = 8; + task->data[3] = 1; + PlaySE(SE_TK_WARPIN); + } +} + +void sub_8087CA4(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + u8 unknown_0839F380[5]; + memcpy(unknown_0839F380, gUnknown_0839F380, sizeof gUnknown_0839F380); + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[gPlayerAvatar.spriteId]; + if ((--task->data[1]) <= 0) + { + task->data[1] = 4; + FieldObjectTurn(mapObject, unknown_0839F380[mapObject->mapobj_unk_18]); + } + sprite->pos1.y -= task->data[3]; + task->data[4] += task->data[3]; + if ((--task->data[2]) <= 0 && (task->data[2] = 4, task->data[3] < 8)) + { + task->data[3] <<= 1; + } + if (task->data[4] > 8 && (sprite->oam.priority = 1, sprite->subspriteMode != 0)) + { + sprite->subspriteMode = 2; + } + if (task->data[4] >= 0xa8) + { + task->data[0]++; + sub_8053FF8(); + fade_8080918(); + } +} + +void sub_8087D78(struct Task *task) +{ + if (!gPaletteFade.active && sub_8054034() == TRUE) + { + Overworld_SetWarpDestToLastHealLoc(); + warp_in(); + SetMainCallback2(CB2_LoadMap); + gFieldCallback = mapldr_08085D88; + DestroyTask(FindTaskIdByFunc(sub_8087BBC)); + } +} + +void sub_8087E1C(u8); + +void mapldr_08085D88(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_map_transition(); + ScriptContext2_Enable(); + FreezeMapObjects(); + gFieldCallback = NULL; + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 1; + CameraObjectReset2(); + CreateTask(sub_8087E1C, 0); +} + +void sub_8087E1C(u8 taskId) +{ + gUnknown_0839F3A0[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_8087E4C(struct Task *task) +{ + struct Sprite *sprite; + s16 centerToCornerVecY; + if (sub_807D770()) + { + sprite = &gSprites[gPlayerAvatar.spriteId]; + centerToCornerVecY = -(sprite->centerToCornerVecY << 1); + sprite->pos2.y = -(sprite->pos1.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY + centerToCornerVecY); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = 0; + task->data[0]++; + task->data[1] = 8; + task->data[2] = 1; + task->data[14] = sprite->subspriteMode; + task->data[15] = player_get_direction_lower_nybble(); + PlaySE(SE_TK_WARPIN); + } +} + +void sub_8087ED8(struct Task *task) +{ + u8 unknown_0839F380[5]; + struct MapObject *mapObject; + struct Sprite *sprite; + memcpy(unknown_0839F380, gUnknown_0839F380, sizeof gUnknown_0839F380); + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[gPlayerAvatar.spriteId]; + if ((sprite->pos2.y += task->data[1]) >= -8) + { + if (task->data[13] == 0) + { + task->data[13]++; + mapObject->mapobj_bit_2 = 1; + sprite->subspriteMode = task->data[14]; + } + } else + { + sprite->oam.priority = 1; + if (sprite->subspriteMode != 0) + { + sprite->subspriteMode = 2; + } + } + if (sprite->pos2.y >= -0x30 && task->data[1] > 1 && !(sprite->pos2.y & 1)) + { + task->data[1]--; + } + if ((--task->data[2]) == 0) + { + task->data[2] = 4; + FieldObjectTurn(mapObject, unknown_0839F380[mapObject->mapobj_unk_18]); + } + if (sprite->pos2.y >= 0) + { + sprite->pos2.y = 0; + task->data[0]++; + task->data[1] = 1; + task->data[2] = 0; + } +} + +void sub_8087FDC(struct Task *task) +{ + u8 unknown_0839F380[5]; + struct MapObject *mapObject; + memcpy(unknown_0839F380, gUnknown_0839F380, sizeof gUnknown_0839F380); + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if ((--task->data[1]) == 0) + { + FieldObjectTurn(mapObject, unknown_0839F380[mapObject->mapobj_unk_18]); + task->data[1] = 8; + if ((++task->data[2]) > 4 && task->data[14] == mapObject->mapobj_unk_18) + { + ScriptContext2_Disable(); + CameraObjectReset1(); + UnfreezeMapObjects(); + DestroyTask(FindTaskIdByFunc(sub_8087E1C)); + } + } +} + +void sub_8088120(u8); +void sub_808847C(u8); +u8 sub_8088830(u32, u32, u32); +void sub_80883DC(void); +void sub_808843C(u16); +void sub_8088890(struct Sprite *); + +bool8 FldEff_FieldMoveShowMon(void) +{ + u8 taskId; + if (is_map_type_1_2_3_5_or_6(Overworld_GetMapTypeOfSaveblockLocation()) == TRUE) + { + taskId = CreateTask(sub_8088120, 0xff); + } else + { + taskId = CreateTask(sub_808847C, 0xff); + } + gTasks[taskId].data[15] = sub_8088830(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + return FALSE; +} + +bool8 FldEff_FieldMoveShowMonInit(void) +{ + struct Pokemon *pokemon; + u32 flag = gFieldEffectArguments[0] & 0x80000000; + pokemon = &gPlayerParty[(u8)gFieldEffectArguments[0]]; + gFieldEffectArguments[0] = GetMonData(pokemon, MON_DATA_SPECIES); + gFieldEffectArguments[1] = GetMonData(pokemon, MON_DATA_OT_ID); + gFieldEffectArguments[2] = GetMonData(pokemon, MON_DATA_PERSONALITY); + gFieldEffectArguments[0] |= flag; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + return FALSE; +} + +void sub_8088120(u8 taskId) +{ + gUnknown_0839F3AC[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_8088150(struct Task *task) +{ + task->data[11] = REG_WININ; + task->data[12] = REG_WINOUT; + StoreWordInTwoHalfwords(&task->data[13], (u32)gMain.vblankCallback); + task->data[1] = 0xf0f1; + task->data[2] = 0x5051; + task->data[3] = 0x3f; + task->data[4] = 0x3e; + REG_WIN0H = task->data[1]; + REG_WIN0V = task->data[2]; + REG_WININ = task->data[3]; + REG_WINOUT = task->data[4]; + SetVBlankCallback(sub_80883DC); + task->data[0]++; +} + +void sub_80881C0(struct Task *task) +{ + u16 offset; + u16 delta; + offset = ((REG_BG0CNT >> 2) << 14); + delta = ((REG_BG0CNT >> 8) << 11); + CpuCopy16(gFieldMoveStreaksTiles, (void *)(VRAM + offset), 0x200); + CpuFill32(0, (void *)(VRAM + delta), 0x800); + LoadPalette(gFieldMoveStreaksPalette, 0xf0, 0x20); + sub_808843C(delta); + task->data[0]++; +} + +void sub_8088228(struct Task *task) +{ + s16 v0; + s16 v2; + s16 v3; + task->data[5] -= 16; + v0 = ((u16)task->data[1] >> 8); + v2 = ((u16)task->data[2] >> 8); + v3 = ((u16)task->data[2] & 0xff); + v0 -= 16; + v2 -= 2; + v3 += 2; + if (v0 < 0) + { + v0 = 0; + } + if (v2 < 0x28) + { + v2 = 0x28; + } + if (v3 > 0x78) + { + v3 = 0x78; + } + task->data[1] = (v0 << 8) | (task->data[1] & 0xff); + task->data[2] = (v2 << 8) | v3; + if (v0 == 0 && v2 == 0x28 && v3 == 0x78) + { + gSprites[task->data[15]].callback = sub_8088890; + task->data[0]++; + } +} + +void sub_80882B4(struct Task *task) +{ + task->data[5] -= 16; + if (gSprites[task->data[15]].data7) + { + task->data[0]++; + } +} + +void sub_80882E4(struct Task *task) +{ + s16 v2; + s16 v3; + task->data[5] -= 16; + v2 = (task->data[2] >> 8); + v3 = (task->data[2] & 0xff); + v2 += 6; + v3 -= 6; + if (v2 > 0x50) + { + v2 = 0x50; + } + if (v3 < 0x51) + { + v3 = 0x51; + } + task->data[2] = (v2 << 8) | v3; + if (v2 == 0x50 && v3 == 0x51) + { + task->data[0]++; + } +} + +void sub_8088338(struct Task *task) +{ + u16 bg0cnt; + bg0cnt = (REG_BG0CNT >> 8) << 11; + CpuFill32(0, (void *)VRAM + bg0cnt, 0x800); + task->data[1] = 0xf1; + task->data[2] = 0xa1; + task->data[3] = task->data[11]; + task->data[4] = task->data[12]; + task->data[0]++; +} + +void sub_8088380(struct Task *task) +{ + IntrCallback callback; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&callback); + SetVBlankCallback(callback); + SetUpWindowConfig(&gWindowConfig_81E6CE4); + InitMenuWindow(&gWindowConfig_81E6CE4); + FreeResourcesAndDestroySprite(&gSprites[task->data[15]]); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON); + DestroyTask(FindTaskIdByFunc(sub_8088120)); +} + +void sub_80883DC(void) +{ + struct Task *task; + IntrCallback callback; + task = &gTasks[FindTaskIdByFunc(sub_8088120)]; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&callback); + callback(); + REG_WIN0H = task->data[1]; + REG_WIN0V = task->data[2]; + REG_WININ = task->data[3]; + REG_WINOUT = task->data[4]; + REG_BG0HOFS = task->data[5]; + REG_BG0VOFS = task->data[6]; +} + +void sub_808843C(u16 offs) +{ + u16 i; + u16 *dest; + dest = (u16 *)(VRAM + 0x140 + offs); + for (i=0; i<0x140; i++, dest++) + { + *dest = gFieldMoveStreaksTilemap[i] | 0xf000; + } +} + +void sub_80886B0(void); +bool8 sub_8088708(struct Task *); +void sub_80886F8(struct Task *); +bool8 sub_80887C0(struct Task *); + +void sub_808847C(u8 taskId) +{ + gUnknown_0839F3C8[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80884AC(struct Task *task) +{ + REG_BG0HOFS = task->data[1]; + REG_BG0VOFS = task->data[2]; + StoreWordInTwoHalfwords((u16 *)&task->data[13], (u32)gMain.vblankCallback); + SetVBlankCallback(sub_80886B0); + task->data[0]++; +} + +void sub_80884E8(struct Task *task) +{ + u16 offset; + u16 delta; + offset = ((REG_BG0CNT >> 2) << 14); + delta = ((REG_BG0CNT >> 8) << 11); + task->data[12] = delta; + CpuCopy16(gDarknessFieldMoveStreaksTiles, (void *)(VRAM + offset), 0x80); + CpuFill32(0, (void *)(VRAM + delta), 0x800); + LoadPalette(gDarknessFieldMoveStreaksPalette, 0xf0, 0x20); + task->data[0]++; +} + +void sub_8088554(struct Task *task) +{ + if (sub_8088708(task)) + { + REG_WIN1H = 0x00f0; + REG_WIN1V = 0x2878; + gSprites[task->data[15]].callback = sub_8088890; + task->data[0]++; + } + sub_80886F8(task); +} + +void sub_80885A8(struct Task *task) +{ + sub_80886F8(task); + if (gSprites[task->data[15]].data7) + { + task->data[0]++; + } +} + +void sub_80885D8(struct Task *task) +{ + sub_80886F8(task); + task->data[3] = task->data[1] & 7; + task->data[4] = 0; + REG_WIN1H = 0xffff; + REG_WIN1V = 0xffff; + task->data[0]++; +} + +void sub_808860C(struct Task *task) +{ + sub_80886F8(task); + if (sub_80887C0(task)) + { + task->data[0]++; + } +} + +void sub_808862C(struct Task *task) +{ + IntrCallback intrCallback; + u16 bg0cnt; + bg0cnt = (REG_BG0CNT >> 8) << 11; + CpuFill32(0, (void *)VRAM + bg0cnt, 0x800); + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&intrCallback); + SetVBlankCallback(intrCallback); + SetUpWindowConfig(&gWindowConfig_81E6CE4); + InitMenuWindow(&gWindowConfig_81E6CE4); + FreeResourcesAndDestroySprite(&gSprites[task->data[15]]); + FieldEffectActiveListRemove(FLDEFF_FIELD_MOVE_SHOW_MON); + DestroyTask(FindTaskIdByFunc(sub_808847C)); +} + +void sub_80886B0(void) +{ + IntrCallback intrCallback; + struct Task *task; + task = &gTasks[FindTaskIdByFunc(sub_808847C)]; + LoadWordFromTwoHalfwords((u16 *)&task->data[13], (u32 *)&intrCallback); + intrCallback(); + REG_BG0HOFS = task->data[1]; + REG_BG0VOFS = task->data[2]; +} + +void sub_80886F8(struct Task *task) +{ + task->data[1] -= 16; + task->data[3] += 16; +} + +#ifdef NONMATCHING +bool8 sub_8088708(struct Task *task) +{ + u16 i; + u16 srcOffs; + u16 dstOffs; + u16 *dest; + if (task->data[4] >= 32) + { + return TRUE; + } + dstOffs = (task->data[3] >> 3) & 0x1f; + if (dstOffs >= task->data[4]) + { + dstOffs = (32 - dstOffs) & 0x1f; + srcOffs = (32 - task->data[4]) & 0x1f; + dest = (u16 *)(VRAM + 0x140 + (u16)task->data[12]); + for (i=0; i<10; i++) + { + dest[dstOffs + i * 32] = gDarknessFieldMoveStreaksTilemap[srcOffs + i * 32] | 0xf000; + dest[((dstOffs + 1) & 0x1f) + i * 32] = gDarknessFieldMoveStreaksTilemap[((srcOffs + 1) & 0x1f) + i * 32] | 0xf000; + } + task->data[4] += 2; + } + return FALSE; +} +#else +__attribute__((naked)) +bool8 sub_8088708(struct Task *task) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r10\n" + "\tmov r6, r9\n" + "\tmov r5, r8\n" + "\tpush {r5-r7}\n" + "\tsub sp, 0x4\n" + "\tadds r5, r0, 0\n" + "\tldrh r2, [r5, 0x10]\n" + "\tmovs r1, 0x10\n" + "\tldrsh r0, [r5, r1]\n" + "\tcmp r0, 0x1F\n" + "\tble _08088724\n" + "\tmovs r0, 0x1\n" + "\tb _080887A8\n" + "_08088724:\n" + "\tldrh r0, [r5, 0xE]\n" + "\tlsls r0, 16\n" + "\tasrs r3, r0, 19\n" + "\tmovs r1, 0x1F\n" + "\tands r3, r1\n" + "\tmovs r4, 0x10\n" + "\tldrsh r0, [r5, r4]\n" + "\tcmp r3, r0\n" + "\tblt _080887A6\n" + "\tmovs r0, 0x20\n" + "\tsubs r3, r0, r3\n" + "\tands r3, r1\n" + "\tsubs r0, r2\n" + "\tmov r12, r0\n" + "\tmov r7, r12\n" + "\tands r7, r1\n" + "\tmov r12, r7\n" + "\tldrh r0, [r5, 0x20]\n" + "\tldr r1, _080887B8 @ =0x06000140\n" + "\tadds r1, r0\n" + "\tmov r8, r1\n" + "\tmovs r4, 0\n" + "\tldr r7, _080887BC @ =gDarknessFieldMoveStreaksTilemap\n" + "\tmov r10, r7\n" + "\tmovs r0, 0xF0\n" + "\tlsls r0, 8\n" + "\tmov r9, r0\n" + "\tadds r1, r3, 0x1\n" + "\tmovs r0, 0x1F\n" + "\tands r1, r0\n" + "\tstr r1, [sp]\n" + "\tmov r6, r12\n" + "\tadds r6, 0x1\n" + "\tands r6, r0\n" + "_08088768:\n" + "\tlsls r1, r4, 5\n" + "\tadds r2, r1, r3\n" + "\tlsls r2, 1\n" + "\tadd r2, r8\n" + "\tmov r7, r12\n" + "\tadds r0, r7, r1\n" + "\tlsls r0, 1\n" + "\tadd r0, r10\n" + "\tldrh r0, [r0]\n" + "\tmov r7, r9\n" + "\torrs r0, r7\n" + "\tstrh r0, [r2]\n" + "\tldr r0, [sp]\n" + "\tadds r2, r1, r0\n" + "\tlsls r2, 1\n" + "\tadd r2, r8\n" + "\tadds r1, r6, r1\n" + "\tlsls r1, 1\n" + "\tadd r1, r10\n" + "\tldrh r0, [r1]\n" + "\tmov r1, r9\n" + "\torrs r0, r1\n" + "\tstrh r0, [r2]\n" + "\tadds r0, r4, 0x1\n" + "\tlsls r0, 16\n" + "\tlsrs r4, r0, 16\n" + "\tcmp r4, 0x9\n" + "\tbls _08088768\n" + "\tldrh r0, [r5, 0x10]\n" + "\tadds r0, 0x2\n" + "\tstrh r0, [r5, 0x10]\n" + "_080887A6:\n" + "\tmovs r0, 0\n" + "_080887A8:\n" + "\tadd sp, 0x4\n" + "\tpop {r3-r5}\n" + "\tmov r8, r3\n" + "\tmov r9, r4\n" + "\tmov r10, r5\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1\n" + "\t.align 2, 0\n" + "_080887B8: .4byte 0x06000140\n" + "_080887BC: .4byte gDarknessFieldMoveStreaksTilemap"); +} +#endif + +bool8 sub_80887C0(struct Task *task) +{ + u16 i; + u16 dstOffs; + u16 *dest; + if (task->data[4] >= 32) + { + return TRUE; + } + dstOffs = task->data[3] >> 3; + if (dstOffs >= task->data[4]) + { + dstOffs = (task->data[1] >> 3) & 0x1f; + dest = (u16 *)(VRAM + 0x140 + (u16)task->data[12]); + for (i=0; i<10; i++) + { + dest[dstOffs + i * 32] = 0xf000; + dest[((dstOffs + 1) & 0x1f) + i * 32] = 0xf000; + } + task->data[4] += 2; + } + return FALSE; +} + +u8 sub_8088830(u32 a0, u32 a1, u32 a2) +{ + u16 v0; + u8 monSprite; + struct Sprite *sprite; + v0 = (a0 & 0x80000000) >> 16; + a0 &= 0x7fffffff; + monSprite = CreateMonSprite_FieldMove(a0, a1, a2, 0x140, 0x50, 0); + sprite = &gSprites[monSprite]; + sprite->callback = SpriteCallbackDummy; + sprite->oam.priority = 0; + sprite->data0 = a0; + sprite->data6 = v0; + return monSprite; +} + +void sub_80888D4(struct Sprite *); + +void sub_8088890(struct Sprite *sprite) +{ + if ((sprite->pos1.x -= 20) <= 0x78) + { + sprite->pos1.x = 0x78; + sprite->data1 = 30; + sprite->callback = sub_80888D4; + if (sprite->data6) + { + PlayCry2(sprite->data0, 0, 0x7d, 0xa); + } else + { + PlayCry1(sprite->data0, 0); + } + } +} + +void sub_80888F0(struct Sprite *); + +void sub_80888D4(struct Sprite *sprite) +{ + if ((--sprite->data1) == 0) + { + sprite->callback = sub_80888F0; + } +} + +void sub_80888F0(struct Sprite *sprite) +{ + if (sprite->pos1.x < -0x40) + { + sprite->data7 = 1; + } else + { + sprite->pos1.x -= 20; + } +} + +void sub_8088954(u8); + +u8 FldEff_UseSurf(void) +{ + u8 taskId; + taskId = CreateTask(sub_8088954, 0xff); + gTasks[taskId].data[15] = gFieldEffectArguments[0]; + Overworld_ClearSavedMusic(); + Overworld_ChangeMusicTo(0x016d); + return FALSE; +} + +void sub_8088954(u8 taskId) +{ + gUnknown_0839F3E4[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_8088984(struct Task *task) +{ + ScriptContext2_Enable(); + FreezeMapObjects(); + gPlayerAvatar.unk6 = 1; + SetPlayerAvatarStateMask(8); + PlayerGetDestCoords(&task->data[1], &task->data[2]); + MoveCoords(gMapObjects[gPlayerAvatar.mapObjectId].placeholder18, &task->data[1], &task->data[2]); + task->data[0]++; +} + +void sub_80889E4(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + sub_8059BF4(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_8088A30(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(mapObject)) + { + gFieldEffectArguments[0] = task->data[15] | 0x80000000; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + task->data[0]++; + } +} + +void sub_8088A78(struct Task *task) +{ + struct MapObject *mapObject; + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sub_805B980(mapObject, GetPlayerAvatarGraphicsIdByStateId(3)); + FieldObjectClearAnimIfSpecialAnimFinished(mapObject); + FieldObjectSetSpecialAnim(mapObject, sub_80608D0(mapObject->placeholder18)); + gFieldEffectArguments[0] = task->data[1]; + gFieldEffectArguments[1] = task->data[2]; + gFieldEffectArguments[2] = gPlayerAvatar.mapObjectId; + mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_SURF_BLOB); + task->data[0]++; + } +} + +void sub_8088AF4(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + gPlayerAvatar.unk6 = 0; + gPlayerAvatar.flags &= 0xdf; + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(mapObject->placeholder18)); + sub_8127ED0(mapObject->mapobj_unk_1A, 1); + UnfreezeMapObjects(); + ScriptContext2_Disable(); + FieldEffectActiveListRemove(FLDEFF_USE_SURF); + DestroyTask(FindTaskIdByFunc(sub_8088954)); + } +} + +void sub_8088BC4(struct Sprite *); + +u8 FldEff_NPCFlyOut(void) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateSprite(gFieldEffectObjectTemplatePointers[26], 0x78, 0, 1); + sprite = &gSprites[spriteId]; + sprite->oam.paletteNum = 0; + sprite->oam.priority = 1; + sprite->callback = sub_8088BC4; + sprite->data1 = gFieldEffectArguments[0]; + PlaySE(SE_W019); + return spriteId; +} + +void sub_8088BC4(struct Sprite *sprite) +{ + struct Sprite *npcSprite; + sprite->pos2.x = Cos(sprite->data2, 0x8c); + sprite->pos2.y = Sin(sprite->data2, 0x48); + sprite->data2 = (sprite->data2 + 4) & 0xff; + if (sprite->data0) + { + npcSprite = &gSprites[sprite->data1]; + npcSprite->coordOffsetEnabled = 0; + npcSprite->pos1.x = sprite->pos1.x + sprite->pos2.x; + npcSprite->pos1.y = sprite->pos1.y + sprite->pos2.y - 8; + npcSprite->pos2.x = 0; + npcSprite->pos2.y = 0; + } + if (sprite->data2 >= 0x80) + { + FieldEffectStop(sprite, FLDEFF_NPCFLY_OUT); + } +} + +void sub_8088C70(u8); +extern void sub_8127EFC(u8, u8); +u8 sub_8088F60(void); +bool8 sub_8088FA4(u8); +void sub_8088FC0(u8); +void sub_8088FFC(u8, u8); +void sub_8089018(struct Sprite *); +void sub_80890D8(struct Sprite *); + +u8 FldEff_UseFly(void) +{ + u8 taskId; + taskId = CreateTask(sub_8088C70, 0xfe); + gTasks[taskId].data[1] = gFieldEffectArguments[0]; + return 0; +} + +void sub_8088C70(u8 taskId) +{ + gUnknown_0839F3F8[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_8088CA0(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[15] = gPlayerAvatar.flags; + gPlayerAvatar.unk6 = 0x01; + SetPlayerAvatarStateMask(1); + sub_8059BF4(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_8088CF8(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + gFieldEffectArguments[0] = task->data[1]; + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + } +} + +void sub_8088D3C(struct Task *task) +{ + struct MapObject *mapObject; + if (!FieldEffectActiveListContains(FLDEFF_FIELD_MOVE_SHOW_MON)) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (task->data[15] & 0x08) + { + sub_8127ED0(mapObject->mapobj_unk_1A, 2); + sub_8127EFC(mapObject->mapobj_unk_1A, 0); + } + task->data[1] = sub_8088F60(); + task->data[0]++; + } +} + +void sub_8088D94(struct Task *task) +{ + if (sub_8088FA4(task->data[1])) + { + task->data[0]++; + task->data[2] = 16; + SetPlayerAvatarTransitionFlags(0x01); + FieldObjectSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], 0x02); + } +} + +void sub_8088DD8(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if ((task->data[2] == 0 || (--task->data[2]) == 0) && FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + PlaySE(SE_W019); + sub_8088FC0(task->data[1]); + } +} + +void sub_8088E2C(struct Task *task) +{ + struct MapObject *mapObject; + if ((++task->data[2]) >= 8) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sub_805B980(mapObject, GetPlayerAvatarGraphicsIdByStateId(0x03)); + StartSpriteAnim(&gSprites[mapObject->spriteId], 0x16); + mapObject->mapobj_bit_12 = 1; + FieldObjectSetSpecialAnim(mapObject, 0x48); + if (task->data[15] & 0x08) + { + DestroySprite(&gSprites[mapObject->mapobj_unk_1A]); + } + task->data[0]++; + task->data[2] = 0; + } +} + +void sub_8088EB4(struct Task *task) +{ + struct MapObject *mapObject; + if ((++task->data[2]) >= 10) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectClearAnimIfSpecialAnimActive(mapObject); + mapObject->mapobj_bit_12 = 0; + mapObject->mapobj_bit_22 = 0; + sub_8088FFC(task->data[1], mapObject->spriteId); + CameraObjectReset2(); + task->data[0]++; + } +} + +void sub_8088F10(struct Task *task) +{ + if (sub_8088FA4(task->data[1])) + { + fade_8080918(); + task->data[0]++; + } +} + +void sub_8088F30(struct Task *task) +{ + if (!gPaletteFade.active) + { + FieldEffectActiveListRemove(FLDEFF_USE_FLY); + DestroyTask(FindTaskIdByFunc(sub_8088C70)); + } +} + +u8 sub_8088F60(void) +{ + u8 spriteId; + struct Sprite *sprite; + spriteId = CreateSprite(gFieldEffectObjectTemplatePointers[26], 0xff, 0xb4, 0x1); + sprite = &gSprites[spriteId]; + sprite->oam.paletteNum = 0; + sprite->oam.priority = 1; + sprite->callback = sub_8089018; + return spriteId; +} + +u8 sub_8088FA4(u8 spriteId) +{ + return gSprites[spriteId].data7; +} + +void sub_8088FC0(u8 spriteId) +{ + struct Sprite *sprite; + sprite = &gSprites[spriteId]; + sprite->callback = sub_80890D8; + sprite->pos1.x = 0x78; + sprite->pos1.y = 0x00; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + memset(&sprite->data0, 0, 8 * sizeof(u16) /* zero all data cells */); + sprite->data6 = 0x40; +} + +void sub_8088FFC(u8 a0, u8 a1) +{ + gSprites[a0].data6 = a1; +} + +void sub_8089018(struct Sprite *sprite) +{ + if (sprite->data7 == 0) + { + if (sprite->data0 == 0) + { + sprite->oam.affineMode = 3; + sprite->affineAnims = gSpriteAffineAnimTable_0839F44C; + InitSpriteAffineAnim(sprite); + StartSpriteAffineAnim(sprite, 0); + sprite->pos1.x = 0x76; + sprite->pos1.y = -0x30; + sprite->data0++; + sprite->data1 = 0x40; + sprite->data2 = 0x100; + } + sprite->data1 += (sprite->data2 >> 8); + sprite->pos2.x = Cos(sprite->data1, 0x78); + sprite->pos2.y = Sin(sprite->data1, 0x78); + if (sprite->data2 < 0x800) + { + sprite->data2 += 0x60; + } + if (sprite->data1 > 0x81) + { + sprite->data7++; + sprite->oam.affineMode = 0; + FreeOamMatrix(sprite->oam.matrixNum); + CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, 0); + } + } +} + +void sub_80890D8(struct Sprite *sprite) +{ + struct Sprite *sprite1; + sprite->pos2.x = Cos(sprite->data2, 0x8c); + sprite->pos2.y = Sin(sprite->data2, 0x48); + sprite->data2 = (sprite->data2 + 4) & 0xff; + if (sprite->data6 != 0x40) + { + sprite1 = &gSprites[sprite->data6]; + sprite1->coordOffsetEnabled = 0; + sprite1->pos1.x = sprite->pos1.x + sprite->pos2.x; + sprite1->pos1.y = sprite->pos1.y + sprite->pos2.y - 8; + sprite1->pos2.x = 0; + sprite1->pos2.y = 0; + } + if (sprite->data2 >= 0x80) + { + sprite->data7 = 1; + } +} + +void sub_808914C(struct Sprite *sprite) +{ + if (sprite->data7 == 0) + { + if (sprite->data0 == 0) + { + sprite->oam.affineMode = 3; + sprite->affineAnims = gSpriteAffineAnimTable_0839F44C; + InitSpriteAffineAnim(sprite); + StartSpriteAffineAnim(sprite, 1); + sprite->pos1.x = 0x5e; + sprite->pos1.y = -0x20; + sprite->data0++; + sprite->data1 = 0xf0; + sprite->data2 = 0x800; + sprite->data4 = 0x80; + } + sprite->data1 += sprite->data2 >> 8; + sprite->data3 += sprite->data2 >> 8; + sprite->data1 &= 0xff; + sprite->pos2.x = Cos(sprite->data1, 0x20); + sprite->pos2.y = Sin(sprite->data1, 0x78); + if (sprite->data2 > 0x100) + { + sprite->data2 -= sprite->data4; + } + if (sprite->data4 < 0x100) + { + sprite->data4 += 24; + } + if (sprite->data2 < 0x100) + { + sprite->data2 = 0x100; + } + if (sprite->data3 >= 60) + { + sprite->data7++; + sprite->oam.affineMode = 0; + FreeOamMatrix(sprite->oam.matrixNum); + sprite->invisible = 1; + } + } +} + +void sub_8089230(u8 spriteId) +{ + sub_8088FC0(spriteId); + gSprites[spriteId].callback = sub_808914C; +} + +void sub_8089270(u8); + +u8 FldEff_FlyIn(void) +{ + CreateTask(sub_8089270, 0xfe); + return 0; +} + +void sub_8089270(u8 taskId) +{ + gUnknown_0839F454[gTasks[taskId].data[0]](&gTasks[taskId]); +} + +void sub_80892A0(struct Task *task) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject) || FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + task->data[0]++; + task->data[2] = 17; + task->data[15] = gPlayerAvatar.flags; + gPlayerAvatar.unk6 = 1; + SetPlayerAvatarStateMask(0x01); + if (task->data[15] & 0x08) + { + sub_8127ED0(mapObject->mapobj_unk_1A, 0); + } + sub_805B980(mapObject, GetPlayerAvatarGraphicsIdByStateId(0x3)); + CameraObjectReset2(); + FieldObjectTurn(mapObject, DIR_WEST); + StartSpriteAnim(&gSprites[mapObject->spriteId], 0x16); + mapObject->mapobj_bit_13 = 0; + task->data[1] = sub_8088F60(); + sub_8088FC0(task->data[1]); + sub_8088FFC(task->data[1], mapObject->spriteId); + } +} + +void sub_8089354(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + if (task->data[2] == 0 || (--task->data[2]) == 0) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[mapObject->spriteId]; + sub_8088FFC(task->data[1], 0x40); + sprite->pos1.x += sprite->pos2.x; + sprite->pos1.y += sprite->pos2.y; + sprite->pos2.x = 0; + sprite->pos2.y = 0; + task->data[0]++; + task->data[2] = 0; + } +} + +void sub_80893C0(struct Task *task) +{ + s16 unknown_0839F470[18]; + struct Sprite *sprite; + memcpy(unknown_0839F470, gUnknown_0839F470, sizeof gUnknown_0839F470); + sprite = &gSprites[gPlayerAvatar.spriteId]; + sprite->pos2.y = unknown_0839F470[task->data[2]]; + if ((++task->data[2]) >= 18) + { + task->data[0]++; + } +} + +void sub_8089414(struct Task *task) +{ + struct MapObject *mapObject; + struct Sprite *sprite; + if (sub_8088FA4(task->data[1])) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + sprite = &gSprites[mapObject->spriteId]; + mapObject->mapobj_bit_12 = 0; + sub_805C058(mapObject, mapObject->coords2.x, mapObject->coords2.y); + sprite->pos2.x = 0; + sprite->pos2.y = 0; + sprite->coordOffsetEnabled = 1; + sub_8059BF4(); + FieldObjectSetSpecialAnim(mapObject, 0x39); + task->data[0]++; + } +} + +void sub_808948C(struct Task *task) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gPlayerAvatar.mapObjectId])) + { + task->data[0]++; + sub_8089230(task->data[1]); + } +} + +void sub_80894C4(struct Task *task) +{ + if (sub_8088FA4(task->data[1])) + { + DestroySprite(&gSprites[task->data[1]]); + task->data[0]++; + task->data[1] = 0x10; + } +} + +void fishE(struct Task *task) +{ + u8 state; + struct MapObject *mapObject; + if ((--task->data[1]) == 0) + { + mapObject = &gMapObjects[gPlayerAvatar.mapObjectId]; + state = 0; + if (task->data[15] & 0x08) + { + state = 3; + sub_8127ED0(mapObject->mapobj_unk_1A, 1); + } + sub_805B980(mapObject, GetPlayerAvatarGraphicsIdByStateId(state)); + FieldObjectTurn(mapObject, DIR_SOUTH); + gPlayerAvatar.flags = task->data[15]; + gPlayerAvatar.unk6 = 0; + FieldEffectActiveListRemove(FLDEFF_FLY_IN); + DestroyTask(FindTaskIdByFunc(sub_8089270)); + } +} diff --git a/src/field/field_effect_helpers.c b/src/field/field_effect_helpers.c new file mode 100644 index 000000000..2ad8bdce3 --- /dev/null +++ b/src/field/field_effect_helpers.c @@ -0,0 +1,1632 @@ +#include "global.h" +#include "sprite.h" +#include "fieldmap.h" +#include "metatile_behavior.h" +#include "songs.h" +#include "sound.h" +#include "field_map_obj.h" +#include "field_camera.h" +#include "field_map_obj_helpers.h" +#include "field_weather.h" +#include "field_effect.h" +#include "field_ground_effect.h" +#include "field_effect_helpers.h" + +static void sub_81269E0(struct Sprite *); +static void npc_pal_op(struct MapObject *mapObject, struct Sprite *sprite); +static void npc_pal_op_A(struct MapObject *, u8); +static void npc_pal_op_B(struct MapObject *, u8); +static void sub_81275A0(struct Sprite *); +static void sub_81275C4(struct Sprite *); +static void sub_8127DA0(struct Sprite *); +static void sub_8127DD0(struct Sprite *); +static void sub_8127E30(struct Sprite *); +static void sub_812882C(struct Sprite *, u8, u8); +static void sub_81278D8(struct Sprite *); +static void sub_8127FD4(struct MapObject *, struct Sprite *); +static void sub_812800C(struct MapObject *, struct Sprite *); +static void sub_81280A0(struct MapObject *, struct Sprite *, struct Sprite *); +static void sub_8128174(struct Sprite *); +static u32 ShowDisguiseFieldEffect(u8, u8, u8); + +const u8 UnusedEggString_8401E28[] = _("タマゴ"); + +const u16 gUnknown_08401E2C[] = { + 0x0c, + 0x1c, + 0x2c +}; + +const u8 gUnknown_08401E32[] = { + 0, + 1, + 2, + 3 +}; + +const u16 gUnknown_08401E36[] = { + 4, + 4, + 4, + 16 +}; + +void (*const gUnknown_08401E40[])(struct Sprite *) = { + sub_81275A0, + sub_81275C4 +}; + +void (*const gUnknown_08401E48[])(struct Sprite *) = { + sub_8127DA0, + sub_8127DD0, + sub_8127E30 +}; + +const u8 gUnknown_08401E54[] = { + 0, + 0, + 1, + 2, + 3 +}; + +const u16 gUnknown_08401E5A[] = { + 3, + 7 +}; + +void SetUpReflection(struct MapObject *mapObject, struct Sprite *sprite, bool8 flag) +{ + struct Sprite *newSprite; + + newSprite = &gSprites[obj_unfreeze(sprite, sprite->pos1.x, sprite->pos1.y, 0x98)]; + newSprite->callback = sub_81269E0; + newSprite->oam.priority = 3; + newSprite->oam.paletteNum = gUnknown_0830FD14[newSprite->oam.paletteNum]; + newSprite->usingSheet = TRUE; + newSprite->anims = gDummySpriteAnimTable; + StartSpriteAnim(newSprite, 0); + newSprite->affineAnims = gDummySpriteAffineAnimTable; + newSprite->affineAnimBeginning = TRUE; + newSprite->subspriteMode = 0; + newSprite->data0 = sprite->data0; + newSprite->data1 = mapObject->localId; + newSprite->data7 = flag; + npc_pal_op(mapObject, newSprite); + if (!flag) + { + newSprite->oam.affineMode = 1; + } +} + +static s16 sub_81268D0(struct MapObject *mapObject) +{ + return GetFieldObjectGraphicsInfo(mapObject->graphicsId)->height - 2; +} + +static void npc_pal_op(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 whichElement; + u16 unk_8041e2c[ARRAY_COUNT(gUnknown_08401E2C)]; + + memcpy(unk_8041e2c, gUnknown_08401E2C, sizeof gUnknown_08401E2C); + sprite->data2 = 0; + if (!GetFieldObjectGraphicsInfo(mapObject->graphicsId)->disableReflectionPaletteLoad && ((whichElement = sub_8057450(mapObject->mapobj_unk_1F)) || (whichElement = sub_8057450(mapObject->mapobj_unk_1E)))) + { + sprite->data2 = unk_8041e2c[whichElement - 1]; + npc_pal_op_A(mapObject, sprite->oam.paletteNum); + } + else + { + npc_pal_op_B(mapObject, sprite->oam.paletteNum); + } +} + +static void npc_pal_op_B(struct MapObject *mapObject, u8 paletteNum) +{ + const struct MapObjectGraphicsInfo *graphicsInfo; + + graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + if (graphicsInfo->paletteTag2 != 0x11ff) + { + if (graphicsInfo->paletteSlot == 0) + { + npc_load_two_palettes__no_record(graphicsInfo->paletteTag1, paletteNum); + } + else if (graphicsInfo->paletteSlot == 10) + { + npc_load_two_palettes__and_record(graphicsInfo->paletteTag1, paletteNum); + } + else + { + pal_patch_for_npc(npc_paltag_by_palslot(paletteNum), paletteNum); + } + sub_807D78C(paletteNum); + } +} + +static void npc_pal_op_A(struct MapObject *mapObject, u8 paletteNum) +{ + const struct MapObjectGraphicsInfo *graphicsInfo; + + graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + if (graphicsInfo->paletteTag2 != 0x11ff) + { + pal_patch_for_npc(graphicsInfo->paletteTag2, paletteNum); + sub_807D78C(paletteNum); + } +} + +static void sub_81269E0(struct Sprite *sprite) +{ + struct MapObject *mapObject; + struct Sprite *oldSprite; + + mapObject = &gMapObjects[sprite->data0]; + oldSprite = &gSprites[mapObject->spriteId]; + if (!mapObject->active || !mapObject->mapobj_bit_17 || mapObject->localId != sprite->data1) + { + sprite->inUse = FALSE; + } + else + { + sprite->oam.paletteNum = gUnknown_0830FD14[oldSprite->oam.paletteNum]; + sprite->oam.shape = oldSprite->oam.shape; + sprite->oam.size = oldSprite->oam.size; + sprite->oam.matrixNum = oldSprite->oam.matrixNum | 0x10; + sprite->oam.tileNum = oldSprite->oam.tileNum; + sprite->subspriteTables = oldSprite->subspriteTables; + sprite->subspriteTableNum = oldSprite->subspriteTableNum; + sprite->invisible = oldSprite->invisible; + sprite->pos1.x = oldSprite->pos1.x; + sprite->pos1.y = oldSprite->pos1.y + sub_81268D0(mapObject) + sprite->data2; + sprite->centerToCornerVecX = oldSprite->centerToCornerVecX; + sprite->centerToCornerVecY = oldSprite->centerToCornerVecY; + sprite->pos2.x = oldSprite->pos2.x; + sprite->pos2.y = -oldSprite->pos2.y; + sprite->coordOffsetEnabled = oldSprite->coordOffsetEnabled; + if (sprite->data7 == FALSE) + { + sprite->oam.matrixNum = 0; + if (oldSprite->oam.matrixNum & 0x8) + { + sprite->oam.matrixNum = 1; + } + } + } +} + +u8 sub_8126B54(void) +{ + u8 spriteId; + struct Sprite *sprite; + + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[8] /*gFieldEffectSpriteTemplate_Arrow*/, 0, 0, 0x52); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->oam.priority = 1; + sprite->coordOffsetEnabled = TRUE; + sprite->invisible = TRUE; + } + return spriteId; +} + +void objid_set_invisible(u8 spriteId) +{ + gSprites[spriteId].invisible = TRUE; +} + +void sub_8126BC4(u8 spriteId, u8 animNum, s16 x, s16 y) +{ + s16 x2; + s16 y2; + struct Sprite *sprite; + + sprite = &gSprites[spriteId]; + if (sprite->invisible || sprite->data0 != x || sprite->data1 != y) + { + sub_80603CC(x, y, &x2, &y2); + sprite = &gSprites[spriteId]; + sprite->pos1.x = x2 + 8; + sprite->pos1.y = y2 + 8; + sprite->invisible = FALSE; + sprite->data0 = x; + sprite->data1 = y; + StartSpriteAnim(sprite, animNum - 1); + } +} + +u32 FldEff_Shadow(void) +{ + u8 mapObjectId; + const struct MapObjectGraphicsInfo *graphicsInfo; + u8 spriteId; + + mapObjectId = GetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + graphicsInfo = GetFieldObjectGraphicsInfo(gMapObjects[mapObjectId].graphicsId); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[gUnknown_08401E32[graphicsInfo->shadowSize]], 0, 0, 0x94); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].coordOffsetEnabled = TRUE; + gSprites[spriteId].data0 = gFieldEffectArguments[0]; + gSprites[spriteId].data1 = gFieldEffectArguments[1]; + gSprites[spriteId].data2 = gFieldEffectArguments[2]; + gSprites[spriteId].data3 = (graphicsInfo->height >> 1) - gUnknown_08401E36[graphicsInfo->shadowSize]; + } + return 0; +} + +void oamc_shadow(struct Sprite *sprite) +{ + u8 mapObjectId; + struct MapObject *mapObject; + struct Sprite *linkedSprite; + + if (TryGetFieldObjectIdByLocalIdAndMap(sprite->data0, sprite->data1, sprite->data2, &mapObjectId)) + { + FieldEffectStop(sprite, FLDEFF_SHADOW); + } + else + { + mapObject = &gMapObjects[mapObjectId]; + linkedSprite = &gSprites[mapObject->spriteId]; + sprite->oam.priority = linkedSprite->oam.priority; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y + sprite->data3; + if (!mapObject->active || !mapObject->mapobj_bit_22 || MetatileBehavior_IsPokeGrass(mapObject->mapobj_unk_1E) || MetatileBehavior_IsSurfableWaterOrUnderwater(mapObject->mapobj_unk_1E) || MetatileBehavior_IsSurfableWaterOrUnderwater(mapObject->mapobj_unk_1F) || MetatileBehavior_IsReflective(mapObject->mapobj_unk_1E) || MetatileBehavior_IsReflective(mapObject->mapobj_unk_1F)) + { + FieldEffectStop(sprite, FLDEFF_SHADOW); + } + } +} + +u32 FldEff_TallGrass(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite *sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_8060470(&x, &y, 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[4], x, y, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = gFieldEffectArguments[2]; + sprite->data1 = gFieldEffectArguments[0]; + sprite->data2 = gFieldEffectArguments[1]; + sprite->data3 = gFieldEffectArguments[4]; + sprite->data4 = gFieldEffectArguments[5]; + sprite->data5 = gFieldEffectArguments[6]; + if (gFieldEffectArguments[7]) + { + SeekSpriteAnim(sprite, 4); + } + } + return 0; +} + +void unc_grass_normal(struct Sprite *sprite) +{ + u8 mapNum; + u8 mapGroup; + u8 metatileBehavior; + u8 localId; + u8 mapObjectId; + struct MapObject *mapObject; + + mapNum = sprite->data5 >> 8; + mapGroup = sprite->data5; + if (gCamera.field_0 && (gSaveBlock1.location.mapNum != mapNum || gSaveBlock1.location.mapGroup != mapGroup)) + { + sprite->data1 -= gCamera.x; + sprite->data2 -= gCamera.y; + sprite->data5 = ((u8)gSaveBlock1.location.mapNum << 8) | (u8)gSaveBlock1.location.mapGroup; + } + localId = sprite->data3 >> 8; + mapNum = sprite->data3; + mapGroup = sprite->data4; + metatileBehavior = MapGridGetMetatileBehaviorAt(sprite->data1, sprite->data2); + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId) || !MetatileBehavior_IsTallGrass(metatileBehavior) || (sprite->data7 && sprite->animEnded)) + { + FieldEffectStop(sprite, FLDEFF_TALL_GRASS); + } + else + { + mapObject = &gMapObjects[mapObjectId]; + if ((mapObject->coords2.x != sprite->data1 || mapObject->coords2.y != sprite->data2) && (mapObject->coords3.x != sprite->data1 || mapObject->coords3.y != sprite->data2)) + { + sprite->data7 = TRUE; + } + metatileBehavior = 0; + if (sprite->animCmdIndex == 0) + { + metatileBehavior = 4; + } + sub_806487C(sprite, 0); + sub_812882C(sprite, sprite->data0, metatileBehavior); + } +} + +u32 FldEff_JumpTallGrass(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[10], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = gFieldEffectArguments[2]; + sprite->data1 = 12; + } + return 0; +} + +u8 sub_8126FF0(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y) +{ + struct Sprite *sprite; + u8 i; + + for (i = 0; i < MAX_SPRITES; i ++) + { + if (gSprites[i].inUse) + { + sprite = &gSprites[i]; + if (sprite->callback == unc_grass_normal && (x == sprite->data1 && y == sprite->data2) && (localId == (u8)(sprite->data3 >> 8) && mapNum == (sprite->data3 & 0xFF) && mapGroup == sprite->data4)) + { + return i; + } + } + } + return MAX_SPRITES; +} + +u32 FldEff_LongGrass(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite *sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_8060470(&x, &y, 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[15], x, y, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = ZCoordToPriority(gFieldEffectArguments[2]); + sprite->data0 = gFieldEffectArguments[2]; + sprite->data1 = gFieldEffectArguments[0]; + sprite->data2 = gFieldEffectArguments[1]; + sprite->data3 = gFieldEffectArguments[4]; + sprite->data4 = gFieldEffectArguments[5]; + sprite->data5 = gFieldEffectArguments[6]; + if (gFieldEffectArguments[7]) + { + SeekSpriteAnim(sprite, 6); + } + } + return 0; +} + +void unc_grass_tall(struct Sprite *sprite) +{ + u8 mapNum; + u8 mapGroup; + u8 metatileBehavior; + u8 localId; + u8 mapObjectId; + struct MapObject *mapObject; + + mapNum = sprite->data5 >> 8; + mapGroup = sprite->data5; + if (gCamera.field_0 && (gSaveBlock1.location.mapNum != mapNum || gSaveBlock1.location.mapGroup != mapGroup)) + { + sprite->data1 -= gCamera.x; + sprite->data2 -= gCamera.y; + sprite->data5 = ((u8)gSaveBlock1.location.mapNum << 8) | (u8)gSaveBlock1.location.mapGroup; + } + localId = sprite->data3 >> 8; + mapNum = sprite->data3; + mapGroup = sprite->data4; + metatileBehavior = MapGridGetMetatileBehaviorAt(sprite->data1, sprite->data2); + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId) || !MetatileBehavior_IsLongGrass(metatileBehavior) || (sprite->data7 && sprite->animEnded)) + { + FieldEffectStop(sprite, FLDEFF_LONG_GRASS); + } + else + { + mapObject = &gMapObjects[mapObjectId]; + if ((mapObject->coords2.x != sprite->data1 || mapObject->coords2.y != sprite->data2) && (mapObject->coords3.x != sprite->data1 || mapObject->coords3.y != sprite->data2)) + { + sprite->data7 = TRUE; + } + sub_806487C(sprite, 0); + sub_812882C(sprite, sprite->data0, 0); + } +} + +u32 FldEff_JumpLongGrass(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[16], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = gFieldEffectArguments[2]; + sprite->data1 = 18; + } + return 0; +} + +u32 FldEff_ShortGrass(void) +{ + u8 mapObjectId; + struct MapObject *mapObject; + u8 spriteId; + struct Sprite *sprite; + + mapObjectId = GetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + mapObject = &gMapObjects[mapObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[30], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &(gSprites[spriteId]); + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[mapObject->spriteId].oam.priority; + sprite->data0 = gFieldEffectArguments[0]; + sprite->data1 = gFieldEffectArguments[1]; + sprite->data2 = gFieldEffectArguments[2]; + sprite->data3 = gSprites[mapObject->spriteId].pos1.x; + sprite->data4 = gSprites[mapObject->spriteId].pos1.y; + } + return 0; +} + +void sub_8127334(struct Sprite *sprite) +{ + u8 mapObjectId; + s16 x; + s16 y; + const struct MapObjectGraphicsInfo *graphicsInfo; + struct Sprite *linkedSprite; + + if (TryGetFieldObjectIdByLocalIdAndMap(sprite->data0, sprite->data1, sprite->data2, &mapObjectId) || !gMapObjects[mapObjectId].mapobj_bit_18) + { + FieldEffectStop(sprite, FLDEFF_SHORT_GRASS); + } + else + { + graphicsInfo = GetFieldObjectGraphicsInfo(gMapObjects[mapObjectId].graphicsId); + linkedSprite = &gSprites[gMapObjects[mapObjectId].spriteId]; + y = linkedSprite->pos1.y; + x = linkedSprite->pos1.x; + if (x != sprite->data3 || y != sprite->data4) + { + sprite->data3 = x; + sprite->data4 = y; + if (sprite->animEnded) + { + StartSpriteAnim(sprite, 0); + } + } + sprite->pos1.x = x; + sprite->pos1.y = y; + sprite->pos2.y = (graphicsInfo->height >> 1) - 8; + sprite->subpriority = linkedSprite->subpriority - 1; + sprite->oam.priority = linkedSprite->oam.priority; + sub_806487C(sprite, linkedSprite->invisible); + } +} + +u32 FldEff_SandFootprints(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[11], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data7 = FLDEFF_SAND_FOOTPRINTS; + StartSpriteAnim(sprite, gFieldEffectArguments[4]); + } + return 0; +} + +u32 FldEff_DeepSandFootprints(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[23], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data7 = FLDEFF_DEEP_SAND_FOOTPRINTS; + StartSpriteAnim(sprite, gFieldEffectArguments[4]); + } + return spriteId; +} + +u32 FldEff_BikeTireTracks(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[27], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data7 = FLDEFF_BIKE_TIRE_TRACKS; + StartSpriteAnim(sprite, gFieldEffectArguments[4]); + } + return spriteId; +} + +void sub_8127584(struct Sprite *sprite) +{ + gUnknown_08401E40[sprite->data0](sprite); +} + +static void sub_81275A0(struct Sprite *sprite) +{ + if (++sprite->data1 > 40) + { + sprite->data0 = 1; + } + sub_806487C(sprite, FALSE); +} + +static void sub_81275C4(struct Sprite *sprite) +{ + sprite->invisible ^= 1; + sprite->data1 ++; + sub_806487C(sprite, sprite->invisible); + if (sprite->data1 > 56) + { + FieldEffectStop(sprite, sprite->data7); + } +} + +u32 FldEff_Splash(void) +{ + u8 mapObjectId; + struct MapObject *mapObject; + u8 spriteId; + struct Sprite *sprite; + const struct MapObjectGraphicsInfo *graphicsInfo; + struct Sprite *linkedSprite; + + mapObjectId = GetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + mapObject = &gMapObjects[mapObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[13], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + linkedSprite = &gSprites[mapObject->spriteId]; + sprite->oam.priority = linkedSprite->oam.priority; + sprite->data0 = gFieldEffectArguments[0]; + sprite->data1 = gFieldEffectArguments[1]; + sprite->data2 = gFieldEffectArguments[2]; + sprite->pos2.y = (graphicsInfo->height >> 1) - 4; + PlaySE(SE_MIZU); + } + return 0; +} + +void sub_81276B4(struct Sprite *sprite) +{ + u8 mapObjectId; + + if (sprite->animEnded || TryGetFieldObjectIdByLocalIdAndMap(sprite->data0, sprite->data1, sprite->data2, &mapObjectId)) + { + FieldEffectStop(sprite, FLDEFF_SPLASH); + } + else + { + sprite->pos1.x = gSprites[gMapObjects[mapObjectId].spriteId].pos1.x; + sprite->pos1.y = gSprites[gMapObjects[mapObjectId].spriteId].pos1.y; + sub_806487C(sprite, FALSE); + } +} + +u32 FldEff_JumpSmallSplash(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[14], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = gFieldEffectArguments[2]; + sprite->data1 = FLDEFF_JUMP_SMALL_SPLASH; + } + return 0; +} + +u32 FldEff_JumpBigSplash(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[12], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = gFieldEffectArguments[2]; + sprite->data1 = FLDEFF_JUMP_BIG_SPLASH; + } + return 0; +} + +u32 FldEff_FeetInFlowingWater(void) +{ + u8 mapObjectId; + struct MapObject *mapObject; + u8 spriteId; + struct Sprite *sprite; + const struct MapObjectGraphicsInfo *graphicsInfo; + + mapObjectId = GetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + mapObject = &gMapObjects[mapObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[13], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + sprite = &gSprites[spriteId]; + sprite->callback = sub_81278D8; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[mapObject->spriteId].oam.priority; + sprite->data0 = gFieldEffectArguments[0]; + sprite->data1 = gFieldEffectArguments[1]; + sprite->data2 = gFieldEffectArguments[2]; + sprite->data3 = -1; + sprite->data4 = -1; + sprite->pos2.y = (graphicsInfo->height >> 1) - 4; + StartSpriteAnim(sprite, 1); + } + return 0; +} + +static void sub_81278D8(struct Sprite *sprite) +{ + u8 mapObjectId; + struct Sprite *linkedSprite; + struct MapObject *mapObject; + + if (TryGetFieldObjectIdByLocalIdAndMap(sprite->data0, sprite->data1, sprite->data2, &mapObjectId) || !gMapObjects[mapObjectId].mapobj_bit_19) + { + FieldEffectStop(sprite, FLDEFF_FEET_IN_FLOWING_WATER); + } + else + { + mapObject = &gMapObjects[mapObjectId]; + linkedSprite = &gSprites[mapObject->spriteId]; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y; + sprite->subpriority = linkedSprite->subpriority; + sub_806487C(sprite, FALSE); + if (mapObject->coords2.x != sprite->data3 || mapObject->coords2.y != sprite->data4) + { + sprite->data3 = mapObject->coords2.x; + sprite->data4 = mapObject->coords2.y; + if (!sprite->invisible) + { + PlaySE(SE_MIZU); + } + } + } +} + +u32 FldEff_Ripple(void) +{ + u8 spriteId; + struct Sprite *sprite; + + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[5], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = FLDEFF_RIPPLE; + } + return 0; +} + +u32 FldEff_HotSpringsWater(void) +{ + u8 mapObjectId; + struct MapObject *mapObject; + u8 spriteId; + struct Sprite *sprite; + + mapObjectId = GetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + mapObject = &gMapObjects[mapObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[31], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[mapObject->spriteId].oam.priority; + sprite->data0 = gFieldEffectArguments[0]; + sprite->data1 = gFieldEffectArguments[1]; + sprite->data2 = gFieldEffectArguments[2]; + sprite->data3 = gSprites[mapObject->spriteId].pos1.x; + sprite->data4 = gSprites[mapObject->spriteId].pos1.y; + } + return 0; +} + +void sub_8127A7C(struct Sprite *sprite) +{ + u8 mapObjectId; + const struct MapObjectGraphicsInfo *graphicsInfo; + struct Sprite *linkedSprite; + + if (TryGetFieldObjectIdByLocalIdAndMap(sprite->data0, sprite->data1, sprite->data2, &mapObjectId) || !gMapObjects[mapObjectId].mapobj_bit_21) + { + FieldEffectStop(sprite, FLDEFF_HOT_SPRINGS_WATER); + } + else + { + graphicsInfo = GetFieldObjectGraphicsInfo(gMapObjects[mapObjectId].graphicsId); + linkedSprite = &gSprites[gMapObjects[mapObjectId].spriteId]; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = (graphicsInfo->height >> 1) + linkedSprite->pos1.y - 8; + sprite->subpriority = linkedSprite->subpriority - 1; + sub_806487C(sprite, FALSE); + } +} + +u32 FldEff_Unknown19(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[17], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = FLDEFF_UNKNOWN_19; + } + return 0; +} + +u32 FldEff_Unknown20(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[18], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = FLDEFF_UNKNOWN_20; + } + return 0; +} + +u32 FldEff_Unknown21(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[19], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = FLDEFF_UNKNOWN_21; + } + return 0; +} + +u32 FldEff_Unknown22(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[20], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = FLDEFF_UNKNOWN_22; + } + return 0; +} + +void ash(s16 x, s16 y, u16 c, s16 d) +{ + gFieldEffectArguments[0] = x; + gFieldEffectArguments[1] = y; + gFieldEffectArguments[2] = 0x52; + gFieldEffectArguments[3] = 1; + gFieldEffectArguments[4] = c; + gFieldEffectArguments[5] = d; + FieldEffectStart(FLDEFF_ASH); +} + +u32 FldEff_Ash(void) +{ + s16 x; + s16 y; + u8 spriteId; + struct Sprite *sprite; + + x = gFieldEffectArguments[0]; + y = gFieldEffectArguments[1]; + sub_8060470(&x, &y, 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[6], x, y, gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data1 = gFieldEffectArguments[0]; + sprite->data2 = gFieldEffectArguments[1]; + sprite->data3 = gFieldEffectArguments[4]; + sprite->data4 = gFieldEffectArguments[5]; + } + return 0; +} + +void sub_8127D84(struct Sprite *sprite) +{ + gUnknown_08401E48[sprite->data0](sprite); +} + +static void sub_8127DA0(struct Sprite *sprite) +{ + sprite->invisible = TRUE; + sprite->animPaused = TRUE; + if (--sprite->data4 == 0) + { + sprite->data0 = 1; + } +} + +static void sub_8127DD0(struct Sprite *sprite) +{ + sprite->invisible = FALSE; + sprite->animPaused = FALSE; + MapGridSetMetatileIdAt(sprite->data1, sprite->data2, sprite->data3); + CurrentMapDrawMetatileAt(sprite->data1, sprite->data2); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_2 = TRUE; + sprite->data0 = 2; +} + +static void sub_8127E30(struct Sprite *sprite) +{ + sub_806487C(sprite, FALSE); + if (sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_ASH); + } +} + +u32 FldEff_SurfBlob(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[7], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x96); + if (spriteId !=MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.paletteNum = 0; + sprite->data2 = gFieldEffectArguments[2]; + sprite->data3 = -1; + sprite->data6 = -1; + sprite->data7 = -1; + } + FieldEffectActiveListRemove(FLDEFF_SURF_BLOB); + return spriteId; +} + +void sub_8127ED0(u8 spriteId, u8 value) +{ + gSprites[spriteId].data0 = (gSprites[spriteId].data0 & ~0xF) | (value & 0xF); +} + +void sub_8127EFC(u8 spriteId, u8 value) +{ + gSprites[spriteId].data0 = (gSprites[spriteId].data0 & ~0xF0) | ((value & 0xF) << 4); +} + +void sub_8127F28(u8 spriteId, u8 value, s16 data1) +{ + gSprites[spriteId].data0 = (gSprites[spriteId].data0 & ~0xF00) | ((value & 0xF) << 8); + gSprites[spriteId].data1 = data1; +} + +static u8 sub_8127F5C(struct Sprite *sprite) +{ + return sprite->data0 & 0xF; +} + +static u8 sub_8127F64(struct Sprite *sprite) +{ + return (sprite->data0 & 0xF0) >> 4; +} + +static u8 sub_8127F70(struct Sprite *sprite) +{ + return (sprite->data0 & 0xF00) >> 8; +} + +void sub_8127F7C(struct Sprite *sprite) +{ + struct MapObject *mapObject; + struct Sprite *linkedSprite; + + mapObject = &gMapObjects[sprite->data2]; + linkedSprite = &gSprites[mapObject->spriteId]; + sub_8127FD4(mapObject, sprite); + sub_812800C(mapObject, sprite); + sub_81280A0(mapObject, linkedSprite, sprite); + sprite->oam.priority = linkedSprite->oam.priority; +} + +static void sub_8127FD4(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 unk_8041E54[ARRAY_COUNT(gUnknown_08401E54)]; + + memcpy(unk_8041E54, gUnknown_08401E54, sizeof gUnknown_08401E54); + if (sub_8127F64(sprite) == 0) + { + StartSpriteAnimIfDifferent(sprite, unk_8041E54[mapObject->placeholder18]); + } +} + +#ifdef NONMATCHING +static void sub_812800C(struct MapObject *mapObject, struct Sprite *sprite) +{ + s16 x; + s16 y; + u8 i; + + x = mapObject->coords2.x; + y = mapObject->coords2.y; + if (sprite->pos2.y == 0 && (x != sprite->data6 || y != sprite->data7)) + { + sprite->data5 = sprite->pos2.y; + for (sprite->data6 = x, sprite->data7 = y, i = DIR_SOUTH; i <= DIR_EAST; i ++, x = sprite->data6, y = sprite->data7) + { + MoveCoords(i, &x, &y); + if (MapGridGetZCoordAt(x, y) == 3) + { + sprite->data5 ++; + break; + } + } + } +} +#else +__attribute__((naked)) static void sub_812800C(struct MapObject *mapObject, struct Sprite *sprite) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r8\n" + "\tpush {r7}\n" + "\tsub sp, 0x4\n" + "\tadds r4, r1, 0\n" + "\tldrh r2, [r0, 0x10]\n" + "\tmov r1, sp\n" + "\tstrh r2, [r1]\n" + "\tldrh r1, [r0, 0x12]\n" + "\tmov r0, sp\n" + "\tadds r0, 0x2\n" + "\tstrh r1, [r0]\n" + "\tmovs r2, 0x26\n" + "\tldrsh r3, [r4, r2]\n" + "\tmov r8, r0\n" + "\tcmp r3, 0\n" + "\tbne _08128094\n" + "\tmov r0, sp\n" + "\tmovs r5, 0\n" + "\tldrsh r2, [r0, r5]\n" + "\tmovs r5, 0x3A\n" + "\tldrsh r0, [r4, r5]\n" + "\tcmp r2, r0\n" + "\tbne _08128048\n" + "\tlsls r0, r1, 16\n" + "\tasrs r0, 16\n" + "\tmovs r5, 0x3C\n" + "\tldrsh r1, [r4, r5]\n" + "\tcmp r0, r1\n" + "\tbeq _08128094\n" + "_08128048:\n" + "\tstrh r3, [r4, 0x38]\n" + "\tstrh r2, [r4, 0x3A]\n" + "\tmov r1, r8\n" + "\tmovs r2, 0\n" + "\tldrsh r0, [r1, r2]\n" + "\tstrh r0, [r4, 0x3C]\n" + "\tmovs r5, 0x1\n" + "\tmov r7, r8\n" + "\tmov r6, sp\n" + "_0812805A:\n" + "\tadds r0, r5, 0\n" + "\tmov r1, sp\n" + "\tadds r2, r7, 0\n" + "\tbl MoveCoords\n" + "\tmovs r1, 0\n" + "\tldrsh r0, [r6, r1]\n" + "\tmovs r2, 0\n" + "\tldrsh r1, [r7, r2]\n" + "\tbl MapGridGetZCoordAt\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tcmp r0, 0x3\n" + "\tbne _08128080\n" + "\tldrh r0, [r4, 0x38]\n" + "\tadds r0, 0x1\n" + "\tstrh r0, [r4, 0x38]\n" + "\tb _08128094\n" + "_08128080:\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r5, r0, 24\n" + "\tldrh r0, [r4, 0x3A]\n" + "\tstrh r0, [r6]\n" + "\tldrh r0, [r4, 0x3C]\n" + "\tmov r1, r8\n" + "\tstrh r0, [r1]\n" + "\tcmp r5, 0x4\n" + "\tbls _0812805A\n" + "_08128094:\n" + "\tadd sp, 0x4\n" + "\tpop {r3}\n" + "\tmov r8, r3\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0"); +} +#endif + +static void sub_81280A0(struct MapObject *mapObject, struct Sprite *linkedSprite, struct Sprite *sprite) +{ + u16 unk_8401E5A[ARRAY_COUNT(gUnknown_08401E5A)]; + u8 v0; + + memcpy(unk_8401E5A, gUnknown_08401E5A, sizeof gUnknown_08401E5A); + v0 = sub_8127F5C(sprite); + if (v0 != 0) + { + if (((u16)(++ sprite->data4) & unk_8401E5A[sprite->data5]) == 0) + { + sprite->pos2.y += sprite->data3; + } + if ((sprite->data4 & 0x0F) == 0) + { + sprite->data3 = -sprite->data3; + } + if (v0 != 2) + { + if (sub_8127F70(sprite) == 0) + { + linkedSprite->pos2.y = sprite->pos2.y; + } + else + { + linkedSprite->pos2.y = sprite->data1 + sprite->pos2.y; + } + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = linkedSprite->pos1.y + 8; + } + } +} + +u8 sub_8128124(u8 oldSpriteId) +{ + u8 spriteId; + struct Sprite *sprite; + + spriteId = CreateSpriteAtEnd(&gDummySpriteTemplate, 0, 0, -1); + sprite = &gSprites[spriteId]; + sprite->callback = sub_8128174; + sprite->invisible = TRUE; + sprite->data0 = oldSpriteId; + sprite->data1 = 1; + return spriteId; +} + +static void sub_8128174(struct Sprite *sprite) +{ + struct Sprite *oldSprite; + + oldSprite = &gSprites[sprite->data0]; + if (((sprite->data2++) & 0x03) == 0) + { + oldSprite->pos2.y += sprite->data1; + } + if ((sprite->data2 & 0x0F) == 0) + { + sprite->data1 = -sprite->data1; + } +} + +u32 FldEff_Dust(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 12); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[9], gFieldEffectArguments[0], gFieldEffectArguments[1], 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->data0 = gFieldEffectArguments[2]; + sprite->data1 = 10; + } + return 0; +} + +u32 FldEff_SandPile(void) +{ + u8 mapObjectId; + struct MapObject *mapObject; + u8 spriteId; + struct Sprite *sprite; + const struct MapObjectGraphicsInfo *graphicsInfo; + + mapObjectId = GetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + mapObject = &gMapObjects[mapObjectId]; + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[29], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gSprites[mapObject->spriteId].oam.priority; + sprite->data0 = gFieldEffectArguments[0]; + sprite->data1 = gFieldEffectArguments[1]; + sprite->data2 = gFieldEffectArguments[2]; + sprite->data3 = gSprites[mapObject->spriteId].pos1.x; + sprite->data4 = gSprites[mapObject->spriteId].pos1.y; + sprite->pos2.y = (graphicsInfo->height >> 1) - 2; + SeekSpriteAnim(sprite, 2); + } + return 0; +} + +void sub_81282E0(struct Sprite *sprite) +{ + u8 mapObjectId; + s16 x; + s16 y; + + if (TryGetFieldObjectIdByLocalIdAndMap(sprite->data0, sprite->data1, sprite->data2, &mapObjectId) || !gMapObjects[mapObjectId].mapobj_bit_20) + { + FieldEffectStop(sprite, FLDEFF_SAND_PILE); + } + else + { + y = gSprites[gMapObjects[mapObjectId].spriteId].pos1.y; + x = gSprites[gMapObjects[mapObjectId].spriteId].pos1.x; + if (x != sprite->data3 || y != sprite->data4) + { + sprite->data3 = x; + sprite->data4 = y; + if (sprite->animEnded) + { + StartSpriteAnim(sprite, 0); + } + } + sprite->pos1.x = x; + sprite->pos1.y = y; + sprite->subpriority = gSprites[gMapObjects[mapObjectId].spriteId].subpriority; + sub_806487C(sprite, FALSE); + } +} + +u32 FldEff_Bubbles(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 0); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[34], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x52); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = 1; + } + return 0; +} + +void sub_8128410(struct Sprite *sprite) +{ + sprite->data0 += 0x80; + sprite->data0 &= 0x100; + sprite->pos1.y -= sprite->data0 >> 8; + sub_806487C(sprite, FALSE); + if (sprite->invisible || sprite->animEnded) + { + FieldEffectStop(sprite, FLDEFF_BUBBLES); + } +} + +u32 FldEff_BerryTreeGrowthSparkle(void) +{ + u8 spriteId; + struct Sprite *sprite; + + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 4); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[22], gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2]); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->oam.priority = gFieldEffectArguments[3]; + sprite->oam.paletteNum = 5; + sprite->data0 = FLDEFF_BERRY_TREE_GROWTH_SPARKLE; + } + return 0; +} + +u32 FldEff_TreeDisguise(void) +{ + return ShowDisguiseFieldEffect(FLDEFF_TREE_DISGUISE, 0x18, 0x04); +} + + +u32 FldEff_MountainDisguise(void) +{ + return ShowDisguiseFieldEffect(FLDEFF_MOUNTAIN_DISGUISE, 0x19, 0x03); +} + + +u32 FldEff_SandDisguise(void) +{ + return ShowDisguiseFieldEffect(FLDEFF_SAND_DISGUISE, 0x1C, 0x02); +} + +static u32 ShowDisguiseFieldEffect(u8 fldEff, u8 templateIdx, u8 paletteNum) +{ + u8 spriteId; + struct Sprite *sprite; + + if (TryGetFieldObjectIdByLocalIdAndMap(gFieldEffectArguments[0], gFieldEffectArguments[1], gFieldEffectArguments[2], &spriteId)) + { + FieldEffectActiveListRemove(fldEff); + return MAX_SPRITES; + } + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[templateIdx], 0, 0, 0); + if (spriteId != MAX_SPRITES) + { + sprite = &gSprites[spriteId]; + sprite->coordOffsetEnabled ++; + sprite->oam.paletteNum = paletteNum; + sprite->data1 = fldEff; + sprite->data2 = gFieldEffectArguments[0]; + sprite->data3 = gFieldEffectArguments[1]; + sprite->data4 = gFieldEffectArguments[2]; + } + return spriteId; +} + +void sub_81285AC(struct Sprite *sprite) +{ + u8 mapObjectId; + const struct MapObjectGraphicsInfo *graphicsInfo; + struct Sprite *linkedSprite; + + if (TryGetFieldObjectIdByLocalIdAndMap(sprite->data2, sprite->data3, sprite->data4, &mapObjectId)) + { + FieldEffectStop(sprite, sprite->data1); + } + // else { + graphicsInfo = GetFieldObjectGraphicsInfo(gMapObjects[mapObjectId].graphicsId); + linkedSprite = &gSprites[gMapObjects[mapObjectId].spriteId]; + sprite->invisible = linkedSprite->invisible; + sprite->pos1.x = linkedSprite->pos1.x; + sprite->pos1.y = (graphicsInfo->height >> 1) + linkedSprite->pos1.y - 16; + sprite->subpriority = linkedSprite->subpriority - 1; + if (sprite->data0 == 1) + { + sprite->data0 ++; + StartSpriteAnim(sprite, 1); + } + if (sprite->data0 == 2 && sprite->animEnded) + { + sprite->data7 = 1; + } + if (sprite->data0 == 3) + { + FieldEffectStop(sprite, sprite->data1); + } + // } +} + +void sub_812869C(struct MapObject *mapObject) +{ + if (mapObject->mapobj_unk_21 == 1) + { + gSprites[mapObject->mapobj_unk_1A].data0 ++; + } +} + +bool8 sub_81286C4(struct MapObject *mapObject) +{ + struct Sprite *sprite; + + if (mapObject->mapobj_unk_21 == 2) + { + return TRUE; + } + if (mapObject->mapobj_unk_21 == 0) + { + return TRUE; + } + sprite = &gSprites[mapObject->mapobj_unk_1A]; + if (sprite->data7) + { + mapObject->mapobj_unk_21 = 2; + sprite->data0 ++; + return TRUE; + } + return FALSE; +} + +u32 FldEff_Sparkle(void) +{ + u8 spriteId; + + gFieldEffectArguments[0] += 7; + gFieldEffectArguments[1] += 7; + sub_8060470((s16 *)&gFieldEffectArguments[0], (s16 *)&gFieldEffectArguments[1], 8, 8); + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[35], gFieldEffectArguments[0], gFieldEffectArguments[1], 0x52); + if (spriteId != MAX_SPRITES) + { + gSprites[spriteId].oam.priority = gFieldEffectArguments[2]; + gSprites[spriteId].coordOffsetEnabled = TRUE; + } + return 0; +} + +void sub_8128774(struct Sprite *sprite) +{ + if (sprite->data0 == 0) + { + if (sprite->animEnded) + { + sprite->invisible = TRUE; + sprite->data0 ++; + } + if (sprite->data0 == 0) + { + return; + } + } + if (++ sprite->data1 >= 35) + { + FieldEffectStop(sprite, FLDEFF_SPARKLE); + } +} + +void sub_81287C4(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, sprite->data1); + } + else + { + sub_806487C(sprite, FALSE); + SetObjectSubpriorityByZCoord(sprite->data0, sprite, 0); + } +} + +void sub_8128800(struct Sprite *sprite) +{ + if (sprite->animEnded) + { + FieldEffectStop(sprite, sprite->data0); + } + else + { + sub_806487C(sprite, FALSE); + } +} + +#ifdef NONMATCHING +static void sub_812882C(struct Sprite *sprite /*r6*/, u8 z, u8 offset) +{ + u8 i; + s16 xlo; + s16 xhi; + s16 lx; + s16 lyhi; + s16 ly; + s16 ylo; + s16 yhi; + struct MapObject *mapObject; // r4 + const struct MapObjectGraphicsInfo *graphicsInfo; // destroyed + struct Sprite *linkedSprite; // r5 + + SetObjectSubpriorityByZCoord(z, sprite, offset); + for (i = 0; i < 16; i ++) + { + mapObject = &gMapObjects[i]; + if (mapObject->active) + { + graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + linkedSprite = &gSprites[mapObject->spriteId]; + xhi = sprite->pos1.x + sprite->centerToCornerVecX; + xlo = sprite->pos1.x - sprite->centerToCornerVecX; + lx = linkedSprite->pos1.x; + if (xhi < lx && xlo > lx) + { + lyhi = linkedSprite->pos1.y + linkedSprite->centerToCornerVecY; + ly = linkedSprite->pos1.y; + ylo = sprite->pos1.y - sprite->centerToCornerVecY; + yhi = ylo + linkedSprite->centerToCornerVecY; + if ((lyhi < yhi || lyhi < ylo) && ly > yhi) + { + if (sprite->subpriority <= linkedSprite->subpriority) + { + sprite->subpriority = linkedSprite->subpriority + 2; + break; + } + } + } + } + } +} +#else +__attribute__((naked)) static void sub_812882C(struct Sprite *sprite /*r6*/, u8 z, u8 offset) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tadds r6, r0, 0\n" + "\tadds r0, r1, 0\n" + "\tlsls r0, 24\n" + "\tlsrs r0, 24\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tadds r1, r6, 0\n" + "\tbl SetObjectSubpriorityByZCoord\n" + "\tmovs r7, 0\n" + "_08128842:\n" + "\tlsls r0, r7, 3\n" + "\tadds r0, r7\n" + "\tlsls r0, 2\n" + "\tldr r1, _081288DC @ =gMapObjects\n" + "\tadds r4, r0, r1\n" + "\tldrb r0, [r4]\n" + "\tlsls r0, 31\n" + "\tcmp r0, 0\n" + "\tbeq _081288E4\n" + "\tldrb r0, [r4, 0x5]\n" + "\tbl GetFieldObjectGraphicsInfo\n" + "\tldrb r1, [r4, 0x4]\n" + "\tlsls r0, r1, 4\n" + "\tadds r0, r1\n" + "\tlsls r0, 2\n" + "\tldr r1, _081288E0 @ =gSprites\n" + "\tadds r5, r0, r1\n" + "\tadds r0, r6, 0\n" + "\tadds r0, 0x28\n" + "\tmovs r2, 0\n" + "\tldrsb r2, [r0, r2]\n" + "\tldrh r0, [r6, 0x20]\n" + "\tadds r1, r0, r2\n" + "\tsubs r0, r2\n" + "\tlsls r0, 16\n" + "\tlsrs r4, r0, 16\n" + "\tlsls r1, 16\n" + "\tasrs r1, 16\n" + "\tmovs r0, 0x20\n" + "\tldrsh r2, [r5, r0]\n" + "\tcmp r1, r2\n" + "\tbge _081288E4\n" + "\tlsls r0, r4, 16\n" + "\tasrs r0, 16\n" + "\tcmp r0, r2\n" + "\tble _081288E4\n" + "\tadds r0, r5, 0\n" + "\tadds r0, 0x29\n" + "\tmovs r3, 0\n" + "\tldrsb r3, [r0, r3]\n" + "\tldrh r2, [r5, 0x22]\n" + "\tadds r2, r3\n" + "\tldrh r4, [r5, 0x22]\n" + "\tadds r0, r6, 0\n" + "\tadds r0, 0x29\n" + "\tmovs r1, 0\n" + "\tldrsb r1, [r0, r1]\n" + "\tldrh r0, [r6, 0x22]\n" + "\tsubs r0, r1\n" + "\tlsls r0, 16\n" + "\tasrs r0, 16\n" + "\tadds r3, r0, r3\n" + "\tlsls r2, 16\n" + "\tasrs r2, 16\n" + "\tlsls r3, 16\n" + "\tasrs r3, 16\n" + "\tcmp r2, r3\n" + "\tblt _081288BC\n" + "\tcmp r2, r0\n" + "\tbge _081288E4\n" + "_081288BC:\n" + "\tlsls r0, r4, 16\n" + "\tasrs r0, 16\n" + "\tcmp r0, r3\n" + "\tble _081288E4\n" + "\tadds r2, r6, 0\n" + "\tadds r2, 0x43\n" + "\tadds r0, r5, 0\n" + "\tadds r0, 0x43\n" + "\tldrb r1, [r0]\n" + "\tldrb r0, [r2]\n" + "\tcmp r0, r1\n" + "\tbhi _081288E4\n" + "\tadds r0, r1, 0x2\n" + "\tstrb r0, [r2]\n" + "\tb _081288EE\n" + "\t.align 2, 0\n" + "_081288DC: .4byte gMapObjects\n" + "_081288E0: .4byte gSprites\n" + "_081288E4:\n" + "\tadds r0, r7, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r7, r0, 24\n" + "\tcmp r7, 0xF\n" + "\tbls _08128842\n" + "_081288EE:\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0"); +} +#endif diff --git a/src/field/field_fadetransition.c b/src/field/field_fadetransition.c new file mode 100644 index 000000000..82776d18c --- /dev/null +++ b/src/field/field_fadetransition.c @@ -0,0 +1,626 @@ +#include "global.h" +#include "cable_club.h" +#include "fieldmap.h" +#include "field_door.h" +#include "field_effect.h" +#include "field_fadetransition.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "field_special_scene.h" +#include "field_weather.h" +#include "fldeff_flash.h" +#include "link.h" +#include "main.h" +#include "map_obj_lock.h" +#include "metatile_behavior.h" +#include "palette.h" +#include "overworld.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "start_menu.h" +#include "task.h" + +void sub_8080B9C(u8); +void task_map_chg_seq_0807E20C(u8); +void task_map_chg_seq_0807E2CC(u8); +void task0A_fade_n_map_maybe(u8); +void sub_808115C(u8); + +void palette_bg_fill_white(void) +{ + CpuFastFill16(RGB_WHITE, gPlttBufferFaded, PLTT_SIZE); +} + +void palette_bg_fill_black(void) +{ + CpuFastFill16(RGB_BLACK, gPlttBufferFaded, PLTT_SIZE); +} + +void pal_fill_for_map_transition(void) +{ + u8 map_light = get_map_type_from_warp0(); + switch (fade_type_for_given_maplight_pair(map_light, Overworld_GetMapTypeOfSaveblockLocation())) + { + case 0: + fade_screen(0, 0); + palette_bg_fill_black(); + break; + case 1: + fade_screen(2, 0); + palette_bg_fill_white(); + } +} + +void pal_fill_black(void) +{ + fade_screen(0, 0); + palette_bg_fill_black(); +} + +void fade_8080918(void) +{ + u8 light_level = Overworld_GetMapTypeOfSaveblockLocation(); + switch (sub_810CDB8(light_level, warp1_get_mapheader()->mapType)) + { + case 0: + fade_screen(1, 0); + break; + case 1: + fade_screen(3, 0); + } +} + +void sub_8080958(u8 arg) +{ + sub_8059B88(!arg); +} + +void task0A_asap_script_env_2_enable_and_set_ctx_running(u8 taskID) +{ + if (sub_8080E70() == TRUE) + { + DestroyTask(taskID); + EnableBothScriptContexts(); + } +} + +void sub_8080990(void) +{ + ScriptContext2_Enable(); + Overworld_PlaySpecialMapMusic(); + pal_fill_black(); + CreateTask(task0A_asap_script_env_2_enable_and_set_ctx_running, 10); +} + +void sub_80809B0(void) +{ + ScriptContext2_Enable(); + pal_fill_black(); + CreateTask(task0A_asap_script_env_2_enable_and_set_ctx_running, 10); +} + +void task_mpl_807DD60(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[1] = sub_8083664(); + task->data[0]++; + break; + case 1: + if (gTasks[task->data[1]].isActive != TRUE) + { + pal_fill_for_map_transition(); + task->data[0]++; + } + break; + case 2: + if (sub_8080E70() == TRUE) + { + ScriptContext2_Disable(); + DestroyTask(taskId); + } + } +} + +void sub_8080A3C(void) +{ + ScriptContext2_Enable(); + Overworld_PlaySpecialMapMusic(); + palette_bg_fill_black(); + CreateTask(task_mpl_807DD60, 10); +} + +void sub_8080A5C(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + sub_80084A4(); + task->data[0]++; + break; + case 1: + if (sub_8007ECC()) + { + pal_fill_for_map_transition(); + task->data[0]++; + } + break; + case 2: + if (sub_8080E70() == TRUE) + { + sub_8007B14(); + ScriptContext2_Disable(); + DestroyTask(taskId); + } + } +} + +void sub_8080AC4(void) +{ + ScriptContext2_Enable(); + Overworld_PlaySpecialMapMusic(); + palette_bg_fill_black(); + CreateTask(sub_8080A5C, 10); +} + +void sub_8080AE4(void) +{ + s16 x, y; + u8 behavior; + TaskFunc func; + PlayerGetDestCoords(&x, &y); + behavior = MapGridGetMetatileBehaviorAt(x, y); + if (MetatileBehavior_IsDoor(behavior) == TRUE) + func = sub_8080B9C; + else if (MetatileBehavior_IsNonAnimDoor(behavior) == TRUE) + func = task_map_chg_seq_0807E20C; + else + func = task_map_chg_seq_0807E2CC; + CreateTask(func, 10); +} + +void mapldr_default(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_map_transition(); + sub_8080AE4(); + ScriptContext2_Enable(); +} + +void sub_8080B60(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_black(); + sub_8080AE4(); + ScriptContext2_Enable(); +} + +void sub_8080B78(void) +{ + Overworld_PlaySpecialMapMusic(); + pal_fill_for_map_transition(); + PlaySE(SE_TK_WARPOUT); + CreateTask(task_map_chg_seq_0807E2CC, 10); + ScriptContext2_Enable(); +} + +void sub_8080B9C(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + s16 *x = &task->data[2]; + s16 *y = &task->data[3]; + + switch (task->data[0]) + { + case 0: + sub_8080958(0); + FreezeMapObjects(); + PlayerGetDestCoords(x, y); + FieldSetDoorOpened(*x, *y); + task->data[0] = 1; + break; + case 1: + if (sub_8080E70()) + { + u8 mapObjId; + sub_8080958(1); + mapObjId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], 8); + task->data[0] = 2; + } + break; + case 2: + if (walkrun_is_standing_still()) + { + u8 mapObjId; + task->data[1] = FieldAnimateDoorClose(*x, *y); + mapObjId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[mapObjId]); + task->data[0] = 3; + } + break; + case 3: + if (task->data[1] < 0 || gTasks[task->data[1]].isActive != TRUE) + { + UnfreezeMapObjects(); + task->data[0] = 4; + } + break; + case 4: + ScriptContext2_Disable(); + DestroyTask(taskId); + break; + } +} + +void task_map_chg_seq_0807E20C(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + s16 *x = &task->data[2]; + s16 *y = &task->data[3]; + + switch (task->data[0]) + { + case 0: + sub_8080958(0); + FreezeMapObjects(); + PlayerGetDestCoords(x, y); + task->data[0] = 1; + break; + case 1: + if (sub_8080E70()) + { + u8 mapObjId; + sub_8080958(1); + mapObjId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], GetGoSpeed0AnimId(player_get_direction_lower_nybble())); + task->data[0] = 2; + } + break; + case 2: + if (walkrun_is_standing_still()) + { + UnfreezeMapObjects(); + task->data[0] = 3; + } + break; + case 3: + ScriptContext2_Disable(); + DestroyTask(taskId); + break; + } +} + +void task_map_chg_seq_0807E2CC(u8 taskId) +{ + switch (gTasks[taskId].data[0]) + { + case 0: + FreezeMapObjects(); + ScriptContext2_Enable(); + gTasks[taskId].data[0]++; + break; + case 1: + if (sub_8080E70()) + { + UnfreezeMapObjects(); + ScriptContext2_Disable(); + DestroyTask(taskId); + } + break; + } +} + +void sub_8080DC4(u8 taskId) +{ + if (sub_8080E70() == TRUE) + { + DestroyTask(taskId); + CreateTask(sub_80712B4, 80); + } +} + +void atk17_seteffectuser(void) +{ + pal_fill_black(); + CreateStartMenuTask(sub_8080DC4); + ScriptContext2_Enable(); +} + +void task_mpl_807E3C8(u8 taskId) +{ + if (sub_8080E70() == 1) + { + ScriptContext2_Disable(); + DestroyTask(taskId); + sub_8064E2C(); + } +} + +void sub_8080E28(void) +{ + ScriptContext2_Enable(); + pal_fill_black(); + CreateTask(task_mpl_807E3C8, 10); +} + +void sub_8080E44(void) +{ + ScriptContext2_Enable(); + Overworld_PlaySpecialMapMusic(); + pal_fill_black(); + CreateTask(task_mpl_807E3C8, 10); +} + +bool32 sub_8080E64(void) +{ + return gPaletteFade.active; +} + +bool32 sub_8080E70(void) +{ + if (sub_807D770() == TRUE) + return TRUE; + else + return FALSE; +} + +void sub_8080E88(void) +{ + ScriptContext2_Enable(); + sub_8053FF8(); + fade_8080918(); + PlayRainSoundEffect(); + PlaySE(SE_KAIDAN); + gFieldCallback = mapldr_default; + CreateTask(task0A_fade_n_map_maybe, 10); +} + +void sp13E_warp_to_last_warp(void) +{ + ScriptContext2_Enable(); + sub_8053FF8(); + fade_8080918(); + PlayRainSoundEffect(); + gFieldCallback = mapldr_default; + CreateTask(task0A_fade_n_map_maybe, 10); +} + +void sub_8080EF0(void) +{ + ScriptContext2_Enable(); + gFieldCallback = mapldr_default; + CreateTask(sub_808115C, 10); +} + +void sp13F_fall_to_last_warp(void) +{ + sp13E_warp_to_last_warp(); + gFieldCallback = sub_8086748; +} + +void sub_8080F2C(u8 metatileBehavior) +{ + ScriptContext2_Enable(); + sub_8086A2C(metatileBehavior, 10); +} + +void sub_8080F48(void) +{ + ScriptContext2_Enable(); + sub_80871B8(10); +} + +void sub_8080F58(void) +{ + ScriptContext2_Enable(); + sub_8087654(10); +} + +void sub_8080F68(void) +{ + ScriptContext2_Enable(); + sub_8053FF8(); + fade_8080918(); + PlaySE(SE_TK_WARPIN); + CreateTask(task0A_fade_n_map_maybe, 10); + gFieldCallback = sub_8080B78; +} + +void sub_8080F9C(void) +{ + ScriptContext2_Enable(); + fade_8080918(); + CreateTask(task0A_fade_n_map_maybe, 10); + gFieldCallback = sub_80C791C; +} + +void sub_8080FC4(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + ScriptContext2_Enable(); + task->data[0]++; + break; + case 1: + if (!sub_8080E64() && sub_8054034()) + { + task->data[0]++; + } + break; + case 2: + warp_in(); + SetMainCallback2(sub_8054588); + DestroyTask(taskId); + break; + } +} + +void DoCableClubWarp(void) +{ + ScriptContext2_Enable(); + sub_8053FF8(); + fade_8080918(); + PlaySE(SE_KAIDAN); + CreateTask(sub_8080FC4, 10); +} + +void sub_8081050(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (data[0]) + { + case 0: + ClearLinkCallback_2(); + fade_screen(1, 0); + sub_8053FF8(); + PlaySE(SE_KAIDAN); + data[0]++; + break; + case 1: + if (!sub_8080E64() && sub_8054034()) + { + sub_800832C(); + data[0]++; + } + break; + case 2: + if (!gReceivedRemoteLinkPlayers) + { + warp_in(); + SetMainCallback2(CB2_LoadMap); + DestroyTask(taskId); + } + break; + } +} + +void sub_80810DC(void) +{ + CreateTask(sub_8081050, 10); +} + +void task0A_fade_n_map_maybe(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + FreezeMapObjects(); + ScriptContext2_Enable(); + task->data[0]++; + break; + case 1: + if (!sub_8080E64() && sub_8054034()) + { + task->data[0]++; + } + break; + case 2: + warp_in(); + SetMainCallback2(CB2_LoadMap); + DestroyTask(taskId); + break; + } +} + +void sub_808115C(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + s16 *x = &task->data[2]; + s16 *y = &task->data[3]; + + switch (task->data[0]) + { + case 0: + FreezeMapObjects(); + PlayerGetDestCoords(x, y); + PlaySE(GetDoorSoundEffect(*x, *y - 1)); + task->data[1] = FieldAnimateDoorOpen(*x, *y - 1); + task->data[0] = 1; + break; + case 1: + if (task->data[1] < 0 || gTasks[task->data[1]].isActive != TRUE) + { + u8 mapObjId; + mapObjId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimActive(&gMapObjects[mapObjId]); + mapObjId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], 9); + task->data[0] = 2; + } + break; + case 2: + if (walkrun_is_standing_still()) + { + u8 mapObjId; + task->data[1] = FieldAnimateDoorClose(*x, *y - 1); + mapObjId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[mapObjId]); + sub_8080958(0); + task->data[0] = 3; + } + break; + case 3: + if (task->data[1] < 0 || gTasks[task->data[1]].isActive != TRUE) + { + task->data[0] = 4; + } + break; + case 4: + sub_8053FF8(); + fade_8080918(); + PlayRainSoundEffect(); + task->data[0] = 0; + task->func = task0A_fade_n_map_maybe; + break; + } +} + +void sub_80812C8(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + FreezeMapObjects(); + ScriptContext2_Enable(); + task->data[0]++; + break; + case 1: + if (!sub_8080E64() && sub_8054034()) + { + task->data[0]++; + } + break; + case 2: + warp_in(); + SetMainCallback2(sub_8054534); + DestroyTask(taskId); + break; + } +} + +void sub_8081334(void) +{ + ScriptContext2_Enable(); + sub_8053FF8(); + fade_8080918(); + PlayRainSoundEffect(); + PlaySE(SE_KAIDAN); + gFieldCallback = sub_8080B60; + CreateTask(sub_80812C8, 10); +} diff --git a/src/field/field_ground_effect.c b/src/field/field_ground_effect.c new file mode 100644 index 000000000..5af8ea3e3 --- /dev/null +++ b/src/field/field_ground_effect.c @@ -0,0 +1,796 @@ +#include "global.h" +#include "field_ground_effect.h" +#include "field_effect.h" +#include "field_effect_helpers.h" +#include "field_map_obj_helpers.h" +#include "fieldmap.h" +#include "metatile_behavior.h" + +static void nullsub(struct MapObject *mapObj, struct Sprite *sprite, u8); +static void DoTracksGroundEffect_Footprints(struct MapObject *mapObj, struct Sprite *sprite, u8); +static void DoTracksGroundEffect_BikeTireTracks( + struct MapObject *mapObj, struct Sprite *sprite, u8); +void GroundEffect_SpawnOnTallGrass(struct MapObject *mapObj, struct Sprite *sprite); +void sub_8063E94(struct MapObject *mapObj, struct Sprite *sprite); +void sub_8063EE0(struct MapObject *mapObj, struct Sprite *sprite); +void sub_8063F2C(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_WaterReflection(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_IceReflection(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_FlowingWater(struct MapObject *mapObj, struct Sprite *sprite); +void sub_8063FA0(struct MapObject *mapObj, struct Sprite *sprite); +void sub_8063FCC(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_Ripple(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_StepOnPuddle(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_SandPile(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_JumpOnTallGrass(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_JumpOnLongGrass(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_JumpOnShallowWater(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_JumpOnWater(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_JumpLandingDust(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_ShortGrass(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_HotSprings(struct MapObject *mapObj, struct Sprite *sprite); +void GroundEffect_Seaweed(struct MapObject *mapObj, struct Sprite *sprite); +u8 GetReflectionTypeByMetatileBehavior(u32 behavior); + +static void GetAllGroundEffectFlags_OnSpawn(struct MapObject *mapObj, u32 *flags) +{ + FieldObjectUpdateMetatileBehaviors(mapObj); + GetGroundEffectFlags_Reflection(mapObj, flags); + GetGroundEffectFlags_TallGrassOnSpawn(mapObj, flags); + GetGroundEffectFlags_LongGrassOnSpawn(mapObj, flags); + GetGroundEffectFlags_SandPile(mapObj, flags); + GetGroundEffectFlags_ShallowFlowingWater(mapObj, flags); + GetGroundEffectFlags_ShortGrass(mapObj, flags); + GetGroundEffectFlags_HotSprings(mapObj, flags); +} + +static void GetAllGroundEffectFlags_OnBeginStep(struct MapObject *mapObj, u32 *flags) +{ + FieldObjectUpdateMetatileBehaviors(mapObj); + GetGroundEffectFlags_Reflection(mapObj, flags); + GetGroundEffectFlags_TallGrassOnBeginStep(mapObj, flags); + GetGroundEffectFlags_LongGrassOnBeginStep(mapObj, flags); + GetGroundEffectFlags_Tracks(mapObj, flags); + GetGroundEffectFlags_SandPile(mapObj, flags); + GetGroundEffectFlags_ShallowFlowingWater(mapObj, flags); + GetGroundEffectFlags_Puddle(mapObj, flags); + GetGroundEffectFlags_ShortGrass(mapObj, flags); + GetGroundEffectFlags_HotSprings(mapObj, flags); +} + +static void GetAllGroundEffectFlags_OnFinishStep(struct MapObject *mapObj, u32 *flags) +{ + FieldObjectUpdateMetatileBehaviors(mapObj); + GetGroundEffectFlags_ShallowFlowingWater(mapObj, flags); + GetGroundEffectFlags_SandPile(mapObj, flags); + GetGroundEffectFlags_Puddle(mapObj, flags); + GetGroundEffectFlags_Ripple(mapObj, flags); + GetGroundEffectFlags_ShortGrass(mapObj, flags); + GetGroundEffectFlags_HotSprings(mapObj, flags); + GetGroundEffectFlags_Seaweed(mapObj, flags); + GetGroundEffectFlags_JumpLanding(mapObj, flags); +} + +void FieldObjectUpdateMetatileBehaviors(struct MapObject *mapObj) +{ + mapObj->mapobj_unk_1F = MapGridGetMetatileBehaviorAt(mapObj->coords3.x, mapObj->coords3.y); + mapObj->mapobj_unk_1E = MapGridGetMetatileBehaviorAt(mapObj->coords2.x, mapObj->coords2.y); +} + +void GetGroundEffectFlags_Reflection(struct MapObject *mapObj, u32 *flags) +{ + u32 reflectionFlags[2] = { 0x00000020, 0x00000010 }; + u8 type = FieldObjectCheckForReflectiveSurface(mapObj); + + if (type) + { + if (!mapObj->mapobj_bit_17) + { + mapObj->mapobj_bit_17 = 0; + mapObj->mapobj_bit_17 = 1; + *flags |= reflectionFlags[type - 1]; + } + } + else + { + mapObj->mapobj_bit_17 = 0; + } +} + +void GetGroundEffectFlags_TallGrassOnSpawn(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsTallGrass(mapObj->mapobj_unk_1E)) + *flags |= 0x1; +} + +void GetGroundEffectFlags_TallGrassOnBeginStep(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsTallGrass(mapObj->mapobj_unk_1E)) + *flags |= 0x2; +} + +void GetGroundEffectFlags_LongGrassOnSpawn(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsLongGrass(mapObj->mapobj_unk_1E)) + *flags |= 0x4; +} + +void GetGroundEffectFlags_LongGrassOnBeginStep(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsLongGrass(mapObj->mapobj_unk_1E)) + *flags |= 0x8; +} + +void GetGroundEffectFlags_Tracks(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsDeepSand(mapObj->mapobj_unk_1F)) + { + *flags |= 0x100; + } + else if (MetatileBehavior_IsSandOrDeepSand(mapObj->mapobj_unk_1F) + || MetatileBehavior_IsUnusedFootprintMetatile(mapObj->mapobj_unk_1F)) + { + *flags |= 0x80; + } +} + +void GetGroundEffectFlags_SandPile(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsDeepSand(mapObj->mapobj_unk_1E) + && MetatileBehavior_IsDeepSand(mapObj->mapobj_unk_1F)) + { + if (!mapObj->mapobj_bit_20) + { + mapObj->mapobj_bit_20 = 0; + mapObj->mapobj_bit_20 = 1; + *flags |= 0x800; + } + } + else + { + mapObj->mapobj_bit_20 = 0; + } +} + +void GetGroundEffectFlags_ShallowFlowingWater(struct MapObject *mapObj, u32 *flags) +{ + if ((MetatileBehavior_IsShallowFlowingWater(mapObj->mapobj_unk_1E) + && MetatileBehavior_IsShallowFlowingWater(mapObj->mapobj_unk_1F)) + || (MetatileBehavior_IsPacifidlogLog(mapObj->mapobj_unk_1E) + && MetatileBehavior_IsPacifidlogLog(mapObj->mapobj_unk_1F))) + { + if (!mapObj->mapobj_bit_19) + { + mapObj->mapobj_bit_19 = 0; + mapObj->mapobj_bit_19 = 1; + *flags |= 0x40; + } + } + else + { + mapObj->mapobj_bit_19 = 0; + } +} + +void GetGroundEffectFlags_Puddle(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsPuddle(mapObj->mapobj_unk_1E) + && MetatileBehavior_IsPuddle(mapObj->mapobj_unk_1F)) + { + *flags |= 0x400; + } +} + +void GetGroundEffectFlags_Ripple(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_HasRipples(mapObj->mapobj_unk_1E)) + *flags |= 0x200; +} + +void GetGroundEffectFlags_ShortGrass(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsShortGrass(mapObj->mapobj_unk_1E) + && MetatileBehavior_IsShortGrass(mapObj->mapobj_unk_1F)) + { + if (!mapObj->mapobj_bit_18) + { + mapObj->mapobj_bit_18 = 0; + mapObj->mapobj_bit_18 = 1; + *flags |= 0x20000; + } + } + else + { + mapObj->mapobj_bit_18 = 0; + } +} + +void GetGroundEffectFlags_HotSprings(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsHotSprings(mapObj->mapobj_unk_1E) + && MetatileBehavior_IsHotSprings(mapObj->mapobj_unk_1F)) + { + if (!mapObj->mapobj_bit_21) + { + mapObj->mapobj_bit_21 = 0; + mapObj->mapobj_bit_21 = 1; + *flags |= 0x40000; + } + } + else + { + mapObj->mapobj_bit_21 = 0; + } +} + +void GetGroundEffectFlags_Seaweed(struct MapObject *mapObj, u32 *flags) +{ + if (MetatileBehavior_IsSeaweed(mapObj->mapobj_unk_1E)) + *flags |= 0x80000; +} + +void GetGroundEffectFlags_JumpLanding(struct MapObject *mapObj, u32 *flags) +{ + typedef bool8 (*MetatileFunc)(u8); + + static const MetatileFunc metatileFuncs[] = { + MetatileBehavior_IsTallGrass, + MetatileBehavior_IsLongGrass, + MetatileBehavior_IsPuddle, + MetatileBehavior_IsSurfableWaterOrUnderwater, + MetatileBehavior_IsShallowFlowingWater, + MetatileBehavior_IsATile, + }; + + static const u32 jumpLandingFlags[] = { + 0x00001000, // Landing in tall grass + 0x00002000, // Landing in long grass + 0x00004000, // Landing on puddle + 0x00008000, // Landing on surfable water or underwater + 0x00004000, // Landing on shallow flowing water + 0x00010000, // Landing on any other type of ground + }; + + if (mapObj->mapobj_bit_5 && !mapObj->mapobj_bit_25) + { + u8 i; + + for (i = 0; i < 6; i++) + { + if (metatileFuncs[i](mapObj->mapobj_unk_1E)) + { + *flags |= jumpLandingFlags[i]; + return; + } + } + } +} + +u8 FieldObjectCheckForReflectiveSurface(struct MapObject *mapObj) +{ + const struct MapObjectGraphicsInfo *info = GetFieldObjectGraphicsInfo(mapObj->graphicsId); + + // ceil div by tile width? + s16 width = (info->width + 8) >> 4; + s16 height = (info->height + 8) >> 4; + s16 i; + s16 j; + u8 result; + u8 b; + s16 one; + +#define RETURN_REFLECTION_TYPE_AT(x, y) \ + b = MapGridGetMetatileBehaviorAt(x, y); \ + result = GetReflectionTypeByMetatileBehavior(b); \ + if (result != 0) \ + return result; + + for (i = 0, one = 1; i < height; i++) + { + RETURN_REFLECTION_TYPE_AT(mapObj->coords2.x, mapObj->coords2.y + one + i) + RETURN_REFLECTION_TYPE_AT(mapObj->coords3.x, mapObj->coords3.y + one + i) + for (j = 1; j < width; j++) + { + RETURN_REFLECTION_TYPE_AT(mapObj->coords2.x + j, mapObj->coords2.y + one + i) + RETURN_REFLECTION_TYPE_AT(mapObj->coords2.x - j, mapObj->coords2.y + one + i) + RETURN_REFLECTION_TYPE_AT(mapObj->coords3.x + j, mapObj->coords3.y + one + i) + RETURN_REFLECTION_TYPE_AT(mapObj->coords3.x - j, mapObj->coords3.y + one + i) + } + } + return 0; + +#undef RETURN_REFLECTION_TYPE_AT +} + +u8 GetReflectionTypeByMetatileBehavior(u32 behavior) +{ + if (MetatileBehavior_IsIce(behavior)) + return 1; + else if (MetatileBehavior_IsReflective(behavior)) + return 2; + else + return 0; +} + +u8 GetLedgeJumpDirection(s16 x, s16 y, u8 z) +{ + static bool8 (*const unknown_08376040[])(u8) = { + MetatileBehavior_IsJumpSouth, + MetatileBehavior_IsJumpNorth, + MetatileBehavior_IsJumpWest, + MetatileBehavior_IsJumpEast, + }; + + u8 b; + u8 index = z; + + if (index == 0) + return 0; + else if (index > 4) + index -= 4; + + index--; + b = MapGridGetMetatileBehaviorAt(x, y); + + if (unknown_08376040[index](b) == 1) + return index + 1; + + return 0; +} + +void FieldObjectSetSpriteOamTableForLongGrass(struct MapObject *mapObj, struct Sprite *sprite) +{ + if (mapObj->mapobj_bit_4) + return; + + if (!MetatileBehavior_IsLongGrass(mapObj->mapobj_unk_1E)) + return; + + if (!MetatileBehavior_IsLongGrass(mapObj->mapobj_unk_1F)) + return; + + sprite->subspriteTableNum = 4; + + if (ZCoordToPriority(mapObj->elevation) == 1) + sprite->subspriteTableNum = 5; +} + +bool8 IsZCoordMismatchAt(u8 z, s16 x, s16 y) +{ + u8 mapZ; + + if (z == 0) + return FALSE; + + mapZ = MapGridGetZCoordAt(x, y); + + if (mapZ == 0 || mapZ == 0xF) + return FALSE; + + if (mapZ != z) + return TRUE; + + return FALSE; +} + +static const u8 sUnknown_08376050[] = { + 0x73, 0x73, 0x53, 0x73, 0x53, 0x73, 0x53, 0x73, 0x53, 0x73, 0x53, 0x73, 0x53, 0x00, 0x00, 0x73 +}; + +// Each byte corresponds to a sprite priority for a field object. +// This is directly the inverse of gFieldObjectPriorities_08376070. +static const u8 sFieldObjectPriorities_08376060[] = { + 2, 2, 2, 2, 1, 2, 1, 2, 1, 2, 1, 2, 1, 0, 0, 2 +}; + +// Each byte corresponds to a sprite priority for a field object. +// This is the inverse of gFieldObjectPriorities_08376060. +// 1 = Above player sprite +// 2 = Below player sprite +static const u8 sFieldObjectPriorities_08376070[] = { + 1, 1, 1, 1, 2, 1, 2, 1, 2, 1, 2, 1, 2, 0, 0, 1, +}; + +void FieldObjectUpdateZCoordAndPriority(struct MapObject *mapObj, struct Sprite *sprite) +{ + if (mapObj->mapobj_bit_26) + return; + + FieldObjectUpdateZCoord(mapObj); + + sprite->subspriteTableNum = sFieldObjectPriorities_08376070[mapObj->elevation]; + sprite->oam.priority = sFieldObjectPriorities_08376060[mapObj->elevation]; +} + +void InitObjectPriorityByZCoord(struct Sprite *sprite, u8 z) +{ + sprite->subspriteTableNum = sFieldObjectPriorities_08376070[z]; + sprite->oam.priority = sFieldObjectPriorities_08376060[z]; +} + +u8 ZCoordToPriority(u8 z) +{ + return sFieldObjectPriorities_08376060[z]; +} + +void FieldObjectUpdateZCoord(struct MapObject *mapObj) +{ + u8 z = MapGridGetZCoordAt(mapObj->coords2.x, mapObj->coords2.y); + u8 z2 = MapGridGetZCoordAt(mapObj->coords3.x, mapObj->coords3.y); + + if (z == 0xF || z2 == 0xF) + return; + + mapObj->mapobj_unk_0B_0 = z; + + if (z != 0 && z != 0xF) + mapObj->elevation = z; +} + +void SetObjectSubpriorityByZCoord(u8 a, struct Sprite *sprite, u8 b) +{ + s32 tmp = sprite->centerToCornerVecY; + u32 tmpa = *(u16 *)&sprite->pos1.y; + u32 tmpb = *(u16 *)&gSpriteCoordOffsetY; + s32 tmp2 = (tmpa - tmp) + tmpb; + u16 tmp3 = (0x10 - ((((u32)tmp2 + 8) & 0xFF) >> 4)) * 2; + sprite->subpriority = tmp3 + sUnknown_08376050[a] + b; +} + +void FieldObjectUpdateSubpriority(struct MapObject *mapObj, struct Sprite *sprite) +{ + if (mapObj->mapobj_bit_26) + return; + + SetObjectSubpriorityByZCoord(mapObj->elevation, sprite, 1); +} + +bool8 AreZCoordsCompatible(u8 a, u8 b) +{ + if (a == 0 || b == 0) + return TRUE; + + if (a != b) + return FALSE; + + return TRUE; +} + +void GroundEffect_SpawnOnTallGrass(struct MapObject *mapObj, struct Sprite *sprite) +{ + u8 *ptr; + + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = 2; + gFieldEffectArguments[4] = (mapObj->localId << 8) | mapObj->mapNum; + gFieldEffectArguments[5] = mapObj->mapGroup; + + ptr = (u8 *)&gSaveBlock1; + gFieldEffectArguments[6] = ((u8)gSaveBlock1.location.mapNum << 8) + | (u8)gSaveBlock1.location.mapGroup; + + gFieldEffectArguments[7] = 1; + FieldEffectStart(FLDEFF_TALL_GRASS); +} + +void sub_8063E94(struct MapObject *mapObj, struct Sprite *sprite) +{ + u8 *ptr; + + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = 2; + gFieldEffectArguments[4] = (mapObj->localId << 8) | mapObj->mapNum; + gFieldEffectArguments[5] = mapObj->mapGroup; + + ptr = (u8 *)&gSaveBlock1; + gFieldEffectArguments[6] = ((u8)gSaveBlock1.location.mapNum << 8) + | (u8)gSaveBlock1.location.mapGroup; + + gFieldEffectArguments[7] = 0; + FieldEffectStart(FLDEFF_TALL_GRASS); +} + +void sub_8063EE0(struct MapObject *mapObj, struct Sprite *sprite) +{ + u8 *ptr; + + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = 2; + gFieldEffectArguments[4] = (mapObj->localId << 8) | mapObj->mapNum; + gFieldEffectArguments[5] = mapObj->mapGroup; + + ptr = (u8 *)&gSaveBlock1; + gFieldEffectArguments[6] = ((u8)gSaveBlock1.location.mapNum << 8) + | (u8)gSaveBlock1.location.mapGroup; + + gFieldEffectArguments[7] = 1; + FieldEffectStart(FLDEFF_LONG_GRASS); +} + +void sub_8063F2C(struct MapObject *mapObj, struct Sprite *sprite) +{ + u8 *ptr; + + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = 2; + gFieldEffectArguments[4] = (mapObj->localId << 8) | mapObj->mapNum; + gFieldEffectArguments[5] = mapObj->mapGroup; + + ptr = (u8 *)&gSaveBlock1; + gFieldEffectArguments[6] = ((u8)gSaveBlock1.location.mapNum << 8) + | (u8)gSaveBlock1.location.mapGroup; + + gFieldEffectArguments[7] = 0; + FieldEffectStart(FLDEFF_LONG_GRASS); +} + +void GroundEffect_WaterReflection(struct MapObject *mapObj, struct Sprite *sprite) +{ + SetUpReflection(mapObj, sprite, 0); +} + +void GroundEffect_IceReflection(struct MapObject *mapObj, struct Sprite *sprite) +{ + SetUpReflection(mapObj, sprite, 1); +} + +void GroundEffect_FlowingWater(struct MapObject *mapObj, struct Sprite *sprite) +{ + oe_exec_and_other_stuff(FLDEFF_FEET_IN_FLOWING_WATER, mapObj); +} + +static void (*const gUnknown_08376080[])(struct MapObject *mapObj, struct Sprite *sprite, u8 a) = { + nullsub, DoTracksGroundEffect_Footprints, DoTracksGroundEffect_BikeTireTracks, +}; + +void sub_8063FA0(struct MapObject *mapObj, struct Sprite *sprite) +{ + const struct MapObjectGraphicsInfo *info = GetFieldObjectGraphicsInfo(mapObj->graphicsId); + gUnknown_08376080[info->tracks](mapObj, sprite, 0); +} + +void sub_8063FCC(struct MapObject *mapObj, struct Sprite *sprite) +{ + const struct MapObjectGraphicsInfo *info = GetFieldObjectGraphicsInfo(mapObj->graphicsId); + gUnknown_08376080[info->tracks](mapObj, sprite, 1); +} + +static void nullsub(struct MapObject *mapObj, struct Sprite *sprite, u8 a) +{ +} + +static void DoTracksGroundEffect_Footprints(struct MapObject *mapObj, struct Sprite *sprite, u8 a) +{ + // First half-word is a Field Effect script id. (gFieldEffectScriptPointers) + u16 sandFootprints_FieldEffectData[2] = { + FLDEFF_SAND_FOOTPRINTS, + FLDEFF_DEEP_SAND_FOOTPRINTS + }; + + gFieldEffectArguments[0] = mapObj->coords3.x; + gFieldEffectArguments[1] = mapObj->coords3.y; + gFieldEffectArguments[2] = 149; + gFieldEffectArguments[3] = 2; + gFieldEffectArguments[4] = mapObj->mapobj_unk_18; + FieldEffectStart(sandFootprints_FieldEffectData[a]); +} + +static void DoTracksGroundEffect_BikeTireTracks( + struct MapObject *mapObj, struct Sprite *sprite, u8 a) +{ + // Specifies which bike track shape to show next. + // For example, when the bike turns from up to right, it will show + // a track that curves to the right. + // Each 4-byte row corresponds to the initial direction of the bike, and + // each byte in that row is for the next direction of the bike in the order + // of down, up, left, right. + static const u8 bikeTireTracks_Transitions[4][4] = { + 1, 2, 7, 8, + 1, 2, 6, 5, + 5, 8, 3, 4, + 6, 7, 3, 4, + }; + + if (mapObj->coords2.x != mapObj->coords3.x || mapObj->coords2.y != mapObj->coords3.y) + { + gFieldEffectArguments[0] = mapObj->coords3.x; + gFieldEffectArguments[1] = mapObj->coords3.y; + gFieldEffectArguments[2] = 149; + gFieldEffectArguments[3] = 2; + gFieldEffectArguments[4] = + bikeTireTracks_Transitions[mapObj->mapobj_unk_20][mapObj->mapobj_unk_18 - 5]; + FieldEffectStart(FLDEFF_BIKE_TIRE_TRACKS); + } +} + +void GroundEffect_Ripple(struct MapObject *mapObj, struct Sprite *sprite) +{ + DoRippleFieldEffect(mapObj, sprite); +} + +void GroundEffect_StepOnPuddle(struct MapObject *mapObj, struct Sprite *sprite) +{ + oe_exec_and_other_stuff(FLDEFF_SPLASH, mapObj); +} + +void GroundEffect_SandPile(struct MapObject *mapObj, struct Sprite *sprite) +{ + oe_exec_and_other_stuff(FLDEFF_SAND_PILE, mapObj); +} + +void GroundEffect_JumpOnTallGrass(struct MapObject *mapObj, struct Sprite *sprite) +{ + u8 spriteId; + + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = 2; + FieldEffectStart(FLDEFF_JUMP_TALL_GRASS); + + spriteId = sub_8126FF0( + mapObj->localId, mapObj->mapNum, mapObj->mapGroup, mapObj->coords2.x, mapObj->coords2.y); + + if (spriteId == MAX_SPRITES) + GroundEffect_SpawnOnTallGrass(mapObj, sprite); +} + +void GroundEffect_JumpOnLongGrass(struct MapObject *mapObj, struct Sprite *sprite) +{ + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = 2; + FieldEffectStart(FLDEFF_JUMP_LONG_GRASS); +} + +void GroundEffect_JumpOnShallowWater(struct MapObject *mapObj, struct Sprite *sprite) +{ + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = sprite->oam.priority; + FieldEffectStart(FLDEFF_JUMP_SMALL_SPLASH); +} + +void GroundEffect_JumpOnWater(struct MapObject *mapObj, struct Sprite *sprite) +{ + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = sprite->oam.priority; + FieldEffectStart(FLDEFF_JUMP_BIG_SPLASH); +} + +void GroundEffect_JumpLandingDust(struct MapObject *mapObj, struct Sprite *sprite) +{ + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + gFieldEffectArguments[2] = mapObj->elevation; + gFieldEffectArguments[3] = sprite->oam.priority; + FieldEffectStart(FLDEFF_DUST); +} + +void GroundEffect_ShortGrass(struct MapObject *mapObj, struct Sprite *sprite) +{ + oe_exec_and_other_stuff(FLDEFF_SHORT_GRASS, mapObj); +} + +void GroundEffect_HotSprings(struct MapObject *mapObj, struct Sprite *sprite) +{ + oe_exec_and_other_stuff(FLDEFF_HOT_SPRINGS_WATER, mapObj); +} + +void GroundEffect_Seaweed(struct MapObject *mapObj, struct Sprite *sprite) +{ + gFieldEffectArguments[0] = mapObj->coords2.x; + gFieldEffectArguments[1] = mapObj->coords2.y; + FieldEffectStart(FLDEFF_BUBBLES); +} + +static void (*const gUnknown_083760A0[])(struct MapObject *mapObj, struct Sprite *sprite) = { + GroundEffect_SpawnOnTallGrass, + sub_8063E94, + sub_8063EE0, + sub_8063F2C, + GroundEffect_WaterReflection, + GroundEffect_IceReflection, + GroundEffect_FlowingWater, + sub_8063FA0, + sub_8063FCC, + GroundEffect_Ripple, + GroundEffect_StepOnPuddle, + GroundEffect_SandPile, + GroundEffect_JumpOnTallGrass, + GroundEffect_JumpOnLongGrass, + GroundEffect_JumpOnShallowWater, + GroundEffect_JumpOnWater, + GroundEffect_JumpLandingDust, + GroundEffect_ShortGrass, + GroundEffect_HotSprings, + GroundEffect_Seaweed +}; + +void sub_8064218(struct MapObject *mapObj, struct Sprite *sprite, u32 flags) +{ + u8 i; + for (i = 0; i < ARRAY_COUNT(gUnknown_083760A0); i++, flags >>= 1) + if (flags & 1) + gUnknown_083760A0[i](mapObj, sprite); +} + +void filters_out_some_ground_effects(struct MapObject *mapObj, u32 *flags) +{ + if (mapObj->mapobj_bit_4) + { + mapObj->mapobj_bit_18 = 0; + mapObj->mapobj_bit_20 = 0; + mapObj->mapobj_bit_19 = 0; + mapObj->mapobj_bit_21 = 0; + *flags &= 0xFFF9F7BD; + } +} + +void FilterOutStepOnPuddleGroundEffectIfJumping(struct MapObject *mapObj, u32 *flags) +{ + if (mapObj->mapobj_bit_5) + *flags &= 0xFFFFFBFF; +} + +void DoGroundEffects_OnSpawn(struct MapObject *mapObj, struct Sprite *sprite) +{ + u32 flags; + + if (mapObj->mapobj_bit_2) + { + flags = 0; + FieldObjectUpdateZCoordAndPriority(mapObj, sprite); + GetAllGroundEffectFlags_OnSpawn(mapObj, &flags); + FieldObjectSetSpriteOamTableForLongGrass(mapObj, sprite); + sub_8064218(mapObj, sprite, flags); + mapObj->mapobj_bit_2 = 0; + mapObj->mapobj_bit_4 = 0; + } +} + +void DoGroundEffects_OnBeginStep(struct MapObject *mapObj, struct Sprite *sprite) +{ + u32 flags; + + if (mapObj->mapobj_bit_2) + { + flags = 0; + FieldObjectUpdateZCoordAndPriority(mapObj, sprite); + GetAllGroundEffectFlags_OnBeginStep(mapObj, &flags); + FieldObjectSetSpriteOamTableForLongGrass(mapObj, sprite); + filters_out_some_ground_effects(mapObj, &flags); + sub_8064218(mapObj, sprite, flags); + mapObj->mapobj_bit_2 = 0; + mapObj->mapobj_bit_4 = 0; + } +} + +void DoGroundEffects_OnFinishStep(struct MapObject *mapObj, struct Sprite *sprite) +{ + u32 flags; + + if (mapObj->mapobj_bit_3) + { + flags = 0; + FieldObjectUpdateZCoordAndPriority(mapObj, sprite); + GetAllGroundEffectFlags_OnFinishStep(mapObj, &flags); + FieldObjectSetSpriteOamTableForLongGrass(mapObj, sprite); + FilterOutStepOnPuddleGroundEffectIfJumping(mapObj, &flags); + sub_8064218(mapObj, sprite, flags); + mapObj->mapobj_bit_3 = 0; + mapObj->mapobj_bit_5 = 0; + } +} diff --git a/src/field/field_map_obj.c b/src/field/field_map_obj.c new file mode 100644 index 000000000..0cba448a9 --- /dev/null +++ b/src/field/field_map_obj.c @@ -0,0 +1,8356 @@ +#include "global.h" +#include "field_map_obj.h" +#include "berry.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_effect.h" +#include "field_effect_helpers.h" +#include "field_ground_effect.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "palette.h" +#include "rng.h" +#include "overworld.h" +#include "sprite.h" +#include "metatile_behavior.h" +#include "map_constants.h" +#include "map_object_constants.h" +#include "trainer_see.h" + +// rodata + +const u8 gUnknown_0830FD14[] = {1, 1, 6, 7, 8, 9, 6, 7, 8, 9, 11, 11, 0, 0, 0, 0}; + +void ObjectCB_CameraObject(struct Sprite *sprite); +const struct SpriteTemplate gSpriteTemplate_830FD24 = {0, 0xFFFF, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, ObjectCB_CameraObject}; + +void CameraObject_0(struct Sprite *); +void CameraObject_1(struct Sprite *); +void CameraObject_2(struct Sprite *); +void (*const gCameraObjectFuncs[])(struct Sprite *) = { + CameraObject_0, + CameraObject_1, + CameraObject_2, +}; + +const u32 gMapObjectPic_BrendanNormal_0[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/00.4bpp"); +const u32 gMapObjectPic_BrendanNormal_1[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/01.4bpp"); +const u32 gMapObjectPic_BrendanNormal_2[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/02.4bpp"); +const u32 gMapObjectPic_BrendanNormal_3[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/03.4bpp"); +const u32 gMapObjectPic_BrendanNormal_4[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/04.4bpp"); +const u32 gMapObjectPic_BrendanNormal_5[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/05.4bpp"); +const u32 gMapObjectPic_BrendanNormal_6[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/06.4bpp"); +const u32 gMapObjectPic_BrendanNormal_7[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/07.4bpp"); +const u32 gMapObjectPic_BrendanNormal_8[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/08.4bpp"); +const u32 gMapObjectPic_BrendanNormal_9[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/09.4bpp"); +const u32 gMapObjectPic_BrendanNormal_10[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/10.4bpp"); +const u32 gMapObjectPic_BrendanNormal_11[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/11.4bpp"); +const u32 gMapObjectPic_BrendanNormal_12[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/12.4bpp"); +const u32 gMapObjectPic_BrendanNormal_13[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/13.4bpp"); +const u32 gMapObjectPic_BrendanNormal_14[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/14.4bpp"); +const u32 gMapObjectPic_BrendanNormal_15[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/15.4bpp"); +const u32 gMapObjectPic_BrendanNormal_16[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/16.4bpp"); +const u32 gMapObjectPic_BrendanNormal_17[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/normal/17.4bpp"); +const u16 gMapObjectPalette8[] = INCBIN_U16("graphics/map_objects/palettes/08.gbapal"); +const u16 NullPalette_8310F68[16] = {}; +const u16 NullPalette_8310F88[16] = {}; +const u16 NullPalette_8310FA8[16] = {}; +const u16 NullPalette_8310FC8[16] = {}; +const u16 NullPalette_8310FE8[16] = {}; +const u16 NullPalette_8311008[16] = {}; +const u16 NullPalette_8311028[16] = {}; +const u16 NullPalette_8311048[16] = {}; +const u16 NullPalette_8311068[16] = {}; +const u16 NullPalette_8311088[16] = {}; +const u16 NullPalette_83110A8[16] = {}; +const u16 NullPalette_83110C8[16] = {}; +const u16 NullPalette_83110E8[16] = {}; +const u16 NullPalette_8311108[16] = {}; +const u16 NullPalette_8311128[16] = {}; +const u16 gMapObjectPalette9[] = INCBIN_U16("graphics/map_objects/palettes/09.gbapal"); +const u16 gMapObjectPalette10[] = INCBIN_U16("graphics/map_objects/palettes/10.gbapal"); +const u32 gMapObjectPic_BrendanFieldMove_0[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/field_move/0.4bpp"); +const u32 gMapObjectPic_BrendanFieldMove_1[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/field_move/1.4bpp"); +const u32 gMapObjectPic_BrendanFieldMove_2[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/field_move/2.4bpp"); +const u32 gMapObjectPic_BrendanFieldMove_3[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/field_move/3.4bpp"); +const u32 gMapObjectPic_BrendanFieldMove_4[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/field_move/4.4bpp"); +const u32 gMapObjectPic_BrendanSurfing_0[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/surfing/0.4bpp"); +const u32 gMapObjectPic_BrendanSurfing_3[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/surfing/3.4bpp"); +const u32 gMapObjectPic_BrendanSurfing_1[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/surfing/1.4bpp"); +const u32 gMapObjectPic_BrendanSurfing_4[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/surfing/4.4bpp"); +const u32 gMapObjectPic_BrendanSurfing_2[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/surfing/2.4bpp"); +const u32 gMapObjectPic_BrendanSurfing_5[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/surfing/5.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_0[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/0.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_1[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/1.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_2[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/2.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_3[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/3.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_4[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/4.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_5[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/5.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_6[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/6.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_7[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/7.4bpp"); +const u32 gMapObjectPic_BrendanMachBike_8[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/mach_bike/8.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_0[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/00.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_1[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/01.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_2[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/02.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_3[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/03.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_4[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/04.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_5[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/05.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_6[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/06.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_7[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/07.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_8[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/08.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_9[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/09.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_10[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/10.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_11[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/11.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_12[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/12.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_13[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/13.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_14[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/14.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_15[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/15.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_16[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/16.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_17[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/17.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_18[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/18.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_19[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/19.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_20[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/20.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_21[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/21.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_22[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/22.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_23[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/23.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_24[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/24.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_25[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/25.4bpp"); +const u32 gMapObjectPic_BrendanAcroBike_26[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/acro_bike/26.4bpp"); +const u32 gMapObjectPic_BrendanFishing_0[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/00.4bpp"); +const u32 gMapObjectPic_BrendanFishing_1[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/01.4bpp"); +const u32 gMapObjectPic_BrendanFishing_2[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/02.4bpp"); +const u32 gMapObjectPic_BrendanFishing_3[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/03.4bpp"); +const u32 gMapObjectPic_BrendanFishing_4[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/04.4bpp"); +const u32 gMapObjectPic_BrendanFishing_5[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/05.4bpp"); +const u32 gMapObjectPic_BrendanFishing_6[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/06.4bpp"); +const u32 gMapObjectPic_BrendanFishing_7[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/07.4bpp"); +const u32 gMapObjectPic_BrendanFishing_8[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/08.4bpp"); +const u32 gMapObjectPic_BrendanFishing_9[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/09.4bpp"); +const u32 gMapObjectPic_BrendanFishing_10[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/10.4bpp"); +const u32 gMapObjectPic_BrendanFishing_11[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/fishing/11.4bpp"); +const u32 gMapObjectPic_BrendanWatering_0[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/watering/0.4bpp"); +const u32 gMapObjectPic_BrendanWatering_3[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/watering/3.4bpp"); +const u32 gMapObjectPic_BrendanWatering_1[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/watering/1.4bpp"); +const u32 gMapObjectPic_BrendanWatering_4[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/watering/4.4bpp"); +const u32 gMapObjectPic_BrendanWatering_2[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/watering/2.4bpp"); +const u32 gMapObjectPic_BrendanWatering_5[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/watering/5.4bpp"); +const u32 gMapObjectPic_BrendanDecorating[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/decorating.4bpp"); +const u32 gMapObjectPic_MayDecorating[] = INCBIN_U32("graphics/map_objects/pics/people/may/decorating.4bpp"); +const u32 gMapObjectPic_BrendanUnderwater_0[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/underwater/0.4bpp"); +const u32 gMapObjectPic_BrendanUnderwater_1[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/underwater/1.4bpp"); +const u32 gMapObjectPic_BrendanUnderwater_2[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/underwater/2.4bpp"); +const u32 gMapObjectPic_BrendanUnderwater_3[] = INCBIN_U32("graphics/map_objects/pics/people/brendan/underwater/3.4bpp"); +const u32 gMapObjectPic_MayUnderwater_0[] = INCBIN_U32("graphics/map_objects/pics/people/may/underwater/0.4bpp"); +const u32 gMapObjectPic_MayUnderwater_1[] = INCBIN_U32("graphics/map_objects/pics/people/may/underwater/1.4bpp"); +const u32 gMapObjectPic_MayUnderwater_2[] = INCBIN_U32("graphics/map_objects/pics/people/may/underwater/2.4bpp"); +const u32 gMapObjectPic_MayUnderwater_3[] = INCBIN_U32("graphics/map_objects/pics/people/may/underwater/3.4bpp"); +const u16 gMapObjectPalette11[] = INCBIN_U16("graphics/map_objects/palettes/11.gbapal"); +const u32 gMapObjectPic_MayNormal_0[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/00.4bpp"); +const u32 gMapObjectPic_MayNormal_1[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/01.4bpp"); +const u32 gMapObjectPic_MayNormal_2[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/02.4bpp"); +const u32 gMapObjectPic_MayNormal_3[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/03.4bpp"); +const u32 gMapObjectPic_MayNormal_4[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/04.4bpp"); +const u32 gMapObjectPic_MayNormal_5[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/05.4bpp"); +const u32 gMapObjectPic_MayNormal_6[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/06.4bpp"); +const u32 gMapObjectPic_MayNormal_7[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/07.4bpp"); +const u32 gMapObjectPic_MayNormal_8[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/08.4bpp"); +const u32 gMapObjectPic_MayNormal_9[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/09.4bpp"); +const u32 gMapObjectPic_MayNormal_10[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/10.4bpp"); +const u32 gMapObjectPic_MayNormal_11[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/11.4bpp"); +const u32 gMapObjectPic_MayNormal_12[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/12.4bpp"); +const u32 gMapObjectPic_MayNormal_13[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/13.4bpp"); +const u32 gMapObjectPic_MayNormal_14[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/14.4bpp"); +const u32 gMapObjectPic_MayNormal_15[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/15.4bpp"); +const u32 gMapObjectPic_MayNormal_16[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/16.4bpp"); +const u32 gMapObjectPic_MayNormal_17[] = INCBIN_U32("graphics/map_objects/pics/people/may/normal/17.4bpp"); +const u16 gMapObjectPalette17[] = INCBIN_U16("graphics/map_objects/palettes/17.gbapal"); +const u16 gMapObjectPalette18[] = INCBIN_U16("graphics/map_objects/palettes/18.gbapal"); +const u16 NullPalette_831B7E8[16] = {}; +const u16 NullPalette_831B808[16] = {}; +const u16 NullPalette_831B828[16] = {}; +const u16 NullPalette_831B848[16] = {}; +const u16 NullPalette_831B868[16] = {}; +const u16 NullPalette_831B888[16] = {}; +const u16 NullPalette_831B8A8[16] = {}; +const u16 NullPalette_831B8C8[16] = {}; +const u16 NullPalette_831B8E8[16] = {}; +const u16 NullPalette_831B908[16] = {}; +const u16 NullPalette_831B928[16] = {}; +const u16 NullPalette_831B948[16] = {}; +const u16 NullPalette_831B968[16] = {}; +const u16 NullPalette_831B988[16] = {}; +const u32 gMapObjectPic_MayMachBike_0[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/0.4bpp"); +const u32 gMapObjectPic_MayMachBike_1[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/1.4bpp"); +const u32 gMapObjectPic_MayMachBike_2[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/2.4bpp"); +const u32 gMapObjectPic_MayMachBike_3[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/3.4bpp"); +const u32 gMapObjectPic_MayMachBike_4[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/4.4bpp"); +const u32 gMapObjectPic_MayMachBike_5[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/5.4bpp"); +const u32 gMapObjectPic_MayMachBike_6[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/6.4bpp"); +const u32 gMapObjectPic_MayMachBike_7[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/7.4bpp"); +const u32 gMapObjectPic_MayMachBike_8[] = INCBIN_U32("graphics/map_objects/pics/people/may/mach_bike/8.4bpp"); +const u32 gMapObjectPic_MayAcroBike_0[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/00.4bpp"); +const u32 gMapObjectPic_MayAcroBike_1[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/01.4bpp"); +const u32 gMapObjectPic_MayAcroBike_2[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/02.4bpp"); +const u32 gMapObjectPic_MayAcroBike_3[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/03.4bpp"); +const u32 gMapObjectPic_MayAcroBike_4[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/04.4bpp"); +const u32 gMapObjectPic_MayAcroBike_5[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/05.4bpp"); +const u32 gMapObjectPic_MayAcroBike_6[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/06.4bpp"); +const u32 gMapObjectPic_MayAcroBike_7[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/07.4bpp"); +const u32 gMapObjectPic_MayAcroBike_8[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/08.4bpp"); +const u32 gMapObjectPic_MayAcroBike_9[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/09.4bpp"); +const u32 gMapObjectPic_MayAcroBike_10[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/10.4bpp"); +const u32 gMapObjectPic_MayAcroBike_11[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/11.4bpp"); +const u32 gMapObjectPic_MayAcroBike_12[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/12.4bpp"); +const u32 gMapObjectPic_MayAcroBike_13[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/13.4bpp"); +const u32 gMapObjectPic_MayAcroBike_14[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/14.4bpp"); +const u32 gMapObjectPic_MayAcroBike_15[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/15.4bpp"); +const u32 gMapObjectPic_MayAcroBike_16[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/16.4bpp"); +const u32 gMapObjectPic_MayAcroBike_17[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/17.4bpp"); +const u32 gMapObjectPic_MayAcroBike_18[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/18.4bpp"); +const u32 gMapObjectPic_MayAcroBike_19[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/19.4bpp"); +const u32 gMapObjectPic_MayAcroBike_20[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/20.4bpp"); +const u32 gMapObjectPic_MayAcroBike_21[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/21.4bpp"); +const u32 gMapObjectPic_MayAcroBike_22[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/22.4bpp"); +const u32 gMapObjectPic_MayAcroBike_23[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/23.4bpp"); +const u32 gMapObjectPic_MayAcroBike_24[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/24.4bpp"); +const u32 gMapObjectPic_MayAcroBike_25[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/25.4bpp"); +const u32 gMapObjectPic_MayAcroBike_26[] = INCBIN_U32("graphics/map_objects/pics/people/may/acro_bike/26.4bpp"); +const u32 gMapObjectPic_MaySurfing_0[] = INCBIN_U32("graphics/map_objects/pics/people/may/surfing/0.4bpp"); +const u32 gMapObjectPic_MaySurfing_3[] = INCBIN_U32("graphics/map_objects/pics/people/may/surfing/3.4bpp"); +const u32 gMapObjectPic_MaySurfing_1[] = INCBIN_U32("graphics/map_objects/pics/people/may/surfing/1.4bpp"); +const u32 gMapObjectPic_MaySurfing_4[] = INCBIN_U32("graphics/map_objects/pics/people/may/surfing/4.4bpp"); +const u32 gMapObjectPic_MaySurfing_2[] = INCBIN_U32("graphics/map_objects/pics/people/may/surfing/2.4bpp"); +const u32 gMapObjectPic_MaySurfing_5[] = INCBIN_U32("graphics/map_objects/pics/people/may/surfing/5.4bpp"); +const u32 gMapObjectPic_MayFieldMove_0[] = INCBIN_U32("graphics/map_objects/pics/people/may/field_move/0.4bpp"); +const u32 gMapObjectPic_MayFieldMove_1[] = INCBIN_U32("graphics/map_objects/pics/people/may/field_move/1.4bpp"); +const u32 gMapObjectPic_MayFieldMove_2[] = INCBIN_U32("graphics/map_objects/pics/people/may/field_move/2.4bpp"); +const u32 gMapObjectPic_MayFieldMove_3[] = INCBIN_U32("graphics/map_objects/pics/people/may/field_move/3.4bpp"); +const u32 gMapObjectPic_MayFieldMove_4[] = INCBIN_U32("graphics/map_objects/pics/people/may/field_move/4.4bpp"); +const u32 gMapObjectPic_MayFishing_0[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/00.4bpp"); +const u32 gMapObjectPic_MayFishing_1[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/01.4bpp"); +const u32 gMapObjectPic_MayFishing_2[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/02.4bpp"); +const u32 gMapObjectPic_MayFishing_3[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/03.4bpp"); +const u32 gMapObjectPic_MayFishing_4[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/04.4bpp"); +const u32 gMapObjectPic_MayFishing_5[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/05.4bpp"); +const u32 gMapObjectPic_MayFishing_6[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/06.4bpp"); +const u32 gMapObjectPic_MayFishing_7[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/07.4bpp"); +const u32 gMapObjectPic_MayFishing_8[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/08.4bpp"); +const u32 gMapObjectPic_MayFishing_9[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/09.4bpp"); +const u32 gMapObjectPic_MayFishing_10[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/10.4bpp"); +const u32 gMapObjectPic_MayFishing_11[] = INCBIN_U32("graphics/map_objects/pics/people/may/fishing/11.4bpp"); +const u32 gMapObjectPic_MayWatering_0[] = INCBIN_U32("graphics/map_objects/pics/people/may/watering/0.4bpp"); +const u32 gMapObjectPic_MayWatering_3[] = INCBIN_U32("graphics/map_objects/pics/people/may/watering/3.4bpp"); +const u32 gMapObjectPic_MayWatering_1[] = INCBIN_U32("graphics/map_objects/pics/people/may/watering/1.4bpp"); +const u32 gMapObjectPic_MayWatering_4[] = INCBIN_U32("graphics/map_objects/pics/people/may/watering/4.4bpp"); +const u32 gMapObjectPic_MayWatering_2[] = INCBIN_U32("graphics/map_objects/pics/people/may/watering/2.4bpp"); +const u32 gMapObjectPic_MayWatering_5[] = INCBIN_U32("graphics/map_objects/pics/people/may/watering/5.4bpp"); +const u16 gMapObjectPalette0[] = INCBIN_U16("graphics/map_objects/palettes/00.gbapal"); +const u16 gMapObjectPalette1[] = INCBIN_U16("graphics/map_objects/palettes/01.gbapal"); +const u16 gMapObjectPalette2[] = INCBIN_U16("graphics/map_objects/palettes/02.gbapal"); +const u16 gMapObjectPalette3[] = INCBIN_U16("graphics/map_objects/palettes/03.gbapal"); +const u16 gMapObjectPalette4[] = INCBIN_U16("graphics/map_objects/palettes/04.gbapal"); +const u16 gMapObjectPalette5[] = INCBIN_U16("graphics/map_objects/palettes/05.gbapal"); +const u16 gMapObjectPalette6[] = INCBIN_U16("graphics/map_objects/palettes/06.gbapal"); +const u16 gMapObjectPalette7[] = INCBIN_U16("graphics/map_objects/palettes/07.gbapal"); +const u32 gMapObjectPic_LittleBoy1_0[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/0.4bpp"); +const u32 gMapObjectPic_LittleBoy1_1[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/1.4bpp"); +const u32 gMapObjectPic_LittleBoy1_2[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/2.4bpp"); +const u32 gMapObjectPic_LittleBoy1_3[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/3.4bpp"); +const u32 gMapObjectPic_LittleBoy1_4[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/4.4bpp"); +const u32 gMapObjectPic_LittleBoy1_5[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/5.4bpp"); +const u32 gMapObjectPic_LittleBoy1_6[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/6.4bpp"); +const u32 gMapObjectPic_LittleBoy1_7[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/7.4bpp"); +const u32 gMapObjectPic_LittleBoy1_8[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_1/8.4bpp"); +const u32 gMapObjectPic_LittleGirl1_0[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/0.4bpp"); +const u32 gMapObjectPic_LittleGirl1_1[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/1.4bpp"); +const u32 gMapObjectPic_LittleGirl1_2[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/2.4bpp"); +const u32 gMapObjectPic_LittleGirl1_3[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/3.4bpp"); +const u32 gMapObjectPic_LittleGirl1_4[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/4.4bpp"); +const u32 gMapObjectPic_LittleGirl1_5[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/5.4bpp"); +const u32 gMapObjectPic_LittleGirl1_6[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/6.4bpp"); +const u32 gMapObjectPic_LittleGirl1_7[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/7.4bpp"); +const u32 gMapObjectPic_LittleGirl1_8[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_1/8.4bpp"); +const u32 gMapObjectPic_Boy1_0[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/0.4bpp"); +const u32 gMapObjectPic_Boy1_1[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/1.4bpp"); +const u32 gMapObjectPic_Boy1_2[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/2.4bpp"); +const u32 gMapObjectPic_Boy1_3[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/3.4bpp"); +const u32 gMapObjectPic_Boy1_4[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/4.4bpp"); +const u32 gMapObjectPic_Boy1_5[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/5.4bpp"); +const u32 gMapObjectPic_Boy1_6[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/6.4bpp"); +const u32 gMapObjectPic_Boy1_7[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/7.4bpp"); +const u32 gMapObjectPic_Boy1_8[] = INCBIN_U32("graphics/map_objects/pics/people/boy_1/8.4bpp"); +const u32 gMapObjectPic_Girl1_0[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/0.4bpp"); +const u32 gMapObjectPic_Girl1_1[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/1.4bpp"); +const u32 gMapObjectPic_Girl1_2[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/2.4bpp"); +const u32 gMapObjectPic_Girl1_3[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/3.4bpp"); +const u32 gMapObjectPic_Girl1_4[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/4.4bpp"); +const u32 gMapObjectPic_Girl1_5[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/5.4bpp"); +const u32 gMapObjectPic_Girl1_6[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/6.4bpp"); +const u32 gMapObjectPic_Girl1_7[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/7.4bpp"); +const u32 gMapObjectPic_Girl1_8[] = INCBIN_U32("graphics/map_objects/pics/people/girl_1/8.4bpp"); +const u32 gMapObjectPic_Boy2_0[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/0.4bpp"); +const u32 gMapObjectPic_Boy2_1[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/1.4bpp"); +const u32 gMapObjectPic_Boy2_2[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/2.4bpp"); +const u32 gMapObjectPic_Boy2_3[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/3.4bpp"); +const u32 gMapObjectPic_Boy2_4[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/4.4bpp"); +const u32 gMapObjectPic_Boy2_5[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/5.4bpp"); +const u32 gMapObjectPic_Boy2_6[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/6.4bpp"); +const u32 gMapObjectPic_Boy2_7[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/7.4bpp"); +const u32 gMapObjectPic_Boy2_8[] = INCBIN_U32("graphics/map_objects/pics/people/boy_2/8.4bpp"); +const u32 gMapObjectPic_Girl2_0[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/0.4bpp"); +const u32 gMapObjectPic_Girl2_1[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/1.4bpp"); +const u32 gMapObjectPic_Girl2_2[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/2.4bpp"); +const u32 gMapObjectPic_Girl2_3[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/3.4bpp"); +const u32 gMapObjectPic_Girl2_4[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/4.4bpp"); +const u32 gMapObjectPic_Girl2_5[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/5.4bpp"); +const u32 gMapObjectPic_Girl2_6[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/6.4bpp"); +const u32 gMapObjectPic_Girl2_7[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/7.4bpp"); +const u32 gMapObjectPic_Girl2_8[] = INCBIN_U32("graphics/map_objects/pics/people/girl_2/8.4bpp"); +const u32 gMapObjectPic_LittleBoy2_0[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/0.4bpp"); +const u32 gMapObjectPic_LittleBoy2_1[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/1.4bpp"); +const u32 gMapObjectPic_LittleBoy2_2[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/2.4bpp"); +const u32 gMapObjectPic_LittleBoy2_3[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/3.4bpp"); +const u32 gMapObjectPic_LittleBoy2_4[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/4.4bpp"); +const u32 gMapObjectPic_LittleBoy2_5[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/5.4bpp"); +const u32 gMapObjectPic_LittleBoy2_6[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/6.4bpp"); +const u32 gMapObjectPic_LittleBoy2_7[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/7.4bpp"); +const u32 gMapObjectPic_LittleBoy2_8[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_2/8.4bpp"); +const u32 gMapObjectPic_LittleGirl2_0[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/0.4bpp"); +const u32 gMapObjectPic_LittleGirl2_1[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/1.4bpp"); +const u32 gMapObjectPic_LittleGirl2_2[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/2.4bpp"); +const u32 gMapObjectPic_LittleGirl2_3[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/3.4bpp"); +const u32 gMapObjectPic_LittleGirl2_4[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/4.4bpp"); +const u32 gMapObjectPic_LittleGirl2_5[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/5.4bpp"); +const u32 gMapObjectPic_LittleGirl2_6[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/6.4bpp"); +const u32 gMapObjectPic_LittleGirl2_7[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/7.4bpp"); +const u32 gMapObjectPic_LittleGirl2_8[] = INCBIN_U32("graphics/map_objects/pics/people/little_girl_2/8.4bpp"); +const u32 gMapObjectPic_Boy3_0[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/0.4bpp"); +const u32 gMapObjectPic_Boy3_1[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/1.4bpp"); +const u32 gMapObjectPic_Boy3_2[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/2.4bpp"); +const u32 gMapObjectPic_Boy3_3[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/3.4bpp"); +const u32 gMapObjectPic_Boy3_4[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/4.4bpp"); +const u32 gMapObjectPic_Boy3_5[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/5.4bpp"); +const u32 gMapObjectPic_Boy3_6[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/6.4bpp"); +const u32 gMapObjectPic_Boy3_7[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/7.4bpp"); +const u32 gMapObjectPic_Boy3_8[] = INCBIN_U32("graphics/map_objects/pics/people/boy_3/8.4bpp"); +const u32 gMapObjectPic_Girl3_0[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/0.4bpp"); +const u32 gMapObjectPic_Girl3_1[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/1.4bpp"); +const u32 gMapObjectPic_Girl3_2[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/2.4bpp"); +const u32 gMapObjectPic_Girl3_3[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/3.4bpp"); +const u32 gMapObjectPic_Girl3_4[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/4.4bpp"); +const u32 gMapObjectPic_Girl3_5[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/5.4bpp"); +const u32 gMapObjectPic_Girl3_6[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/6.4bpp"); +const u32 gMapObjectPic_Girl3_7[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/7.4bpp"); +const u32 gMapObjectPic_Girl3_8[] = INCBIN_U32("graphics/map_objects/pics/people/girl_3/8.4bpp"); +const u32 gMapObjectPic_Boy4_0[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/0.4bpp"); +const u32 gMapObjectPic_Boy4_1[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/1.4bpp"); +const u32 gMapObjectPic_Boy4_2[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/2.4bpp"); +const u32 gMapObjectPic_Boy4_3[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/3.4bpp"); +const u32 gMapObjectPic_Boy4_4[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/4.4bpp"); +const u32 gMapObjectPic_Boy4_5[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/5.4bpp"); +const u32 gMapObjectPic_Boy4_6[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/6.4bpp"); +const u32 gMapObjectPic_Boy4_7[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/7.4bpp"); +const u32 gMapObjectPic_Boy4_8[] = INCBIN_U32("graphics/map_objects/pics/people/boy_4/8.4bpp"); +const u32 gMapObjectPic_Woman1_0[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/0.4bpp"); +const u32 gMapObjectPic_Woman1_1[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/1.4bpp"); +const u32 gMapObjectPic_Woman1_2[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/2.4bpp"); +const u32 gMapObjectPic_Woman1_3[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/3.4bpp"); +const u32 gMapObjectPic_Woman1_4[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/4.4bpp"); +const u32 gMapObjectPic_Woman1_5[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/5.4bpp"); +const u32 gMapObjectPic_Woman1_6[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/6.4bpp"); +const u32 gMapObjectPic_Woman1_7[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/7.4bpp"); +const u32 gMapObjectPic_Woman1_8[] = INCBIN_U32("graphics/map_objects/pics/people/woman_1/8.4bpp"); +const u32 gMapObjectPic_FatMan_0[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/0.4bpp"); +const u32 gMapObjectPic_FatMan_1[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/1.4bpp"); +const u32 gMapObjectPic_FatMan_2[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/2.4bpp"); +const u32 gMapObjectPic_FatMan_3[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/3.4bpp"); +const u32 gMapObjectPic_FatMan_4[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/4.4bpp"); +const u32 gMapObjectPic_FatMan_5[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/5.4bpp"); +const u32 gMapObjectPic_FatMan_6[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/6.4bpp"); +const u32 gMapObjectPic_FatMan_7[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/7.4bpp"); +const u32 gMapObjectPic_FatMan_8[] = INCBIN_U32("graphics/map_objects/pics/people/fat_man/8.4bpp"); +const u32 gMapObjectPic_Woman2_0[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/0.4bpp"); +const u32 gMapObjectPic_Woman2_1[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/1.4bpp"); +const u32 gMapObjectPic_Woman2_2[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/2.4bpp"); +const u32 gMapObjectPic_Woman2_3[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/3.4bpp"); +const u32 gMapObjectPic_Woman2_4[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/4.4bpp"); +const u32 gMapObjectPic_Woman2_5[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/5.4bpp"); +const u32 gMapObjectPic_Woman2_6[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/6.4bpp"); +const u32 gMapObjectPic_Woman2_7[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/7.4bpp"); +const u32 gMapObjectPic_Woman2_8[] = INCBIN_U32("graphics/map_objects/pics/people/woman_2/8.4bpp"); +const u32 gMapObjectPic_Man1_0[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/0.4bpp"); +const u32 gMapObjectPic_Man1_1[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/1.4bpp"); +const u32 gMapObjectPic_Man1_2[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/2.4bpp"); +const u32 gMapObjectPic_Man1_3[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/3.4bpp"); +const u32 gMapObjectPic_Man1_4[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/4.4bpp"); +const u32 gMapObjectPic_Man1_5[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/5.4bpp"); +const u32 gMapObjectPic_Man1_6[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/6.4bpp"); +const u32 gMapObjectPic_Man1_7[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/7.4bpp"); +const u32 gMapObjectPic_Man1_8[] = INCBIN_U32("graphics/map_objects/pics/people/man_1/8.4bpp"); +const u32 gMapObjectPic_Woman3_0[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/0.4bpp"); +const u32 gMapObjectPic_Woman3_1[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/1.4bpp"); +const u32 gMapObjectPic_Woman3_2[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/2.4bpp"); +const u32 gMapObjectPic_Woman3_3[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/3.4bpp"); +const u32 gMapObjectPic_Woman3_4[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/4.4bpp"); +const u32 gMapObjectPic_Woman3_5[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/5.4bpp"); +const u32 gMapObjectPic_Woman3_6[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/6.4bpp"); +const u32 gMapObjectPic_Woman3_7[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/7.4bpp"); +const u32 gMapObjectPic_Woman3_8[] = INCBIN_U32("graphics/map_objects/pics/people/woman_3/8.4bpp"); +const u32 gMapObjectPic_OldMan1_0[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/0.4bpp"); +const u32 gMapObjectPic_OldMan1_1[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/1.4bpp"); +const u32 gMapObjectPic_OldMan1_2[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/2.4bpp"); +const u32 gMapObjectPic_OldMan1_3[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/3.4bpp"); +const u32 gMapObjectPic_OldMan1_4[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/4.4bpp"); +const u32 gMapObjectPic_OldMan1_5[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/5.4bpp"); +const u32 gMapObjectPic_OldMan1_6[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/6.4bpp"); +const u32 gMapObjectPic_OldMan1_7[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/7.4bpp"); +const u32 gMapObjectPic_OldMan1_8[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_1/8.4bpp"); +const u32 gMapObjectPic_OldWoman1_0[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/0.4bpp"); +const u32 gMapObjectPic_OldWoman1_1[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/1.4bpp"); +const u32 gMapObjectPic_OldWoman1_2[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/2.4bpp"); +const u32 gMapObjectPic_OldWoman1_3[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/3.4bpp"); +const u32 gMapObjectPic_OldWoman1_4[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/4.4bpp"); +const u32 gMapObjectPic_OldWoman1_5[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/5.4bpp"); +const u32 gMapObjectPic_OldWoman1_6[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/6.4bpp"); +const u32 gMapObjectPic_OldWoman1_7[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/7.4bpp"); +const u32 gMapObjectPic_OldWoman1_8[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_1/8.4bpp"); +const u32 gMapObjectPic_Man2_0[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/0.4bpp"); +const u32 gMapObjectPic_Man2_1[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/1.4bpp"); +const u32 gMapObjectPic_Man2_2[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/2.4bpp"); +const u32 gMapObjectPic_Man2_3[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/3.4bpp"); +const u32 gMapObjectPic_Man2_4[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/4.4bpp"); +const u32 gMapObjectPic_Man2_5[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/5.4bpp"); +const u32 gMapObjectPic_Man2_6[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/6.4bpp"); +const u32 gMapObjectPic_Man2_7[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/7.4bpp"); +const u32 gMapObjectPic_Man2_8[] = INCBIN_U32("graphics/map_objects/pics/people/man_2/8.4bpp"); +const u32 gMapObjectPic_Woman4_0[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/0.4bpp"); +const u32 gMapObjectPic_Woman4_1[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/1.4bpp"); +const u32 gMapObjectPic_Woman4_2[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/2.4bpp"); +const u32 gMapObjectPic_Woman4_3[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/3.4bpp"); +const u32 gMapObjectPic_Woman4_4[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/4.4bpp"); +const u32 gMapObjectPic_Woman4_5[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/5.4bpp"); +const u32 gMapObjectPic_Woman4_6[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/6.4bpp"); +const u32 gMapObjectPic_Woman4_7[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/7.4bpp"); +const u32 gMapObjectPic_Woman4_8[] = INCBIN_U32("graphics/map_objects/pics/people/woman_4/8.4bpp"); +const u32 gMapObjectPic_Man3_0[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/0.4bpp"); +const u32 gMapObjectPic_Man3_1[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/1.4bpp"); +const u32 gMapObjectPic_Man3_2[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/2.4bpp"); +const u32 gMapObjectPic_Man3_3[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/3.4bpp"); +const u32 gMapObjectPic_Man3_4[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/4.4bpp"); +const u32 gMapObjectPic_Man3_5[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/5.4bpp"); +const u32 gMapObjectPic_Man3_6[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/6.4bpp"); +const u32 gMapObjectPic_Man3_7[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/7.4bpp"); +const u32 gMapObjectPic_Man3_8[] = INCBIN_U32("graphics/map_objects/pics/people/man_3/8.4bpp"); +const u32 gMapObjectPic_Woman5_0[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/0.4bpp"); +const u32 gMapObjectPic_Woman5_1[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/1.4bpp"); +const u32 gMapObjectPic_Woman5_2[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/2.4bpp"); +const u32 gMapObjectPic_Woman5_3[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/3.4bpp"); +const u32 gMapObjectPic_Woman5_4[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/4.4bpp"); +const u32 gMapObjectPic_Woman5_5[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/5.4bpp"); +const u32 gMapObjectPic_Woman5_6[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/6.4bpp"); +const u32 gMapObjectPic_Woman5_7[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/7.4bpp"); +const u32 gMapObjectPic_Woman5_8[] = INCBIN_U32("graphics/map_objects/pics/people/woman_5/8.4bpp"); +const u32 gMapObjectPic_Cook_0[] = INCBIN_U32("graphics/map_objects/pics/people/cook/0.4bpp"); +const u32 gMapObjectPic_Cook_1[] = INCBIN_U32("graphics/map_objects/pics/people/cook/1.4bpp"); +const u32 gMapObjectPic_Cook_2[] = INCBIN_U32("graphics/map_objects/pics/people/cook/2.4bpp"); +const u32 gMapObjectPic_Woman6_0[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/0.4bpp"); +const u32 gMapObjectPic_Woman6_1[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/1.4bpp"); +const u32 gMapObjectPic_Woman6_2[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/2.4bpp"); +const u32 gMapObjectPic_Woman6_3[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/3.4bpp"); +const u32 gMapObjectPic_Woman6_4[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/4.4bpp"); +const u32 gMapObjectPic_Woman6_5[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/5.4bpp"); +const u32 gMapObjectPic_Woman6_6[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/6.4bpp"); +const u32 gMapObjectPic_Woman6_7[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/7.4bpp"); +const u32 gMapObjectPic_Woman6_8[] = INCBIN_U32("graphics/map_objects/pics/people/woman_6/8.4bpp"); +const u32 gMapObjectPic_OldMan2_0[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_2/0.4bpp"); +const u32 gMapObjectPic_OldMan2_1[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_2/1.4bpp"); +const u32 gMapObjectPic_OldMan2_2[] = INCBIN_U32("graphics/map_objects/pics/people/old_man_2/2.4bpp"); +const u32 gMapObjectPic_OldWoman2_0[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_2/0.4bpp"); +const u32 gMapObjectPic_OldWoman2_1[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_2/1.4bpp"); +const u32 gMapObjectPic_OldWoman2_2[] = INCBIN_U32("graphics/map_objects/pics/people/old_woman_2/2.4bpp"); +const u32 gMapObjectPic_Camper_0[] = INCBIN_U32("graphics/map_objects/pics/people/camper/0.4bpp"); +const u32 gMapObjectPic_Camper_1[] = INCBIN_U32("graphics/map_objects/pics/people/camper/1.4bpp"); +const u32 gMapObjectPic_Camper_2[] = INCBIN_U32("graphics/map_objects/pics/people/camper/2.4bpp"); +const u32 gMapObjectPic_Camper_3[] = INCBIN_U32("graphics/map_objects/pics/people/camper/3.4bpp"); +const u32 gMapObjectPic_Camper_4[] = INCBIN_U32("graphics/map_objects/pics/people/camper/4.4bpp"); +const u32 gMapObjectPic_Camper_5[] = INCBIN_U32("graphics/map_objects/pics/people/camper/5.4bpp"); +const u32 gMapObjectPic_Camper_6[] = INCBIN_U32("graphics/map_objects/pics/people/camper/6.4bpp"); +const u32 gMapObjectPic_Camper_7[] = INCBIN_U32("graphics/map_objects/pics/people/camper/7.4bpp"); +const u32 gMapObjectPic_Camper_8[] = INCBIN_U32("graphics/map_objects/pics/people/camper/8.4bpp"); +const u32 gMapObjectPic_Picnicker_0[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/0.4bpp"); +const u32 gMapObjectPic_Picnicker_1[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/1.4bpp"); +const u32 gMapObjectPic_Picnicker_2[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/2.4bpp"); +const u32 gMapObjectPic_Picnicker_3[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/3.4bpp"); +const u32 gMapObjectPic_Picnicker_4[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/4.4bpp"); +const u32 gMapObjectPic_Picnicker_5[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/5.4bpp"); +const u32 gMapObjectPic_Picnicker_6[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/6.4bpp"); +const u32 gMapObjectPic_Picnicker_7[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/7.4bpp"); +const u32 gMapObjectPic_Picnicker_8[] = INCBIN_U32("graphics/map_objects/pics/people/picnicker/8.4bpp"); +const u32 gMapObjectPic_Man4_0[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/0.4bpp"); +const u32 gMapObjectPic_Man4_1[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/1.4bpp"); +const u32 gMapObjectPic_Man4_2[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/2.4bpp"); +const u32 gMapObjectPic_Man4_3[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/3.4bpp"); +const u32 gMapObjectPic_Man4_4[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/4.4bpp"); +const u32 gMapObjectPic_Man4_5[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/5.4bpp"); +const u32 gMapObjectPic_Man4_6[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/6.4bpp"); +const u32 gMapObjectPic_Man4_7[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/7.4bpp"); +const u32 gMapObjectPic_Man4_8[] = INCBIN_U32("graphics/map_objects/pics/people/man_4/8.4bpp"); +const u32 gMapObjectPic_Woman7_0[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/0.4bpp"); +const u32 gMapObjectPic_Woman7_1[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/1.4bpp"); +const u32 gMapObjectPic_Woman7_2[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/2.4bpp"); +const u32 gMapObjectPic_Woman7_3[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/3.4bpp"); +const u32 gMapObjectPic_Woman7_4[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/4.4bpp"); +const u32 gMapObjectPic_Woman7_5[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/5.4bpp"); +const u32 gMapObjectPic_Woman7_6[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/6.4bpp"); +const u32 gMapObjectPic_Woman7_7[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/7.4bpp"); +const u32 gMapObjectPic_Woman7_8[] = INCBIN_U32("graphics/map_objects/pics/people/woman_7/8.4bpp"); +const u32 gMapObjectPic_Youngster_0[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/0.4bpp"); +const u32 gMapObjectPic_Youngster_1[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/1.4bpp"); +const u32 gMapObjectPic_Youngster_2[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/2.4bpp"); +const u32 gMapObjectPic_Youngster_3[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/3.4bpp"); +const u32 gMapObjectPic_Youngster_4[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/4.4bpp"); +const u32 gMapObjectPic_Youngster_5[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/5.4bpp"); +const u32 gMapObjectPic_Youngster_6[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/6.4bpp"); +const u32 gMapObjectPic_Youngster_7[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/7.4bpp"); +const u32 gMapObjectPic_Youngster_8[] = INCBIN_U32("graphics/map_objects/pics/people/youngster/8.4bpp"); +const u32 gMapObjectPic_BugCatcher_0[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/0.4bpp"); +const u32 gMapObjectPic_BugCatcher_1[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/1.4bpp"); +const u32 gMapObjectPic_BugCatcher_2[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/2.4bpp"); +const u32 gMapObjectPic_BugCatcher_3[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/3.4bpp"); +const u32 gMapObjectPic_BugCatcher_4[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/4.4bpp"); +const u32 gMapObjectPic_BugCatcher_5[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/5.4bpp"); +const u32 gMapObjectPic_BugCatcher_6[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/6.4bpp"); +const u32 gMapObjectPic_BugCatcher_7[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/7.4bpp"); +const u32 gMapObjectPic_BugCatcher_8[] = INCBIN_U32("graphics/map_objects/pics/people/bug_catcher/8.4bpp"); +const u32 gMapObjectPic_PsychicM_0[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/0.4bpp"); +const u32 gMapObjectPic_PsychicM_1[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/1.4bpp"); +const u32 gMapObjectPic_PsychicM_2[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/2.4bpp"); +const u32 gMapObjectPic_PsychicM_3[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/3.4bpp"); +const u32 gMapObjectPic_PsychicM_4[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/4.4bpp"); +const u32 gMapObjectPic_PsychicM_5[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/5.4bpp"); +const u32 gMapObjectPic_PsychicM_6[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/6.4bpp"); +const u32 gMapObjectPic_PsychicM_7[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/7.4bpp"); +const u32 gMapObjectPic_PsychicM_8[] = INCBIN_U32("graphics/map_objects/pics/people/psychic_m/8.4bpp"); +const u32 gMapObjectPic_SchoolKidM_0[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/0.4bpp"); +const u32 gMapObjectPic_SchoolKidM_1[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/1.4bpp"); +const u32 gMapObjectPic_SchoolKidM_2[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/2.4bpp"); +const u32 gMapObjectPic_SchoolKidM_3[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/3.4bpp"); +const u32 gMapObjectPic_SchoolKidM_4[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/4.4bpp"); +const u32 gMapObjectPic_SchoolKidM_5[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/5.4bpp"); +const u32 gMapObjectPic_SchoolKidM_6[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/6.4bpp"); +const u32 gMapObjectPic_SchoolKidM_7[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/7.4bpp"); +const u32 gMapObjectPic_SchoolKidM_8[] = INCBIN_U32("graphics/map_objects/pics/people/school_kid_m/8.4bpp"); +const u32 gMapObjectPic_Maniac_0[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/0.4bpp"); +const u32 gMapObjectPic_Maniac_1[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/1.4bpp"); +const u32 gMapObjectPic_Maniac_2[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/2.4bpp"); +const u32 gMapObjectPic_Maniac_3[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/3.4bpp"); +const u32 gMapObjectPic_Maniac_4[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/4.4bpp"); +const u32 gMapObjectPic_Maniac_5[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/5.4bpp"); +const u32 gMapObjectPic_Maniac_6[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/6.4bpp"); +const u32 gMapObjectPic_Maniac_7[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/7.4bpp"); +const u32 gMapObjectPic_Maniac_8[] = INCBIN_U32("graphics/map_objects/pics/people/maniac/8.4bpp"); +const u32 gMapObjectPic_HexManiac_0[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/0.4bpp"); +const u32 gMapObjectPic_HexManiac_1[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/1.4bpp"); +const u32 gMapObjectPic_HexManiac_2[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/2.4bpp"); +const u32 gMapObjectPic_HexManiac_3[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/3.4bpp"); +const u32 gMapObjectPic_HexManiac_4[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/4.4bpp"); +const u32 gMapObjectPic_HexManiac_5[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/5.4bpp"); +const u32 gMapObjectPic_HexManiac_6[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/6.4bpp"); +const u32 gMapObjectPic_HexManiac_7[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/7.4bpp"); +const u32 gMapObjectPic_HexManiac_8[] = INCBIN_U32("graphics/map_objects/pics/people/hex_maniac/8.4bpp"); +const u32 gMapObjectPic_Woman8_0[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/0.4bpp"); +const u32 gMapObjectPic_Woman8_1[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/1.4bpp"); +const u32 gMapObjectPic_Woman8_2[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/2.4bpp"); +const u32 gMapObjectPic_Woman8_3[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/3.4bpp"); +const u32 gMapObjectPic_Woman8_4[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/4.4bpp"); +const u32 gMapObjectPic_Woman8_5[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/5.4bpp"); +const u32 gMapObjectPic_Woman8_6[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/6.4bpp"); +const u32 gMapObjectPic_Woman8_7[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/7.4bpp"); +const u32 gMapObjectPic_Woman8_8[] = INCBIN_U32("graphics/map_objects/pics/people/woman_8/8.4bpp"); +const u32 gMapObjectPic_SwimmerM_0[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/0.4bpp"); +const u32 gMapObjectPic_SwimmerM_1[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/1.4bpp"); +const u32 gMapObjectPic_SwimmerM_2[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/2.4bpp"); +const u32 gMapObjectPic_SwimmerM_3[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/3.4bpp"); +const u32 gMapObjectPic_SwimmerM_4[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/4.4bpp"); +const u32 gMapObjectPic_SwimmerM_5[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/5.4bpp"); +const u32 gMapObjectPic_SwimmerM_6[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/6.4bpp"); +const u32 gMapObjectPic_SwimmerM_7[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/7.4bpp"); +const u32 gMapObjectPic_SwimmerM_8[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_m/8.4bpp"); +const u32 gMapObjectPic_SwimmerF_0[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/0.4bpp"); +const u32 gMapObjectPic_SwimmerF_1[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/1.4bpp"); +const u32 gMapObjectPic_SwimmerF_2[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/2.4bpp"); +const u32 gMapObjectPic_SwimmerF_3[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/3.4bpp"); +const u32 gMapObjectPic_SwimmerF_4[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/4.4bpp"); +const u32 gMapObjectPic_SwimmerF_5[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/5.4bpp"); +const u32 gMapObjectPic_SwimmerF_6[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/6.4bpp"); +const u32 gMapObjectPic_SwimmerF_7[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/7.4bpp"); +const u32 gMapObjectPic_SwimmerF_8[] = INCBIN_U32("graphics/map_objects/pics/people/swimmer_f/8.4bpp"); +const u32 gMapObjectPic_BlackBelt_0[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/0.4bpp"); +const u32 gMapObjectPic_BlackBelt_1[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/1.4bpp"); +const u32 gMapObjectPic_BlackBelt_2[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/2.4bpp"); +const u32 gMapObjectPic_BlackBelt_3[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/3.4bpp"); +const u32 gMapObjectPic_BlackBelt_4[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/4.4bpp"); +const u32 gMapObjectPic_BlackBelt_5[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/5.4bpp"); +const u32 gMapObjectPic_BlackBelt_6[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/6.4bpp"); +const u32 gMapObjectPic_BlackBelt_7[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/7.4bpp"); +const u32 gMapObjectPic_BlackBelt_8[] = INCBIN_U32("graphics/map_objects/pics/people/black_belt/8.4bpp"); +const u32 gMapObjectPic_Beauty_0[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/0.4bpp"); +const u32 gMapObjectPic_Beauty_1[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/1.4bpp"); +const u32 gMapObjectPic_Beauty_2[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/2.4bpp"); +const u32 gMapObjectPic_Beauty_3[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/3.4bpp"); +const u32 gMapObjectPic_Beauty_4[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/4.4bpp"); +const u32 gMapObjectPic_Beauty_5[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/5.4bpp"); +const u32 gMapObjectPic_Beauty_6[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/6.4bpp"); +const u32 gMapObjectPic_Beauty_7[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/7.4bpp"); +const u32 gMapObjectPic_Beauty_8[] = INCBIN_U32("graphics/map_objects/pics/people/beauty/8.4bpp"); +const u32 gMapObjectPic_Scientist1_0[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/0.4bpp"); +const u32 gMapObjectPic_Scientist1_1[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/1.4bpp"); +const u32 gMapObjectPic_Scientist1_2[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/2.4bpp"); +const u32 gMapObjectPic_Scientist1_3[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/3.4bpp"); +const u32 gMapObjectPic_Scientist1_4[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/4.4bpp"); +const u32 gMapObjectPic_Scientist1_5[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/5.4bpp"); +const u32 gMapObjectPic_Scientist1_6[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/6.4bpp"); +const u32 gMapObjectPic_Scientist1_7[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/7.4bpp"); +const u32 gMapObjectPic_Scientist1_8[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_1/8.4bpp"); +const u32 gMapObjectPic_Lass_0[] = INCBIN_U32("graphics/map_objects/pics/people/lass/0.4bpp"); +const u32 gMapObjectPic_Lass_1[] = INCBIN_U32("graphics/map_objects/pics/people/lass/1.4bpp"); +const u32 gMapObjectPic_Lass_2[] = INCBIN_U32("graphics/map_objects/pics/people/lass/2.4bpp"); +const u32 gMapObjectPic_Lass_3[] = INCBIN_U32("graphics/map_objects/pics/people/lass/3.4bpp"); +const u32 gMapObjectPic_Lass_4[] = INCBIN_U32("graphics/map_objects/pics/people/lass/4.4bpp"); +const u32 gMapObjectPic_Lass_5[] = INCBIN_U32("graphics/map_objects/pics/people/lass/5.4bpp"); +const u32 gMapObjectPic_Lass_6[] = INCBIN_U32("graphics/map_objects/pics/people/lass/6.4bpp"); +const u32 gMapObjectPic_Lass_7[] = INCBIN_U32("graphics/map_objects/pics/people/lass/7.4bpp"); +const u32 gMapObjectPic_Lass_8[] = INCBIN_U32("graphics/map_objects/pics/people/lass/8.4bpp"); +const u32 gMapObjectPic_Gentleman_0[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/0.4bpp"); +const u32 gMapObjectPic_Gentleman_1[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/1.4bpp"); +const u32 gMapObjectPic_Gentleman_2[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/2.4bpp"); +const u32 gMapObjectPic_Gentleman_3[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/3.4bpp"); +const u32 gMapObjectPic_Gentleman_4[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/4.4bpp"); +const u32 gMapObjectPic_Gentleman_5[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/5.4bpp"); +const u32 gMapObjectPic_Gentleman_6[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/6.4bpp"); +const u32 gMapObjectPic_Gentleman_7[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/7.4bpp"); +const u32 gMapObjectPic_Gentleman_8[] = INCBIN_U32("graphics/map_objects/pics/people/gentleman/8.4bpp"); +const u32 gMapObjectPic_Sailor_0[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/0.4bpp"); +const u32 gMapObjectPic_Sailor_1[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/1.4bpp"); +const u32 gMapObjectPic_Sailor_2[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/2.4bpp"); +const u32 gMapObjectPic_Sailor_3[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/3.4bpp"); +const u32 gMapObjectPic_Sailor_4[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/4.4bpp"); +const u32 gMapObjectPic_Sailor_5[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/5.4bpp"); +const u32 gMapObjectPic_Sailor_6[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/6.4bpp"); +const u32 gMapObjectPic_Sailor_7[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/7.4bpp"); +const u32 gMapObjectPic_Sailor_8[] = INCBIN_U32("graphics/map_objects/pics/people/sailor/8.4bpp"); +const u32 gMapObjectPic_Fisherman_0[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/0.4bpp"); +const u32 gMapObjectPic_Fisherman_1[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/1.4bpp"); +const u32 gMapObjectPic_Fisherman_2[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/2.4bpp"); +const u32 gMapObjectPic_Fisherman_3[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/3.4bpp"); +const u32 gMapObjectPic_Fisherman_4[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/4.4bpp"); +const u32 gMapObjectPic_Fisherman_5[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/5.4bpp"); +const u32 gMapObjectPic_Fisherman_6[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/6.4bpp"); +const u32 gMapObjectPic_Fisherman_7[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/7.4bpp"); +const u32 gMapObjectPic_Fisherman_8[] = INCBIN_U32("graphics/map_objects/pics/people/fisherman/8.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_0[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/0.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_1[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/1.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_2[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/2.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_3[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/3.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_4[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/4.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_5[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/5.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_6[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/6.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_7[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/7.4bpp"); +const u32 gMapObjectPic_RunningTriathleteM_8[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_m/8.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_0[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/0.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_1[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/1.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_2[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/2.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_3[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/3.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_4[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/4.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_5[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/5.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_6[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/6.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_7[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/7.4bpp"); +const u32 gMapObjectPic_RunningTriathleteF_8[] = INCBIN_U32("graphics/map_objects/pics/people/running_triathlete_f/8.4bpp"); +const u32 gMapObjectPic_TuberF_0[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/0.4bpp"); +const u32 gMapObjectPic_TuberF_1[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/1.4bpp"); +const u32 gMapObjectPic_TuberF_2[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/2.4bpp"); +const u32 gMapObjectPic_TuberF_3[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/3.4bpp"); +const u32 gMapObjectPic_TuberF_4[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/4.4bpp"); +const u32 gMapObjectPic_TuberF_5[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/5.4bpp"); +const u32 gMapObjectPic_TuberF_6[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/6.4bpp"); +const u32 gMapObjectPic_TuberF_7[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/7.4bpp"); +const u32 gMapObjectPic_TuberF_8[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_f/8.4bpp"); +const u32 gMapObjectPic_TuberM_0[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/0.4bpp"); +const u32 gMapObjectPic_TuberM_1[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/1.4bpp"); +const u32 gMapObjectPic_TuberM_2[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/2.4bpp"); +const u32 gMapObjectPic_TuberM_3[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/3.4bpp"); +const u32 gMapObjectPic_TuberM_4[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/4.4bpp"); +const u32 gMapObjectPic_TuberM_5[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/5.4bpp"); +const u32 gMapObjectPic_TuberM_6[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/6.4bpp"); +const u32 gMapObjectPic_TuberM_7[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/7.4bpp"); +const u32 gMapObjectPic_TuberM_8[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m/8.4bpp"); +const u32 gMapObjectPic_Hiker_0[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/0.4bpp"); +const u32 gMapObjectPic_Hiker_1[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/1.4bpp"); +const u32 gMapObjectPic_Hiker_2[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/2.4bpp"); +const u32 gMapObjectPic_Hiker_3[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/3.4bpp"); +const u32 gMapObjectPic_Hiker_4[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/4.4bpp"); +const u32 gMapObjectPic_Hiker_5[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/5.4bpp"); +const u32 gMapObjectPic_Hiker_6[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/6.4bpp"); +const u32 gMapObjectPic_Hiker_7[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/7.4bpp"); +const u32 gMapObjectPic_Hiker_8[] = INCBIN_U32("graphics/map_objects/pics/people/hiker/8.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_0[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/0.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_1[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/1.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_2[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/2.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_3[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/3.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_4[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/4.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_5[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/5.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_6[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/6.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_7[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/7.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteM_8[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_m/8.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_0[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/0.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_1[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/1.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_2[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/2.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_3[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/3.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_4[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/4.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_5[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/5.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_6[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/6.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_7[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/7.4bpp"); +const u32 gMapObjectPic_CyclingTriathleteF_8[] = INCBIN_U32("graphics/map_objects/pics/people/cycling_triathlete_f/8.4bpp"); +const u32 gMapObjectPic_Man5_0[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/0.4bpp"); +const u32 gMapObjectPic_Man5_1[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/1.4bpp"); +const u32 gMapObjectPic_Man5_2[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/2.4bpp"); +const u32 gMapObjectPic_Man5_3[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/3.4bpp"); +const u32 gMapObjectPic_Man5_4[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/4.4bpp"); +const u32 gMapObjectPic_Man5_5[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/5.4bpp"); +const u32 gMapObjectPic_Man5_6[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/6.4bpp"); +const u32 gMapObjectPic_Man5_7[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/7.4bpp"); +const u32 gMapObjectPic_Man5_8[] = INCBIN_U32("graphics/map_objects/pics/people/man_5/8.4bpp"); +const u32 gMapObjectPic_Man6_0[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/0.4bpp"); +const u32 gMapObjectPic_Man6_1[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/1.4bpp"); +const u32 gMapObjectPic_Man6_2[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/2.4bpp"); +const u32 gMapObjectPic_Man6_3[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/3.4bpp"); +const u32 gMapObjectPic_Man6_4[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/4.4bpp"); +const u32 gMapObjectPic_Man6_5[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/5.4bpp"); +const u32 gMapObjectPic_Man6_6[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/6.4bpp"); +const u32 gMapObjectPic_Man6_7[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/7.4bpp"); +const u32 gMapObjectPic_Man6_8[] = INCBIN_U32("graphics/map_objects/pics/people/man_6/8.4bpp"); +const u32 gMapObjectPic_Nurse_0[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/0.4bpp"); +const u32 gMapObjectPic_Nurse_1[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/1.4bpp"); +const u32 gMapObjectPic_Nurse_2[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/2.4bpp"); +const u32 gMapObjectPic_Nurse_3[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/3.4bpp"); +const u32 gMapObjectPic_Nurse_4[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/4.4bpp"); +const u32 gMapObjectPic_Nurse_5[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/5.4bpp"); +const u32 gMapObjectPic_Nurse_6[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/6.4bpp"); +const u32 gMapObjectPic_Nurse_7[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/7.4bpp"); +const u32 gMapObjectPic_Nurse_8[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/8.4bpp"); +const u32 gMapObjectPic_Nurse_9[] = INCBIN_U32("graphics/map_objects/pics/people/nurse/9.4bpp"); +const u32 gMapObjectPic_ItemBall[] = INCBIN_U32("graphics/map_objects/pics/misc/item_ball.4bpp"); +const u32 gMapObjectPic_ProfBirch_0[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/0.4bpp"); +const u32 gMapObjectPic_ProfBirch_1[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/1.4bpp"); +const u32 gMapObjectPic_ProfBirch_2[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/2.4bpp"); +const u32 gMapObjectPic_ProfBirch_3[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/3.4bpp"); +const u32 gMapObjectPic_ProfBirch_4[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/4.4bpp"); +const u32 gMapObjectPic_ProfBirch_5[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/5.4bpp"); +const u32 gMapObjectPic_ProfBirch_6[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/6.4bpp"); +const u32 gMapObjectPic_ProfBirch_7[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/7.4bpp"); +const u32 gMapObjectPic_ProfBirch_8[] = INCBIN_U32("graphics/map_objects/pics/people/prof_birch/8.4bpp"); +const u32 gMapObjectPic_ReporterM_0[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/0.4bpp"); +const u32 gMapObjectPic_ReporterM_1[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/1.4bpp"); +const u32 gMapObjectPic_ReporterM_2[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/2.4bpp"); +const u32 gMapObjectPic_ReporterM_3[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/3.4bpp"); +const u32 gMapObjectPic_ReporterM_4[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/4.4bpp"); +const u32 gMapObjectPic_ReporterM_5[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/5.4bpp"); +const u32 gMapObjectPic_ReporterM_6[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/6.4bpp"); +const u32 gMapObjectPic_ReporterM_7[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/7.4bpp"); +const u32 gMapObjectPic_ReporterM_8[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_m/8.4bpp"); +const u32 gMapObjectPic_ReporterF_0[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/0.4bpp"); +const u32 gMapObjectPic_ReporterF_1[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/1.4bpp"); +const u32 gMapObjectPic_ReporterF_2[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/2.4bpp"); +const u32 gMapObjectPic_ReporterF_3[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/3.4bpp"); +const u32 gMapObjectPic_ReporterF_4[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/4.4bpp"); +const u32 gMapObjectPic_ReporterF_5[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/5.4bpp"); +const u32 gMapObjectPic_ReporterF_6[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/6.4bpp"); +const u32 gMapObjectPic_ReporterF_7[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/7.4bpp"); +const u32 gMapObjectPic_ReporterF_8[] = INCBIN_U32("graphics/map_objects/pics/people/reporter_f/8.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_0[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/0.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_1[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/1.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_2[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/2.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_3[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/3.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_4[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/4.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_5[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/5.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_6[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/6.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_7[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/7.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan1_8[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_1/8.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_0[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/0.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_1[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/1.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_2[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/2.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_3[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/3.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_4[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/4.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_5[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/5.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_6[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/6.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_7[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/7.4bpp"); +const u32 gMapObjectPic_MauvilleOldMan2_8[] = INCBIN_U32("graphics/map_objects/pics/people/mauville_old_man_2/8.4bpp"); +const u32 gMapObjectPic_MartEmployee_0[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/0.4bpp"); +const u32 gMapObjectPic_MartEmployee_1[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/1.4bpp"); +const u32 gMapObjectPic_MartEmployee_2[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/2.4bpp"); +const u32 gMapObjectPic_MartEmployee_3[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/3.4bpp"); +const u32 gMapObjectPic_MartEmployee_4[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/4.4bpp"); +const u32 gMapObjectPic_MartEmployee_5[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/5.4bpp"); +const u32 gMapObjectPic_MartEmployee_6[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/6.4bpp"); +const u32 gMapObjectPic_MartEmployee_7[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/7.4bpp"); +const u32 gMapObjectPic_MartEmployee_8[] = INCBIN_U32("graphics/map_objects/pics/people/mart_employee/8.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_0[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/0.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_1[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/1.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_2[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/2.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_3[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/3.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_4[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/4.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_5[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/5.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_6[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/6.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_7[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/7.4bpp"); +const u32 gMapObjectPic_RooftopSaleWoman_8[] = INCBIN_U32("graphics/map_objects/pics/people/rooftop_sale_woman/8.4bpp"); +const u32 gMapObjectPic_Teala_0[] = INCBIN_U32("graphics/map_objects/pics/people/teala/0.4bpp"); +const u32 gMapObjectPic_Teala_1[] = INCBIN_U32("graphics/map_objects/pics/people/teala/1.4bpp"); +const u32 gMapObjectPic_Teala_2[] = INCBIN_U32("graphics/map_objects/pics/people/teala/2.4bpp"); +const u32 gMapObjectPic_Teala_3[] = INCBIN_U32("graphics/map_objects/pics/people/teala/3.4bpp"); +const u32 gMapObjectPic_Teala_4[] = INCBIN_U32("graphics/map_objects/pics/people/teala/4.4bpp"); +const u32 gMapObjectPic_Teala_5[] = INCBIN_U32("graphics/map_objects/pics/people/teala/5.4bpp"); +const u32 gMapObjectPic_Teala_6[] = INCBIN_U32("graphics/map_objects/pics/people/teala/6.4bpp"); +const u32 gMapObjectPic_Teala_7[] = INCBIN_U32("graphics/map_objects/pics/people/teala/7.4bpp"); +const u32 gMapObjectPic_Teala_8[] = INCBIN_U32("graphics/map_objects/pics/people/teala/8.4bpp"); +const u32 gMapObjectPic_Artist_0[] = INCBIN_U32("graphics/map_objects/pics/people/artist/0.4bpp"); +const u32 gMapObjectPic_Artist_1[] = INCBIN_U32("graphics/map_objects/pics/people/artist/1.4bpp"); +const u32 gMapObjectPic_Artist_2[] = INCBIN_U32("graphics/map_objects/pics/people/artist/2.4bpp"); +const u32 gMapObjectPic_Artist_3[] = INCBIN_U32("graphics/map_objects/pics/people/artist/3.4bpp"); +const u32 gMapObjectPic_Artist_4[] = INCBIN_U32("graphics/map_objects/pics/people/artist/4.4bpp"); +const u32 gMapObjectPic_Artist_5[] = INCBIN_U32("graphics/map_objects/pics/people/artist/5.4bpp"); +const u32 gMapObjectPic_Artist_6[] = INCBIN_U32("graphics/map_objects/pics/people/artist/6.4bpp"); +const u32 gMapObjectPic_Artist_7[] = INCBIN_U32("graphics/map_objects/pics/people/artist/7.4bpp"); +const u32 gMapObjectPic_Artist_8[] = INCBIN_U32("graphics/map_objects/pics/people/artist/8.4bpp"); +const u32 gMapObjectPic_Cameraman_0[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/0.4bpp"); +const u32 gMapObjectPic_Cameraman_1[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/1.4bpp"); +const u32 gMapObjectPic_Cameraman_2[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/2.4bpp"); +const u32 gMapObjectPic_Cameraman_3[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/3.4bpp"); +const u32 gMapObjectPic_Cameraman_4[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/4.4bpp"); +const u32 gMapObjectPic_Cameraman_5[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/5.4bpp"); +const u32 gMapObjectPic_Cameraman_6[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/6.4bpp"); +const u32 gMapObjectPic_Cameraman_7[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/7.4bpp"); +const u32 gMapObjectPic_Cameraman_8[] = INCBIN_U32("graphics/map_objects/pics/people/cameraman/8.4bpp"); +const u32 gMapObjectPic_Scientist2_0[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/0.4bpp"); +const u32 gMapObjectPic_Scientist2_1[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/1.4bpp"); +const u32 gMapObjectPic_Scientist2_2[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/2.4bpp"); +const u32 gMapObjectPic_Scientist2_3[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/3.4bpp"); +const u32 gMapObjectPic_Scientist2_4[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/4.4bpp"); +const u32 gMapObjectPic_Scientist2_5[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/5.4bpp"); +const u32 gMapObjectPic_Scientist2_6[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/6.4bpp"); +const u32 gMapObjectPic_Scientist2_7[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/7.4bpp"); +const u32 gMapObjectPic_Scientist2_8[] = INCBIN_U32("graphics/map_objects/pics/people/scientist_2/8.4bpp"); +const u32 gMapObjectPic_Man7_0[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/0.4bpp"); +const u32 gMapObjectPic_Man7_1[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/1.4bpp"); +const u32 gMapObjectPic_Man7_2[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/2.4bpp"); +const u32 gMapObjectPic_Man7_3[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/3.4bpp"); +const u32 gMapObjectPic_Man7_4[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/4.4bpp"); +const u32 gMapObjectPic_Man7_5[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/5.4bpp"); +const u32 gMapObjectPic_Man7_6[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/6.4bpp"); +const u32 gMapObjectPic_Man7_7[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/7.4bpp"); +const u32 gMapObjectPic_Man7_8[] = INCBIN_U32("graphics/map_objects/pics/people/man_7/8.4bpp"); +const u32 gMapObjectPic_AquaMemberM_0[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/0.4bpp"); +const u32 gMapObjectPic_AquaMemberM_1[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/1.4bpp"); +const u32 gMapObjectPic_AquaMemberM_2[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/2.4bpp"); +const u32 gMapObjectPic_AquaMemberM_3[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/3.4bpp"); +const u32 gMapObjectPic_AquaMemberM_4[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/4.4bpp"); +const u32 gMapObjectPic_AquaMemberM_5[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/5.4bpp"); +const u32 gMapObjectPic_AquaMemberM_6[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/6.4bpp"); +const u32 gMapObjectPic_AquaMemberM_7[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/7.4bpp"); +const u32 gMapObjectPic_AquaMemberM_8[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_m/8.4bpp"); +const u32 gMapObjectPic_AquaMemberF_0[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/0.4bpp"); +const u32 gMapObjectPic_AquaMemberF_1[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/1.4bpp"); +const u32 gMapObjectPic_AquaMemberF_2[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/2.4bpp"); +const u32 gMapObjectPic_AquaMemberF_3[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/3.4bpp"); +const u32 gMapObjectPic_AquaMemberF_4[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/4.4bpp"); +const u32 gMapObjectPic_AquaMemberF_5[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/5.4bpp"); +const u32 gMapObjectPic_AquaMemberF_6[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/6.4bpp"); +const u32 gMapObjectPic_AquaMemberF_7[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/7.4bpp"); +const u32 gMapObjectPic_AquaMemberF_8[] = INCBIN_U32("graphics/map_objects/pics/people/aqua_member_f/8.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_0[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/0.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_1[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/1.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_2[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/2.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_3[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/3.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_4[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/4.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_5[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/5.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_6[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/6.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_7[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/7.4bpp"); +const u32 gMapObjectPic_MagmaMemberM_8[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_m/8.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_0[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/0.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_1[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/1.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_2[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/2.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_3[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/3.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_4[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/4.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_5[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/5.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_6[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/6.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_7[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/7.4bpp"); +const u32 gMapObjectPic_MagmaMemberF_8[] = INCBIN_U32("graphics/map_objects/pics/people/magma_member_f/8.4bpp"); +const u32 gMapObjectPic_Sidney_0[] = INCBIN_U32("graphics/map_objects/pics/people/sidney/0.4bpp"); +const u32 gMapObjectPic_Sidney_1[] = INCBIN_U32("graphics/map_objects/pics/people/sidney/1.4bpp"); +const u32 gMapObjectPic_Sidney_2[] = INCBIN_U32("graphics/map_objects/pics/people/sidney/2.4bpp"); +const u32 gMapObjectPic_Phoebe_0[] = INCBIN_U32("graphics/map_objects/pics/people/phoebe/0.4bpp"); +const u32 gMapObjectPic_Phoebe_1[] = INCBIN_U32("graphics/map_objects/pics/people/phoebe/1.4bpp"); +const u32 gMapObjectPic_Phoebe_2[] = INCBIN_U32("graphics/map_objects/pics/people/phoebe/2.4bpp"); +const u32 gMapObjectPic_Glacia_0[] = INCBIN_U32("graphics/map_objects/pics/people/glacia/0.4bpp"); +const u32 gMapObjectPic_Glacia_1[] = INCBIN_U32("graphics/map_objects/pics/people/glacia/1.4bpp"); +const u32 gMapObjectPic_Glacia_2[] = INCBIN_U32("graphics/map_objects/pics/people/glacia/2.4bpp"); +const u32 gMapObjectPic_Drake_0[] = INCBIN_U32("graphics/map_objects/pics/people/drake/0.4bpp"); +const u32 gMapObjectPic_Drake_1[] = INCBIN_U32("graphics/map_objects/pics/people/drake/1.4bpp"); +const u32 gMapObjectPic_Drake_2[] = INCBIN_U32("graphics/map_objects/pics/people/drake/2.4bpp"); +const u32 gMapObjectPic_Roxanne_0[] = INCBIN_U32("graphics/map_objects/pics/people/roxanne/0.4bpp"); +const u32 gMapObjectPic_Roxanne_1[] = INCBIN_U32("graphics/map_objects/pics/people/roxanne/1.4bpp"); +const u32 gMapObjectPic_Roxanne_2[] = INCBIN_U32("graphics/map_objects/pics/people/roxanne/2.4bpp"); +const u32 gMapObjectPic_Brawly_0[] = INCBIN_U32("graphics/map_objects/pics/people/brawly/0.4bpp"); +const u32 gMapObjectPic_Brawly_1[] = INCBIN_U32("graphics/map_objects/pics/people/brawly/1.4bpp"); +const u32 gMapObjectPic_Brawly_2[] = INCBIN_U32("graphics/map_objects/pics/people/brawly/2.4bpp"); +const u32 gMapObjectPic_Wattson_0[] = INCBIN_U32("graphics/map_objects/pics/people/wattson/0.4bpp"); +const u32 gMapObjectPic_Wattson_1[] = INCBIN_U32("graphics/map_objects/pics/people/wattson/1.4bpp"); +const u32 gMapObjectPic_Wattson_2[] = INCBIN_U32("graphics/map_objects/pics/people/wattson/2.4bpp"); +const u32 gMapObjectPic_Flannery_0[] = INCBIN_U32("graphics/map_objects/pics/people/flannery/0.4bpp"); +const u32 gMapObjectPic_Flannery_1[] = INCBIN_U32("graphics/map_objects/pics/people/flannery/1.4bpp"); +const u32 gMapObjectPic_Flannery_2[] = INCBIN_U32("graphics/map_objects/pics/people/flannery/2.4bpp"); +const u32 gMapObjectPic_Norman_0[] = INCBIN_U32("graphics/map_objects/pics/people/norman/0.4bpp"); +const u32 gMapObjectPic_Norman_1[] = INCBIN_U32("graphics/map_objects/pics/people/norman/1.4bpp"); +const u32 gMapObjectPic_Norman_2[] = INCBIN_U32("graphics/map_objects/pics/people/norman/2.4bpp"); +const u32 gMapObjectPic_Norman_3[] = INCBIN_U32("graphics/map_objects/pics/people/norman/3.4bpp"); +const u32 gMapObjectPic_Norman_4[] = INCBIN_U32("graphics/map_objects/pics/people/norman/4.4bpp"); +const u32 gMapObjectPic_Norman_5[] = INCBIN_U32("graphics/map_objects/pics/people/norman/5.4bpp"); +const u32 gMapObjectPic_Norman_6[] = INCBIN_U32("graphics/map_objects/pics/people/norman/6.4bpp"); +const u32 gMapObjectPic_Norman_7[] = INCBIN_U32("graphics/map_objects/pics/people/norman/7.4bpp"); +const u32 gMapObjectPic_Norman_8[] = INCBIN_U32("graphics/map_objects/pics/people/norman/8.4bpp"); +const u32 gMapObjectPic_Winona_0[] = INCBIN_U32("graphics/map_objects/pics/people/winona/0.4bpp"); +const u32 gMapObjectPic_Winona_1[] = INCBIN_U32("graphics/map_objects/pics/people/winona/1.4bpp"); +const u32 gMapObjectPic_Winona_2[] = INCBIN_U32("graphics/map_objects/pics/people/winona/2.4bpp"); +const u32 gMapObjectPic_Liza_0[] = INCBIN_U32("graphics/map_objects/pics/people/liza/0.4bpp"); +const u32 gMapObjectPic_Liza_1[] = INCBIN_U32("graphics/map_objects/pics/people/liza/1.4bpp"); +const u32 gMapObjectPic_Liza_2[] = INCBIN_U32("graphics/map_objects/pics/people/liza/2.4bpp"); +const u32 gMapObjectPic_Tate_0[] = INCBIN_U32("graphics/map_objects/pics/people/tate/0.4bpp"); +const u32 gMapObjectPic_Tate_1[] = INCBIN_U32("graphics/map_objects/pics/people/tate/1.4bpp"); +const u32 gMapObjectPic_Tate_2[] = INCBIN_U32("graphics/map_objects/pics/people/tate/2.4bpp"); +const u32 gMapObjectPic_Wallace_0[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/0.4bpp"); +const u32 gMapObjectPic_Wallace_1[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/1.4bpp"); +const u32 gMapObjectPic_Wallace_2[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/2.4bpp"); +const u32 gMapObjectPic_Wallace_3[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/3.4bpp"); +const u32 gMapObjectPic_Wallace_4[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/4.4bpp"); +const u32 gMapObjectPic_Wallace_5[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/5.4bpp"); +const u32 gMapObjectPic_Wallace_6[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/6.4bpp"); +const u32 gMapObjectPic_Wallace_7[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/7.4bpp"); +const u32 gMapObjectPic_Wallace_8[] = INCBIN_U32("graphics/map_objects/pics/people/wallace/8.4bpp"); +const u32 gMapObjectPic_Steven_0[] = INCBIN_U32("graphics/map_objects/pics/people/steven/0.4bpp"); +const u32 gMapObjectPic_Steven_1[] = INCBIN_U32("graphics/map_objects/pics/people/steven/1.4bpp"); +const u32 gMapObjectPic_Steven_2[] = INCBIN_U32("graphics/map_objects/pics/people/steven/2.4bpp"); +const u32 gMapObjectPic_Steven_3[] = INCBIN_U32("graphics/map_objects/pics/people/steven/3.4bpp"); +const u32 gMapObjectPic_Steven_4[] = INCBIN_U32("graphics/map_objects/pics/people/steven/4.4bpp"); +const u32 gMapObjectPic_Steven_5[] = INCBIN_U32("graphics/map_objects/pics/people/steven/5.4bpp"); +const u32 gMapObjectPic_Steven_6[] = INCBIN_U32("graphics/map_objects/pics/people/steven/6.4bpp"); +const u32 gMapObjectPic_Steven_7[] = INCBIN_U32("graphics/map_objects/pics/people/steven/7.4bpp"); +const u32 gMapObjectPic_Steven_8[] = INCBIN_U32("graphics/map_objects/pics/people/steven/8.4bpp"); +const u32 gMapObjectPic_Wally_0[] = INCBIN_U32("graphics/map_objects/pics/people/wally/0.4bpp"); +const u32 gMapObjectPic_Wally_1[] = INCBIN_U32("graphics/map_objects/pics/people/wally/1.4bpp"); +const u32 gMapObjectPic_Wally_2[] = INCBIN_U32("graphics/map_objects/pics/people/wally/2.4bpp"); +const u32 gMapObjectPic_Wally_3[] = INCBIN_U32("graphics/map_objects/pics/people/wally/3.4bpp"); +const u32 gMapObjectPic_Wally_4[] = INCBIN_U32("graphics/map_objects/pics/people/wally/4.4bpp"); +const u32 gMapObjectPic_Wally_5[] = INCBIN_U32("graphics/map_objects/pics/people/wally/5.4bpp"); +const u32 gMapObjectPic_Wally_6[] = INCBIN_U32("graphics/map_objects/pics/people/wally/6.4bpp"); +const u32 gMapObjectPic_Wally_7[] = INCBIN_U32("graphics/map_objects/pics/people/wally/7.4bpp"); +const u32 gMapObjectPic_Wally_8[] = INCBIN_U32("graphics/map_objects/pics/people/wally/8.4bpp"); +const u32 gMapObjectPic_LittleBoy3_0[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/0.4bpp"); +const u32 gMapObjectPic_LittleBoy3_1[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/1.4bpp"); +const u32 gMapObjectPic_LittleBoy3_2[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/2.4bpp"); +const u32 gMapObjectPic_LittleBoy3_3[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/3.4bpp"); +const u32 gMapObjectPic_LittleBoy3_4[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/4.4bpp"); +const u32 gMapObjectPic_LittleBoy3_5[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/5.4bpp"); +const u32 gMapObjectPic_LittleBoy3_6[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/6.4bpp"); +const u32 gMapObjectPic_LittleBoy3_7[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/7.4bpp"); +const u32 gMapObjectPic_LittleBoy3_8[] = INCBIN_U32("graphics/map_objects/pics/people/little_boy_3/8.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_0[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/0.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_1[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/1.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_2[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/2.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_3[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/3.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_4[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/4.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_5[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/5.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_6[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/6.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_7[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/7.4bpp"); +const u32 gMapObjectPic_HotSpringsOldWoman_8[] = INCBIN_U32("graphics/map_objects/pics/people/hot_springs_old_woman/8.4bpp"); +const u32 gMapObjectPic_LatiasLatios_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/latias_latios/0.4bpp"); +const u32 gMapObjectPic_LatiasLatios_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/latias_latios/1.4bpp"); +const u32 gMapObjectPic_LatiasLatios_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/latias_latios/2.4bpp"); +const u32 gMapObjectPic_Boy5_0[] = INCBIN_U32("graphics/map_objects/pics/people/boy_5/0.4bpp"); +const u32 gMapObjectPic_Boy5_1[] = INCBIN_U32("graphics/map_objects/pics/people/boy_5/1.4bpp"); +const u32 gMapObjectPic_Boy5_2[] = INCBIN_U32("graphics/map_objects/pics/people/boy_5/2.4bpp"); +const u32 gMapObjectPic_ContestJudge_0[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/0.4bpp"); +const u32 gMapObjectPic_ContestJudge_1[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/1.4bpp"); +const u32 gMapObjectPic_ContestJudge_2[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/2.4bpp"); +const u32 gMapObjectPic_ContestJudge_3[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/3.4bpp"); +const u32 gMapObjectPic_ContestJudge_4[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/4.4bpp"); +const u32 gMapObjectPic_ContestJudge_5[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/5.4bpp"); +const u32 gMapObjectPic_ContestJudge_6[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/6.4bpp"); +const u32 gMapObjectPic_ContestJudge_7[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/7.4bpp"); +const u32 gMapObjectPic_ContestJudge_8[] = INCBIN_U32("graphics/map_objects/pics/people/contest_judge/8.4bpp"); +const u32 gMapObjectPic_Archie_0[] = INCBIN_U32("graphics/map_objects/pics/people/archie/0.4bpp"); +const u32 gMapObjectPic_Archie_1[] = INCBIN_U32("graphics/map_objects/pics/people/archie/1.4bpp"); +const u32 gMapObjectPic_Archie_2[] = INCBIN_U32("graphics/map_objects/pics/people/archie/2.4bpp"); +const u32 gMapObjectPic_Archie_3[] = INCBIN_U32("graphics/map_objects/pics/people/archie/3.4bpp"); +const u32 gMapObjectPic_Archie_4[] = INCBIN_U32("graphics/map_objects/pics/people/archie/4.4bpp"); +const u32 gMapObjectPic_Archie_5[] = INCBIN_U32("graphics/map_objects/pics/people/archie/5.4bpp"); +const u32 gMapObjectPic_Archie_6[] = INCBIN_U32("graphics/map_objects/pics/people/archie/6.4bpp"); +const u32 gMapObjectPic_Archie_7[] = INCBIN_U32("graphics/map_objects/pics/people/archie/7.4bpp"); +const u32 gMapObjectPic_Archie_8[] = INCBIN_U32("graphics/map_objects/pics/people/archie/8.4bpp"); +const u32 gMapObjectPic_Maxie_0[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/0.4bpp"); +const u32 gMapObjectPic_Maxie_1[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/1.4bpp"); +const u32 gMapObjectPic_Maxie_2[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/2.4bpp"); +const u32 gMapObjectPic_Maxie_3[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/3.4bpp"); +const u32 gMapObjectPic_Maxie_4[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/4.4bpp"); +const u32 gMapObjectPic_Maxie_5[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/5.4bpp"); +const u32 gMapObjectPic_Maxie_6[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/6.4bpp"); +const u32 gMapObjectPic_Maxie_7[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/7.4bpp"); +const u32 gMapObjectPic_Maxie_8[] = INCBIN_U32("graphics/map_objects/pics/people/maxie/8.4bpp"); +const u32 gMapObjectPic_Kyogre_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/kyogre/0.4bpp"); +const u32 gMapObjectPic_Kyogre_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/kyogre/1.4bpp"); +const u32 gMapObjectPic_Groudon_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/groudon/0.4bpp"); +const u32 gMapObjectPic_Groudon_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/groudon/1.4bpp"); +const u32 gMapObjectPic_Regi[] = INCBIN_U32("graphics/map_objects/pics/pokemon/regi.4bpp"); +const u32 gMapObjectPic_Skitty_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/skitty/0.4bpp"); +const u32 gMapObjectPic_Skitty_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/skitty/1.4bpp"); +const u32 gMapObjectPic_Skitty_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/skitty/2.4bpp"); +const u32 gMapObjectPic_Kecleon_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/kecleon/0.4bpp"); +const u32 gMapObjectPic_Kecleon_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/kecleon/1.4bpp"); +const u32 gMapObjectPic_Kecleon_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/kecleon/2.4bpp"); +const u32 gMapObjectPic_Rayquaza_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/rayquaza/0.4bpp"); +const u32 gMapObjectPic_Rayquaza_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/rayquaza/1.4bpp"); +const u32 gMapObjectPic_Zigzagoon_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/zigzagoon/0.4bpp"); +const u32 gMapObjectPic_Zigzagoon_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/zigzagoon/1.4bpp"); +const u32 gMapObjectPic_Zigzagoon_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/zigzagoon/2.4bpp"); +const u32 gMapObjectPic_Pikachu_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/pikachu/0.4bpp"); +const u32 gMapObjectPic_Pikachu_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/pikachu/1.4bpp"); +const u32 gMapObjectPic_Pikachu_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/pikachu/2.4bpp"); +const u32 gMapObjectPic_Azumarill_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/azumarill/0.4bpp"); +const u32 gMapObjectPic_Azumarill_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/azumarill/1.4bpp"); +const u32 gMapObjectPic_Azumarill_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/azumarill/2.4bpp"); +const u32 gMapObjectPic_Wingull_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/wingull/0.4bpp"); +const u32 gMapObjectPic_Wingull_3[] = INCBIN_U32("graphics/map_objects/pics/pokemon/wingull/3.4bpp"); +const u32 gMapObjectPic_Wingull_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/wingull/1.4bpp"); +const u32 gMapObjectPic_Wingull_4[] = INCBIN_U32("graphics/map_objects/pics/pokemon/wingull/4.4bpp"); +const u32 gMapObjectPic_Wingull_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/wingull/2.4bpp"); +const u32 gMapObjectPic_Wingull_5[] = INCBIN_U32("graphics/map_objects/pics/pokemon/wingull/5.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_0[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/0.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_1[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/1.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_2[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/2.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_3[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/3.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_4[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/4.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_5[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/5.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_6[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/6.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_7[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/7.4bpp"); +const u32 gMapObjectPic_TuberMSwimming_8[] = INCBIN_U32("graphics/map_objects/pics/people/tuber_m_swimming/8.4bpp"); +const u32 gMapObjectPic_Azurill_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/azurill/0.4bpp"); +const u32 gMapObjectPic_Azurill_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/azurill/1.4bpp"); +const u32 gMapObjectPic_Azurill_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/azurill/2.4bpp"); +const u32 gMapObjectPic_Mom_0[] = INCBIN_U32("graphics/map_objects/pics/people/mom/0.4bpp"); +const u32 gMapObjectPic_Mom_1[] = INCBIN_U32("graphics/map_objects/pics/people/mom/1.4bpp"); +const u32 gMapObjectPic_Mom_2[] = INCBIN_U32("graphics/map_objects/pics/people/mom/2.4bpp"); +const u32 gMapObjectPic_Mom_3[] = INCBIN_U32("graphics/map_objects/pics/people/mom/3.4bpp"); +const u32 gMapObjectPic_Mom_4[] = INCBIN_U32("graphics/map_objects/pics/people/mom/4.4bpp"); +const u32 gMapObjectPic_Mom_5[] = INCBIN_U32("graphics/map_objects/pics/people/mom/5.4bpp"); +const u32 gMapObjectPic_Mom_6[] = INCBIN_U32("graphics/map_objects/pics/people/mom/6.4bpp"); +const u32 gMapObjectPic_Mom_7[] = INCBIN_U32("graphics/map_objects/pics/people/mom/7.4bpp"); +const u32 gMapObjectPic_Mom_8[] = INCBIN_U32("graphics/map_objects/pics/people/mom/8.4bpp"); +const u16 gMapObjectPalette22[] = INCBIN_U16("graphics/map_objects/palettes/22.gbapal"); +const u16 gMapObjectPalette23[] = INCBIN_U16("graphics/map_objects/palettes/23.gbapal"); +const u16 gMapObjectPalette24[] = INCBIN_U16("graphics/map_objects/palettes/24.gbapal"); +const u16 gMapObjectPalette25[] = INCBIN_U16("graphics/map_objects/palettes/25.gbapal"); +const u32 gMapObjectPic_UnusedNatuDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/unused_natu_doll.4bpp"); +const u32 gMapObjectPic_UnusedMagnemiteDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/unused_magnemite_doll.4bpp"); +const u32 gMapObjectPic_UnusedSquirtleDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/unused_squirtle_doll.4bpp"); +const u32 gMapObjectPic_UnusedWooperDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/unused_wooper_doll.4bpp"); +const u32 gMapObjectPic_UnusedPikachuDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/unused_pikachu_doll.4bpp"); +const u32 gMapObjectPic_UnusedPorygon2Doll[] = INCBIN_U32("graphics/map_objects/pics/dolls/unused_porygon2_doll.4bpp"); +const u32 gMapObjectPic_PichuDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/pichu_doll.4bpp"); +const u32 gMapObjectPic_PikachuDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/pikachu_doll.4bpp"); +const u32 gMapObjectPic_MarillDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/marill_doll.4bpp"); +const u32 gMapObjectPic_TogepiDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/togepi_doll.4bpp"); +const u32 gMapObjectPic_CyndaquilDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/cyndaquil_doll.4bpp"); +const u32 gMapObjectPic_ChikoritaDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/chikorita_doll.4bpp"); +const u32 gMapObjectPic_TotodileDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/totodile_doll.4bpp"); +const u32 gMapObjectPic_JigglypuffDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/jigglypuff_doll.4bpp"); +const u32 gMapObjectPic_MeowthDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/meowth_doll.4bpp"); +const u32 gMapObjectPic_ClefairyDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/clefairy_doll.4bpp"); +const u32 gMapObjectPic_DittoDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/ditto_doll.4bpp"); +const u32 gMapObjectPic_SmoochumDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/smoochum_doll.4bpp"); +const u32 gMapObjectPic_TreeckoDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/treecko_doll.4bpp"); +const u32 gMapObjectPic_TorchicDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/torchic_doll.4bpp"); +const u32 gMapObjectPic_MudkipDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/mudkip_doll.4bpp"); +const u32 gMapObjectPic_DuskullDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/duskull_doll.4bpp"); +const u32 gMapObjectPic_WynautDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/wynaut_doll.4bpp"); +const u32 gMapObjectPic_BaltoyDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/baltoy_doll.4bpp"); +const u32 gMapObjectPic_KecleonDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/kecleon_doll.4bpp"); +const u32 gMapObjectPic_AzurillDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/azurill_doll.4bpp"); +const u32 gMapObjectPic_SkittyDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/skitty_doll.4bpp"); +const u32 gMapObjectPic_SwabluDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/swablu_doll.4bpp"); +const u32 gMapObjectPic_GulpinDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/gulpin_doll.4bpp"); +const u32 gMapObjectPic_LotadDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/lotad_doll.4bpp"); +const u32 gMapObjectPic_SeedotDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/seedot_doll.4bpp"); +const u32 gMapObjectPic_PikaCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/pika_cushion.4bpp"); +const u32 gMapObjectPic_RoundCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/round_cushion.4bpp"); +const u32 gMapObjectPic_KissCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/kiss_cushion.4bpp"); +const u32 gMapObjectPic_ZigzagCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/zigzag_cushion.4bpp"); +const u32 gMapObjectPic_SpinCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/spin_cushion.4bpp"); +const u32 gMapObjectPic_DiamondCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/diamond_cushion.4bpp"); +const u32 gMapObjectPic_BallCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/ball_cushion.4bpp"); +const u32 gMapObjectPic_GrassCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/grass_cushion.4bpp"); +const u32 gMapObjectPic_FireCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/fire_cushion.4bpp"); +const u32 gMapObjectPic_WaterCushion[] = INCBIN_U32("graphics/map_objects/pics/cushions/water_cushion.4bpp"); +const u32 gMapObjectPic_BigSnorlaxDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_snorlax_doll.4bpp"); +const u32 gMapObjectPic_BigRhydonDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_rhydon_doll.4bpp"); +const u32 gMapObjectPic_BigLaprasDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_lapras_doll.4bpp"); +const u32 gMapObjectPic_BigVenusaurDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_venusaur_doll.4bpp"); +const u32 gMapObjectPic_BigCharizardDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_charizard_doll.4bpp"); +const u32 gMapObjectPic_BigBlastoiseDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_blastoise_doll.4bpp"); +const u32 gMapObjectPic_BigWailmerDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_wailmer_doll.4bpp"); +const u32 gMapObjectPic_BigRegirockDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_regirock_doll.4bpp"); +const u32 gMapObjectPic_BigRegiceDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_regice_doll.4bpp"); +const u32 gMapObjectPic_BigRegisteelDoll[] = INCBIN_U32("graphics/map_objects/pics/dolls/big_registeel_doll.4bpp"); +const u32 gMapObjectPic_CuttableTree_0[] = INCBIN_U32("graphics/map_objects/pics/misc/cuttable_tree/0.4bpp"); +const u32 gMapObjectPic_CuttableTree_1[] = INCBIN_U32("graphics/map_objects/pics/misc/cuttable_tree/1.4bpp"); +const u32 gMapObjectPic_CuttableTree_2[] = INCBIN_U32("graphics/map_objects/pics/misc/cuttable_tree/2.4bpp"); +const u32 gMapObjectPic_CuttableTree_3[] = INCBIN_U32("graphics/map_objects/pics/misc/cuttable_tree/3.4bpp"); +const u32 gMapObjectPic_BreakableRock_0[] = INCBIN_U32("graphics/map_objects/pics/misc/breakable_rock/0.4bpp"); +const u32 gMapObjectPic_BreakableRock_1[] = INCBIN_U32("graphics/map_objects/pics/misc/breakable_rock/1.4bpp"); +const u32 gMapObjectPic_BreakableRock_2[] = INCBIN_U32("graphics/map_objects/pics/misc/breakable_rock/2.4bpp"); +const u32 gMapObjectPic_BreakableRock_3[] = INCBIN_U32("graphics/map_objects/pics/misc/breakable_rock/3.4bpp"); +const u32 gMapObjectPic_PushableBoulder[] = INCBIN_U32("graphics/map_objects/pics/misc/pushable_boulder.4bpp"); +const u32 gMapObjectPic_MrBrineysBoat_0[] = INCBIN_U32("graphics/map_objects/pics/misc/mr_brineys_boat/0.4bpp"); +const u32 gMapObjectPic_MrBrineysBoat_1[] = INCBIN_U32("graphics/map_objects/pics/misc/mr_brineys_boat/1.4bpp"); +const u32 gMapObjectPic_MrBrineysBoat_2[] = INCBIN_U32("graphics/map_objects/pics/misc/mr_brineys_boat/2.4bpp"); +const u32 gMapObjectPic_Fossil[] = INCBIN_U32("graphics/map_objects/pics/misc/fossil.4bpp"); +const u32 gMapObjectPic_SubmarineShadow[] = INCBIN_U32("graphics/map_objects/pics/misc/submarine_shadow.4bpp"); +const u16 gMapObjectPalette26[] = INCBIN_U16("graphics/map_objects/palettes/26.gbapal"); +const u32 gMapObjectPic_Truck[] = INCBIN_U32("graphics/map_objects/pics/misc/truck.4bpp"); +const u16 gMapObjectPalette14[] = INCBIN_U16("graphics/map_objects/palettes/14.gbapal"); +const u32 gMapObjectPic_MachokeCarryingBox_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/machoke_carrying_box/0.4bpp"); +const u32 gMapObjectPic_MachokeCarryingBox_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/machoke_carrying_box/1.4bpp"); +const u32 gMapObjectPic_MachokeCarryingBox_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/machoke_carrying_box/2.4bpp"); +const u32 gMapObjectPic_MachokeFacingAway_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/machoke_facing_away/0.4bpp"); +const u32 gMapObjectPic_MachokeFacingAway_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/machoke_facing_away/1.4bpp"); +const u16 gMapObjectPalette15[] = INCBIN_U16("graphics/map_objects/palettes/15.gbapal"); +const u32 gMapObjectPic_BirchsBag[] = INCBIN_U32("graphics/map_objects/pics/misc/birchs_bag.4bpp"); +const u32 gMapObjectPic_Poochyena_0[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/0.4bpp"); +const u32 gMapObjectPic_Poochyena_1[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/1.4bpp"); +const u32 gMapObjectPic_Poochyena_2[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/2.4bpp"); +const u32 gMapObjectPic_Poochyena_3[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/3.4bpp"); +const u32 gMapObjectPic_Poochyena_4[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/4.4bpp"); +const u32 gMapObjectPic_Poochyena_5[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/5.4bpp"); +const u32 gMapObjectPic_Poochyena_6[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/6.4bpp"); +const u32 gMapObjectPic_Poochyena_7[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/7.4bpp"); +const u32 gMapObjectPic_Poochyena_8[] = INCBIN_U32("graphics/map_objects/pics/pokemon/poochyena/8.4bpp"); +const u16 gMapObjectPalette16[] = INCBIN_U16("graphics/map_objects/palettes/16.gbapal"); +const u32 gMapObjectPic_CableCar[] = INCBIN_U32("graphics/map_objects/pics/misc/cable_car.4bpp"); +const u16 gMapObjectPalette20[] = INCBIN_U16("graphics/map_objects/palettes/20.gbapal"); +const u32 gMapObjectPic_SSTidal[] = INCBIN_U32("graphics/map_objects/pics/misc/ss_tidal.4bpp"); +const u16 gMapObjectPalette21[] = INCBIN_U16("graphics/map_objects/palettes/21.gbapal"); +const u32 gFieldEffectPic_BerryTreeGrowthSparkle_0[] = INCBIN_U32("graphics/field_effect_objects/pics/berry_tree_growth_sparkle/0.4bpp"); +const u32 gFieldEffectPic_BerryTreeGrowthSparkle_1[] = INCBIN_U32("graphics/field_effect_objects/pics/berry_tree_growth_sparkle/1.4bpp"); +const u32 gFieldEffectPic_BerryTreeGrowthSparkle_2[] = INCBIN_U32("graphics/field_effect_objects/pics/berry_tree_growth_sparkle/2.4bpp"); +const u32 gFieldEffectPic_BerryTreeGrowthSparkle_3[] = INCBIN_U32("graphics/field_effect_objects/pics/berry_tree_growth_sparkle/3.4bpp"); +const u32 gFieldEffectPic_BerryTreeGrowthSparkle_4[] = INCBIN_U32("graphics/field_effect_objects/pics/berry_tree_growth_sparkle/4.4bpp"); +const u32 gFieldEffectPic_BerryTreeGrowthSparkle_5[] = INCBIN_U32("graphics/field_effect_objects/pics/berry_tree_growth_sparkle/5.4bpp"); +const u32 gMapObjectPic_BerryTreeDirtPile[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/dirt_pile.4bpp"); +const u32 gMapObjectPic_BerryTreeSprout_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/sprout/0.4bpp"); +const u32 gMapObjectPic_BerryTreeSprout_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/sprout/1.4bpp"); +const u32 gMapObjectPic_PechaBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pecha/0.4bpp"); +const u32 gMapObjectPic_PechaBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pecha/1.4bpp"); +const u32 gMapObjectPic_PechaBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pecha/2.4bpp"); +const u32 gMapObjectPic_PechaBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pecha/3.4bpp"); +const u32 gMapObjectPic_PechaBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pecha/4.4bpp"); +const u32 gMapObjectPic_PechaBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pecha/5.4bpp"); +const u32 gMapObjectPic_KelpsyBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/kelpsy/0.4bpp"); +const u32 gMapObjectPic_KelpsyBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/kelpsy/1.4bpp"); +const u32 gMapObjectPic_KelpsyBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/kelpsy/2.4bpp"); +const u32 gMapObjectPic_KelpsyBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/kelpsy/3.4bpp"); +const u32 gMapObjectPic_KelpsyBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/kelpsy/4.4bpp"); +const u32 gMapObjectPic_KelpsyBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/kelpsy/5.4bpp"); +const u32 gMapObjectPic_WepearBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wepear/0.4bpp"); +const u32 gMapObjectPic_WepearBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wepear/1.4bpp"); +const u32 gMapObjectPic_WepearBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wepear/2.4bpp"); +const u32 gMapObjectPic_WepearBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wepear/3.4bpp"); +const u32 gMapObjectPic_WepearBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wepear/4.4bpp"); +const u32 gMapObjectPic_WepearBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wepear/5.4bpp"); +const u32 gMapObjectPic_IapapaBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/iapapa/0.4bpp"); +const u32 gMapObjectPic_IapapaBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/iapapa/1.4bpp"); +const u32 gMapObjectPic_IapapaBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/iapapa/2.4bpp"); +const u32 gMapObjectPic_IapapaBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/iapapa/3.4bpp"); +const u32 gMapObjectPic_IapapaBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/iapapa/4.4bpp"); +const u32 gMapObjectPic_IapapaBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/iapapa/5.4bpp"); +const u32 gMapObjectPic_CheriBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cheri/0.4bpp"); +const u32 gMapObjectPic_CheriBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cheri/1.4bpp"); +const u32 gMapObjectPic_CheriBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cheri/2.4bpp"); +const u32 gMapObjectPic_CheriBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cheri/3.4bpp"); +const u32 gMapObjectPic_CheriBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cheri/4.4bpp"); +const u32 gMapObjectPic_CheriBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cheri/5.4bpp"); +const u32 gMapObjectPic_FigyBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/figy/0.4bpp"); +const u32 gMapObjectPic_FigyBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/figy/1.4bpp"); +const u32 gMapObjectPic_FigyBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/figy/2.4bpp"); +const u32 gMapObjectPic_FigyBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/figy/3.4bpp"); +const u32 gMapObjectPic_FigyBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/figy/4.4bpp"); +const u32 gMapObjectPic_FigyBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/figy/5.4bpp"); +const u32 gMapObjectPic_MagoBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/mago/0.4bpp"); +const u32 gMapObjectPic_MagoBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/mago/1.4bpp"); +const u32 gMapObjectPic_MagoBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/mago/2.4bpp"); +const u32 gMapObjectPic_MagoBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/mago/3.4bpp"); +const u32 gMapObjectPic_MagoBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/mago/4.4bpp"); +const u32 gMapObjectPic_MagoBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/mago/5.4bpp"); +const u32 gMapObjectPic_LumBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lum/0.4bpp"); +const u32 gMapObjectPic_LumBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lum/1.4bpp"); +const u32 gMapObjectPic_LumBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lum/2.4bpp"); +const u32 gMapObjectPic_LumBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lum/3.4bpp"); +const u32 gMapObjectPic_LumBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lum/4.4bpp"); +const u32 gMapObjectPic_LumBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lum/5.4bpp"); +const u32 gMapObjectPic_RazzBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/razz/0.4bpp"); +const u32 gMapObjectPic_RazzBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/razz/1.4bpp"); +const u32 gMapObjectPic_RazzBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/razz/2.4bpp"); +const u32 gMapObjectPic_RazzBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/razz/3.4bpp"); +const u32 gMapObjectPic_RazzBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/razz/4.4bpp"); +const u32 gMapObjectPic_RazzBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/razz/5.4bpp"); +const u32 gMapObjectPic_GrepaBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/grepa/0.4bpp"); +const u32 gMapObjectPic_GrepaBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/grepa/1.4bpp"); +const u32 gMapObjectPic_GrepaBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/grepa/2.4bpp"); +const u32 gMapObjectPic_GrepaBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/grepa/3.4bpp"); +const u32 gMapObjectPic_GrepaBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/grepa/4.4bpp"); +const u32 gMapObjectPic_GrepaBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/grepa/5.4bpp"); +const u32 gMapObjectPic_RabutaBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rabuta/0.4bpp"); +const u32 gMapObjectPic_RabutaBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rabuta/1.4bpp"); +const u32 gMapObjectPic_RabutaBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rabuta/2.4bpp"); +const u32 gMapObjectPic_RabutaBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rabuta/3.4bpp"); +const u32 gMapObjectPic_RabutaBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rabuta/4.4bpp"); +const u32 gMapObjectPic_RabutaBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rabuta/5.4bpp"); +const u32 gMapObjectPic_NomelBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/nomel/0.4bpp"); +const u32 gMapObjectPic_NomelBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/nomel/1.4bpp"); +const u32 gMapObjectPic_NomelBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/nomel/2.4bpp"); +const u32 gMapObjectPic_NomelBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/nomel/3.4bpp"); +const u32 gMapObjectPic_NomelBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/nomel/4.4bpp"); +const u32 gMapObjectPic_NomelBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/nomel/5.4bpp"); +const u32 gMapObjectPic_LeppaBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/leppa/0.4bpp"); +const u32 gMapObjectPic_LeppaBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/leppa/1.4bpp"); +const u32 gMapObjectPic_LeppaBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/leppa/2.4bpp"); +const u32 gMapObjectPic_LeppaBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/leppa/3.4bpp"); +const u32 gMapObjectPic_LeppaBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/leppa/4.4bpp"); +const u32 gMapObjectPic_LeppaBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/leppa/5.4bpp"); +const u32 gMapObjectPic_LiechiBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/liechi/0.4bpp"); +const u32 gMapObjectPic_LiechiBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/liechi/1.4bpp"); +const u32 gMapObjectPic_LiechiBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/liechi/2.4bpp"); +const u32 gMapObjectPic_LiechiBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/liechi/3.4bpp"); +const u32 gMapObjectPic_LiechiBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/liechi/4.4bpp"); +const u32 gMapObjectPic_LiechiBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/liechi/5.4bpp"); +const u32 gMapObjectPic_HondewBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/hondew/0.4bpp"); +const u32 gMapObjectPic_HondewBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/hondew/1.4bpp"); +const u32 gMapObjectPic_HondewBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/hondew/2.4bpp"); +const u32 gMapObjectPic_HondewBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/hondew/3.4bpp"); +const u32 gMapObjectPic_HondewBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/hondew/4.4bpp"); +const u32 gMapObjectPic_HondewBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/hondew/5.4bpp"); +const u32 gMapObjectPic_AguavBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aguav/0.4bpp"); +const u32 gMapObjectPic_AguavBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aguav/1.4bpp"); +const u32 gMapObjectPic_AguavBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aguav/2.4bpp"); +const u32 gMapObjectPic_AguavBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aguav/3.4bpp"); +const u32 gMapObjectPic_AguavBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aguav/4.4bpp"); +const u32 gMapObjectPic_AguavBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aguav/5.4bpp"); +const u32 gMapObjectPic_WikiBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wiki/0.4bpp"); +const u32 gMapObjectPic_WikiBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wiki/1.4bpp"); +const u32 gMapObjectPic_WikiBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wiki/2.4bpp"); +const u32 gMapObjectPic_WikiBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wiki/3.4bpp"); +const u32 gMapObjectPic_WikiBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wiki/4.4bpp"); +const u32 gMapObjectPic_WikiBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/wiki/5.4bpp"); +const u32 gMapObjectPic_PomegBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pomeg/0.4bpp"); +const u32 gMapObjectPic_PomegBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pomeg/1.4bpp"); +const u32 gMapObjectPic_PomegBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pomeg/2.4bpp"); +const u32 gMapObjectPic_PomegBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pomeg/3.4bpp"); +const u32 gMapObjectPic_PomegBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pomeg/4.4bpp"); +const u32 gMapObjectPic_PomegBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pomeg/5.4bpp"); +const u32 gMapObjectPic_RawstBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rawst/0.4bpp"); +const u32 gMapObjectPic_RawstBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rawst/1.4bpp"); +const u32 gMapObjectPic_RawstBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rawst/2.4bpp"); +const u32 gMapObjectPic_RawstBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rawst/3.4bpp"); +const u32 gMapObjectPic_RawstBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rawst/4.4bpp"); +const u32 gMapObjectPic_RawstBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/rawst/5.4bpp"); +const u32 gMapObjectPic_SpelonBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/spelon/0.4bpp"); +const u32 gMapObjectPic_SpelonBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/spelon/1.4bpp"); +const u32 gMapObjectPic_SpelonBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/spelon/2.4bpp"); +const u32 gMapObjectPic_SpelonBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/spelon/3.4bpp"); +const u32 gMapObjectPic_SpelonBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/spelon/4.4bpp"); +const u32 gMapObjectPic_SpelonBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/spelon/5.4bpp"); +const u32 gMapObjectPic_ChestoBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/chesto/0.4bpp"); +const u32 gMapObjectPic_ChestoBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/chesto/1.4bpp"); +const u32 gMapObjectPic_ChestoBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/chesto/2.4bpp"); +const u32 gMapObjectPic_ChestoBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/chesto/3.4bpp"); +const u32 gMapObjectPic_ChestoBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/chesto/4.4bpp"); +const u32 gMapObjectPic_ChestoBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/chesto/5.4bpp"); +const u32 gMapObjectPic_OranBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/oran/0.4bpp"); +const u32 gMapObjectPic_OranBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/oran/1.4bpp"); +const u32 gMapObjectPic_OranBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/oran/2.4bpp"); +const u32 gMapObjectPic_OranBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/oran/3.4bpp"); +const u32 gMapObjectPic_OranBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/oran/4.4bpp"); +const u32 gMapObjectPic_OranBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/oran/5.4bpp"); +const u32 gMapObjectPic_PersimBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/persim/0.4bpp"); +const u32 gMapObjectPic_PersimBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/persim/1.4bpp"); +const u32 gMapObjectPic_PersimBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/persim/2.4bpp"); +const u32 gMapObjectPic_PersimBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/persim/3.4bpp"); +const u32 gMapObjectPic_PersimBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/persim/4.4bpp"); +const u32 gMapObjectPic_PersimBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/persim/5.4bpp"); +const u32 gMapObjectPic_SitrusBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/sitrus/0.4bpp"); +const u32 gMapObjectPic_SitrusBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/sitrus/1.4bpp"); +const u32 gMapObjectPic_SitrusBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/sitrus/2.4bpp"); +const u32 gMapObjectPic_SitrusBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/sitrus/3.4bpp"); +const u32 gMapObjectPic_SitrusBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/sitrus/4.4bpp"); +const u32 gMapObjectPic_SitrusBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/sitrus/5.4bpp"); +const u32 gMapObjectPic_AspearBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aspear/0.4bpp"); +const u32 gMapObjectPic_AspearBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aspear/1.4bpp"); +const u32 gMapObjectPic_AspearBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aspear/2.4bpp"); +const u32 gMapObjectPic_AspearBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aspear/3.4bpp"); +const u32 gMapObjectPic_AspearBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aspear/4.4bpp"); +const u32 gMapObjectPic_AspearBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/aspear/5.4bpp"); +const u32 gMapObjectPic_PamtreBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pamtre/0.4bpp"); +const u32 gMapObjectPic_PamtreBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pamtre/1.4bpp"); +const u32 gMapObjectPic_PamtreBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pamtre/2.4bpp"); +const u32 gMapObjectPic_PamtreBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pamtre/3.4bpp"); +const u32 gMapObjectPic_PamtreBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pamtre/4.4bpp"); +const u32 gMapObjectPic_PamtreBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/pamtre/5.4bpp"); +const u32 gMapObjectPic_CornnBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cornn/0.4bpp"); +const u32 gMapObjectPic_CornnBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cornn/1.4bpp"); +const u32 gMapObjectPic_CornnBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cornn/2.4bpp"); +const u32 gMapObjectPic_CornnBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cornn/3.4bpp"); +const u32 gMapObjectPic_CornnBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cornn/4.4bpp"); +const u32 gMapObjectPic_CornnBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/cornn/5.4bpp"); +const u32 gMapObjectPic_LansatBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lansat/0.4bpp"); +const u32 gMapObjectPic_LansatBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lansat/1.4bpp"); +const u32 gMapObjectPic_LansatBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lansat/2.4bpp"); +const u32 gMapObjectPic_LansatBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lansat/3.4bpp"); +const u32 gMapObjectPic_LansatBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lansat/4.4bpp"); +const u32 gMapObjectPic_LansatBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/lansat/5.4bpp"); +const u32 gMapObjectPic_DurinBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/durin/0.4bpp"); +const u32 gMapObjectPic_DurinBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/durin/1.4bpp"); +const u32 gMapObjectPic_DurinBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/durin/2.4bpp"); +const u32 gMapObjectPic_DurinBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/durin/3.4bpp"); +const u32 gMapObjectPic_DurinBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/durin/4.4bpp"); +const u32 gMapObjectPic_DurinBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/durin/5.4bpp"); +const u32 gMapObjectPic_TamatoBerryTree_0[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/tamato/0.4bpp"); +const u32 gMapObjectPic_TamatoBerryTree_1[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/tamato/1.4bpp"); +const u32 gMapObjectPic_TamatoBerryTree_2[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/tamato/2.4bpp"); +const u32 gMapObjectPic_TamatoBerryTree_3[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/tamato/3.4bpp"); +const u32 gMapObjectPic_TamatoBerryTree_4[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/tamato/4.4bpp"); +const u32 gMapObjectPic_TamatoBerryTree_5[] = INCBIN_U32("graphics/map_objects/pics/berry_trees/tamato/5.4bpp"); +const u32 gFieldEffectPic_SurfBlob_0[] = INCBIN_U32("graphics/field_effect_objects/pics/surf_blob/0.4bpp"); +const u32 gFieldEffectPic_SurfBlob_1[] = INCBIN_U32("graphics/field_effect_objects/pics/surf_blob/1.4bpp"); +const u32 gFieldEffectPic_SurfBlob_2[] = INCBIN_U32("graphics/field_effect_objects/pics/surf_blob/2.4bpp"); +const u32 gMapObjectPic_QuintyPlump_0[] = INCBIN_U32("graphics/map_objects/pics/people/quinty_plump/0.4bpp"); +const u32 gMapObjectPic_QuintyPlump_1[] = INCBIN_U32("graphics/map_objects/pics/people/quinty_plump/1.4bpp"); +const u32 gMapObjectPic_QuintyPlump_2[] = INCBIN_U32("graphics/map_objects/pics/people/quinty_plump/2.4bpp"); +const u32 gMapObjectPic_QuintyPlump_3[] = INCBIN_U32("graphics/map_objects/pics/people/quinty_plump/3.4bpp"); +const u32 gMapObjectPic_QuintyPlump_4[] = INCBIN_U32("graphics/map_objects/pics/people/quinty_plump/4.4bpp"); +const u32 gMapObjectPic_QuintyPlump_5[] = INCBIN_U32("graphics/map_objects/pics/people/quinty_plump/5.4bpp"); +const u32 gMapObjectPic_QuintyPlump_6[] = INCBIN_U32("graphics/map_objects/pics/people/quinty_plump/6.4bpp"); +const u16 gMapObjectPalette12[] = INCBIN_U16("graphics/map_objects/palettes/12.gbapal"); +const u16 gMapObjectPalette13[] = INCBIN_U16("graphics/map_objects/palettes/13.gbapal"); + +const u32 gFieldEffectPic_ShadowSmall[] = INCBIN_U32("graphics/field_effect_objects/pics/shadow_small.4bpp"); +const u32 gFieldEffectPic_ShadowMedium[] = INCBIN_U32("graphics/field_effect_objects/pics/shadow_medium.4bpp"); +const u32 gFieldEffectPic_ShadowLarge[] = INCBIN_U32("graphics/field_effect_objects/pics/shadow_large.4bpp"); +const u32 gFieldEffectPic_ShadowExtraLarge[] = INCBIN_U32("graphics/field_effect_objects/pics/shadow_extra_large.4bpp"); +const u32 filler_8368A08[0x48] = {}; +const u32 gFieldEffectPic_CutGrass[] = INCBIN_U32("graphics/field_effect_objects/pics/cut_grass.4bpp"); +const u32 FieldEffectPic_CutGrass_Copy[] = INCBIN_U32("graphics/field_effect_objects/pics/cut_grass.4bpp"); +const u16 gFieldEffectObjectPalette6[] = INCBIN_U16("graphics/field_effect_objects/palettes/06.gbapal"); +const u32 gFieldEffectPic_Ripple_0[] = INCBIN_U32("graphics/field_effect_objects/pics/ripple/0.4bpp"); +const u32 gFieldEffectPic_Ripple_1[] = INCBIN_U32("graphics/field_effect_objects/pics/ripple/1.4bpp"); +const u32 gFieldEffectPic_Ripple_2[] = INCBIN_U32("graphics/field_effect_objects/pics/ripple/2.4bpp"); +const u32 gFieldEffectPic_Ripple_3[] = INCBIN_U32("graphics/field_effect_objects/pics/ripple/3.4bpp"); +const u32 gFieldEffectPic_Ripple_4[] = INCBIN_U32("graphics/field_effect_objects/pics/ripple/4.4bpp"); +const u32 gFieldEffectPic_Ash_0[] = INCBIN_U32("graphics/field_effect_objects/pics/ash/0.4bpp"); +const u32 gFieldEffectPic_Ash_1[] = INCBIN_U32("graphics/field_effect_objects/pics/ash/1.4bpp"); +const u32 gFieldEffectPic_Ash_2[] = INCBIN_U32("graphics/field_effect_objects/pics/ash/2.4bpp"); +const u32 gFieldEffectPic_Ash_3[] = INCBIN_U32("graphics/field_effect_objects/pics/ash/3.4bpp"); +const u32 gFieldEffectPic_Ash_4[] = INCBIN_U32("graphics/field_effect_objects/pics/ash/4.4bpp"); +const u32 gFieldEffectPic_Arrow_0[] = INCBIN_U32("graphics/field_effect_objects/pics/arrow/0.4bpp"); +const u32 gFieldEffectPic_Arrow_1[] = INCBIN_U32("graphics/field_effect_objects/pics/arrow/1.4bpp"); +const u32 gFieldEffectPic_Arrow_2[] = INCBIN_U32("graphics/field_effect_objects/pics/arrow/2.4bpp"); +const u32 gFieldEffectPic_Arrow_3[] = INCBIN_U32("graphics/field_effect_objects/pics/arrow/3.4bpp"); +const u32 gFieldEffectPic_Arrow_4[] = INCBIN_U32("graphics/field_effect_objects/pics/arrow/4.4bpp"); +const u32 gFieldEffectPic_Arrow_5[] = INCBIN_U32("graphics/field_effect_objects/pics/arrow/5.4bpp"); +const u32 gFieldEffectPic_Arrow_6[] = INCBIN_U32("graphics/field_effect_objects/pics/arrow/6.4bpp"); +const u32 gFieldEffectPic_Arrow_7[] = INCBIN_U32("graphics/field_effect_objects/pics/arrow/7.4bpp"); +const u16 gFieldEffectObjectPalette0[] = INCBIN_U16("graphics/field_effect_objects/palettes/00.gbapal"); +const u16 gFieldEffectObjectPalette1[] = INCBIN_U16("graphics/field_effect_objects/palettes/01.gbapal"); +const u32 gFieldEffectPic_Dust_0[] = INCBIN_U32("graphics/field_effect_objects/pics/dust/0.4bpp"); +const u32 gFieldEffectPic_Dust_1[] = INCBIN_U32("graphics/field_effect_objects/pics/dust/1.4bpp"); +const u32 gFieldEffectPic_Dust_2[] = INCBIN_U32("graphics/field_effect_objects/pics/dust/2.4bpp"); +const u32 unknown_8369588[] = INCBIN_U32("graphics/field_effect_objects/unknown.bin"); +const u32 gFieldEffectPic_JumpTallGrass_0[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_tall_grass/0.4bpp"); +const u32 gFieldEffectPic_JumpTallGrass_1[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_tall_grass/1.4bpp"); +const u32 gFieldEffectPic_JumpTallGrass_2[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_tall_grass/2.4bpp"); +const u32 gFieldEffectPic_JumpTallGrass_3[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_tall_grass/3.4bpp"); +const u32 UnusedGrass0[] = INCBIN_U32("graphics/field_effect_objects/pics/unused_grass/0.4bpp"); +const u32 UnusedGrass1[] = INCBIN_U32("graphics/field_effect_objects/pics/unused_grass/1.4bpp"); +const u32 UnusedGrass2[] = INCBIN_U32("graphics/field_effect_objects/pics/unused_grass/2.4bpp"); +const u32 UnusedGrass3[] = INCBIN_U32("graphics/field_effect_objects/pics/unused_grass/3.4bpp"); +const u32 gFieldEffectPic_JumpLongGrass_0[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_long_grass/0.4bpp"); +const u32 gFieldEffectPic_JumpLongGrass_1[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_long_grass/1.4bpp"); +const u32 gFieldEffectPic_JumpLongGrass_2[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_long_grass/2.4bpp"); +const u32 gFieldEffectPic_JumpLongGrass_3[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_long_grass/3.4bpp"); +const u32 gFieldEffectPic_JumpLongGrass_4[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_long_grass/4.4bpp"); +const u32 UnusedGrassLong[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_long_grass/unused.4bpp"); +const u32 gFieldEffectPic_JumpLongGrass_5[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_long_grass/5.4bpp"); +const u32 gFieldEffectPic_Unknown17_0[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_17/0.4bpp"); +const u32 gFieldEffectPic_Unknown17_1[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_17/1.4bpp"); +const u32 gFieldEffectPic_Unknown17_2[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_17/2.4bpp"); +const u32 gFieldEffectPic_Unknown17_3[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_17/3.4bpp"); +const u32 gFieldEffectPic_Unknown17_4[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_17/4.4bpp"); +const u32 gFieldEffectPic_Unknown17_5[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_17/5.4bpp"); +const u32 gFieldEffectPic_Unknown17_6[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_17/6.4bpp"); +const u32 gFieldEffectPic_Unknown17_7[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_17/7.4bpp"); +const u32 gFieldEffectPic_Unknown18_0[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_18/0.4bpp"); +const u32 gFieldEffectPic_Unknown18_1[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_18/1.4bpp"); +const u32 gFieldEffectPic_Unknown18_2[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_18/2.4bpp"); +const u32 gFieldEffectPic_Unknown18_3[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_18/3.4bpp"); +const u32 gFieldEffectPic_LongGrass_0[] = INCBIN_U32("graphics/field_effect_objects/pics/long_grass/0.4bpp"); +const u32 gFieldEffectPic_LongGrass_1[] = INCBIN_U32("graphics/field_effect_objects/pics/long_grass/1.4bpp"); +const u32 gFieldEffectPic_LongGrass_2[] = INCBIN_U32("graphics/field_effect_objects/pics/long_grass/2.4bpp"); +const u32 gFieldEffectPic_LongGrass_3[] = INCBIN_U32("graphics/field_effect_objects/pics/long_grass/3.4bpp"); +const u32 gFieldEffectPic_TallGrass_0[] = INCBIN_U32("graphics/field_effect_objects/pics/tall_grass/0.4bpp"); +const u32 gFieldEffectPic_TallGrass_1[] = INCBIN_U32("graphics/field_effect_objects/pics/tall_grass/1.4bpp"); +const u32 gFieldEffectPic_TallGrass_2[] = INCBIN_U32("graphics/field_effect_objects/pics/tall_grass/2.4bpp"); +const u32 gFieldEffectPic_TallGrass_3[] = INCBIN_U32("graphics/field_effect_objects/pics/tall_grass/3.4bpp"); +const u32 gFieldEffectPic_TallGrass_4[] = INCBIN_U32("graphics/field_effect_objects/pics/tall_grass/4.4bpp"); +const u32 gFieldEffectPic_ShortGrass_0[] = INCBIN_U32("graphics/field_effect_objects/pics/short_grass/0.4bpp"); +const u32 gFieldEffectPic_ShortGrass_1[] = INCBIN_U32("graphics/field_effect_objects/pics/short_grass/1.4bpp"); +const u32 gFieldEffectPic_SandFootprints_0[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_footprints/0.4bpp"); +const u32 gFieldEffectPic_SandFootprints_1[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_footprints/1.4bpp"); +const u32 gFieldEffectPic_DeepSandFootprints_0[] = INCBIN_U32("graphics/field_effect_objects/pics/deep_sand_footprints/0.4bpp"); +const u32 gFieldEffectPic_DeepSandFootprints_1[] = INCBIN_U32("graphics/field_effect_objects/pics/deep_sand_footprints/1.4bpp"); +const u32 gFieldEffectPic_BikeTireTracks_0[] = INCBIN_U32("graphics/field_effect_objects/pics/bike_tire_tracks/0.4bpp"); +const u32 gFieldEffectPic_BikeTireTracks_1[] = INCBIN_U32("graphics/field_effect_objects/pics/bike_tire_tracks/1.4bpp"); +const u32 gFieldEffectPic_BikeTireTracks_2[] = INCBIN_U32("graphics/field_effect_objects/pics/bike_tire_tracks/2.4bpp"); +const u32 gFieldEffectPic_BikeTireTracks_3[] = INCBIN_U32("graphics/field_effect_objects/pics/bike_tire_tracks/3.4bpp"); +const u32 gFieldEffectPic_Unknown19_0[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_19/0.4bpp"); +const u32 gFieldEffectPic_Unknown19_1[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_19/1.4bpp"); +const u32 gFieldEffectPic_Unknown19_2[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_19/2.4bpp"); +const u32 gFieldEffectPic_Unknown19_3[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_19/3.4bpp"); +const u32 gFieldEffectPic_SandPile_0[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_pile/0.4bpp"); +const u32 gFieldEffectPic_SandPile_1[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_pile/1.4bpp"); +const u32 gFieldEffectPic_SandPile_2[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_pile/2.4bpp"); +const u32 gFieldEffectPic_JumpBigSplash_0[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_big_splash/0.4bpp"); +const u32 gFieldEffectPic_JumpBigSplash_1[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_big_splash/1.4bpp"); +const u32 gFieldEffectPic_JumpBigSplash_2[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_big_splash/2.4bpp"); +const u32 gFieldEffectPic_JumpBigSplash_3[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_big_splash/3.4bpp"); +const u32 gFieldEffectPic_Splash_0[] = INCBIN_U32("graphics/field_effect_objects/pics/splash/0.4bpp"); +const u32 gFieldEffectPic_Splash_1[] = INCBIN_U32("graphics/field_effect_objects/pics/splash/1.4bpp"); +const u32 gFieldEffectPic_JumpSmallSplash_0[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_small_splash/0.4bpp"); +const u32 gFieldEffectPic_JumpSmallSplash_1[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_small_splash/1.4bpp"); +const u32 gFieldEffectPic_JumpSmallSplash_2[] = INCBIN_U32("graphics/field_effect_objects/pics/jump_small_splash/2.4bpp"); +const u32 gFieldEffectPic_Unknown20_0[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_20/0.4bpp"); +const u32 gFieldEffectPic_Unknown20_1[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_20/1.4bpp"); +const u32 gFieldEffectPic_Unknown20_2[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_20/2.4bpp"); +const u32 gFieldEffectPic_Unknown20_3[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_20/3.4bpp"); +const u32 gFieldEffectPic_Unknown20_4[] = INCBIN_U32("graphics/field_effect_objects/pics/unknown_20/4.4bpp"); +const u32 gFieldEffectPic_TreeDisguise_0[] = INCBIN_U32("graphics/field_effect_objects/pics/tree_disguise/0.4bpp"); +const u32 gFieldEffectPic_TreeDisguise_1[] = INCBIN_U32("graphics/field_effect_objects/pics/tree_disguise/1.4bpp"); +const u32 gFieldEffectPic_TreeDisguise_2[] = INCBIN_U32("graphics/field_effect_objects/pics/tree_disguise/2.4bpp"); +const u32 gFieldEffectPic_TreeDisguise_3[] = INCBIN_U32("graphics/field_effect_objects/pics/tree_disguise/3.4bpp"); +const u32 gFieldEffectPic_TreeDisguise_4[] = INCBIN_U32("graphics/field_effect_objects/pics/tree_disguise/4.4bpp"); +const u32 gFieldEffectPic_TreeDisguise_5[] = INCBIN_U32("graphics/field_effect_objects/pics/tree_disguise/5.4bpp"); +const u32 gFieldEffectPic_TreeDisguise_6[] = INCBIN_U32("graphics/field_effect_objects/pics/tree_disguise/6.4bpp"); +const u32 gFieldEffectPic_MountainDisguise_0[] = INCBIN_U32("graphics/field_effect_objects/pics/mountain_disguise/0.4bpp"); +const u32 gFieldEffectPic_MountainDisguise_1[] = INCBIN_U32("graphics/field_effect_objects/pics/mountain_disguise/1.4bpp"); +const u32 gFieldEffectPic_MountainDisguise_2[] = INCBIN_U32("graphics/field_effect_objects/pics/mountain_disguise/2.4bpp"); +const u32 gFieldEffectPic_MountainDisguise_3[] = INCBIN_U32("graphics/field_effect_objects/pics/mountain_disguise/3.4bpp"); +const u32 gFieldEffectPic_MountainDisguise_4[] = INCBIN_U32("graphics/field_effect_objects/pics/mountain_disguise/4.4bpp"); +const u32 gFieldEffectPic_MountainDisguise_5[] = INCBIN_U32("graphics/field_effect_objects/pics/mountain_disguise/5.4bpp"); +const u32 gFieldEffectPic_MountainDisguise_6[] = INCBIN_U32("graphics/field_effect_objects/pics/mountain_disguise/6.4bpp"); +const u32 gFieldEffectPic_SandDisguise_0[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_disguise/0.4bpp"); +const u32 gFieldEffectPic_SandDisguise_1[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_disguise/1.4bpp"); +const u32 gFieldEffectPic_SandDisguise_2[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_disguise/2.4bpp"); +const u32 gFieldEffectPic_SandDisguise_3[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_disguise/3.4bpp"); +const u32 gFieldEffectPic_SandDisguise_4[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_disguise/4.4bpp"); +const u32 gFieldEffectPic_SandDisguise_5[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_disguise/5.4bpp"); +const u32 gFieldEffectPic_SandDisguise_6[] = INCBIN_U32("graphics/field_effect_objects/pics/sand_disguise/6.4bpp"); +const u32 gFieldEffectPic_HotSpringsWater[] = INCBIN_U32("graphics/field_effect_objects/pics/hot_springs_water.4bpp"); +const u16 gFieldEffectObjectPalette2[] = INCBIN_U16("graphics/field_effect_objects/palettes/02.gbapal"); +const u32 gFieldEffectPic_PopOutOfAsh_0[] = INCBIN_U32("graphics/field_effect_objects/pics/pop_out_of_ash/0.4bpp"); +const u32 gFieldEffectPic_PopOutOfAsh_1[] = INCBIN_U32("graphics/field_effect_objects/pics/pop_out_of_ash/1.4bpp"); +const u32 gFieldEffectPic_PopOutOfAsh_2[] = INCBIN_U32("graphics/field_effect_objects/pics/pop_out_of_ash/2.4bpp"); +const u32 gFieldEffectPic_PopOutOfAsh_3[] = INCBIN_U32("graphics/field_effect_objects/pics/pop_out_of_ash/3.4bpp"); +const u32 gFieldEffectPic_PopOutOfAsh_4[] = INCBIN_U32("graphics/field_effect_objects/pics/pop_out_of_ash/4.4bpp"); +const u32 gFieldEffectPic_LavaridgeGymWarp_0[] = INCBIN_U32("graphics/field_effect_objects/pics/lavaridge_gym_warp/0.4bpp"); +const u32 gFieldEffectPic_LavaridgeGymWarp_1[] = INCBIN_U32("graphics/field_effect_objects/pics/lavaridge_gym_warp/1.4bpp"); +const u32 gFieldEffectPic_LavaridgeGymWarp_2[] = INCBIN_U32("graphics/field_effect_objects/pics/lavaridge_gym_warp/2.4bpp"); +const u32 gFieldEffectPic_LavaridgeGymWarp_3[] = INCBIN_U32("graphics/field_effect_objects/pics/lavaridge_gym_warp/3.4bpp"); +const u32 gFieldEffectPic_LavaridgeGymWarp_4[] = INCBIN_U32("graphics/field_effect_objects/pics/lavaridge_gym_warp/4.4bpp"); +const u32 gFieldEffectPic_Bubbles_0[] = INCBIN_U32("graphics/field_effect_objects/pics/bubbles/0.4bpp"); +const u32 gFieldEffectPic_Bubbles_1[] = INCBIN_U32("graphics/field_effect_objects/pics/bubbles/1.4bpp"); +const u32 gFieldEffectPic_Bubbles_2[] = INCBIN_U32("graphics/field_effect_objects/pics/bubbles/2.4bpp"); +const u32 gFieldEffectPic_Bubbles_3[] = INCBIN_U32("graphics/field_effect_objects/pics/bubbles/3.4bpp"); +const u32 gFieldEffectPic_Bubbles_4[] = INCBIN_U32("graphics/field_effect_objects/pics/bubbles/4.4bpp"); +const u32 gFieldEffectPic_Bubbles_5[] = INCBIN_U32("graphics/field_effect_objects/pics/bubbles/5.4bpp"); +const u32 gFieldEffectPic_Bubbles_6[] = INCBIN_U32("graphics/field_effect_objects/pics/bubbles/6.4bpp"); +const u32 gFieldEffectPic_Bubbles_7[] = INCBIN_U32("graphics/field_effect_objects/pics/bubbles/7.4bpp"); +const u32 gFieldEffectPic_Sparkle_0[] = INCBIN_U32("graphics/field_effect_objects/pics/sparkle/0.4bpp"); +const u32 gFieldEffectPic_Sparkle_1[] = INCBIN_U32("graphics/field_effect_objects/pics/sparkle/1.4bpp"); +const u16 gFieldEffectObjectPalette3[] = INCBIN_U16("graphics/field_effect_objects/palettes/03.gbapal"); +const u32 gFieldEffectPic_Bird[] = INCBIN_U32("graphics/field_effect_objects/pics/bird.4bpp"); + +void (*const gUnknown_0836DA88[])(struct Sprite *) = +{ + sub_805C884, + sub_805CDE8, + sub_805C8AC, + sub_805CF28, + sub_805CF28, + sub_805D0AC, + sub_805D0AC, + sub_805D230, + sub_805D230, + sub_805D230, + sub_805D230, + sub_80587B4, + FieldObjectCB_BerryTree, + sub_805D4F4, + sub_805D634, + sub_805D774, + sub_805D8B4, + sub_805D9F4, + sub_805DB34, + sub_805DC74, + sub_805DDB4, + sub_805DEF4, + sub_805E034, + sub_805E174, + sub_805E278, + sub_805E37C, + sub_805E37C, + sub_805E37C, + sub_805E37C, + sub_805E5DC, + sub_805E668, + sub_805E6F4, + sub_805E780, + sub_805E80C, + sub_805E898, + sub_805E924, + sub_805E9B0, + sub_805EA3C, + sub_805EAC8, + sub_805EB54, + sub_805EBE0, + sub_805EC6C, + sub_805ECF8, + sub_805ED84, + sub_805EE10, + sub_805EE9C, + sub_805EF28, + sub_805EFB4, + sub_805F040, + sub_805F0CC, + sub_805F158, + sub_805F1E4, + sub_805F270, + sub_805F2FC, + sub_805F2FC, + sub_805F2FC, + sub_805F2FC, + FieldObjectCB_TreeDisguise, + FieldObjectCB_MountainDisguise, + sub_805F8E0, + sub_805F8E0, + sub_805F8E0, + sub_805F8E0, + FieldObjectCB_Hidden1, + sub_805FB20, + sub_805FB20, + sub_805FB20, + sub_805FB20, + sub_805FB90, + sub_805FB90, + sub_805FB90, + sub_805FB90, + sub_805FC00, + sub_805FC00, + sub_805FC00, + sub_805FC00, + sub_805FC70 +}; + +const u8 gUnknown_0836DBBC[] = {0, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; +const u8 gUnknown_0836DC09[] = {DIR_SOUTH, DIR_SOUTH, DIR_SOUTH, DIR_NORTH, DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_SOUTH, DIR_SOUTH, DIR_SOUTH, DIR_WEST, DIR_NORTH, DIR_NORTH, DIR_SOUTH, DIR_SOUTH, DIR_SOUTH, DIR_SOUTH, DIR_NORTH, DIR_SOUTH, DIR_SOUTH, DIR_SOUTH, DIR_NORTH, DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_EAST, DIR_SOUTH, DIR_WEST, DIR_NORTH, DIR_WEST, DIR_SOUTH, DIR_EAST, DIR_WEST, DIR_NORTH, DIR_EAST, DIR_SOUTH, DIR_EAST, DIR_NORTH, DIR_WEST, DIR_SOUTH, DIR_NORTH, DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_SOUTH, DIR_SOUTH, DIR_NORTH, DIR_SOUTH, DIR_WEST, DIR_EAST, DIR_SOUTH, DIR_SOUTH, DIR_NORTH, DIR_WEST, DIR_EAST, DIR_SOUTH, DIR_NORTH, DIR_WEST, DIR_EAST, DIR_SOUTH, DIR_NORTH, DIR_WEST, DIR_EAST, DIR_SOUTH}; + +#include "data/field_map_obj/map_object_graphics_info_pointers.h" +#include "data/field_map_obj/field_effect_object_template_pointers.h" +#include "data/field_map_obj/map_object_pic_tables.h" +#include "data/field_map_obj/map_object_anims.h" +#include "data/field_map_obj/base_oam.h" +#include "data/field_map_obj/map_object_subsprites.h" +#include "data/field_map_obj/map_object_graphics_info.h" + +const struct SpritePalette gUnknown_0837377C[] = { + {gMapObjectPalette0, 0x1103}, + {gMapObjectPalette1, 0x1104}, + {gMapObjectPalette2, 0x1105}, + {gMapObjectPalette3, 0x1106}, + {gMapObjectPalette4, 0x1107}, + {gMapObjectPalette5, 0x1108}, + {gMapObjectPalette6, 0x1109}, + {gMapObjectPalette7, 0x110A}, + {gMapObjectPalette8, 0x1100}, + {gMapObjectPalette9, 0x1101}, + {gMapObjectPalette10, 0x1102}, + {gMapObjectPalette11, 0x1115}, + {gMapObjectPalette12, 0x110B}, + {gMapObjectPalette13, 0x110C}, + {gMapObjectPalette14, 0x110D}, + {gMapObjectPalette15, 0x110E}, + {gMapObjectPalette16, 0x110F}, + {gMapObjectPalette17, 0x1110}, + {gMapObjectPalette18, 0x1111}, + {gMapObjectPalette19, 0x1112}, + {gMapObjectPalette20, 0x1113}, + {gMapObjectPalette21, 0x1114}, + {gMapObjectPalette22, 0x1116}, + {gMapObjectPalette23, 0x1117}, + {gMapObjectPalette24, 0x1118}, + {gMapObjectPalette25, 0x1119}, + {gMapObjectPalette26, 0x111A}, + {NULL, 0x0000} +}; + +const u16 Palettes_837385C[] = { + 0x1101, + 0x1101, + 0x1101, + 0x1101 +}; + +const u16 Palettes_8373864[] = { + 0x1111, + 0x1111, + 0x1111, + 0x1111 +}; + +const u16 Palettes_837386C[] = { + 0x1115, + 0x1115, + 0x1115, + 0x1115 +}; + +const struct PairedPalettes gUnknown_08373874[] = { + {0x1100, Palettes_837385C}, + {0x1110, Palettes_837385C}, + {0x1115, Palettes_837386C}, + {0x11FF, NULL} +}; + +const u16 Palettes_8373894[] = { + 0x110C, + 0x110C, + 0x110C, + 0x110C +}; + +const u16 Palettes_837389C[] = { + 0x110D, + 0x110D, + 0x110D, + 0x110D +}; + +const u16 Palettes_83738A4[] = { + 0x110E, + 0x110E, + 0x110E, + 0x110E +}; + +const u16 Palettes_83738AC[] = { + 0x1112, + 0x1112, + 0x1112, + 0x1112 +}; + +const u16 Palettes_83738B4[] = { + 0x1113, + 0x1113, + 0x1113, + 0x1113 +}; + +const u16 Palettes_83738BC[] = { + 0x1114, + 0x1114, + 0x1114, + 0x1114 +}; + +const u16 Palettes_83738C4[] = { + 0x111A, + 0x111A, + 0x111A, + 0x111A +}; + +const u16 Palettes_83738CC[] = { + 0x1117, + 0x1117, + 0x1117, + 0x1117 +}; + +const u16 Palettes_83738D4[] = { + 0x1119, + 0x1119, + 0x1119, + 0x1119 +}; + +const u16 Palettes_83738DC[] = { + 0x1109, + 0x1109, + 0x1109, + 0x1109 +}; + +const struct PairedPalettes gUnknown_083738E4[] = { + {0x1100, Palettes_837385C}, + {0x1110, Palettes_837385C}, + {0x110B, Palettes_8373894}, + {0x110D, Palettes_837389C}, + {0x110E, Palettes_83738A4}, + {0x1112, Palettes_83738AC}, + {0x1113, Palettes_83738B4}, + {0x1114, Palettes_83738BC}, + {0x1116, Palettes_83738CC}, + {0x1118, Palettes_83738D4}, + {0x1105, Palettes_83738DC}, + {0x111A, Palettes_83738C4}, + {0x11FF, NULL} +}; + +const u16 Unknown_837394C[] = { + 0x1100, + 0x1101, + 0x1103, + 0x1104, + 0x1105, + 0x1106, + 0x1107, + 0x1108, + 0x1109, + 0x110A +}; + +const u16 Unknown_8373960[] = { + 0x1100, + 0x1101, + 0x1103, + 0x1104, + 0x1105, + 0x1106, + 0x1107, + 0x1108, + 0x1109, + 0x110A +}; + +const u16 Unknown_8373974[] = { + 0x1100, + 0x1101, + 0x1103, + 0x1104, + 0x1105, + 0x1106, + 0x1107, + 0x1108, + 0x1109, + 0x110A +}; + +const u16 Unknown_8373988[] = { + 0x1100, + 0x1101, + 0x1103, + 0x1104, + 0x1105, + 0x1106, + 0x1107, + 0x1108, + 0x1109, + 0x110A +}; + +const u16 *const gUnknown_0837399C[] = { + Unknown_837394C, + Unknown_8373960, + Unknown_8373974, + Unknown_8373988 +}; + +#include "data/field_map_obj/berry_tree_graphics_tables.h" +#include "data/field_map_obj/field_effect_objects.h" + +const s16 gUnknown_0837520C[] = {0x20, 0x40, 0x60, 0x80}; +const s16 gUnknown_08375204[] = {0x20, 0x40, 0x80, 0xc0}; +const s16 gUnknown_0837521C[] = {0x20, 0x30, 0x40, 0x50}; + +#include "data/field_map_obj/callback_subroutine_pointers.h" + +const u8 gUnknown_083755F4[] = {0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x01, 0x01}; +const u8 gUnknown_083755FD[] = {0x04, 0x04, 0x05, 0x06, 0x07, 0x04, 0x04, 0x05, 0x05}; +const u8 gUnknown_08375606[] = {0x08, 0x08, 0x09, 0x0A, 0x0B, 0x08, 0x08, 0x09, 0x09}; +const u8 gUnknown_0837560F[] = {0x0C, 0x0C, 0x0D, 0x0E, 0x0F, 0x0C, 0x0C, 0x0D, 0x0D}; +const u8 gUnknown_08375618[] = {0x10, 0x10, 0x11, 0x12, 0x13, 0x10, 0x10, 0x11, 0x11}; +const u8 gUnknown_08375621[] = {0x14, 0x14, 0x15, 0x16, 0x17, 0x14, 0x14, 0x15, 0x15}; +const u8 gUnknown_0837562A[] = {0x14, 0x14, 0x15, 0x16, 0x17, 0x14, 0x14, 0x15, 0x15}; +const u8 gUnknown_08375633[] = {0x18, 0x18, 0x19, 0x1A, 0x1B, 0x18, 0x18, 0x19, 0x19}; +const u8 gUnknown_0837563C[] = {0x1C, 0x1C, 0x1D, 0x1E, 0x1F, 0x1C, 0x1C, 0x1D, 0x1D}; +const u8 gUnknown_08375645[] = {0x20, 0x20, 0x21, 0x22, 0x23, 0x20, 0x20, 0x21, 0x21}; +const u8 gUnknown_0837564E[] = {0x24, 0x24, 0x25, 0x26, 0x27, 0x24, 0x24, 0x25, 0x25}; +const u8 gUnknown_08375657[] = {0x00, 0x00, 0x01, 0x02, 0x03, 0x00, 0x00, 0x01, 0x01}; +const u8 gUnknown_08375660[] = {0x04, 0x04, 0x05, 0x06, 0x07, 0x04, 0x04, 0x05, 0x05}; +const u8 gUnknown_08375669[] = {0x08, 0x08, 0x09, 0x0A, 0x0B, 0x08, 0x08, 0x09, 0x09}; +const u8 gUnknown_08375672[] = {0x14, 0x14, 0x15, 0x16, 0x17, 0x14, 0x14, 0x15, 0x15}; +const u8 gUnknown_0837567B[] = {0x08, 0x08, 0x07, 0x09, 0x0A, 0x08, 0x08, 0x07, 0x07}; + +bool8 (*const gUnknown_08375684[])(u8) = { + MetatileBehavior_IsSouthBlocked, + MetatileBehavior_IsNorthBlocked, + MetatileBehavior_IsWestBlocked, + MetatileBehavior_IsEastBlocked +}; + +bool8 (*const gUnknown_08375694[])(u8) = { + MetatileBehavior_IsNorthBlocked, + MetatileBehavior_IsSouthBlocked, + MetatileBehavior_IsEastBlocked, + MetatileBehavior_IsWestBlocked +}; + +const struct Coords16 gDirectionToVector[] = { + { 0, 0}, + { 0, 1}, + { 0, -1}, + {-1, 0}, + { 1, 0}, + {-1, 1}, + { 1, 1}, + {-1, -1}, + { 1, -1} +}; + +const u8 gUnknown_083756C8[] = {0x00, 0x00, 0x01, 0x02, 0x03}; +const u8 gUnknown_083756CD[] = {0x04, 0x04, 0x05, 0x06, 0x07}; +const u8 gUnknown_083756D2[] = {0x08, 0x08, 0x09, 0x0A, 0x0B}; +const u8 gUnknown_083756D7[] = {0x15, 0x15, 0x16, 0x17, 0x18}; +const u8 gUnknown_083756DC[] = {0x29, 0x29, 0x2A, 0x2B, 0x2C}; +const u8 gUnknown_083756E1[] = {0x2D, 0x2D, 0x2E, 0x2F, 0x30}; +const u8 gUnknown_083756E6[] = {0x31, 0x31, 0x32, 0x33, 0x34}; +const u8 gUnknown_083756EB[] = {0x35, 0x35, 0x36, 0x37, 0x38}; +const u8 gUnknown_083756F0[] = {0x0C, 0x0C, 0x0D, 0x0E, 0x0F}; +const u8 gUnknown_083756F5[] = {0x46, 0x46, 0x47, 0x48, 0x49}; +const u8 gUnknown_083756FA[] = {0x4B, 0x4B, 0x4A, 0x4D, 0x4C}; +const u8 gUnknown_083756FF[] = {0x42, 0x42, 0x43, 0x44, 0x45}; +const u8 gUnknown_08375704[] = {0x3A, 0x3A, 0x3B, 0x3C, 0x3D}; +const u8 gUnknown_08375709[] = {0x19, 0x19, 0x1A, 0x1B, 0x1C}; +const u8 gUnknown_0837570E[] = {0x1D, 0x1D, 0x1E, 0x1F, 0x20}; +const u8 gUnknown_08375713[] = {0x21, 0x21, 0x22, 0x23, 0x24}; +const u8 gUnknown_08375718[] = {0x25, 0x25, 0x26, 0x27, 0x28}; +const u8 gUnknown_0837571D[] = {0x62, 0x62, 0x63, 0x64, 0x65}; +const u8 gUnknown_08375722[] = {0x66, 0x66, 0x67, 0x68, 0x69}; +const u8 gUnknown_08375727[] = {0x6A, 0x6A, 0x6B, 0x6C, 0x6D}; +const u8 gUnknown_0837572C[] = {0x6E, 0x6E, 0x6F, 0x70, 0x71}; +const u8 gUnknown_08375731[] = {0x72, 0x72, 0x73, 0x74, 0x75}; +const u8 gUnknown_08375736[] = {0x76, 0x76, 0x77, 0x78, 0x79}; +const u8 gUnknown_0837573B[] = {0x7A, 0x7A, 0x7B, 0x7C, 0x7D}; +const u8 gUnknown_08375740[] = {0x7E, 0x7E, 0x7F, 0x80, 0x81}; +const u8 gUnknown_08375745[] = {0x82, 0x82, 0x83, 0x84, 0x85}; +const u8 gUnknown_0837574A[] = {0x86, 0x86, 0x87, 0x88, 0x89}; + +const u8 gUnknown_0837574F[] = {2, 1, 4, 3, 8, 7, 6, 5}; + +const u8 gUnknown_08375757[][4] = { + {2, 1, 4, 3}, + {1, 2, 3, 4}, + {3, 4, 2, 1}, + {4, 3, 1, 2} +}; + +const u8 gUnknown_08375767[][4] = { + {2, 1, 4, 3}, + {1, 2, 3, 4}, + {4, 3, 1, 2}, + {3, 4, 2, 1} +}; + +#include "data/field_map_obj/anim_func_ptrs.h" + +// text + +extern void strange_npc_table_clear(void); +extern void ClearPlayerAvatarInfo(void); +extern void npc_load_two_palettes__no_record(u16, u8); +extern void npc_load_two_palettes__and_record(u16, u8); +extern void sub_8060388(s16, s16, s16 *, s16 *); +void sub_80634D0(struct MapObject *, struct Sprite *); +extern void pal_patch_for_npc(u16, u16); +extern void CameraObjectReset1(void); + +extern struct LinkPlayerMapObject gLinkPlayerMapObjects[]; +extern u8 gReservedSpritePaletteCount; +extern struct Camera gCamera; + +static u8 gUnknown_030005A4; +static u16 gUnknown_030005A6; + +struct MapObject gMapObjects[16]; + +void npc_clear_ids_and_state(struct MapObject *mapObj) +{ + memset(mapObj, 0, sizeof(struct MapObject)); + mapObj->localId = 0xFF; + mapObj->mapNum = 0xFF; + mapObj->mapGroup = 0xFF; + mapObj->mapobj_unk_1C = 0xFF; +} + +void npcs_clear_ids_and_state(void) +{ + u8 i; + + for (i = 0; i < 16; i++) + npc_clear_ids_and_state(&gMapObjects[i]); +} + +void sub_805AA98(void) +{ + strange_npc_table_clear(); + npcs_clear_ids_and_state(); + ClearPlayerAvatarInfo(); + sub_805AAB0(); +} + +void sub_805AAB0(void) +{ + u8 spriteId; + + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[21], 0, 0, 0x1F); + + gSprites[spriteId].oam.affineMode = 1; + InitSpriteAffineAnim(&gSprites[spriteId]); + StartSpriteAffineAnim(&gSprites[spriteId], 0); + gSprites[spriteId].invisible = 1; + + spriteId = CreateSpriteAtEnd(gFieldEffectObjectTemplatePointers[21], 0, 0, 0x1F); + + gSprites[spriteId].oam.affineMode = 1; + InitSpriteAffineAnim(&gSprites[spriteId]); + StartSpriteAffineAnim(&gSprites[spriteId], 1); + gSprites[spriteId].invisible = 1; +} + +u8 sub_805AB54(void) +{ + u8 i; + + for (i = 0; i < 16; i++) + { + if (!gMapObjects[i].active) + break; + } + return i; +} + +u8 GetFieldObjectIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) +{ + if (localId <= 0xFE) + return GetFieldObjectIdByLocalIdAndMapInternal(localId, mapNum, mapGroup); + else + return GetFieldObjectIdByLocalId(localId); +} + +bool8 TryGetFieldObjectIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup, u8 *mapObjectId) +{ + *mapObjectId = GetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup); + if (*mapObjectId == 16) + return TRUE; + else + return FALSE; +} + +u8 GetFieldObjectIdByXY(s16 x, s16 y) +{ + u8 i; + + for (i = 0; i < 16; i++) + { + if (gMapObjects[i].active && gMapObjects[i].coords2.x == x && gMapObjects[i].coords2.y == y) + break; + } + return i; +} + +u8 GetFieldObjectIdByLocalIdAndMapInternal(u8 localId, u8 mapNum, u8 mapGroup) +{ + u8 i; + + for (i = 0; i < 16; i++) + { + if (gMapObjects[i].active && gMapObjects[i].localId == localId && gMapObjects[i].mapNum == mapNum && gMapObjects[i].mapGroup == mapGroup) + return i; + } + return 16; +} + +u8 GetFieldObjectIdByLocalId(u8 localId) +{ + u8 i; + + for (i = 0; i < 16; i++) + { + if (gMapObjects[i].active && gMapObjects[i].localId == localId) + return i; + } + return 16; +} + +#ifdef NONMATCHING +u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u8 b, u8 c) +{ + struct MapObject2 *mapObj; //TODO: resolve the mapobj_unk_19b weirdness + u8 var; + u16 r3; + u16 r2; + + //asm("nop"::"r"(b)); + if (GetAvailableFieldObjectSlot(template->localId, b, c, &var) != 0) + return 16; + //_0805ACCE + mapObj = (struct MapObject2 *)&gMapObjects[var]; + npc_clear_ids_and_state((struct MapObject *)mapObj); + r3 = template->x + 7; + r2 = template->y + 7; + mapObj->active = TRUE; + mapObj->mapobj_bit_2 = TRUE; + mapObj->graphicsId = template->graphicsId; + mapObj->animPattern = template->movementType; + mapObj->localId = template->localId; + mapObj->mapNum = b; + mapObj->mapGroup = c; + mapObj->coords1.x = r3; + mapObj->coords1.y = r2; + mapObj->coords2.x = r3; + mapObj->coords2.y = r2; + mapObj->coords3.x = r3; + mapObj->coords3.y = r2; + mapObj->mapobj_unk_0B_0 = template->elevation; + mapObj->elevation = template->elevation; + mapObj->mapobj_unk_19 = template->unkA_0; + mapObj->mapobj_unk_19b = template->unkA_4; + mapObj->trainerType = template->unkC; + mapObj->trainerRange_berryTreeId = template->unkE; + mapObj->mapobj_unk_20 = gUnknown_0836DC09[template->movementType]; + FieldObjectSetDirection((struct MapObject *)mapObj, mapObj->mapobj_unk_20); + FieldObjectHandleDynamicGraphicsId(mapObj); + //asm("":::"r5","r6"); + if (gUnknown_0836DBBC[mapObj->animPattern] != 0) + { + if (mapObj->mapobj_unk_19 == 0) + mapObj->mapobj_unk_19++; + if (mapObj->mapobj_unk_19b == 0) + mapObj->mapobj_unk_19b++; + } + return var; +} +#else +__attribute__((naked)) +u8 InitFieldObjectStateFromTemplate(struct MapObjectTemplate *template, u8 b, u8 c) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r9\n\ + mov r6, r8\n\ + push {r6,r7}\n\ + sub sp, 0x4\n\ + adds r5, r0, 0\n\ + lsls r1, 24\n\ + lsrs r6, r1, 24\n\ + lsls r2, 24\n\ + lsrs r7, r2, 24\n\ + ldrb r0, [r5]\n\ + adds r1, r6, 0\n\ + adds r2, r7, 0\n\ + mov r3, sp\n\ + bl GetAvailableFieldObjectSlot\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _0805ACCE\n\ + movs r0, 0x10\n\ + b _0805ADC2\n\ +_0805ACCE:\n\ + mov r0, sp\n\ + ldrb r1, [r0]\n\ + lsls r0, r1, 3\n\ + adds r0, r1\n\ + lsls r0, 2\n\ + ldr r1, _0805ADD0 @ =gMapObjects\n\ + adds r4, r0, r1\n\ + adds r0, r4, 0\n\ + bl npc_clear_ids_and_state\n\ + ldrh r3, [r5, 0x4]\n\ + adds r3, 0x7\n\ + lsls r3, 16\n\ + lsrs r3, 16\n\ + ldrh r2, [r5, 0x6]\n\ + adds r2, 0x7\n\ + lsls r2, 16\n\ + lsrs r2, 16\n\ + ldrb r0, [r4]\n\ + movs r1, 0x1\n\ + orrs r0, r1\n\ + movs r1, 0x4\n\ + orrs r0, r1\n\ + strb r0, [r4]\n\ + ldrb r0, [r5, 0x1]\n\ + strb r0, [r4, 0x5]\n\ + ldrb r0, [r5, 0x9]\n\ + strb r0, [r4, 0x6]\n\ + ldrb r0, [r5]\n\ + strb r0, [r4, 0x8]\n\ + strb r6, [r4, 0x9]\n\ + strb r7, [r4, 0xA]\n\ + strh r3, [r4, 0xC]\n\ + strh r2, [r4, 0xE]\n\ + strh r3, [r4, 0x10]\n\ + strh r2, [r4, 0x12]\n\ + strh r3, [r4, 0x14]\n\ + strh r2, [r4, 0x16]\n\ + ldrb r0, [r5, 0x8]\n\ + movs r7, 0xF\n\ + adds r1, r7, 0\n\ + ands r1, r0\n\ + ldrb r2, [r4, 0xB]\n\ + movs r0, 0x10\n\ + negs r0, r0\n\ + mov r8, r0\n\ + ands r0, r2\n\ + orrs r0, r1\n\ + strb r0, [r4, 0xB]\n\ + ldrb r1, [r5, 0x8]\n\ + lsls r1, 4\n\ + ands r0, r7\n\ + orrs r0, r1\n\ + strb r0, [r4, 0xB]\n\ + ldrb r1, [r5, 0xA]\n\ + lsls r1, 28\n\ + movs r0, 0xF\n\ + mov r9, r0\n\ + lsrs r1, 28\n\ + ldrb r2, [r4, 0x19]\n\ + mov r0, r8\n\ + ands r0, r2\n\ + orrs r0, r1\n\ + strb r0, [r4, 0x19]\n\ + ldrb r1, [r5, 0xA]\n\ + lsrs r1, 4\n\ + lsls r1, 4\n\ + ands r0, r7\n\ + orrs r0, r1\n\ + strb r0, [r4, 0x19]\n\ + ldrh r0, [r5, 0xC]\n\ + strb r0, [r4, 0x7]\n\ + ldrh r0, [r5, 0xE]\n\ + strb r0, [r4, 0x1D]\n\ + ldr r1, _0805ADD4 @ =gUnknown_0836DC09\n\ + ldrb r0, [r5, 0x9]\n\ + adds r0, r1\n\ + ldrb r1, [r0]\n\ + adds r0, r4, 0\n\ + adds r0, 0x20\n\ + strb r1, [r0]\n\ + ldrb r1, [r0]\n\ + adds r0, r4, 0\n\ + bl FieldObjectSetDirection\n\ + adds r0, r4, 0\n\ + bl FieldObjectHandleDynamicGraphicsId\n\ + ldr r1, _0805ADD8 @ =gUnknown_0836DBBC\n\ + ldrb r0, [r4, 0x6]\n\ + adds r0, r1\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + beq _0805ADBE\n\ + ldrb r2, [r4, 0x19]\n\ + adds r0, r7, 0\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + bne _0805ADA6\n\ + lsls r0, r2, 28\n\ + lsrs r0, 28\n\ + adds r0, 0x1\n\ + mov r1, r9\n\ + ands r0, r1\n\ + mov r1, r8\n\ + ands r1, r2\n\ + orrs r1, r0\n\ + strb r1, [r4, 0x19]\n\ +_0805ADA6:\n\ + ldrb r2, [r4, 0x19]\n\ + movs r0, 0xF0\n\ + ands r0, r2\n\ + cmp r0, 0\n\ + bne _0805ADBE\n\ + lsrs r1, r2, 4\n\ + adds r1, 0x1\n\ + lsls r1, 4\n\ + adds r0, r7, 0\n\ + ands r0, r2\n\ + orrs r0, r1\n\ + strb r0, [r4, 0x19]\n\ +_0805ADBE:\n\ + mov r0, sp\n\ + ldrb r0, [r0]\n\ +_0805ADC2:\n\ + add sp, 0x4\n\ + pop {r3,r4}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .align 2, 0\n\ +_0805ADD0: .4byte gMapObjects\n\ +_0805ADD4: .4byte gUnknown_0836DC09\n\ +_0805ADD8: .4byte gUnknown_0836DBBC\n\ + .syntax divided\n"); +} +#endif + +u8 sub_805ADDC(u8 localId) +{ + u8 objectCount; + u8 i; + + if (gMapHeader.events == NULL) + return 16; + objectCount = gMapHeader.events->mapObjectCount; + for (i = 0; i < objectCount; i++) + { + struct MapObjectTemplate *template = &gSaveBlock1.mapObjectTemplates[i]; + + if (template->localId == localId && !FlagGet(template->flagId)) + return InitFieldObjectStateFromTemplate(template, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + } + return 16; +} + +u8 GetAvailableFieldObjectSlot(u16 a, u8 b, u8 c, u8 *d) +{ + u8 i = 0; + + for (i = 0; i < 16 && gMapObjects[i].active; i++) + { + if (gMapObjects[i].localId == a && gMapObjects[i].mapNum == b && gMapObjects[i].mapGroup == c) + return 1; + } + if (i >= 16) + return 1; + *d = i; + for (; i < 16; i++) + { + if (gMapObjects[i].active && gMapObjects[i].localId == a && gMapObjects[i].mapNum == b && gMapObjects[i].mapGroup == c) + return 1; + } + return 0; +} + +void RemoveFieldObject(struct MapObject *mapObject) +{ + mapObject->active = FALSE; + RemoveFieldObjectInternal(mapObject); +} + +void RemoveFieldObjectByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) +{ + u8 mapObjectId; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + return; + FlagSet(GetFieldObjectFlagIdByFieldObjectId(mapObjectId)); + RemoveFieldObject(&gMapObjects[mapObjectId]); +} + +void RemoveFieldObjectInternal(struct MapObject *mapObject) +{ + struct SpriteFrameImage image; + const struct MapObjectGraphicsInfo *gfxInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + + image.size = gfxInfo->size; + gSprites[mapObject->spriteId].images = ℑ + DestroySprite(&gSprites[mapObject->spriteId]); +} + +void npc_hide_all_but_player(void) +{ + u8 i; + + for (i = 0; i < 16; i++) + { + if (i != gPlayerAvatar.mapObjectId) + RemoveFieldObject(&gMapObjects[i]); + } +} + +u8 sub_805AFCC(struct MapObjectTemplate *mapObjTemplate, struct SpriteTemplate *sprTemplate, u8 c, u8 d, s16 e, s16 f) +{ + u8 mapObjectId; + u8 spriteId; + const struct MapObjectGraphicsInfo *gfxInfo; + struct MapObject *mapObject; + struct Sprite *sprite; + + mapObjectId = InitFieldObjectStateFromTemplate(mapObjTemplate, c, d); + if (mapObjectId == 16) + return 16; + + mapObject = &gMapObjects[mapObjectId]; + gfxInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + if (gfxInfo->paletteSlot == 0) + npc_load_two_palettes__no_record(gfxInfo->paletteTag1, gfxInfo->paletteSlot); + else if (gfxInfo->paletteSlot == 10) + npc_load_two_palettes__and_record(gfxInfo->paletteTag1, gfxInfo->paletteSlot); + if (mapObject->animPattern == 0x4C) + mapObject->mapobj_bit_13 = TRUE; + +#ifdef NONMATCHING + sprTemplate->paletteTag = 0xFFFF; +#else + *(u16 *)&sprTemplate->paletteTag = 0xFFFF; +#endif + spriteId = CreateSprite(sprTemplate, 0, 0, 0); + if (spriteId == 64) + { + gMapObjects[mapObjectId].active = FALSE; + return 16; + } + sprite = &gSprites[spriteId]; + sub_8060388(e + mapObject->coords2.x, f + mapObject->coords2.y, &sprite->pos1.x, &sprite->pos1.y); + sprite->centerToCornerVecX = -(gfxInfo->width >> 1); + sprite->centerToCornerVecY = -(gfxInfo->height >> 1); + sprite->pos1.x += 8; + sprite->pos1.y += 16 + sprite->centerToCornerVecY; + sprite->oam.paletteNum = gfxInfo->paletteSlot; + sprite->coordOffsetEnabled = TRUE; + sprite->data0 = mapObjectId; + mapObject->spriteId = spriteId; + mapObject->mapobj_bit_12 = gfxInfo->inanimate; + if (!mapObject->mapobj_bit_12) + StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(mapObject->mapobj_unk_18)); + SetObjectSubpriorityByZCoord(mapObject->elevation, sprite, 1); + sub_80634D0(mapObject, sprite); + return mapObjectId; +} + +u8 SpawnFieldObject(struct MapObjectTemplate *mapObjTemplate, u8 b, u8 c, s16 d, s16 e) +{ + struct SpriteTemplate spriteTemplate; + const struct SubspriteTable *subspriteTables = NULL; + struct SpriteFrameImage spriteFrameImage; + const struct MapObjectGraphicsInfo *gfxInfo; + u8 mapObjectId; + + gfxInfo = GetFieldObjectGraphicsInfo(mapObjTemplate->graphicsId); + MakeObjectTemplateFromFieldObjectTemplate(mapObjTemplate, &spriteTemplate, &subspriteTables); + spriteFrameImage.size = gfxInfo->size; + spriteTemplate.images = &spriteFrameImage; + mapObjectId = sub_805AFCC(mapObjTemplate, &spriteTemplate, b, c, d, e); + if (mapObjectId == 16) + return 16; + gSprites[gMapObjects[mapObjectId].spriteId].images = gfxInfo->images; + if (subspriteTables != NULL) + SetSubspriteTables(&gSprites[gMapObjects[mapObjectId].spriteId], subspriteTables); + return mapObjectId; +} + +u8 SpawnSpecialFieldObject(struct MapObjectTemplate *mapObjTemplate) +{ + s16 x; + s16 y; + + GetFieldObjectMovingCameraOffset(&x, &y); + return SpawnFieldObject(mapObjTemplate, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, x, y); +} + +u8 SpawnSpecialFieldObjectParametrized(u8 a, u8 b, u8 c, s16 d, s16 e, u8 f) +{ + struct MapObjectTemplate mapObjTemplate; + + d -= 7; + e -= 7; + mapObjTemplate.localId = c; + mapObjTemplate.graphicsId = a; + mapObjTemplate.unk2 = 0; + mapObjTemplate.x = d; + mapObjTemplate.y = e; + mapObjTemplate.elevation = f; + mapObjTemplate.movementType = b; + mapObjTemplate.unkA_0 = 0; + mapObjTemplate.unkA_4 = 0; + mapObjTemplate.unkC = 0; + mapObjTemplate.unkE = 0; + return SpawnSpecialFieldObject(&mapObjTemplate); +} + +u8 show_sprite(u8 a, u8 b, u8 c) +{ + struct MapObjectTemplate *r5; + s16 x; + s16 y; + + r5 = GetFieldObjectTemplateByLocalIdAndMap(a, b, c); + if (r5 == NULL) + return 16; + GetFieldObjectMovingCameraOffset(&x, &y); + return SpawnFieldObject(r5, b, c, x, y); +} + +void MakeObjectTemplateFromFieldObjectGraphicsInfo(u16 graphicsId, void (*callback)(struct Sprite *), struct SpriteTemplate *sprTemplate, const struct SubspriteTable **subspriteTables) +{ + const struct MapObjectGraphicsInfo *gfxInfo = GetFieldObjectGraphicsInfo(graphicsId); + + sprTemplate->tileTag = gfxInfo->tileTag; + sprTemplate->paletteTag = gfxInfo->paletteTag1; + sprTemplate->oam = gfxInfo->oam; + sprTemplate->anims = gfxInfo->anims; + sprTemplate->images = gfxInfo->images; + sprTemplate->affineAnims = gfxInfo->affineAnims; + sprTemplate->callback = callback; + *subspriteTables = gfxInfo->subspriteTables; +} + +void MakeObjectTemplateFromFieldObjectGraphicsInfoWithCallbackIndex(u16 graphicsId, u16 callbackIndex, struct SpriteTemplate *sprTemplate, const struct SubspriteTable **subspriteTables) +{ + MakeObjectTemplateFromFieldObjectGraphicsInfo(graphicsId, gUnknown_0836DA88[callbackIndex], sprTemplate, subspriteTables); +} + +void MakeObjectTemplateFromFieldObjectTemplate(struct MapObjectTemplate *mapObjTemplate, struct SpriteTemplate *sprTemplate, const struct SubspriteTable **subspriteTables) +{ + MakeObjectTemplateFromFieldObjectGraphicsInfoWithCallbackIndex(mapObjTemplate->graphicsId, mapObjTemplate->movementType, sprTemplate, subspriteTables); +} + +u8 AddPseudoFieldObject(u16 graphicsId, void (*callback)(struct Sprite *), s16 c, s16 d, u8 subpriority) +{ + struct SpriteTemplate spriteTemplate; + const struct SubspriteTable *subspriteTables; + u8 spriteId; + + MakeObjectTemplateFromFieldObjectGraphicsInfo(graphicsId, callback, &spriteTemplate, &subspriteTables); + if (spriteTemplate.paletteTag != 0xFFFF) + sub_805BDF8(spriteTemplate.paletteTag); + spriteId = CreateSprite(&spriteTemplate, c, d, subpriority); + if (spriteId != 64 && subspriteTables != NULL) + { + SetSubspriteTables(&gSprites[spriteId], subspriteTables); + gSprites[spriteId].subspriteMode = 2; + } + return spriteId; +} + +extern void sub_8064970(struct Sprite *); +extern void sub_8060470(s16 *, s16 *, s16, s16); +extern void InitObjectPriorityByZCoord(); + +u8 sub_805B410(u8 graphicsId, u8 b, s16 x, s16 y, u8 elevation, u8 direction) +{ + const struct MapObjectGraphicsInfo *gfxInfo; + struct SpriteTemplate spriteTemplate; + const struct SubspriteTable *subspriteTables; + u8 spriteId; + + gfxInfo = GetFieldObjectGraphicsInfo(graphicsId); + MakeObjectTemplateFromFieldObjectGraphicsInfo(graphicsId, sub_8064970, &spriteTemplate, &subspriteTables); +#ifdef NONMATCHING + spriteTemplate.paletteTag = 0xFFFF; +#else + *(u16 *)&spriteTemplate.paletteTag = 0xFFFF; +#endif + x += 7; + y += 7; + sub_8060470(&x, &y, 8, 16); + spriteId = CreateSpriteAtEnd(&spriteTemplate, x, y, 0); + if (spriteId != 64) + { + struct Sprite *sprite = &gSprites[spriteId]; + + sprite->centerToCornerVecX = -(gfxInfo->width >> 1); + sprite->centerToCornerVecY = -(gfxInfo->height >> 1); + sprite->pos1.y += sprite->centerToCornerVecY; + sprite->oam.paletteNum = gfxInfo->paletteSlot; + sprite->coordOffsetEnabled = TRUE; + sprite->data0 = b; + sprite->data1 = elevation; + if (gfxInfo->paletteSlot == 10) + npc_load_two_palettes__and_record(gfxInfo->paletteTag1, gfxInfo->paletteSlot); + if (subspriteTables != NULL) + { + SetSubspriteTables(sprite, subspriteTables); + sprite->subspriteMode = 2; + } + InitObjectPriorityByZCoord(sprite, elevation); + SetObjectSubpriorityByZCoord(elevation, sprite, 1); + StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(direction)); + } + return spriteId; +} + +void sub_805B55C(s16 a, s16 b) +{ + u8 i; + + if (gMapHeader.events != NULL) + { + s16 r9 = gSaveBlock1.pos.x - 2; + s16 sp8 = gSaveBlock1.pos.x + 17; + s16 r10 = gSaveBlock1.pos.y; + s16 spC = gSaveBlock1.pos.y + 16; + u8 objectCount = gMapHeader.events->mapObjectCount; + + for (i = 0; i < objectCount; i++) + { + struct MapObjectTemplate *template = &gSaveBlock1.mapObjectTemplates[i]; + s16 foo = template->x + 7; + s16 bar = template->y + 7; + + if (r10 <= bar && spC >= bar && r9 <= foo && sp8 >= foo + && !FlagGet(template->flagId)) + SpawnFieldObject(template, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, a, b); + } + } +} + +void RemoveFieldObjectIfOutsideView(struct MapObject *mapObject); + +void RemoveFieldObjectsOutsideView(void) +{ + u8 i; + u8 j; + + for (i = 0; i < 16; i++) + { + bool8 isActiveLinkPlayer; + + for (j = 0, isActiveLinkPlayer = 0; j < 4; j++) + { + if (gLinkPlayerMapObjects[j].active && i == gLinkPlayerMapObjects[j].mapObjId) + isActiveLinkPlayer = TRUE; + } + if (!isActiveLinkPlayer) + { + struct MapObject *mapObject = &gMapObjects[i]; + + if (mapObject->active && !mapObject->mapobj_bit_16) + RemoveFieldObjectIfOutsideView(mapObject); + } + } +} + +void RemoveFieldObjectIfOutsideView(struct MapObject *mapObject) +{ + s16 r7 = gSaveBlock1.pos.x - 2; + s16 r5 = gSaveBlock1.pos.x + 17; + s16 r4 = gSaveBlock1.pos.y; + s16 r6 = gSaveBlock1.pos.y + 16; + + if (mapObject->coords2.x >= r7 && mapObject->coords2.x <= r5 + && mapObject->coords2.y >= r4 && mapObject->coords2.y <= r6) + return; + if (mapObject->coords1.x >= r7 && mapObject->coords1.x <= r5 + && mapObject->coords1.y >= r4 && mapObject->coords1.y <= r6) + return; + RemoveFieldObject(mapObject); +} + +void sub_805B75C(u8, s16, s16); + +void sub_805B710(u16 a, u16 b) +{ + u8 i; + + ClearPlayerAvatarInfo(); + for (i = 0; i < 16; i++) + { + if (gMapObjects[i].active) + sub_805B75C(i, a, b); + } + sub_805AAB0(); +} + +extern void SetPlayerAvatarFieldObjectIdAndObjectId(u8, u8); +extern void sub_805B914(struct MapObject *); + +void sub_805B75C(u8 a, s16 b, s16 c) +{ + struct SpriteTemplate sp0; + struct SpriteFrameImage sp18; + const struct SubspriteTable *subspriteTables; + const struct MapObjectGraphicsInfo *gfxInfo; + struct MapObject *mapObject; + u8 spriteId; + + #define i spriteId + for (i = 0; i < 4; i++) + { + if (gLinkPlayerMapObjects[i].active && a == gLinkPlayerMapObjects[i].mapObjId) + return; + } + #undef i + + mapObject = &gMapObjects[a]; + asm("":::"r5"); + subspriteTables = NULL; + gfxInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + sp18.size = gfxInfo->size; + MakeObjectTemplateFromFieldObjectGraphicsInfoWithCallbackIndex(mapObject->graphicsId, mapObject->animPattern, &sp0, &subspriteTables); + sp0.images = &sp18; + *(u16 *)&sp0.paletteTag = 0xFFFF; + if (gfxInfo->paletteSlot == 0) + npc_load_two_palettes__no_record(gfxInfo->paletteTag1, gfxInfo->paletteSlot); + if (gfxInfo->paletteSlot > 9) + npc_load_two_palettes__and_record(gfxInfo->paletteTag1, gfxInfo->paletteSlot); + *(u16 *)&sp0.paletteTag = 0xFFFF; + spriteId = CreateSprite(&sp0, 0, 0, 0); + if (spriteId != 64) + { + struct Sprite *sprite = &gSprites[spriteId]; + + sub_8060388(b + mapObject->coords2.x, c + mapObject->coords2.y, &sprite->pos1.x, &sprite->pos1.y); + sprite->centerToCornerVecX = -(gfxInfo->width >> 1); + sprite->centerToCornerVecY = -(gfxInfo->height >> 1); + sprite->pos1.x += 8; + sprite->pos1.y += 16 + sprite->centerToCornerVecY; + sprite->images = gfxInfo->images; + if (mapObject->animPattern == 11) + { + SetPlayerAvatarFieldObjectIdAndObjectId(a, spriteId); + mapObject->mapobj_unk_1B = sub_8126B54(); + } + if (subspriteTables != NULL) + SetSubspriteTables(sprite, subspriteTables); + sprite->oam.paletteNum = gfxInfo->paletteSlot; + sprite->coordOffsetEnabled = TRUE; + sprite->data0 = a; + mapObject->spriteId = spriteId; + if (!mapObject->mapobj_bit_12 && mapObject->animPattern != 11) + StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(mapObject->mapobj_unk_18)); + sub_805B914(mapObject); + SetObjectSubpriorityByZCoord(mapObject->elevation, sprite, 1); + } +} + +void sub_805B914(struct MapObject *mapObject) +{ + mapObject->mapobj_bit_1 = FALSE; + mapObject->mapobj_bit_2 = TRUE; + mapObject->mapobj_bit_22 = FALSE; + mapObject->mapobj_bit_17 = FALSE; + mapObject->mapobj_bit_18 = FALSE; + mapObject->mapobj_bit_19 = FALSE; + mapObject->mapobj_bit_20 = FALSE; + mapObject->mapobj_bit_21 = FALSE; + FieldObjectClearAnim(mapObject); +} + +void SetPlayerAvatarFieldObjectIdAndObjectId(u8 mapObjectId, u8 spriteId) +{ + gPlayerAvatar.mapObjectId = mapObjectId; + gPlayerAvatar.spriteId = spriteId; + gPlayerAvatar.gender = GetPlayerAvatarGenderByGraphicsId(gMapObjects[mapObjectId].graphicsId); + SetPlayerAvatarExtraStateTransition(gMapObjects[mapObjectId].graphicsId, 0x20); +} + +void sub_805B980(struct MapObject *mapObject, u8 graphicsId) +{ + const struct MapObjectGraphicsInfo *gfxInfo; + struct Sprite *sprite; + + gfxInfo = GetFieldObjectGraphicsInfo(graphicsId); + sprite = &gSprites[mapObject->spriteId]; + if (gfxInfo->paletteSlot == 0) + pal_patch_for_npc(gfxInfo->paletteTag1, gfxInfo->paletteSlot); + if (gfxInfo->paletteSlot == 10) + npc_load_two_palettes__and_record(gfxInfo->paletteTag1, gfxInfo->paletteSlot); + sprite->oam.shape = gfxInfo->oam->shape; + sprite->oam.size = gfxInfo->oam->size; + sprite->images = gfxInfo->images; + sprite->anims = gfxInfo->anims; + sprite->subspriteTables = gfxInfo->subspriteTables; + sprite->oam.paletteNum = gfxInfo->paletteSlot; + mapObject->mapobj_bit_12 = gfxInfo->inanimate; + mapObject->graphicsId = graphicsId; + sub_80603CC(mapObject->coords2.x, mapObject->coords2.y, &sprite->pos1.x, &sprite->pos1.y); + sprite->centerToCornerVecX = -(gfxInfo->width >> 1); + sprite->centerToCornerVecY = -(gfxInfo->height >> 1); + sprite->pos1.x += 8; + sprite->pos1.y += 16 + sprite->centerToCornerVecY; + if (mapObject->mapobj_bit_15) + CameraObjectReset1(); +} + +void unref_sub_805BA80(u8 localId, u8 mapNum, u8 mapGroup, u8 graphicsId) +{ + u8 mapObjectId; + + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + sub_805B980(&gMapObjects[mapObjectId], graphicsId); +} + +void FieldObjectTurn(struct MapObject *mapObject, u8 direction) +{ + FieldObjectSetDirection(mapObject, direction); + if (!mapObject->mapobj_bit_12) + { + StartSpriteAnim(&gSprites[mapObject->spriteId], FieldObjectDirectionToImageAnimId(mapObject->mapobj_unk_18)); + SeekSpriteAnim(&gSprites[mapObject->spriteId], 0); + } +} + +void FieldObjectTurnByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup, u8 direction) +{ + u8 mapObjectId; + + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + FieldObjectTurn(&gMapObjects[mapObjectId], direction); +} + +void unref_TurnPlayer(struct PlayerAvatar *player, u8 direction) +{ + FieldObjectTurn(&gMapObjects[player->mapObjectId], direction); +} + +void get_berry_tree_graphics(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 treeStage; + u8 treeId; + + mapObject->mapobj_bit_13 = TRUE; + sprite->invisible = TRUE; + treeStage = GetStageByBerryTreeId(mapObject->trainerRange_berryTreeId); + if (treeStage != 0) + { + mapObject->mapobj_bit_13 = FALSE; + sprite->invisible = FALSE; + treeId = GetBerryTypeByBerryTreeId(mapObject->trainerRange_berryTreeId) - 1; + treeStage--; + if (treeId > 0x2B) + treeId = 0; + sub_805B980(mapObject, gBerryTreeGraphicsIdTablePointers[treeId][treeStage]); + sprite->images = gBerryTreePicTablePointers[treeId]; + sprite->oam.paletteNum = gBerryTreePaletteSlotTablePointers[treeId][treeStage]; + StartSpriteAnim(sprite, treeStage); + } +} + +const struct MapObjectGraphicsInfo *GetFieldObjectGraphicsInfo(u8 graphicsId) +{ + if (graphicsId > 0xEF) + graphicsId = VarGetFieldObjectGraphicsId(graphicsId + 16); + if (graphicsId > 0xD9) + graphicsId = 5; + return gMapObjectGraphicsInfoPointers[graphicsId]; +} + +void FieldObjectHandleDynamicGraphicsId(struct MapObject *mapObject) +{ + if (mapObject->graphicsId > 0xEF) + mapObject->graphicsId = VarGetFieldObjectGraphicsId(mapObject->graphicsId + 16); +} + +void npc_by_local_id_and_map_set_field_1_bit_x20(u8 localId, u8 mapNum, u8 mapGroup, u8 d) +{ + u8 mapObjectId; + + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + gMapObjects[mapObjectId].mapobj_bit_13 = d; +} + +void FieldObjectGetLocalIdAndMap(struct MapObject *mapObject, u8 *localId, u8 *mapNum, u8 *mapGroup) +{ + *localId = mapObject->localId; + *mapNum = mapObject->mapNum; + *mapGroup = mapObject->mapGroup; +} + +void sub_805BCC0(s16 x, s16 y) +{ + u8 mapObjectId; + struct MapObject *mapObject; + + mapObjectId = GetFieldObjectIdByXY(x, y); + if (mapObjectId != 16) + { + mapObject = &gMapObjects[mapObjectId]; + mapObject->mapobj_bit_2 = TRUE; + } +} + +void sub_805BCF0(u8 localId, u8 mapNum, u8 mapGroup, u8 subpriority) +{ + u8 mapObjectId; + struct MapObject *mapObject; + struct Sprite *sprite; + + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + { + mapObject = &gMapObjects[mapObjectId]; + sprite = &gSprites[mapObject->spriteId]; + mapObject->mapobj_bit_26 = TRUE; + sprite->subpriority = subpriority; + } +} + +void sub_805BD48(u8 localId, u8 mapNum, u8 mapGroup) +{ + u8 mapObjectId; + struct MapObject *mapObject; + + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + { + mapObject = &gMapObjects[mapObjectId]; + mapObject->mapobj_bit_26 = FALSE; + mapObject->mapobj_bit_2 = TRUE; + } +} + +void sub_805BD90(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y) +{ + u8 mapObjectId; + struct Sprite *sprite; + + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + { + sprite = &gSprites[gMapObjects[mapObjectId].spriteId]; + sprite->pos2.x = x; + sprite->pos2.y = y; + } +} + +void gpu_pal_allocator_reset__manage_upper_four(void) +{ + FreeAllSpritePalettes(); + gReservedSpritePaletteCount = 12; +} + +void sub_805BDF8(u16 tag) +{ + u16 paletteIndex = FindFieldObjectPaletteIndexByTag(tag); + + if (paletteIndex != 0x11FF) //always happens. FindFieldObjectPaletteIndexByTag returns u8 + sub_805BE58(&gUnknown_0837377C[paletteIndex]); +} + +void unref_sub_805BE24(u16 *arr) +{ + u8 i; + + for (i = 0; arr[i] != 0x11FF; i++) + sub_805BDF8(arr[i]); +} + +u8 sub_805BE58(const struct SpritePalette *palette) +{ + if (IndexOfSpritePaletteTag(palette->tag) != 0xFF) + return 0xFF; + else + return LoadSpritePalette(palette); +} + +void pal_patch_for_npc(u16 a, u16 b) +{ + u8 var = b; + u8 paletteIndex = FindFieldObjectPaletteIndexByTag(a); + + LoadPalette(gUnknown_0837377C[paletteIndex].data, var * 16 + 0x100, 0x20); +} + +void pal_patch_for_npc_range(const u16 *arr, u8 b, u8 c) +{ + for (; b < c; arr++, b++) + pal_patch_for_npc(*arr, b); +} + +u8 FindFieldObjectPaletteIndexByTag(u16 tag) +{ + u8 i; + + for (i = 0; gUnknown_0837377C[i].tag != 0x11FF; i++) + { + if (gUnknown_0837377C[i].tag == tag) + return i; + } + return 0xFF; +} + +void npc_load_two_palettes__no_record(u16 a, u8 b) +{ + u8 i; + + pal_patch_for_npc(a, b); + for (i = 0; gUnknown_08373874[i].tag != 0x11FF; i++) + { + if (gUnknown_08373874[i].tag == a) + { + pal_patch_for_npc(gUnknown_08373874[i].data[gUnknown_030005A4], gUnknown_0830FD14[b]); + break; + } + } +} + +void npc_load_two_palettes__and_record(u16 a, u8 b) +{ + u8 i; + + gUnknown_030005A6 = a; + pal_patch_for_npc(a, b); + for (i = 0; gUnknown_083738E4[i].tag != 0x11FF; i++) + { + if (gUnknown_083738E4[i].tag == a) + { + pal_patch_for_npc(gUnknown_083738E4[i].data[gUnknown_030005A4], gUnknown_0830FD14[b]); + break; + } + } +} + +void unref_sub_805C014(struct MapObject *mapObject, s16 x, s16 y) +{ + mapObject->coords3.x = mapObject->coords2.x; + mapObject->coords3.y = mapObject->coords2.y; + mapObject->coords2.x += x; + mapObject->coords2.y += y; +} + +void npc_coords_shift(struct MapObject *mapObject, s16 x, s16 y) +{ + mapObject->coords3.x = mapObject->coords2.x; + mapObject->coords3.y = mapObject->coords2.y; + mapObject->coords2.x = x; + mapObject->coords2.y = y; +} + +void npc_coords_set(struct MapObject *mapObject, s16 x, s16 y) +{ + mapObject->coords3.x = x; + mapObject->coords3.y = y; + mapObject->coords2.x = x; + mapObject->coords2.y = y; +} + +void sub_805C058(struct MapObject *mapObject, s16 x, s16 y) +{ + struct Sprite *sprite = &gSprites[mapObject->spriteId]; + const struct MapObjectGraphicsInfo *gfxInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + + npc_coords_set(mapObject, x, y); + sub_80603CC(mapObject->coords2.x, mapObject->coords2.y, &sprite->pos1.x, &sprite->pos1.y); + sprite->centerToCornerVecX = -(gfxInfo->width >> 1); + sprite->centerToCornerVecY = -(gfxInfo->height >> 1); + sprite->pos1.x += 8; + sprite->pos1.y += 16 + sprite->centerToCornerVecY; + sub_805B914(mapObject); + if (mapObject->mapobj_bit_15) + CameraObjectReset1(); +} + +void sub_805C0F8(u8 localId, u8 mapNum, u8 mapGroup, s16 x, s16 y) +{ + u8 mapObjectId; + + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + { + x += 7; + y += 7; + sub_805C058(&gMapObjects[mapObjectId], x, y); + } +} + +void npc_coords_shift_still(struct MapObject *mapObject) +{ + npc_coords_shift(mapObject, mapObject->coords2.x, mapObject->coords2.y); +} + +void UpdateFieldObjectCoordsForCameraUpdate(void) +{ + u8 i; + s16 deltaX; + s16 deltaY; + + if (gCamera.field_0) + { + deltaX = gCamera.x; + deltaY = gCamera.y; + for (i = 0; i < 16; i++) + { + + if (gMapObjects[i].active) + { + gMapObjects[i].coords1.x -= deltaX; + gMapObjects[i].coords1.y -= deltaY; + gMapObjects[i].coords2.x -= deltaX; + gMapObjects[i].coords2.y -= deltaY; + gMapObjects[i].coords3.x -= deltaX; + gMapObjects[i].coords3.y -= deltaY; + } + } + } +} + +bool8 FieldObjectDoesZCoordMatch(struct MapObject *, u8); + +u8 GetFieldObjectIdByXYZ(u16 x, u16 y, u8 z) +{ + u8 i; + + for (i = 0; i < 16; i++) + { + if (gMapObjects[i].active && gMapObjects[i].coords2.x == x && gMapObjects[i].coords2.y == y + && FieldObjectDoesZCoordMatch(&gMapObjects[i], z)) + return i; + } + return 16; +} + +bool8 FieldObjectDoesZCoordMatch(struct MapObject *mapObject, u8 z) +{ + if (mapObject->mapobj_unk_0B_0 != 0 && z != 0 + && mapObject->mapobj_unk_0B_0 != z) + return FALSE; + else + return TRUE; +} + +void UpdateFieldObjectsForCameraUpdate(s16 x, s16 y) +{ + UpdateFieldObjectCoordsForCameraUpdate(); + sub_805B55C(x, y); + RemoveFieldObjectsOutsideView(); +} + +u8 AddCameraObject(u8 a) +{ + u8 spriteId = CreateSprite(&gSpriteTemplate_830FD24, 0, 0, 4); + + gSprites[spriteId].invisible = TRUE; + gSprites[spriteId].data0 = a; + return spriteId; +} + +void ObjectCB_CameraObject(struct Sprite *sprite) +{ + void (*cameraObjectFuncs[3])(struct Sprite *); + memcpy(cameraObjectFuncs, gCameraObjectFuncs, sizeof gCameraObjectFuncs); + cameraObjectFuncs[sprite->data1](sprite); +} + +void CameraObject_0(struct Sprite *sprite) +{ + sprite->pos1.x = gSprites[sprite->data0].pos1.x; + sprite->pos1.y = gSprites[sprite->data0].pos1.y; + sprite->invisible = TRUE; + sprite->data1 = 1; + CameraObject_1(sprite); +} + +void CameraObject_1(struct Sprite *sprite) +{ + s16 x = gSprites[sprite->data0].pos1.x; + s16 y = gSprites[sprite->data0].pos1.y; + + sprite->data2 = x - sprite->pos1.x; + sprite->data3 = y - sprite->pos1.y; + sprite->pos1.x = x; + sprite->pos1.y = y; +} + +void CameraObject_2(struct Sprite *sprite) +{ + sprite->pos1.x = gSprites[sprite->data0].pos1.x; + sprite->pos1.y = gSprites[sprite->data0].pos1.y; + sprite->data2 = 0; + sprite->data3 = 0; +} + +struct Sprite *FindCameraObject(void) +{ + u8 i; + + for (i = 0; i < 64; i++) + { + if (gSprites[i].inUse && gSprites[i].callback == ObjectCB_CameraObject) + return &gSprites[i]; + } + return NULL; +} + +void CameraObjectReset1(void) +{ + struct Sprite *cameraSprite = FindCameraObject(); + + if (cameraSprite != NULL) + { + cameraSprite->data1 = 0; + cameraSprite->callback(cameraSprite); + } +} + +void CameraObjectSetFollowedObjectId(u8 spriteId) +{ + struct Sprite *cameraSprite = FindCameraObject(); + + if (cameraSprite != NULL) + { + cameraSprite->data0 = spriteId; + CameraObjectReset1(); + } +} + +u8 CameraObjectGetFollowedObjectId(void) +{ + struct Sprite *cameraSprite = FindCameraObject(); + + if (cameraSprite == NULL) + return 64; + else + return cameraSprite->data0; +} + +void CameraObjectReset2(void) +{ + struct Sprite *cameraSprite = FindCameraObject(); + + cameraSprite->data1 = 2; +} + +u8 unref_sub_805C43C(struct Sprite *src, s16 x, s16 y, u8 subpriority) +{ + u8 i; + + for (i = 0; i < 64; i++) + { + if (!gSprites[i].inUse) + { + gSprites[i] = *src; + gSprites[i].pos1.x = x; + gSprites[i].pos1.y = y; + gSprites[i].subpriority = subpriority; + break; + } + } + return i; +} + +u8 obj_unfreeze(struct Sprite *src, s16 x, s16 y, u8 subpriority) +{ + s16 i; + + for (i = 63; i > -1; i--) + { + if (!gSprites[i].inUse) + { + gSprites[i] = *src; + gSprites[i].pos1.x = x; + gSprites[i].pos1.y = y; + gSprites[i].subpriority = subpriority; + return i; + } + } + return 64; +} + +void FieldObjectSetDirection(struct MapObject *mapObject, u8 direction) +{ + mapObject->mapobj_unk_20 = mapObject->mapobj_unk_18; + if (!mapObject->mapobj_bit_9) + { + s8 _direction = direction; //needed for the asm to match + mapObject->mapobj_unk_18 = _direction; + } + mapObject->placeholder18 = direction; +} + +u8 *GetFieldObjectScriptPointerByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) +{ + struct MapObjectTemplate *template = GetFieldObjectTemplateByLocalIdAndMap(localId, mapNum, mapGroup); + + return template->script; +} + +u8 *GetFieldObjectScriptPointerByFieldObjectId(u8 mapObjectId) +{ + return GetFieldObjectScriptPointerByLocalIdAndMap(gMapObjects[mapObjectId].localId, gMapObjects[mapObjectId].mapNum, gMapObjects[mapObjectId].mapGroup); +} + +u16 GetFieldObjectFlagIdByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) +{ + struct MapObjectTemplate *template = GetFieldObjectTemplateByLocalIdAndMap(localId, mapNum, mapGroup); + + return template->flagId; +} + +u16 GetFieldObjectFlagIdByFieldObjectId(u8 mapObjectId) +{ + return GetFieldObjectFlagIdByLocalIdAndMap(gMapObjects[mapObjectId].localId, gMapObjects[mapObjectId].mapNum, gMapObjects[mapObjectId].mapGroup); +} + +u8 unref_sub_805C5D0(u8 localId, u8 mapNum, u8 mapGroup) +{ + u8 mapObjectId; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + return 0xFF; + else + return gMapObjects[mapObjectId].trainerType; +} + +u8 unref_sub_805C60C(u8 mapObjectId) +{ + return gMapObjects[mapObjectId].trainerType; +} + +u8 unref_sub_805C624(u8 localId, u8 mapNum, u8 mapGroup) +{ + u8 mapObjectId; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + return 0xFF; + else + return gMapObjects[mapObjectId].trainerRange_berryTreeId; +} + +u8 FieldObjectGetBerryTreeId(u8 mapObjectId) +{ + return gMapObjects[mapObjectId].trainerRange_berryTreeId; +} + +struct MapObjectTemplate *FindFieldObjectTemplateInArrayByLocalId(u8, struct MapObjectTemplate *, u8); + +struct MapObjectTemplate *GetFieldObjectTemplateByLocalIdAndMap(u8 localId, u8 mapNum, u8 mapGroup) +{ + if (gSaveBlock1.location.mapNum == mapNum && gSaveBlock1.location.mapGroup == mapGroup) + return FindFieldObjectTemplateInArrayByLocalId(localId, gSaveBlock1.mapObjectTemplates, gMapHeader.events->mapObjectCount); + else + { + struct MapHeader *mapHeader = Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum); + + return FindFieldObjectTemplateInArrayByLocalId(localId, mapHeader->events->mapObjects, mapHeader->events->mapObjectCount); + } +} + +struct MapObjectTemplate *FindFieldObjectTemplateInArrayByLocalId(u8 localId, struct MapObjectTemplate *templates, u8 count) +{ + u8 i; + + for (i = 0; i < count; i++) + { + if (templates[i].localId == localId) + return &templates[i]; + } + return NULL; +} + +struct MapObjectTemplate *sub_805C700(struct MapObject *mapObject) +{ + s32 i; + + if (mapObject->mapNum != gSaveBlock1.location.mapNum + || mapObject->mapGroup != gSaveBlock1.location.mapGroup) + return NULL; + + for (i = 0; i < 64; i++) + { + if (mapObject->localId == gSaveBlock1.mapObjectTemplates[i].localId) + return &gSaveBlock1.mapObjectTemplates[i]; + } + return NULL; +} + +void sub_805C754(struct MapObject *mapObject) +{ + struct MapObjectTemplate *template = sub_805C700(mapObject); + + if (template != NULL) + { + template->x = mapObject->coords2.x - 7; + template->y = mapObject->coords2.y - 7; + } +} + +void sub_805C774(struct MapObject *mapObject, u8 movementType) +{ + struct MapObjectTemplate *template = sub_805C700(mapObject); + + if (template != NULL) + template->movementType = movementType; +} + +void sub_805C78C(u8 localId, u8 mapNum, u8 mapGroup) +{ + u8 mapObjectId; + + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + sub_805C754(&gMapObjects[mapObjectId]); +} + +void sub_805C7C4(u8 a) +{ + gpu_pal_allocator_reset__manage_upper_four(); + gUnknown_030005A6 = 0x11FF; + gUnknown_030005A4 = a; + pal_patch_for_npc_range(gUnknown_0837399C[gUnknown_030005A4], 0, 10); +} + +u16 npc_paltag_by_palslot(u8 a) +{ + u8 i; + + if (a < 10) + return gUnknown_0837399C[gUnknown_030005A4][a]; + + for (i = 0; gUnknown_083738E4[i].tag != 0x11FF; i++) + { + if (gUnknown_083738E4[i].tag == gUnknown_030005A6) + { + return gUnknown_083738E4[i].data[gUnknown_030005A4]; + } + } + return 0x11FF; +} + +fieldmap_object_null_cb(sub_805C884, sub_805C8A8); +fieldmap_object_cb(sub_805C8AC, sub_805C8D0, gUnknown_08375224); + +u8 sub_805C8F0(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +extern void FieldObjectSetRegularAnim(struct MapObject *, struct Sprite *, u8); + +u8 sub_805C904(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +extern u8 FieldObjectExecRegularAnim(struct MapObject *, struct Sprite *); +extern void sub_8064820(struct Sprite *, s16); + +u8 sub_805C930(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite) == 0) + { + return 0; + } + sub_8064820(sprite, gUnknown_0837520C[Random() & 3]); + sprite->data1 = 3; + return 1; +} + +extern u8 sub_8064824(struct Sprite *); + +u8 sub_805C96C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) != 0) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +extern u8 sub_805FF20(struct MapObject *, u8); + +u8 sub_805C98C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[4]; + memcpy(directions, gUnknown_08375240, 4); + direction = directions[Random() & 3]; + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 5; + if (sub_805FF20(mapObject, direction) != 0) + { + sprite->data1 = 1; + } + return 1; +} + +u8 sub_805C9D8(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed0AnimId(mapObject->placeholder18)); + mapObject->mapobj_bit_1 = 1; + sprite->data1 = 6; + return 1; +} + +u8 sub_805CA08(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite) != 0) + { + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 1; + } + return 0; +} + +u8 FieldObjectIsTrainerAndCloseToPlayer(struct MapObject *mapObject) +{ + s16 x; + s16 y; + s16 objx; + s16 objy; + s16 minx; + s16 maxx; + s16 miny; + s16 maxy; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_DASH) == 0) + { + return 0; + } + if (mapObject->trainerType != 1 && mapObject->trainerType != 3) + { + return 0; + } + PlayerGetDestCoords(&x, &y); + objx = mapObject->coords2.x; + objy = mapObject->coords2.y; + minx = objx - mapObject->trainerRange_berryTreeId; + miny = objy - mapObject->trainerRange_berryTreeId; + maxx = objx + mapObject->trainerRange_berryTreeId; + maxy = objy + mapObject->trainerRange_berryTreeId; + if (minx > x || maxx < x || miny > y || maxy < y) + { + return 0; + } + return 1; +} + +u8 sub_805CAAC(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + if (a2 > a3) + { + dirn = DIR_EAST; + if (a0 < 0) + { + dirn = DIR_WEST; + } + } + else + { + dirn = DIR_SOUTH; + if (a1 < 0) + { + dirn = DIR_NORTH; + } + } + return dirn; +} + +u8 sub_805CADC(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = DIR_SOUTH; + if (a1 < 0) + { + dirn = DIR_NORTH; + } + return dirn; +} + +u8 sub_805CAEC(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = DIR_EAST; + if (a0 < 0) + { + dirn = DIR_WEST; + } + return dirn; +} + +u8 sub_805CB00(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = sub_805CAAC(a0, a1, a2, a3); + if (dirn == DIR_SOUTH) + { + dirn = sub_805CAEC(a0, a1, a2, a3); + if (dirn == DIR_EAST) + { + dirn = DIR_NORTH; + } + } + else if (dirn == DIR_EAST) + { + dirn = sub_805CADC(a0, a1, a2, a3); + if (dirn == DIR_SOUTH) + { + dirn = DIR_NORTH; + } + } + return dirn; +} + +u8 sub_805CB5C(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = sub_805CAAC(a0, a1, a2, a3); + if (dirn == DIR_SOUTH) + { + dirn = sub_805CAEC(a0, a1, a2, a3); + if (dirn == DIR_WEST) + { + dirn = DIR_NORTH; + } + } + else if (dirn == DIR_WEST) + { + dirn = sub_805CADC(a0, a1, a2, a3); + if (dirn == DIR_SOUTH) + { + dirn = DIR_NORTH; + } + } + return dirn; +} + +u8 sub_805CBB8(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = sub_805CAAC(a0, a1, a2, a3); + if (dirn == DIR_NORTH) + { + dirn = sub_805CAEC(a0, a1, a2, a3); + if (dirn == DIR_EAST) + { + dirn = DIR_SOUTH; + } + } + else if (dirn == DIR_EAST) + { + dirn = sub_805CADC(a0, a1, a2, a3); + if (dirn == DIR_NORTH) + { + dirn = DIR_SOUTH; + } + } + return dirn; +} + +u8 sub_805CC14(s16 a0, s16 a1, s16 a2, s16 a3) { + u8 dirn; + dirn = sub_805CAAC(a0, a1, a2, a3); + if (dirn == DIR_NORTH) + { + dirn = sub_805CAEC(a0, a1, a2, a3); + if (dirn == DIR_WEST) + { + dirn = DIR_SOUTH; + } + } + else if (dirn == DIR_WEST) + { + dirn = sub_805CADC(a0, a1, a2, a3); + if (dirn == DIR_NORTH) + { + dirn = DIR_SOUTH; + } + } + return dirn; +} + +u8 sub_805CC70(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = sub_805CAAC(a0, a1, a2, a3); + if (dirn == DIR_EAST) + { + dirn = sub_805CADC(a0, a1, a2, a3); + } + return dirn; +} + +u8 sub_805CCAC(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = sub_805CAAC(a0, a1, a2, a3); + if (dirn == DIR_WEST) + { + dirn = sub_805CADC(a0, a1, a2, a3); + } + return dirn; +} + +u8 sub_805CCE8(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = sub_805CAAC(a0, a1, a2, a3); + if (dirn == DIR_SOUTH) + { + dirn = sub_805CAEC(a0, a1, a2, a3); + } + return dirn; +} + +u8 sub_805CD24(s16 a0, s16 a1, s16 a2, s16 a3) +{ + u8 dirn; + dirn = sub_805CAAC(a0, a1, a2, a3); + if (dirn == DIR_NORTH) + { + dirn = sub_805CAEC(a0, a1, a2, a3); + } + return dirn; +} + +u8 sub_805CD60(struct MapObject *mapObject, u8 a1) +{ + s16 x; + s16 y; + s16 x2; + s16 y2; + if (!FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + return 0; + } + PlayerGetDestCoords(&x, &y); + x -= mapObject->coords2.x; + y -= mapObject->coords2.y; + x2 = x; + y2 = y; + if (x2 < 0) + { + x2 = -x2; + } + if (y2 < 0) + { + y2 = -y2; + } + return gUnknown_08375244[a1](x, y, x2, y2); +} + +fieldmap_object_cb(sub_805CDE8, sub_805CE0c, gUnknown_08375270); + +u8 sub_805CE2C(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805CE40(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805CE6C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite) != 0) + { + sub_8064820(sprite, gUnknown_0837520C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805CEB0(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805CEE0(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[4]; + memcpy(directions, gUnknown_08375240, 4); + direction = sub_805CD60(mapObject, 0); + if (direction == 0) + { + direction = directions[Random() & 3]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805CF28, sub_805CF4C, gUnknown_08375284); + +u8 sub_805CF6C(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805CF80(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805CFAC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite) == 0) + { + return 0; + } + sub_8064820(sprite, gUnknown_0837520C[Random() & 3]); + sprite->data1 = 3; + return 1; +} + +u8 sub_805CFE8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) != 0) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805D008(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[2]; + memcpy(directions, gUnknown_083752A0, 2); + direction = directions[Random() & 1]; + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 5; + if (sub_805FF20(mapObject, direction) != 0) + { + sprite->data1 = 1; + } + return 1; +} + +u8 sub_805D054(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed0AnimId(mapObject->placeholder18)); + mapObject->mapobj_bit_1 = 1; + sprite->data1 = 6; + return 1; +} + +u8 sub_805D084(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite) != 0) + { + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 1; + } + return 0; +} + +fieldmap_object_cb(sub_805D0AC, sub_805D0D0, gUnknown_083752A4); + +u8 sub_805D0F0(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805D104(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805D130(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite) == 0) + { + return 0; + } + sub_8064820(sprite, gUnknown_0837520C[Random() & 3]); + sprite->data1 = 3; + return 1; +} + +u8 sub_805D16C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) != 0) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805D18C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[2]; + memcpy(directions, gUnknown_083752C0, 2); + direction = directions[Random() & 1]; + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 5; + if (sub_805FF20(mapObject, direction) != 0) + { + sprite->data1 = 1; + } + return 1; +} + +u8 sub_805D1D8(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed0AnimId(mapObject->placeholder18)); + mapObject->mapobj_bit_1 = 1; + sprite->data1 = 6; + return 1; +} + +u8 sub_805D208(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite) != 0) + { + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 1; + } + return 0; +} + +fieldmap_object_cb(sub_805D230, sub_805D254, gUnknown_083752C4); + +u8 sub_805D274(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 1; + return 1; +} + +u8 sub_805D2A0(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite) != 0) + { + sprite->data1 = 2; + return 1; + } + return 0; +} + +u8 sub_805D2C0(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_1 = 0; + return 0; +} + +u8 sub_805D314(struct MapObject *mapObject, struct Sprite *sprite); + +void FieldObjectCB_BerryTree(struct Sprite *sprite) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[sprite->data0]; + if (!(sprite->data7 & 1)) + { + get_berry_tree_graphics(mapObject, sprite); + sprite->data7 |= 1; + } + meta_step(mapObject, sprite, sub_805D314); +} + +u8 sub_805D314(struct MapObject *mapObject, struct Sprite *sprite) +{ + return gUnknown_083752D0[sprite->data1](mapObject, sprite); +} + +u8 do_berry_tree_growth_sparkle_1(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 berryTreeStage; + npc_reset(mapObject, sprite); + mapObject->mapobj_bit_13 = 1; + sprite->invisible = 1; + berryTreeStage = GetStageByBerryTreeId(mapObject->trainerRange_berryTreeId); + if (!berryTreeStage) + { + if (!(sprite->data7 & 4) && sprite->animNum == 4) + { + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + FieldEffectStart(FLDEFF_BERRY_TREE_GROWTH_SPARKLE); + sprite->animNum = 0; + } + return 0; + } + mapObject->mapobj_bit_13 = 0; + sprite->invisible = 0; + berryTreeStage--; + if (sprite->animNum != berryTreeStage) + { + sprite->data1 = 2; + return 1; + } + get_berry_tree_graphics(mapObject, sprite); + FieldObjectSetRegularAnim(mapObject, sprite, 0x39); + sprite->data1 = 1; + return 1; +} + +u8 sub_805D3EC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sprite->data1 = 0; + return 1; + } + return 0; +} + +u8 do_berry_tree_growth_sparkle_2(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_1 = 1; + sprite->data1 = 3; + sprite->data2 = 0; + sprite->data7 |= 2; + gFieldEffectArguments[0] = mapObject->coords2.x; + gFieldEffectArguments[1] = mapObject->coords2.y; + gFieldEffectArguments[2] = sprite->subpriority - 1; + gFieldEffectArguments[3] = sprite->oam.priority; + FieldEffectStart(FLDEFF_BERRY_TREE_GROWTH_SPARKLE); + return 1; +} + +u8 sub_805D458(struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->data2++; + mapObject->mapobj_bit_13 = ((sprite->data2 & 0x2) >> 1); + sprite->animPaused = 1; + if (sprite->data2 > 64) + { + get_berry_tree_graphics(mapObject, sprite); + sprite->data1 = 4; + sprite->data2 = 0; + return 1; + } + return 0; +} + +u8 sub_805D4A8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->data2++; + mapObject->mapobj_bit_13 = ((sprite->data2 & 0x2) >> 1); + sprite->animPaused = 1; + if (sprite->data2 > 64) + { + sprite->data1 = 0; + sprite->data7 &= (-3); + return 1; + } + return 0; +} + +fieldmap_object_cb(sub_805D4F4, sub_805D518, gUnknown_083752E4); + +u8 sub_805D538(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805D54C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805D578(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837520C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805D5BC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805D5EC(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[2]; + memcpy(directions, gUnknown_083752A0, 2); + direction = sub_805CD60(mapObject, 1); + if (direction == 0) + { + direction = directions[Random() & 1]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805D634, sub_805D658, gUnknown_083752F8); + +u8 sub_805D678(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805D68C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805D6B8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837520C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805D6FC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805D72C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[2]; + memcpy(directions, gUnknown_083752C0, 2); + direction = sub_805CD60(mapObject, 2); + if (direction == 0) + { + direction = directions[Random() & 1]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805D774, sub_805D798, gUnknown_0837530C); + +u8 sub_805D7B8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805D7CC(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805D7F8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837521C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805D83C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805D86C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[2]; + memcpy(directions, gUnknown_08375320, 2); + direction = sub_805CD60(mapObject, 3); + if (direction == 0) + { + direction = directions[Random() & 1]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805D8B4, sub_805D8D8, gUnknown_08375324); + +u8 sub_805D8F8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805D90C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805D938(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837521C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805D97C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805D9AC(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[2]; + memcpy(directions, gUnknown_08375338, 2); + direction = sub_805CD60(mapObject, 4); + if (direction == 0) + { + direction = directions[Random() & 1]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805D9F4, sub_805DA18, gUnknown_0837533C); + +u8 sub_805DA38(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805DA4C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805DA78(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837521C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805DABC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805DAEC(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[2]; + memcpy(directions, gUnknown_08375350, 2); + direction = sub_805CD60(mapObject, 5); + if (direction == 0) + { + direction = directions[Random() & 1]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805DB34, sub_805DB58, gUnknown_08375354); + +u8 sub_805DB78(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805DB8C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805DBB8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837521C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805DBFC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805DC2C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[2]; + memcpy(directions, gUnknown_08375368, 2); + direction = sub_805CD60(mapObject, 6); + if (direction == 0) + { + direction = directions[Random() & 1]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805DC74, sub_805DC98, gUnknown_0837536C); + +u8 sub_805DCB8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805DCCC(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805DCF8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837521C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805DD3C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805DD6C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[4]; + memcpy(directions, gUnknown_08375380, 4); + direction = sub_805CD60(mapObject, 7); + if (direction == 0) + { + direction = directions[Random() & 3]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805DDB4, sub_805DDD8, gUnknown_08375384); + +u8 sub_805DDF8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805DE0C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805DE38(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837521C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805DE7C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805DEAC(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[4]; + memcpy(directions, gUnknown_08375398, 4); + direction = sub_805CD60(mapObject, 8); + if (direction == 0) + { + direction = directions[Random() & 3]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805DEF4, sub_805DF18, gUnknown_0837539C); + +u8 sub_805DF38(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805DF4C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805DF78(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837521C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805DFBC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805DFEC(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[4]; + memcpy(directions, gUnknown_083753B0, 4); + direction = sub_805CD60(mapObject, 9); + if (direction == 0) + { + direction = directions[Random() & 3]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805E034, sub_805E058, gUnknown_083753B4); + +u8 sub_805E078(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805E08C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 2; + return 1; +} + +u8 sub_805E0B8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, gUnknown_0837521C[Random() & 3]); + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805E0FC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 4; + return 1; + } + return 0; +} + +u8 sub_805E12C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[4]; + memcpy(directions, gUnknown_083753C8, 4); + direction = sub_805CD60(mapObject, 10); + if (direction == 0) + { + direction = directions[Random() & 3]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805E174, sub_805E198, gUnknown_083753CC); + +u8 sub_805E1B8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 1; + return 1; +} + +u8 sub_805E1E4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, 0x30); + sprite->data1 = 2; + } + return 0; +} + +u8 sub_805E208(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805E234(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[5]; + memcpy(directions, gUnknown_083753DC, 5); + direction = sub_805CD60(mapObject, 0); + if (direction == 0) + { + direction = directions[mapObject->mapobj_unk_18]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 0; + return 1; +} + +fieldmap_object_cb(sub_805E278, sub_803E29C, gUnknown_083753E4); + +u8 sub_805E2BC(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 1; + return 1; +} + +u8 sub_805E2E8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sub_8064820(sprite, 0x30); + sprite->data1 = 2; + } + return 0; +} + +u8 sub_805E30C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064824(sprite) || FieldObjectIsTrainerAndCloseToPlayer(mapObject)) + { + sprite->data1 = 3; + } + return 0; +} + +u8 sub_805E338(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + u8 directions[5]; + memcpy(directions, gUnknown_083753F4, 5); + direction = sub_805CD60(mapObject, 0); + if (direction == 0) + { + direction = directions[mapObject->mapobj_unk_18]; + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 0; + return 1; +} + +fieldmap_object_cb(sub_805E37C, sub_805E3A0, gUnknown_083753FC); + +u8 sub_805E3C0(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 sub_805E3D4(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 direction; + direction = gUnknown_0836DC09[mapObject->animPattern]; + if (mapObject->mapobj_unk_21 != 0) + { + direction = GetOppositeDirection(direction); + } + FieldObjectSetDirection(mapObject, direction); + sprite->data1 = 2; + return 1; +} + +u8 sub_805E40C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 v0; + u8 goSpeed0AnimId; + if (mapObject->mapobj_unk_21 && mapObject->coords1.x == mapObject->coords2.x && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 0; + FieldObjectSetDirection(mapObject, GetOppositeDirection(mapObject->placeholder18)); + } + v0 = sub_805FF20(mapObject, mapObject->placeholder18); + goSpeed0AnimId = GetGoSpeed0AnimId(mapObject->placeholder18); + if (v0 == 1) + { + mapObject->mapobj_unk_21 ++; + FieldObjectSetDirection(mapObject, GetOppositeDirection(mapObject->placeholder18)); + goSpeed0AnimId = GetGoSpeed0AnimId(mapObject->placeholder18); + v0 = sub_805FF20(mapObject, mapObject->placeholder18); + } + if (v0 != 0) + { + goSpeed0AnimId = GetStepInPlaceDelay16AnimId(mapObject->mapobj_unk_18); + } + FieldObjectSetRegularAnim(mapObject, sprite, goSpeed0AnimId); + mapObject->mapobj_bit_1 = 1; + sprite->data1 = 3; + return 1; +} + +u8 sub_805E4C4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 1; + } + return 0; +} + +u8 sub_805E4EC(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + sprite->data1 = 1; + return 1; +} + +u8 MoveFieldObjectInNextDirectionInSequence(struct MapObject *mapObject, struct Sprite *sprite, u8 *directionSequence) +{ + u8 v0; + u8 goSpeed0AnimId; + if (mapObject->mapobj_unk_21 == 3 && mapObject->coords1.x == mapObject->coords2.x && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 0; + } + FieldObjectSetDirection(mapObject, directionSequence[mapObject->mapobj_unk_21]); + goSpeed0AnimId = GetGoSpeed0AnimId(mapObject->placeholder18); + v0 = sub_805FF20(mapObject, mapObject->placeholder18); + if (v0 == 1) + { + mapObject->mapobj_unk_21 ++; + FieldObjectSetDirection(mapObject, directionSequence[mapObject->mapobj_unk_21]); + goSpeed0AnimId = GetGoSpeed0AnimId(mapObject->placeholder18); + v0 = sub_805FF20(mapObject, mapObject->placeholder18); + } + if (v0 != 0) + { + goSpeed0AnimId = GetStepInPlaceDelay16AnimId(mapObject->mapobj_unk_18); + } + FieldObjectSetRegularAnim(mapObject, sprite, goSpeed0AnimId); + mapObject->mapobj_bit_1 = 1; + sprite->data1 = 2; + return 1; +} + +u8 sub_805E5B4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 1; + } + return 0; +} + +fieldmap_object_cb(sub_805E5DC, sub_805E600, gUnknown_0837540C); + +u8 sub_805E620(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375418, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805E668, sub_805E68C, gUnknown_0837541C); + +u8 sub_805E6AC(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375428, 4); + if (mapObject->mapobj_unk_21 == 1 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 2; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805E6F4, sub_805E718, gUnknown_0837542C); + +u8 sub_805E738(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375438, 4); + if (mapObject->mapobj_unk_21 == 1 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 2; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805E780, sub_805E7A4, gUnknown_0837543C); + +u8 sub_805E7C4(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375448, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + + + +fieldmap_object_cb(sub_805E80C, sub_805E830, gUnknown_0837544C); + +u8 sub_805E850(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375458, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805E898, sub_805E8BC, gUnknown_0837545C); + +u8 sub_805E8DC(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375468, 4); + if (mapObject->mapobj_unk_21 == 1 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 2; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805E924, sub_805E948, gUnknown_0837546C); + +u8 sub_805E968(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375240, 4); + if (mapObject->mapobj_unk_21 == 1 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 2; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805E9B0, sub_805E9D4, gUnknown_08375478); + +u8 sub_805E9F4(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375484, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EA3C, sub_805EA60, gUnknown_08375488); + +u8 sub_805EA80(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375494, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EAC8, sub_805EAEC, gUnknown_08375498); + +u8 sub_805EB0C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_083754A4, 4); + if (mapObject->mapobj_unk_21 == 1 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 2; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EB54, sub_805EB78, gUnknown_083754A8); + +u8 sub_805EB98(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_083754B4, 4); + if (mapObject->mapobj_unk_21 == 1 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 2; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EBE0, sub_805EC04, gUnknown_083754B8); + +u8 sub_805EC24(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_083754C4, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EC6C, sub_805EC90, gUnknown_083754C8); + +u8 sub_805ECB0(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_083754D4, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805ECF8, sub_805ED1C, gUnknown_083754D8); + +u8 sub_805ED3C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_083754E4, 4); + if (mapObject->mapobj_unk_21 == 1 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 2; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805ED84, sub_805EDA8, gUnknown_083754E8); + +u8 sub_805EDC8(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_083754F4, 4); + if (mapObject->mapobj_unk_21 == 1 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 2; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EE10, sub_805EE34, gUnknown_083754F8); + +u8 sub_805EE54(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375504, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EE9C, sub_805EEC0, gUnknown_08375508); + +u8 sub_805EEE0(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375514, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EF28, sub_805EF4C, gUnknown_08375518); + +u8 sub_805EF6C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375524, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805EFB4, sub_805EFD8, gUnknown_08375528); + +u8 sub_805EFF8(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375534, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805F040, sub_805F064, gUnknown_08375538); + +u8 sub_805F084(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375544, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805F0CC, sub_805F0F0, gUnknown_08375548); + +u8 sub_805F110(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375554, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805F158, sub_805F17C, gUnknown_08375558); + +u8 sub_805F19C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375564, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.y == mapObject->coords2.y) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805F1E4, sub_805F208, gUnknown_08375568); + +u8 sub_805F228(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375574, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +} + +fieldmap_object_cb(sub_805F270, sub_805F294, gUnknown_08375578); + +u8 sub_805F2B4(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 directions[4]; + memcpy(directions, gUnknown_08375584, 4); + if (mapObject->mapobj_unk_21 == 2 && mapObject->coords1.x == mapObject->coords2.x) + { + mapObject->mapobj_unk_21 = 3; + } + return MoveFieldObjectInNextDirectionInSequence(mapObject, sprite, directions); +}; + +fieldmap_object_cb(sub_805F2FC, sub_805F320, gUnknown_08375588); + +u8 mss_npc_reset_oampriv3_1_unk2_unk3(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + if (mapObject->mapobj_unk_21 == 0) + { + mapObject->mapobj_unk_21 = player_get_direction_lower_nybble(); + } + sprite->data1 = 1; + return 1; +} + +u8 sub_805F364(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1C == 0xFF || gPlayerAvatar.running1 == 2) + { + return 0; + } + return gUnknown_08375594[player_get_x22()](mapObject, sprite, player_get_direction_upper_nybble(), NULL); +} + +u8 sub_805F3C4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + mapObject->mapobj_bit_1 = 0; + sprite->data1 = 1; + } + return 0; +} + +bool8 sub_805F3EC(struct MapObject *mapObject, struct Sprite *sprite, u8 a2, bool8 a3(u8)) +{ + return 0; +} + +bool8 sub_805F3F0(struct MapObject *mapObject, struct Sprite *sprite, u8 a2, bool8 a3(u8)) +{ + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(state_to_direction(gUnknown_0836DC09[mapObject->animPattern], mapObject->mapobj_unk_21, a2))); + mapObject->mapobj_bit_1 = 1; + sprite->data1 = 2; + return 1; +} + +bool8 sub_805F438(struct MapObject *mapObject, struct Sprite *sprite, u8 a2, bool8 a3(u8)) +{ + u32 direction; + s16 x; + s16 y; + + direction = a2; + direction = state_to_direction(gUnknown_0836DC09[mapObject->animPattern], mapObject->mapobj_unk_21, direction); + FieldObjectMoveDestCoords(mapObject, direction, &x, &y); + FieldObjectSetRegularAnim(mapObject, sprite, GetGoSpeed0AnimId(direction)); + if (npc_block_way(mapObject, x, y, direction) || (a3 != NULL && !a3(MapGridGetMetatileBehaviorAt(x, y)))) + { + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction)); + } + mapObject->mapobj_bit_1 = 1; + sprite->data1 = 2; + return 1; +} + +bool8 sub_805F4F0(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8)) +{ + u32 direction; + s16 x; + s16 y; + + direction = playerDirection; + direction = state_to_direction(gUnknown_0836DC09[mapObject->animPattern], mapObject->mapobj_unk_21, direction); + FieldObjectMoveDestCoords(mapObject, direction, &x, &y); + FieldObjectSetRegularAnim(mapObject, sprite, sub_8060744(direction)); + if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y)))) + { + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction)); + } + mapObject->mapobj_bit_1 = TRUE; + sprite->data1 = 2; + return TRUE; +} + +bool8 sub_805F5A8(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8)) +{ + u32 direction; + s16 x; + s16 y; + + direction = playerDirection; + direction = state_to_direction(gUnknown_0836DC09[mapObject->animPattern], mapObject->mapobj_unk_21, direction); + FieldObjectMoveDestCoords(mapObject, direction, &x, &y); + FieldObjectSetRegularAnim(mapObject, sprite, sub_806079C(direction)); + if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y)))) + { + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction)); + } + mapObject->mapobj_bit_1 = TRUE; + sprite->data1 = 2; + return TRUE; +} + +bool8 sub_805F660(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8)) +{ + u32 direction; + s16 x; + s16 y; + + direction = playerDirection; + direction = state_to_direction(gUnknown_0836DC09[mapObject->animPattern], mapObject->mapobj_unk_21, direction); + FieldObjectMoveDestCoords(mapObject, direction, &x, &y); + FieldObjectSetRegularAnim(mapObject, sprite, sub_80607C8(direction)); + if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y)))) + { + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction)); + } + mapObject->mapobj_bit_1 = TRUE; + sprite->data1 = 2; + return TRUE; +} + +bool8 cph_IM_DIFFERENT(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8)) +{ + u32 direction; + + direction = playerDirection; + direction = state_to_direction(gUnknown_0836DC09[mapObject->animPattern], mapObject->mapobj_unk_21, direction); + FieldObjectSetRegularAnim(mapObject, sprite, sub_806084C(direction)); + mapObject->mapobj_bit_1 = TRUE; + sprite->data1 = 2; + return TRUE; +} + +bool8 sub_805F760(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8)) +{ + u32 direction; + s16 x; + s16 y; + + direction = playerDirection; + direction = state_to_direction(gUnknown_0836DC09[mapObject->animPattern], mapObject->mapobj_unk_21, direction); + FieldObjectMoveDestCoords(mapObject, direction, &x, &y); + FieldObjectSetRegularAnim(mapObject, sprite, sub_80608A4(direction)); + if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y)))) + { + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction)); + } + mapObject->mapobj_bit_1 = TRUE; + sprite->data1 = 2; + return TRUE; +} + +bool8 oac_hopping(struct MapObject *mapObject, struct Sprite *sprite, u8 playerDirection, bool8 tileCB(u8)) +{ + u32 direction; + s16 x; + s16 y; + + direction = playerDirection; + direction = state_to_direction(gUnknown_0836DC09[mapObject->animPattern], mapObject->mapobj_unk_21, direction); + x = mapObject->coords2.x; + y = mapObject->coords2.y; + sub_8060320(direction, &x, &y, 2, 2); + FieldObjectSetRegularAnim(mapObject, sprite, GetJumpLedgeAnimId(direction)); + if (npc_block_way(mapObject, x, y, direction) || (tileCB != NULL && !tileCB(MapGridGetMetatileBehaviorAt(x, y)))) + { + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(direction)); + } + mapObject->mapobj_bit_1 = TRUE; + sprite->data1 = 2; + return TRUE; +} + +fieldmap_object_cb(sub_805F8E0, sub_805F904, gUnknown_083755C0); + +u8 mss_08062EA4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1C == 0xFF || gPlayerAvatar.running1 == 2) + { + return 0; + } + return gUnknown_08375594[player_get_x22()](mapObject, sprite, player_get_direction_upper_nybble(), MetatileBehavior_IsPokeGrass); +} + +u8 sub_805F9F8(struct MapObject *, struct Sprite *); + +void FieldObjectCB_TreeDisguise(struct Sprite *sprite) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[sprite->data0]; + if (mapObject->mapobj_unk_21 == 0 || (mapObject->mapobj_unk_21 == 1 && sprite->data7 == 0)) + { + FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_TREE_DISGUISE); + mapObject->mapobj_unk_21 = 1; + sprite->data7 ++; + } + meta_step(&gMapObjects[sprite->data0], sprite, sub_805F9F8); +} + +u8 sub_805F9F8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + return 0; +} + +void FieldObjectCB_MountainDisguise(struct Sprite *sprite) +{ + struct MapObject *mapObject; + mapObject = &gMapObjects[sprite->data0]; + if (mapObject->mapobj_unk_21 == 0 || (mapObject->mapobj_unk_21 == 1 && sprite->data7 == 0)) + { + FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + mapObject->mapobj_unk_1A = FieldEffectStart(FLDEFF_MOUNTAIN_DISGUISE); + mapObject->mapobj_unk_21 = 1; + sprite->data7 ++; + } + meta_step(&gMapObjects[sprite->data0], sprite, sub_805F9F8); +} + +u8 sub_805FAD8(struct MapObject *mapObject, struct Sprite *sprite); + +void FieldObjectCB_Hidden1(struct Sprite *sprite) +{ + if (sprite->data7 == 0) + { + gMapObjects[sprite->data0].mapobj_bit_26 = 1; + sprite->subspriteMode = 2; + sprite->oam.priority = 3; + sprite->data7 ++; + } + meta_step(&gMapObjects[sprite->data0], sprite, sub_805FAD8); +} + +u8 sub_805FAD8(struct MapObject *mapObject, struct Sprite *sprite) +{ + return gUnknown_083755CC[sprite->data1](mapObject, sprite); +} + +u8 sub_805FAF8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + return 0; +} + +u8 sub_805FB04(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sprite->data1 = 0; + } + return 0; +} + +fieldmap_object_cb(sub_805FB20, sub_805FB44, gUnknown_083755D0); + +u8 sub_805FB64(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + FieldObjectSetRegularAnim(mapObject, sprite, GetStepInPlaceDelay16AnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805FB90, sub_805FBB4, gUnknown_083755D8); + +u8 sub_805FBD4(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + FieldObjectSetRegularAnim(mapObject, sprite, GetStepInPlaceDelay8AnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805FC00, sub_805FC24, gUnknown_083755E0); + +u8 sub_805FC44(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + FieldObjectSetRegularAnim(mapObject, sprite, GetStepInPlaceDelay4AnimId(mapObject->mapobj_unk_18)); + sprite->data1 = 1; + return 1; +} + +fieldmap_object_cb(sub_805FC70, sub_805FC94, gUnknown_083755E8); + +u8 sub_805FCB4(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_reset(mapObject, sprite); + FieldObjectSetRegularAnim(mapObject, sprite, GetFaceDirectionAnimId(mapObject->mapobj_unk_18)); + mapObject->mapobj_bit_13 = 1; + sprite->data1 = 1; + return 1; +} + +u8 sub_805FCE8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (FieldObjectExecRegularAnim(mapObject, sprite)) + { + sprite->data1 = 2; + return 1; + } + return 0; +} + +u8 sub_805FD08(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_1 = 0; + return 0; +} + +void sub_805FC70(struct Sprite *sprite); + +void npc_reset(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_1 = 0; + mapObject->mapobj_bit_6 = 0; + mapObject->mapobj_bit_7 = 0; + mapObject->mapobj_unk_1C = 0xff; + sprite->data1 = 0; +} + +u8 FieldObjectDirectionToImageAnimId(u8 direction) +{ + return gUnknown_083755F4[direction]; +} + +u8 get_go_image_anim_num(u8 direction) +{ + return gUnknown_083755FD[direction]; +} + +u8 get_go_fast_image_anim_num(u8 direction) +{ + return gUnknown_08375606[direction]; +} + +u8 get_go_faster_image_anim_num(u8 direction) +{ + return gUnknown_0837560F[direction]; +} + +u8 sub_805FD78(u8 direction) +{ + return gUnknown_08375618[direction]; +} + +u8 sub_805FD88(u8 direction) +{ + return gUnknown_08375621[direction]; +} + +u8 sub_805FD98(u8 direction) +{ + return gUnknown_0837562A[direction]; +} + +u8 unref_sub_805FDA8(u8 direction) +{ + return gUnknown_08375633[direction]; +} + +u8 sub_805FDB8(u8 direction) +{ + return gUnknown_0837563C[direction]; +} + +u8 sub_805FDC8(u8 direction) +{ + return gUnknown_08375645[direction]; +} + +u8 sub_805FDD8(u8 direction) +{ + return gUnknown_0837564E[direction]; +} + +u8 sub_805FDE8(u8 direction) +{ + return gUnknown_08375657[direction]; +} + +u8 sub_805FDF8(u8 direction) +{ + return gUnknown_08375660[direction]; +} + +u8 sub_805FE08(u8 direction) +{ + return gUnknown_08375669[direction]; +} + +u8 get_run_image_anim_num(u8 direction) +{ + return gUnknown_08375672[direction]; +} + +void sub_805FE28(struct MapObject *mapObject, struct Sprite *sprite, u8 animNum) +{ + if (!mapObject->mapobj_bit_12) + { + sprite->animNum = animNum; + if (sprite->animCmdIndex == 1) + { + sprite->animCmdIndex = 2; + } else if (sprite->animCmdIndex == 3) + { + sprite->animCmdIndex = 0; + } + SeekSpriteAnim(sprite, sprite->animCmdIndex); + } +} + +void sub_805FE64(struct MapObject *mapObject, struct Sprite *sprite, u8 animNum) +{ + u8 animCmdIndex; + if (!mapObject->mapobj_bit_12) + { + sprite->animNum = animNum; + animCmdIndex = 3; + if (sprite->animCmdIndex < 2) + { + animCmdIndex = 1; + } + SeekSpriteAnim(sprite, animCmdIndex); + } +} + +u8 sub_805FE90(s16 a0, s16 a1, s16 a2, s16 a3) +{ + if (a0 > a2) + { + return DIR_WEST; + } else if (a0 < a2) + { + return DIR_EAST; + } else if (a1 > a3) + { + return DIR_NORTH; + } else + { + return DIR_SOUTH; + } +} + +void npc_set_running_behaviour_etc(struct MapObject *mapObject, u8 animPattern) +{ + mapObject->animPattern = animPattern; + mapObject->mapobj_unk_21 = 0; + mapObject->animId = 0; + gSprites[mapObject->spriteId].callback = gUnknown_0836DA88[animPattern]; + gSprites[mapObject->spriteId].data1 = 0; +} + +u8 npc_running_behaviour_by_direction(u8 direction) +{ + return gUnknown_0837567B[direction]; +} + +u8 sub_805FF20(struct MapObject *mapObject, u8 direction) +{ + s16 x; + s16 y; + x = mapObject->coords2.x; + y = mapObject->coords2.y; + MoveCoords(direction, &x, &y); + return npc_block_way(mapObject, x, y, direction); +} + +bool8 IsCoordOutsideFieldObjectMovementRect(struct MapObject2 *mapObject, s16 x, s16 y); +static bool8 DoesObjectCollideWithObjectAt(struct MapObject *mapObject, s16 x, s16 y); +bool8 IsMetatileDirectionallyImpassable(struct MapObject *mapObject, s16 x, s16 y, u8 direction); + +u8 npc_block_way(struct MapObject *mapObject, s16 x, s16 y, u32 dirn) +{ + u8 direction; + direction = dirn; + if (IsCoordOutsideFieldObjectMovementRect((struct MapObject2 *)mapObject, x, y)) + return 1; + else if (MapGridIsImpassableAt(x, y) || GetMapBorderIdAt(x, y) == -1 || IsMetatileDirectionallyImpassable(mapObject, x, y, direction)) + return 2; + else if (mapObject->mapobj_bit_15 && !CanCameraMoveInDirection(direction)) + return 2; + else if (IsZCoordMismatchAt(mapObject->mapobj_unk_0B_0, x, y)) + return 3; + else if (DoesObjectCollideWithObjectAt(mapObject, x, y)) + return 4; + return 0; +} + +u8 sub_8060024(struct MapObject *mapObject, s16 x, s16 y, u8 direction) +{ + u8 flags = 0; + + if (IsCoordOutsideFieldObjectMovementRect((struct MapObject2 *)mapObject, x, y)) + flags |= 1; + if (MapGridIsImpassableAt(x, y) || GetMapBorderIdAt(x, y) == -1 || IsMetatileDirectionallyImpassable(mapObject, x, y, direction) || (mapObject->mapobj_bit_15 && !CanCameraMoveInDirection(direction))) + flags |= 2; + if (IsZCoordMismatchAt(mapObject->mapobj_unk_0B_0, x, y)) + flags |= 4; + if (DoesObjectCollideWithObjectAt(mapObject, x, y)) + flags |= 8; + return flags; +} + +bool8 IsCoordOutsideFieldObjectMovementRect(struct MapObject2 *mapObject, s16 x, s16 y) +{ + s16 minv; + s16 maxv; + + if (mapObject->mapobj_unk_19 != 0) + { + minv = mapObject->coords1.x - (mapObject->mapobj_unk_19); + maxv = mapObject->coords1.x + (mapObject->mapobj_unk_19); + if (minv > x || maxv < x) + return TRUE; + } + if (mapObject->mapobj_unk_19b != 0) + { + minv = mapObject->coords1.y - (mapObject->mapobj_unk_19b); + maxv = mapObject->coords1.y + (mapObject->mapobj_unk_19b); + if (minv > y || maxv < y) + return TRUE; + } + return FALSE; +} + +bool8 IsMetatileDirectionallyImpassable(struct MapObject *mapObject, s16 x, s16 y, u8 direction) +{ + if (gUnknown_08375684[direction - 1](mapObject->mapobj_unk_1E) || gUnknown_08375694[direction - 1](MapGridGetMetatileBehaviorAt(x, y))) + { + return 1; + } + return 0; +} + +static bool8 DoesObjectCollideWithObjectAt(struct MapObject *mapObject, s16 x, s16 y) +{ + u8 i; + + for (i = 0; i < 16; i++) + { + struct MapObject *mapObject2 = &gMapObjects[i]; + + if (mapObject2->active && mapObject2 != mapObject) + { + if (((mapObject2->coords2.x == x && mapObject2->coords2.y == y) || (mapObject2->coords3.x == x && mapObject2->coords3.y == y)) + && AreZCoordsCompatible(mapObject->mapobj_unk_0B_0, mapObject2->mapobj_unk_0B_0)) + return TRUE; + } + } + return 0; +} + +bool8 sub_8060234(u8 localId, u8 mapNum, u8 mapGroup) +{ + u8 mapObjectId; + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + { + if (gSprites[gMapObjects[mapObjectId].spriteId].data7 & 2) + { + return 1; + } + } + return 0; +} + +void sub_8060288(u8 localId, u8 mapNum, u8 mapGroup) +{ + u8 mapObjectId; + if (!TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjectId)) + { + gSprites[gMapObjects[mapObjectId].spriteId].data7 |= 4; + } +} + +void MoveCoords(u8 direction, s16 *x, s16 *y) +{ + *x += gDirectionToVector[direction].x; + *y += gDirectionToVector[direction].y; +} + +void unref_sub_80602F8(u8 direction, s16 *x, s16 *y) +{ + *x += gDirectionToVector[direction].x << 4; + *y += gDirectionToVector[direction].y << 4; +} + +void sub_8060320(u32 dirn, s16 *x, s16 *y, s16 deltaX, s16 deltaY) +{ + u8 direction = dirn; + s16 dx2 = deltaX; + s16 dy2 = deltaY; + if (gDirectionToVector[direction].x > 0) + { + *x += dx2; + } + if (gDirectionToVector[direction].x < 0) + { + *x -= dx2; + } + if (gDirectionToVector[direction].y > 0) + { + *y += dy2; + } + if (gDirectionToVector[direction].y < 0) + { + *y -= dy2; + } +} + +void sub_8060388(s16 x1, s16 y1, s16 *x2, s16 *y2) +{ + *x2 = (x1 - gSaveBlock1.pos.x) << 4; + *y2 = (y1 - gSaveBlock1.pos.y) << 4; + *x2 -= gUnknown_0300489C; + *y2 -= gUnknown_03004898; +} + +void sub_80603CC(s16 x1, s16 y1, s16 *x2, s16 *y2) +{ + s16 x3; + s16 y3; + x3 = -gUnknown_0300489C - gUnknown_03004880.unk10; + y3 = -gUnknown_03004898 - gUnknown_03004880.unk14; + if (gUnknown_03004880.unk10 > 0) + { + x3 += 0x10; + } + if (gUnknown_03004880.unk10 < 0) + { + x3 -= 0x10; + } + if (gUnknown_03004880.unk14 > 0) + { + y3 += 0x10; + } + if (gUnknown_03004880.unk14 < 0) + { + y3 -= 0x10; + } + *x2 = ((x1 - gSaveBlock1.pos.x) << 4) + x3; + *y2 = ((y1 - gSaveBlock1.pos.y) << 4) + y3; +} + +void sub_8060470(s16 *x, s16 *y, s16 dx, s16 dy) +{ + sub_80603CC(*x, *y, x, y); + *x += dx; + *y += dy; +} + +void GetFieldObjectMovingCameraOffset(s16 *x, s16 *y) +{ + *x = 0; + *y = 0; + if (gUnknown_03004880.unk10 > 0) + { + (*x)++; + } + if (gUnknown_03004880.unk10 < 0) + { + (*x)--; + } + if (gUnknown_03004880.unk14 > 0) + { + (*y)++; + } + if (gUnknown_03004880.unk14 < 0) + { + (*y)--; + } +} + +void FieldObjectMoveDestCoords(struct MapObject *mapObject, u32 direction, s16 *x, s16 *y) +{ + u8 newDirn = direction; + *x = mapObject->coords2.x; + *y = mapObject->coords2.y; + MoveCoords(newDirn, x, y); +} + +bool8 FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(struct MapObject *mapObject) +{ + if (mapObject->mapobj_bit_1 || mapObject->mapobj_bit_6) + { + return TRUE; + } + return FALSE; +} + +bool8 FieldObjectIsSpecialAnimActive(struct MapObject *mapObject) +{ + if (mapObject->mapobj_bit_6 && mapObject->mapobj_unk_1C != 0xff) + { + return TRUE; + } + return FALSE; +} + +bool8 FieldObjectSetSpecialAnim(struct MapObject *mapObject, u8 specialAnimId) +{ + if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(mapObject)) + { + return TRUE; + } + UnfreezeMapObject(mapObject); + mapObject->mapobj_unk_1C = specialAnimId; + mapObject->mapobj_bit_6 = 1; + mapObject->mapobj_bit_7 = 0; + gSprites[mapObject->spriteId].data2 = 0; + return FALSE; +} + +void FieldObjectForceSetSpecialAnim(struct MapObject *mapObject, u8 specialAnimId) +{ + FieldObjectClearAnimIfSpecialAnimActive(mapObject); + FieldObjectSetSpecialAnim(mapObject, specialAnimId); +} + +void FieldObjectClearAnimIfSpecialAnimActive(struct MapObject *mapObject) +{ + if (mapObject->mapobj_bit_6) + { + FieldObjectClearAnim(mapObject); + } +} + +void FieldObjectClearAnim(struct MapObject *mapObject) +{ + mapObject->mapobj_unk_1C = 0xFF; + mapObject->mapobj_bit_6 = 0; + mapObject->mapobj_bit_7 = 0; + gSprites[mapObject->spriteId].data1 = 0; + gSprites[mapObject->spriteId].data2 = 0; +} + +bool8 FieldObjectCheckIfSpecialAnimFinishedOrInactive(struct MapObject *mapObject) +{ + if (mapObject->mapobj_bit_6) + return mapObject->mapobj_bit_7; + return 0x10; +} + +bool8 FieldObjectClearAnimIfSpecialAnimFinished(struct MapObject *mapObject) +{ + u8 specialAnimStatus; + specialAnimStatus = FieldObjectCheckIfSpecialAnimFinishedOrInactive(mapObject); + if (specialAnimStatus != 0 && specialAnimStatus != 0x10) + { + FieldObjectClearAnimIfSpecialAnimActive(mapObject); + } + return specialAnimStatus; +} + +u8 FieldObjectGetSpecialAnim(struct MapObject *mapObject) +{ + if (mapObject->mapobj_bit_6) + { + return mapObject->mapobj_unk_1C; + } + return 0xFF; +} + +extern void DoGroundEffects_OnSpawn(struct MapObject *mapObject, struct Sprite *sprite); +extern void DoGroundEffects_OnBeginStep(struct MapObject *mapObject, struct Sprite *sprite); +extern void DoGroundEffects_OnFinishStep(struct MapObject *mapObject, struct Sprite *sprite); +void npc_obj_transfer_image_anim_pause_flag(struct MapObject *mapObject, struct Sprite *sprite); +void sub_80634A0(struct MapObject *mapObject, struct Sprite *sprite); +void FieldObjectExecSpecialAnim(struct MapObject *mapObject, struct Sprite *sprite); +void FieldObjectUpdateSubpriority(struct MapObject *mapObject, struct Sprite *sprite); + +void meta_step(struct MapObject *mapObject, struct Sprite *sprite, u8 (*callback)(struct MapObject *, struct Sprite *)) +{ + DoGroundEffects_OnSpawn(mapObject, sprite); + sub_80634A0(mapObject, sprite); + if (FieldObjectIsSpecialAnimActive(mapObject)) + { + FieldObjectExecSpecialAnim(mapObject, sprite); + } else + { + if (!mapObject->mapobj_bit_8) + { + while (callback(mapObject, sprite)); + } + } + DoGroundEffects_OnBeginStep(mapObject, sprite); + DoGroundEffects_OnFinishStep(mapObject, sprite); + npc_obj_transfer_image_anim_pause_flag(mapObject, sprite); + sub_80634D0(mapObject, sprite); + FieldObjectUpdateSubpriority(mapObject, sprite); +} + +#define dirn_to_anim(name, table)\ +u8 name(u32 idx)\ +{\ + u8 direction;\ + u8 animIds[sizeof(table)];\ + direction = idx;\ + memcpy(animIds, (table), sizeof(table));\ + if (direction > DIR_EAST) direction = 0;\ + return animIds[direction];\ +} + +dirn_to_anim(GetFaceDirectionAnimId, gUnknown_083756C8) +dirn_to_anim(GetSimpleGoAnimId, gUnknown_083756CD) +dirn_to_anim(GetGoSpeed0AnimId, gUnknown_083756D2) +dirn_to_anim(sub_8060744, gUnknown_083756D7) +dirn_to_anim(d2s_08064034, gUnknown_083756DC) +dirn_to_anim(sub_806079C, gUnknown_083756E1) +dirn_to_anim(sub_80607C8, gUnknown_083756E6) +dirn_to_anim(sub_80607F4, gUnknown_083756EB) +dirn_to_anim(GetJumpLedgeAnimId, gUnknown_083756F0) +dirn_to_anim(sub_806084C, gUnknown_083756F5) +dirn_to_anim(sub_8060878, gUnknown_083756FA) +dirn_to_anim(sub_80608A4, gUnknown_083756FF) +dirn_to_anim(sub_80608D0, gUnknown_08375704) +dirn_to_anim(GetStepInPlaceDelay32AnimId, gUnknown_08375709) +dirn_to_anim(GetStepInPlaceDelay16AnimId, gUnknown_0837570E) +dirn_to_anim(GetStepInPlaceDelay8AnimId, gUnknown_08375713) +dirn_to_anim(GetStepInPlaceDelay4AnimId, gUnknown_08375718) + +u8 FieldObjectFaceOppositeDirection(struct MapObject *mapObject, u8 direction) +{ + return FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(GetOppositeDirection(direction))); +} + +u8 sub_80609D8(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_0837571D, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060A04(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_08375722, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060A30(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_08375727, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060A5C(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_0837572C, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060A88(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_08375731, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060AB4(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_08375736, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060AE0(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_0837573B, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060B0C(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_08375740, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060B38(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_08375745, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 sub_8060B64(u8 index) +{ + u8 directions[5]; + memcpy(directions, gUnknown_0837574A, 5); + if (index >= 5) + { + index = 0; + } + return directions[index]; +} + +u8 GetOppositeDirection(u8 direction) +{ + u8 directions[8]; + memcpy(directions, gUnknown_0837574F, 8); + if (direction == 0 || direction > 8) + { + return direction; + } + return directions[direction - 1]; +} + +u32 zffu_offset_calc(u8 a0, u8 a1) +{ + return gUnknown_08375757[a0 - 1][a1 - 1]; +} + +u32 state_to_direction(u8 a0, u32 a1, u32 a2) +{ + u32 zffuOffset; + u8 a1_2 = a1; + u8 a2_2 = a2; + if (a1_2 == 0 || a2_2 == 0 || a1_2 > DIR_EAST || a2_2 > DIR_EAST) + { + return 0; + } + zffuOffset = zffu_offset_calc(a1_2, a2); + return gUnknown_08375767[a0 - 1][zffuOffset - 1]; +} + +void FieldObjectExecSpecialAnim(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (gUnknown_08375778[mapObject->mapobj_unk_1C][sprite->data2](mapObject, sprite)) + { + mapObject->mapobj_bit_7 = 1; + } +} + +bool8 FieldObjectExecRegularAnim(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (gUnknown_08375778[mapObject->mapobj_unk_1C][sprite->data2](mapObject, sprite)) + { + mapObject->mapobj_unk_1C = 0xFF; + sprite->data2 = 0; + return 1; + } + return 0; +} + +void FieldObjectSetRegularAnim(struct MapObject *mapObject, struct Sprite *sprite, u8 animId) +{ + mapObject->mapobj_unk_1C = animId; + sprite->data2 = 0; +} + +void an_look_any(struct MapObject *mapObject, struct Sprite *sprite, u8 direction) +{ + FieldObjectSetDirection(mapObject, direction); + npc_coords_shift_still(mapObject); + sub_805FE64(mapObject, sprite, get_go_image_anim_num(mapObject->mapobj_unk_18)); + sprite->animPaused = 1; + sprite->data2 = 1; +} + +u8 sub_8060CE0(struct MapObject *mapObject, struct Sprite *sprite) +{ + an_look_any(mapObject, sprite, DIR_SOUTH); + return 1; +} + +u8 sub_8060CF0(struct MapObject *mapObject, struct Sprite *sprite) +{ + an_look_any(mapObject, sprite, DIR_NORTH); + return 1; +} + +u8 sub_8060D00(struct MapObject *mapObject, struct Sprite *sprite) +{ + an_look_any(mapObject, sprite, DIR_WEST); + return 1; +} + +u8 sub_8060D10(struct MapObject *mapObject, struct Sprite *sprite) +{ + an_look_any(mapObject, sprite, DIR_EAST); + return 1; +} + +void sub_8060D20(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 a3) +{ + s16 x; + s16 y; + x = mapObject->coords2.x; + y = mapObject->coords2.y; + FieldObjectSetDirection(mapObject, direction); + MoveCoords(direction, &x, &y); + npc_coords_shift(mapObject, x, y); + oamt_npc_ministep_reset(sprite, direction, a3); + sprite->animPaused = 0; + mapObject->mapobj_bit_2 = 1; + sprite->data2 = 1; +} + +extern u8 (*const gUnknown_083759C0[5])(u8); + +void do_go_anim(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 a3) +{ + u8 (*const functions[5])(u8); + memcpy((void *)functions, gUnknown_083759C0, sizeof(gUnknown_083759C0)); + sub_8060D20(mapObject, sprite, direction, a3); + sub_805FE28(mapObject, sprite, functions[a3](mapObject->mapobj_unk_18)); +} + +void do_run_anim(struct MapObject *mapObject, struct Sprite *sprite, u8 direction) +{ + sub_8060D20(mapObject, sprite, direction, 1); + sub_805FE28(mapObject, sprite, get_run_image_anim_num(mapObject->mapobj_unk_18)); +} + +bool8 obj_npc_ministep(struct Sprite *); + +bool8 npc_obj_ministep_stop_on_arrival(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (obj_npc_ministep(sprite)) + { + npc_coords_shift_still(mapObject); + mapObject->mapobj_bit_3 = 1; + sprite->animPaused = 1; + return 1; + } + return 0; +} + +void sub_8060E68(struct MapObject *mapObject, struct Sprite *sprite, u8 direction) +{ + s16 x; + s16 y; + x = mapObject->coords2.x; + y = mapObject->coords2.y; + FieldObjectSetDirection(mapObject, direction); + MoveCoords(direction, &x, &y); + npc_coords_shift(mapObject, x, y); + sub_806467C(sprite, direction); + sprite->animPaused = 0; + mapObject->mapobj_bit_2 = 1; + sprite->data2 = 1; +} + +void sub_8060ED8(struct MapObject *mapObject, struct Sprite *sprite, u8 direction) +{ + sub_8060E68(mapObject, sprite, direction); + sub_805FE28(mapObject, sprite, get_go_image_anim_num(mapObject->mapobj_unk_18)); +} + +bool8 an_walk_any_2(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_806468C(sprite)) + { + npc_coords_shift_still(mapObject); + mapObject->mapobj_bit_3 = 1; + sprite->animPaused = 1; + return TRUE; + } + return FALSE; +} + +bool8 sub_8060F5C(struct MapObject *, struct Sprite *); + +bool8 sub_8060F3C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8060ED8(mapObject, sprite, DIR_SOUTH); + return sub_8060F5C(mapObject, sprite); +} + +bool8 sub_8060F5C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (an_walk_any_2(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8060F9C(struct MapObject *, struct Sprite *); + +bool8 sub_8060F7C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8060ED8(mapObject, sprite, DIR_NORTH); + return sub_8060F9C(mapObject, sprite); +} + +bool8 sub_8060F9C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (an_walk_any_2(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8060FDC(struct MapObject *, struct Sprite *); + +bool8 sub_8060FBC(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8060ED8(mapObject, sprite, DIR_WEST); + return sub_8060FDC(mapObject, sprite); +} + +bool8 sub_8060FDC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (an_walk_any_2(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806101C(struct MapObject *, struct Sprite *); + +bool8 sub_8060FFC(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8060ED8(mapObject, sprite, DIR_EAST); + return sub_806101C(mapObject, sprite); +} + +bool8 sub_806101C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (an_walk_any_2(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806105C(struct MapObject *, struct Sprite *); + +bool8 sub_806103C(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_SOUTH, 0); + return sub_806105C(mapObject, sprite); +} + +bool8 sub_806105C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806109C(struct MapObject *, struct Sprite *); + +bool8 sub_806107C(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_NORTH, 0); + return sub_806109C(mapObject, sprite); +} + +bool8 sub_806109C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80610DC(struct MapObject *, struct Sprite *); + +bool8 sub_80610BC(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_WEST, 0); + return sub_80610DC(mapObject, sprite); +} + +bool8 sub_80610DC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806111C(struct MapObject *, struct Sprite *); + +bool8 sub_80610FC(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_EAST, 0); + return sub_806111C(mapObject, sprite); +} + +bool8 sub_806111C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +void sub_806113C(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 a4, u8 a5) +{ + s16 vSPp4[3]; + s16 x; + s16 y; + memcpy(vSPp4, gUnknown_08375A34, sizeof gUnknown_08375A34); + x = 0; + y = 0; + FieldObjectSetDirection(mapObject, direction); + sub_8060320(direction, &x, &y, vSPp4[a4], vSPp4[a4]); + npc_coords_shift(mapObject, mapObject->coords2.x + x, mapObject->coords2.y + y); + sub_80646E4(sprite, direction, a4, a5); + sprite->data2 = 1; + sprite->animPaused = 0; + mapObject->mapobj_bit_2 = 1; + mapObject->mapobj_bit_4 = 1; +} + +void maybe_shadow_1(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 a4, u8 a5) +{ + sub_806113C(mapObject, sprite, direction, a4, a5); + sub_805FE28(mapObject, sprite, get_go_image_anim_num(mapObject->mapobj_unk_18)); + DoShadowFieldEffect(mapObject); +} + +u8 sub_806123C(struct MapObject *mapObject, struct Sprite *sprite, u8 (*const callback)(struct Sprite *)) +{ + s16 vSPp4[3]; + s16 x; + s16 y; + u8 retval; + memcpy(vSPp4, gUnknown_08375A3A, sizeof gUnknown_08375A3A); + retval = callback(sprite); + if (retval == 1 && vSPp4[sprite->data4] != 0) + { + x = 0; + y = 0; + sub_8060320(mapObject->placeholder18, &x, &y, vSPp4[sprite->data4], vSPp4[sprite->data4]); + npc_coords_shift(mapObject, mapObject->coords2.x + x, mapObject->coords2.y + y); + mapObject->mapobj_bit_2 = 1; + mapObject->mapobj_bit_4 = 1; + } else if (retval == 0xff) + { + npc_coords_shift_still(mapObject); + mapObject->mapobj_bit_3 = 1; + mapObject->mapobj_bit_5 = 1; + sprite->animPaused = 1; + } + return retval; +} + +u8 sub_8061300(struct MapObject *mapObject, struct Sprite *sprite) +{ + return sub_806123C(mapObject, sprite, sub_8064704); +} + +u8 sub_8061314(struct MapObject *mapObject, struct Sprite *sprite) +{ + return sub_806123C(mapObject, sprite, sub_806478C); +} + +bool8 sub_8061328(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061300(mapObject, sprite) == 0xFF) + { + return TRUE; + } + return FALSE; +} + +bool8 sub_8061340(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061314(mapObject, sprite) == 0xFF) + { + return TRUE; + } + return FALSE; +} + +bool8 sub_8061358(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 retval; + + retval = sub_8061300(mapObject, sprite); + if (retval != 1) + { + if (retval == 0xFF) + { + return TRUE; + } + return FALSE; + } + FieldObjectSetDirection(mapObject, GetOppositeDirection(mapObject->placeholder18)); + sub_805FE64(mapObject, sprite, get_go_image_anim_num(mapObject->mapobj_unk_18)); + return FALSE; +} + +bool8 sub_80613D4(struct MapObject *, struct Sprite *); +bool8 sub_806142C(struct MapObject *, struct Sprite *); +bool8 sub_8061484(struct MapObject *, struct Sprite *); +bool8 sub_80614DC(struct MapObject *, struct Sprite *); + +bool8 sub_80613A8(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_SOUTH, 2, 0); + return sub_80613D4(mapObject, sprite); +} + +bool8 sub_80613D4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061400(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_NORTH, 2, 0); + return sub_806142C(mapObject, sprite); +} + +bool8 sub_806142C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061458(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_WEST, 2, 0); + return sub_8061484(mapObject, sprite); +} + +bool8 sub_8061484(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80614B0(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_EAST, 2, 0); + return sub_80614DC(mapObject, sprite); +} + +bool8 sub_80614DC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +void sub_8061508(struct Sprite *sprite, u16 duration) +{ + sprite->data2 = 1; + sprite->data3 = duration; +} + +bool8 sub_8061510(struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->data3--; + if (!sprite->data3) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806152C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061508(sprite, 1); + return sub_8061510(mapObject, sprite); +} + +bool8 sub_806154C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061508(sprite, 2); + return sub_8061510(mapObject, sprite); +} + +bool8 sub_806156C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061508(sprite, 4); + return sub_8061510(mapObject, sprite); +} + +bool8 sub_806158C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061508(sprite, 8); + return sub_8061510(mapObject, sprite); +} + +bool8 sub_80615AC(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061508(sprite, 16); + return sub_8061510(mapObject, sprite); +} + +bool8 sub_80615EC(struct MapObject *mapObject, struct Sprite *sprite); +bool8 sub_806162C(struct MapObject *mapObject, struct Sprite *sprite); +bool8 sub_806166C(struct MapObject *mapObject, struct Sprite *sprite); +bool8 sub_80616AC(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_80615CC(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_SOUTH, 1); + return sub_80615EC(mapObject, sprite); +} + +bool8 sub_80615EC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} +bool8 sub_806160C(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_NORTH, 1); + return sub_806162C(mapObject, sprite); +} + +bool8 sub_806162C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} +bool8 sub_806164C(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_WEST, 1); + return sub_806166C(mapObject, sprite); +} + +bool8 sub_806166C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} +bool8 sub_806168C(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_EAST, 1); + return sub_80616AC(mapObject, sprite); +} + +bool8 sub_80616AC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +void sub_80616CC(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 animId, u16 duration) +{ + FieldObjectSetDirection(mapObject, direction); + sub_805FE28(mapObject, sprite, animId); + sprite->animPaused = 0; + sprite->data2 = 1; + sprite->data3 = duration; +} + +bool8 sub_8061714(struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->data3--; + if (sprite->data3 == 0) + { + sprite->data2 = 2; + sprite->animPaused = 1; + return TRUE; + } + return FALSE; +} + +bool8 sub_806173C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sprite->data3 & 1) + { + sprite->animDelayCounter++; + } + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061778(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_SOUTH, get_go_image_anim_num(DIR_SOUTH), 32); + return sub_806173C(mapObject, sprite); +} + +bool8 sub_80617B0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_NORTH, get_go_image_anim_num(DIR_NORTH), 32); + return sub_806173C(mapObject, sprite); +} + +bool8 sub_80617E8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_WEST, get_go_image_anim_num(DIR_WEST), 32); + return sub_806173C(mapObject, sprite); +} + +bool8 sub_8061820(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_EAST, get_go_image_anim_num(DIR_EAST), 32); + return sub_806173C(mapObject, sprite); +} + +bool8 sub_8061858(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_SOUTH, get_go_image_anim_num(DIR_SOUTH), 16); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061890(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_NORTH, get_go_image_anim_num(DIR_NORTH), 16); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_80618C8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_WEST, get_go_image_anim_num(DIR_WEST), 16); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061900(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_EAST, get_go_image_anim_num(DIR_EAST), 16); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061938(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_SOUTH, get_go_fast_image_anim_num(DIR_SOUTH), 8); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061970(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_NORTH, get_go_fast_image_anim_num(DIR_NORTH), 8); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_80619A8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_WEST, get_go_fast_image_anim_num(DIR_WEST), 8); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_80619E0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_EAST, get_go_fast_image_anim_num(DIR_EAST), 8); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061A18(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_SOUTH, get_go_faster_image_anim_num(DIR_SOUTH), 4); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061A50(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_NORTH, get_go_faster_image_anim_num(DIR_NORTH), 4); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061A88(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_WEST, get_go_faster_image_anim_num(DIR_WEST), 4); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061AC0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_EAST, get_go_faster_image_anim_num(DIR_EAST), 4); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8061B18(struct MapObject *, struct Sprite *); + +bool8 sub_8061AF8(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_SOUTH, 2); + return sub_8061B18(mapObject, sprite); +} + +bool8 sub_8061B18(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + + +bool8 sub_8061B58(struct MapObject *, struct Sprite *); + +bool8 sub_8061B38(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_NORTH, 2); + return sub_8061B58(mapObject, sprite); +} + +bool8 sub_8061B58(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + + +bool8 sub_8061B98(struct MapObject *, struct Sprite *); + +bool8 sub_8061B78(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_WEST, 2); + return sub_8061B98(mapObject, sprite); +} + +bool8 sub_8061B98(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + + +bool8 sub_8061BD8(struct MapObject *, struct Sprite *); + +bool8 sub_8061BB8(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_EAST, 2); + return sub_8061BD8(mapObject, sprite); +} + +bool8 sub_8061BD8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061C18(struct MapObject *, struct Sprite *); + +bool8 sub_8061BF8(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_SOUTH, 3); + return sub_8061C18(mapObject, sprite); +} + +bool8 sub_8061C18(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061C58(struct MapObject *, struct Sprite *); + +bool8 sub_8061C38(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_NORTH, 3); + return sub_8061C58(mapObject, sprite); +} + +bool8 sub_8061C58(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + + +bool8 sub_8061C98(struct MapObject *, struct Sprite *); + +bool8 sub_8061C78(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_WEST, 3); + return sub_8061C98(mapObject, sprite); +} + +bool8 sub_8061C98(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + + +bool8 sub_8061CD8(struct MapObject *, struct Sprite *); + +bool8 sub_8061CB8(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_EAST, 3); + return sub_8061CD8(mapObject, sprite); +} + +bool8 sub_8061CD8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061D18(struct MapObject *, struct Sprite *); + +bool8 sub_8061CF8(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_SOUTH, 4); + return sub_8061D18(mapObject, sprite); +} + +bool8 sub_8061D18(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061D58(struct MapObject *, struct Sprite *); + +bool8 sub_8061D38(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_NORTH, 4); + return sub_8061D58(mapObject, sprite); +} + +bool8 sub_8061D58(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + + +bool8 sub_8061D98(struct MapObject *, struct Sprite *); + +bool8 sub_8061D78(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_WEST, 4); + return sub_8061D98(mapObject, sprite); +} + +bool8 sub_8061D98(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + + +bool8 sub_8061DD8(struct MapObject *, struct Sprite *); + +bool8 sub_8061DB8(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_go_anim(mapObject, sprite, DIR_EAST, 4); + return sub_8061DD8(mapObject, sprite); +} + +bool8 sub_8061DD8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061E18(struct MapObject *, struct Sprite *); + +bool8 do_run_south_anim(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_run_anim(mapObject, sprite, DIR_SOUTH); + return sub_8061E18(mapObject, sprite); +} + +bool8 sub_8061E18(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061E58(struct MapObject *, struct Sprite *); + +bool8 do_run_north_anim(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_run_anim(mapObject, sprite, DIR_NORTH); + return sub_8061E58(mapObject, sprite); +} + +bool8 sub_8061E58(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061E98(struct MapObject *, struct Sprite *); + +bool8 do_run_west_anim(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_run_anim(mapObject, sprite, DIR_WEST); + return sub_8061E98(mapObject, sprite); +} + +bool8 sub_8061E98(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061ED8(struct MapObject *, struct Sprite *); + +bool8 do_run_east_anim(struct MapObject *mapObject, struct Sprite *sprite) +{ + do_run_anim(mapObject, sprite, DIR_EAST); + return sub_8061ED8(mapObject, sprite); +} + +bool8 sub_8061ED8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +void npc_set_direction_and_anim__an_proceed(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 animNum) +{ + obj_anim_image_set_and_seek(sprite, animNum, 0); + FieldObjectSetDirection(mapObject, direction); + sprite->data2 = 1; +} + +bool8 sub_8061F24(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, mapObject->placeholder18, sprite->animNum); + return FALSE; +} + +bool8 sub_8064864(struct Sprite *); + +bool8 sub_8061F3C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064864(sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +void sub_8061F5C(struct MapObject *mapObject, struct Sprite *sprite, u8 direction) +{ + sub_806113C(mapObject, sprite, direction, 1, 0); + StartSpriteAnim(sprite, sub_805FD88(direction)); +} + +bool8 sub_8061FB0(struct MapObject *, struct Sprite *); + +bool8 sub_8061F90(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061F5C(mapObject, sprite, DIR_SOUTH); + return sub_8061FB0(mapObject, sprite); +} + +bool8 sub_8061FB0(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061340(mapObject, sprite)) + { + sprite->data2 = 2; + mapObject->mapobj_bit_5 = 0; + return TRUE; + } + return FALSE; +} + +bool8 sub_8061FF8(struct MapObject *, struct Sprite *); + +bool8 sub_8061FD8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061F5C(mapObject, sprite, DIR_NORTH); + return sub_8061FF8(mapObject, sprite); +} + +bool8 sub_8061FF8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061340(mapObject, sprite)) + { + sprite->data2 = 2; + mapObject->mapobj_bit_5 = 0; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062040(struct MapObject *, struct Sprite *); + +bool8 sub_8062020(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061F5C(mapObject, sprite, DIR_WEST); + return sub_8062040(mapObject, sprite); +} + +bool8 sub_8062040(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061340(mapObject, sprite)) + { + sprite->data2 = 2; + mapObject->mapobj_bit_5 = 0; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062088(struct MapObject *, struct Sprite *); + +bool8 sub_8062068(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8061F5C(mapObject, sprite, DIR_EAST); + return sub_8062088(mapObject, sprite); +} + +bool8 sub_8062088(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061340(mapObject, sprite)) + { + sprite->data2 = 2; + mapObject->mapobj_bit_5 = 0; + return TRUE; + } + return FALSE; +} + +bool8 sub_80620B0(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 objectId; + if (!TryGetFieldObjectIdByLocalIdAndMap(0xFF, MAP_GROUP_PETALBURG_CITY, MAP_ID_PETALBURG_CITY, &objectId)) + { + an_look_any(mapObject, sprite, sub_805FE90(mapObject->coords2.x, mapObject->coords2.y, gMapObjects[objectId].coords2.x, gMapObjects[objectId].coords2.y)); + } + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_806210C(struct MapObject *mapObject, struct Sprite *sprite) +{ + u8 objectId; + if (!TryGetFieldObjectIdByLocalIdAndMap(0xFF, MAP_GROUP_PETALBURG_CITY, MAP_ID_PETALBURG_CITY, &objectId)) + { + an_look_any(mapObject, sprite, GetOppositeDirection(sub_805FE90(mapObject->coords2.x, mapObject->coords2.y, gMapObjects[objectId].coords2.x, gMapObjects[objectId].coords2.y))); + } + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_8062170(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_9 = 1; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_8062180(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_9 = 0; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_80621BC(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_8062190(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_SOUTH, 1, 2); + return sub_80621BC(mapObject, sprite); +} + +bool8 sub_80621BC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062214(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_80621E8(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_NORTH, 1, 2); + return sub_8062214(mapObject, sprite); +} + +bool8 sub_8062214(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806226C(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_8062240(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_WEST, 1, 2); + return sub_806226C(mapObject, sprite); +} + +bool8 sub_806226C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80622C4(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_8062298(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_EAST, 1, 2); + return sub_80622C4(mapObject, sprite); +} + +bool8 sub_80622C4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806231C(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_80622F0(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_SOUTH, 0, 0); + return sub_806231C(mapObject, sprite); +} + +bool8 sub_806231C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062374(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_8062348(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_NORTH, 0, 0); + return sub_8062374(mapObject, sprite); +} + +bool8 sub_8062374(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80623CC(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_80623A0(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_WEST, 0, 0); + return sub_80623CC(mapObject, sprite); +} + +bool8 sub_80623CC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062424(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_80623F8(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_EAST, 0, 0); + return sub_8062424(mapObject, sprite); +} + +bool8 sub_8062424(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806247C(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_8062450(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_SOUTH, 0, 2); + return sub_806247C(mapObject, sprite); +} + +bool8 sub_806247C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061358(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80624D4(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_80624A8(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_NORTH, 0, 2); + return sub_80624D4(mapObject, sprite); +} + +bool8 sub_80624D4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061358(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_806252C(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_8062500(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_WEST, 0, 2); + return sub_806252C(mapObject, sprite); +} + +bool8 sub_806252C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061358(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062584(struct MapObject *mapObject, struct Sprite *sprite); + +bool8 sub_8062558(struct MapObject *mapObject, struct Sprite *sprite) +{ + maybe_shadow_1(mapObject, sprite, DIR_EAST, 0, 2); + return sub_8062584(mapObject, sprite); +} + +bool8 sub_8062584(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061358(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80625B0(struct MapObject *mapObject, struct Sprite *sprite) +{ + an_look_any(mapObject, sprite, gUnknown_0836DC09[mapObject->animPattern]); + return TRUE; +} + +bool8 sub_80625C8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_SOUTH, 0x14); + return FALSE; +} + +bool8 sub_80625D8(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_25 = 0; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_80625E8(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_25 = 1; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_80625F8(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_12 = 1; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_8062608(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_12 = GetFieldObjectGraphicsInfo(mapObject->graphicsId)->inanimate; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_8062634(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_13 = 1; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_8062644(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_13 = 0; + sprite->data2 = 1; + return TRUE; +} + +bool8 do_exclamation_mark_bubble_1(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_1); + sprite->data2 = 1; + return TRUE; +} + +bool8 do_exclamation_mark_bubble_2(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_2); + sprite->data2 = 1; + return TRUE; +} + +bool8 do_heart_bubble(struct MapObject *mapObject, struct Sprite *sprite) +{ + FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + FieldEffectStart(FLDEFF_HEART_ICON); + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_8062704(struct MapObject *, struct Sprite *); + +bool8 sub_80626C0(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (mapObject->animPattern == 0x3F) + { + sub_8084794(mapObject); + return FALSE; + } + else if (mapObject->animPattern != 0x39 && mapObject->animPattern != 0x3A) + { + sprite->data2 = 2; + return TRUE; + } + else + { + sub_812869C(mapObject); + sprite->data2 = 1; + return sub_8062704(mapObject, sprite); + } +} + +bool8 sub_8062704(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_81286C4(mapObject)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062724(struct MapObject *mapObject, struct Sprite *sprite) +{ + obj_anim_image_set_and_seek(sprite, 1, 0); + sprite->data2 = 1; + return FALSE; +} + +bool8 sub_8062740(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064864(sprite)) + { + sub_8064820(sprite, 0x20); + sprite->data2 = 2; + } + return FALSE; +} + +bool8 sub_8062764(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_13 ^= 1; + if (sub_8064824(sprite)) + { + mapObject->mapobj_bit_13 = 1; + sprite->data2 = 3; + } + return FALSE; +} + +bool8 sub_80627A0(struct MapObject *mapObject, struct Sprite *sprite) +{ + obj_anim_image_set_and_seek(sprite, 1, 0); + sprite->data2 = 1; + return FALSE; +} + +bool8 sub_80627BC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8064864(sprite)) + { + sub_8064820(sprite, 0x20); + sprite->data2 = 2; + } + return FALSE; +} + +bool8 sub_80627E0(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_13 ^= 1; + if (sub_8064824(sprite)) + { + mapObject->mapobj_bit_13 = 1; + sprite->data2 = 3; + } + return FALSE; +} + +bool8 sub_806281C(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_26 = 1; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_806282C(struct MapObject *mapObject, struct Sprite *sprite) +{ + mapObject->mapobj_bit_26 = 0; + sprite->data2 = 1; + return TRUE; +} + +bool8 sub_806283C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->oam.affineMode = 3; + InitSpriteAffineAnim(sprite); + sprite->affineAnimPaused = 1; + sprite->subspriteMode = 0; + return TRUE; +} + +bool8 sub_806286C(struct MapObject *mapObject, struct Sprite *sprite) +{ + FreeOamMatrix(sprite->oam.matrixNum); + sprite->oam.affineMode = 0; + CalcCenterToCornerVec(sprite, sprite->oam.shape, sprite->oam.size, sprite->oam.affineMode); + return TRUE; +} + +bool8 sub_80628D0(struct MapObject *, struct Sprite *); + +bool8 sub_806289C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8060ED8(mapObject, sprite, DIR_SOUTH); + sprite->affineAnimPaused = 0; + StartSpriteAffineAnimIfDifferent(sprite, 0); + return sub_80628D0(mapObject, sprite); +} + +bool8 sub_80628D0(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (an_walk_any_2(mapObject, sprite)) + { + sprite->affineAnimPaused = 1; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062930(struct MapObject *, struct Sprite *); + +bool8 sub_80628FC(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8060ED8(mapObject, sprite, DIR_SOUTH); + sprite->affineAnimPaused = 0; + ChangeSpriteAffineAnimIfDifferent(sprite, 1); + return sub_8062930(mapObject, sprite); +} + +bool8 sub_8062930(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (an_walk_any_2(mapObject, sprite)) + { + sprite->affineAnimPaused = 1; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +void sub_806295C(struct MapObject *mapObject, struct Sprite *sprite, u8 direction) +{ + FieldObjectSetDirection(mapObject, direction); + npc_coords_shift_still(mapObject); + sub_805FE64(mapObject, sprite, sub_805FDD8(direction)); + sprite->animPaused = 1; + sprite->data2 = 1; +} + +bool8 sub_806299C(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_806295C(mapObject, sprite, DIR_SOUTH); + return TRUE; +} + +bool8 sub_80629AC(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_806295C(mapObject, sprite, DIR_NORTH); + return TRUE; +} + +bool8 sub_80629BC(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_806295C(mapObject, sprite, DIR_WEST); + return TRUE; +} + +bool8 sub_80629CC(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_806295C(mapObject, sprite, DIR_EAST); + return TRUE; +} + +bool8 sub_80629DC(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_SOUTH, sub_805FD98(DIR_SOUTH)); + return FALSE; +} + +bool8 sub_8062A00(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_NORTH, sub_805FD98(DIR_NORTH)); + return FALSE; +} + +bool8 sub_8062A24(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_WEST, sub_805FD98(DIR_WEST)); + return FALSE; +} + +bool8 sub_8062A48(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_EAST, sub_805FD98(DIR_EAST)); + return FALSE; +} + +bool8 sub_8062A6C(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_SOUTH, sub_805FDB8(DIR_SOUTH)); + return FALSE; +} + +bool8 sub_8062A90(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_NORTH, sub_805FDB8(DIR_NORTH)); + return FALSE; +} + +bool8 sub_8062AB4(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_WEST, sub_805FDB8(DIR_WEST)); + return FALSE; +} + +bool8 sub_8062AD8(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_EAST, sub_805FDB8(DIR_EAST)); + return FALSE; +} + +bool8 sub_8062AFC(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_SOUTH, sub_805FDC8(DIR_SOUTH)); + return FALSE; +} + +bool8 sub_8062B20(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_NORTH, sub_805FDC8(DIR_NORTH)); + return FALSE; +} + +bool8 sub_8062B44(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_WEST, sub_805FDC8(DIR_WEST)); + return FALSE; +} + +bool8 sub_8062B68(struct MapObject *mapObject, struct Sprite *sprite) +{ + npc_set_direction_and_anim__an_proceed(mapObject, sprite, DIR_EAST, sub_805FDC8(DIR_EAST)); + return FALSE; +} + +void sub_8062B8C(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 a3, u8 a4) +{ + sub_806113C(mapObject, sprite, direction, a3, a4); + StartSpriteAnimIfDifferent(sprite, sub_805FD98(direction)); + DoShadowFieldEffect(mapObject); +} + +bool8 sub_8062BFC(struct MapObject *, struct Sprite *); + +bool8 sub_8062BD0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_SOUTH, 0, 1); + return sub_8062BFC(mapObject, sprite); +} + +bool8 sub_8062BFC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062C54(struct MapObject *, struct Sprite *); + +bool8 sub_8062C28(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_NORTH, 0, 1); + return sub_8062C54(mapObject, sprite); +} + +bool8 sub_8062C54(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062CAC(struct MapObject *, struct Sprite *); + +bool8 sub_8062C80(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_WEST, 0, 1); + return sub_8062CAC(mapObject, sprite); +} + +bool8 sub_8062CAC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062D04(struct MapObject *, struct Sprite *); + +bool8 sub_8062CD8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_EAST, 0, 1); + return sub_8062D04(mapObject, sprite); +} + +bool8 sub_8062D04(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062D5C(struct MapObject *, struct Sprite *); + +bool8 sub_8062D30(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_SOUTH, 1, 1); + return sub_8062D5C(mapObject, sprite); +} + +bool8 sub_8062D5C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062DB4(struct MapObject *, struct Sprite *); + +bool8 sub_8062D88(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_NORTH, 1, 1); + return sub_8062DB4(mapObject, sprite); +} + +bool8 sub_8062DB4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062E0C(struct MapObject *, struct Sprite *); + +bool8 sub_8062DE0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_WEST, 1, 1); + return sub_8062E0C(mapObject, sprite); +} + +bool8 sub_8062E0C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062E64(struct MapObject *, struct Sprite *); + +bool8 sub_8062E38(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_EAST, 1, 1); + return sub_8062E64(mapObject, sprite); +} + +bool8 sub_8062E64(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062EBC(struct MapObject *, struct Sprite *); + +bool8 sub_8062E90(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_SOUTH, 2, 0); + return sub_8062EBC(mapObject, sprite); +} + +bool8 sub_8062EBC(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062F14(struct MapObject *, struct Sprite *); + +bool8 sub_8062EE8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_NORTH, 2, 0); + return sub_8062F14(mapObject, sprite); +} + +bool8 sub_8062F14(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062F6C(struct MapObject *, struct Sprite *); + +bool8 sub_8062F40(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_WEST, 2, 0); + return sub_8062F6C(mapObject, sprite); +} + +bool8 sub_8062F6C(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062FC4(struct MapObject *, struct Sprite *); + +bool8 sub_8062F98(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8062B8C(mapObject, sprite, DIR_EAST, 2, 0); + return sub_8062FC4(mapObject, sprite); +} + +bool8 sub_8062FC4(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (sub_8061328(mapObject, sprite)) + { + mapObject->mapobj_bit_22 = 0; + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8062FF0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_SOUTH, sub_805FDD8(DIR_SOUTH), 8); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8063028(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_NORTH, sub_805FDD8(DIR_NORTH), 8); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8063060(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_WEST, sub_805FDD8(DIR_WEST), 8); + return sub_8061714(mapObject, sprite); +} + +bool8 sub_8063098(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80616CC(mapObject, sprite, DIR_EAST, sub_805FDD8(DIR_EAST), 8); + return sub_8061714(mapObject, sprite); +} + +void sub_80630D0(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 a3) +{ + sub_8060D20(mapObject, sprite, direction, a3); + StartSpriteAnim(sprite, sub_805FD98(mapObject->mapobj_unk_18)); + SeekSpriteAnim(sprite, 0); +} + +bool8 sub_8063128(struct MapObject *, struct Sprite *); + +bool8 sub_8063108(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80630D0(mapObject, sprite, DIR_SOUTH, 1); + return sub_8063128(mapObject, sprite); +} + +bool8 sub_8063128(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8063168(struct MapObject *, struct Sprite *); + +bool8 sub_8063148(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80630D0(mapObject, sprite, DIR_NORTH, 1); + return sub_8063168(mapObject, sprite); +} + +bool8 sub_8063168(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80631A8(struct MapObject *, struct Sprite *); + +bool8 sub_8063188(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80630D0(mapObject, sprite, DIR_WEST, 1); + return sub_80631A8(mapObject, sprite); +} + +bool8 sub_80631A8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80631E8(struct MapObject *, struct Sprite *); + +bool8 sub_80631C8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80630D0(mapObject, sprite, DIR_EAST, 1); + return sub_80631E8(mapObject, sprite); +} + +bool8 sub_80631E8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +void sub_8063208(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 a3) +{ + sub_8060D20(mapObject, sprite, direction, a3); + sub_805FE28(mapObject, sprite, sub_805FDD8(mapObject->mapobj_unk_18)); +} + +bool8 sub_8063258(struct MapObject *, struct Sprite *); + +bool8 sub_8063238(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8063208(mapObject, sprite, DIR_SOUTH, 1); + return sub_8063258(mapObject, sprite); +} + +bool8 sub_8063258(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8063298(struct MapObject *, struct Sprite *); + +bool8 sub_8063278(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8063208(mapObject, sprite, DIR_NORTH, 1); + return sub_8063298(mapObject, sprite); +} + +bool8 sub_8063298(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80632D8(struct MapObject *, struct Sprite *); + +bool8 sub_80632B8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8063208(mapObject, sprite, DIR_WEST, 1); + return sub_80632D8(mapObject, sprite); +} + +bool8 sub_80632D8(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8063318(struct MapObject *, struct Sprite *); + +bool8 sub_80632F8(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8063208(mapObject, sprite, DIR_EAST, 1); + return sub_8063318(mapObject, sprite); +} + +bool8 sub_8063318(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +void sub_8063338(struct MapObject *mapObject, struct Sprite *sprite, u8 direction, u8 a3) +{ + sub_8060D20(mapObject, sprite, direction, a3); + StartSpriteAnim(sprite, sub_805FDB8(mapObject->mapobj_unk_18)); + SeekSpriteAnim(sprite, 0); +} + +bool8 sub_8063390(struct MapObject *, struct Sprite *); + +bool8 sub_8063370(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8063338(mapObject, sprite, DIR_SOUTH, 1); + return sub_8063390(mapObject, sprite); +} + +bool8 sub_8063390(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_80633D0(struct MapObject *, struct Sprite *); + +bool8 sub_80633B0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8063338(mapObject, sprite, DIR_NORTH, 1); + return sub_80633D0(mapObject, sprite); +} + +bool8 sub_80633D0(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8063410(struct MapObject *, struct Sprite *); + +bool8 sub_80633F0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8063338(mapObject, sprite, DIR_WEST, 1); + return sub_8063410(mapObject, sprite); +} + +bool8 sub_8063410(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8063450(struct MapObject *, struct Sprite *); + +bool8 sub_8063430(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_8063338(mapObject, sprite, DIR_EAST, 1); + return sub_8063450(mapObject, sprite); +} + +bool8 sub_8063450(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (npc_obj_ministep_stop_on_arrival(mapObject, sprite)) + { + sprite->data2 = 2; + return TRUE; + } + return FALSE; +} + +bool8 sub_8063470(struct MapObject *mapObject, struct Sprite *sprite) +{ + return TRUE; +} + +bool8 sub_8063474(struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->animPaused = 1; + return TRUE; +} + +void npc_obj_transfer_image_anim_pause_flag(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (mapObject->mapobj_bit_10) + { + sprite->animPaused = 1; + } +} + +void sub_80634A0(struct MapObject *mapObject, struct Sprite *sprite) +{ + if (mapObject->mapobj_bit_11) + { + sprite->animPaused = 0; + mapObject->mapobj_bit_10 = 0; + mapObject->mapobj_bit_11 = 0; + } +} + +void sub_80634E8(struct MapObject *, struct Sprite *); +static void UpdateMapObjSpriteVisibility(struct MapObject *, struct Sprite *); + +void sub_80634D0(struct MapObject *mapObject, struct Sprite *sprite) +{ + sub_80634E8(mapObject, sprite); + UpdateMapObjSpriteVisibility(mapObject, sprite); +} + +#ifdef NONMATCHING +void sub_80634E8(struct MapObject *mapObject, struct Sprite *sprite) +{ + u16 x; + u16 y; + s16 x2; + s16 y2; + const struct MapObjectGraphicsInfo *graphicsInfo; + mapObject->mapobj_bit_14 = 0; + graphicsInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + if (sprite->coordOffsetEnabled) + { + x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX; + y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY; + } else + { + x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX; + y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY; + } + x2 = graphicsInfo->width + x; // offending line + y2 = graphicsInfo->height + y; // similarly offending line + if ((s16)x >= 0x100 || x2 < -0x10) + { + mapObject->mapobj_bit_14 = 1; + } + if ((s16)y >= 0xB0 || y2 < -0x10) + { + mapObject->mapobj_bit_14 = 1; + } +} +#else +__attribute__((naked)) +void sub_80634E8(struct MapObject *mapObject, struct Sprite *sprite) { + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + adds r5, r0, 0\n\ + adds r4, r1, 0\n\ + ldrb r1, [r5, 0x1]\n\ + movs r0, 0x41\n\ + negs r0, r0\n\ + ands r0, r1\n\ + strb r0, [r5, 0x1]\n\ + ldrb r0, [r5, 0x5]\n\ + bl GetFieldObjectGraphicsInfo\n\ + adds r6, r0, 0\n\ + adds r0, r4, 0\n\ + adds r0, 0x3E\n\ + ldrb r1, [r0]\n\ + movs r0, 0x2\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _0806354C\n\ + ldrh r1, [r4, 0x24]\n\ + ldrh r0, [r4, 0x20]\n\ + adds r1, r0\n\ + adds r0, r4, 0\n\ + adds r0, 0x28\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + ldr r2, _08063544 @ =gSpriteCoordOffsetX\n\ + adds r0, r1\n\ + ldrh r2, [r2]\n\ + adds r0, r2\n\ + lsls r0, 16\n\ + lsrs r3, r0, 16\n\ + ldrh r1, [r4, 0x26]\n\ + ldrh r0, [r4, 0x22]\n\ + adds r1, r0\n\ + adds r0, r4, 0\n\ + adds r0, 0x29\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + ldr r2, _08063548 @ =gSpriteCoordOffsetY\n\ + adds r0, r1\n\ + ldrh r2, [r2]\n\ + adds r0, r2\n\ + b _08063574\n\ + .align 2, 0\n\ +_08063544: .4byte gSpriteCoordOffsetX\n\ +_08063548: .4byte gSpriteCoordOffsetY\n\ +_0806354C:\n\ + ldrh r1, [r4, 0x24]\n\ + ldrh r0, [r4, 0x20]\n\ + adds r1, r0\n\ + adds r0, r4, 0\n\ + adds r0, 0x28\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + adds r0, r1\n\ + lsls r0, 16\n\ + lsrs r3, r0, 16\n\ + ldrh r1, [r4, 0x26]\n\ + ldrh r0, [r4, 0x22]\n\ + adds r1, r0\n\ + adds r0, r4, 0\n\ + adds r0, 0x29\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + adds r0, r1\n\ +_08063574:\n\ + lsls r0, 16\n\ + lsrs r2, r0, 16\n\ + ldrh r0, [r6, 0x8]\n\ + adds r0, r3\n\ + lsls r0, 16\n\ + lsrs r1, r0, 16\n\ + ldrh r0, [r6, 0xA]\n\ + adds r0, r2\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + lsls r0, r3, 16\n\ + asrs r0, 16\n\ + cmp r0, 0xFF\n\ + bgt _0806359C\n\ + lsls r0, r1, 16\n\ + asrs r0, 16\n\ + movs r1, 0x10\n\ + negs r1, r1\n\ + cmp r0, r1\n\ + bge _080635A4\n\ +_0806359C:\n\ + ldrb r0, [r5, 0x1]\n\ + movs r1, 0x40\n\ + orrs r0, r1\n\ + strb r0, [r5, 0x1]\n\ +_080635A4:\n\ + lsls r0, r2, 16\n\ + asrs r0, 16\n\ + cmp r0, 0xAF\n\ + bgt _080635B8\n\ + lsls r0, r4, 16\n\ + asrs r0, 16\n\ + movs r1, 0x10\n\ + negs r1, r1\n\ + cmp r0, r1\n\ + bge _080635C0\n\ +_080635B8:\n\ + ldrb r0, [r5, 0x1]\n\ + movs r1, 0x40\n\ + orrs r0, r1\n\ + strb r0, [r5, 0x1]\n\ +_080635C0:\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ +.syntax divided\n"); +} +#endif + +void UpdateMapObjSpriteVisibility(struct MapObject *mapObject, struct Sprite *sprite) +{ + sprite->invisible = 0; + if (mapObject->mapobj_bit_13 || mapObject->mapobj_bit_14) + { + sprite->invisible = 1; + } +} diff --git a/src/field/field_map_obj_helpers.c b/src/field/field_map_obj_helpers.c new file mode 100644 index 000000000..b453d3794 --- /dev/null +++ b/src/field/field_map_obj_helpers.c @@ -0,0 +1,318 @@ +#include "global.h" +#include "field_map_obj_helpers.h" +#include "field_effect.h" +#include "field_ground_effect.h" +#include "field_map_obj.h" +#include "sprite.h" + +typedef void (*SpriteStepFunc)(struct Sprite *sprite, u8 dir); + +extern s16 gUnknown_08376194[]; +extern SpriteStepFunc *gUnknown_08376180[]; +extern s8 *gUnknown_083761D0[]; +extern s16 gUnknown_083761DC[]; +extern u8 gUnknown_083761E2[]; +extern s16 gUnknown_083761E6[]; +extern u8 gUnknown_083761EC[]; + +bool8 FreezeMapObject(struct MapObject *mapObject) +{ + if (mapObject->mapobj_bit_6 || mapObject->mapobj_bit_8) + { + return TRUE; + } + else + { + mapObject->mapobj_bit_8 = 1; + mapObject->mapobj_bit_23 = gSprites[mapObject->spriteId].animPaused; + mapObject->mapobj_bit_24 = gSprites[mapObject->spriteId].affineAnimPaused; + gSprites[mapObject->spriteId].animPaused = 1; + gSprites[mapObject->spriteId].affineAnimPaused = 1; + return FALSE; + } +} + +void FreezeMapObjects(void) +{ + u8 i; + for (i = 0; i < 16; i++) + if (gMapObjects[i].active && i != gPlayerAvatar.mapObjectId) + FreezeMapObject(&gMapObjects[i]); +} + +void FreezeMapObjectsExceptOne(u8 a1) +{ + u8 i; + for (i = 0; i < 16; i++) + if (i != a1 && gMapObjects[i].active && i != gPlayerAvatar.mapObjectId) + FreezeMapObject(&gMapObjects[i]); +} + +void UnfreezeMapObject(struct MapObject *mapObject) +{ + if (mapObject->active && mapObject->mapobj_bit_8) + { + mapObject->mapobj_bit_8 = 0; + gSprites[mapObject->spriteId].animPaused = mapObject->mapobj_bit_23; + gSprites[mapObject->spriteId].affineAnimPaused = mapObject->mapobj_bit_24; + } +} + +void UnfreezeMapObjects(void) +{ + u8 i; + for (i = 0; i < 16; i++) + if (gMapObjects[i].active) + UnfreezeMapObject(&gMapObjects[i]); +} + +void Step1(struct Sprite *sprite, u8 dir) +{ + sprite->pos1.x += gDirectionToVector[dir].x; + sprite->pos1.y += gDirectionToVector[dir].y; +} + +void Step2(struct Sprite *sprite, u8 dir) +{ + sprite->pos1.x += 2 * (u16) gDirectionToVector[dir].x; + sprite->pos1.y += 2 * (u16) gDirectionToVector[dir].y; +} + +void Step3(struct Sprite *sprite, u8 dir) +{ + sprite->pos1.x += 2 * (u16) gDirectionToVector[dir].x + (u16) gDirectionToVector[dir].x; + sprite->pos1.y += 2 * (u16) gDirectionToVector[dir].y + (u16) gDirectionToVector[dir].y; +} + +void Step4(struct Sprite *sprite, u8 dir) +{ + sprite->pos1.x += 4 * (u16) gDirectionToVector[dir].x; + sprite->pos1.y += 4 * (u16) gDirectionToVector[dir].y; +} + +void Step8(struct Sprite *sprite, u8 dir) +{ + sprite->pos1.x += 8 * (u16) gDirectionToVector[dir].x; + sprite->pos1.y += 8 * (u16) gDirectionToVector[dir].y; +} + +void oamt_npc_ministep_reset(struct Sprite *sprite, u8 a2, u8 a3) +{ + sprite->data3 = a2; + sprite->data4 = a3; + sprite->data5 = 0; +} + +bool8 obj_npc_ministep(struct Sprite *sprite) +{ + if (sprite->data5 >= gUnknown_08376194[sprite->data4]) + return FALSE; + + gUnknown_08376180[sprite->data4][sprite->data5](sprite, sprite->data3); + + sprite->data5++; + + if (sprite->data5 < gUnknown_08376194[sprite->data4]) + return FALSE; + + return TRUE; +} + +void sub_806467C(struct Sprite *sprite, u8 a2) +{ + sprite->data3 = a2; + sprite->data4 = 0; + sprite->data5 = 0; +} + +bool8 sub_806468C(struct Sprite *sprite) +{ + if (!(sprite->data4 & 1)) + { + Step1(sprite, sprite->data3); + sprite->data5++; + } + + sprite->data4++; + + if (sprite->data5 > 15) + return TRUE; + else + return FALSE; +} + +s16 sub_80646C8(s16 a1, u8 a2) +{ + return gUnknown_083761D0[a2][a1]; +} + +void sub_80646E4(struct Sprite *sprite, u8 a2, u8 a3, u8 a4) +{ + sprite->data3 = a2; + sprite->data4 = a3; + sprite->data5 = a4; + sprite->data6 = 0; +} + +u8 sub_8064704(struct Sprite *sprite) +{ + u8 v2; + s16 v5[3]; + u8 v6[3]; + + memcpy(v5, gUnknown_083761DC, 6); + memcpy(v6, gUnknown_083761E2, 3); + + v2 = 0; + + if (sprite->data4) + Step1(sprite, sprite->data3); + + sprite->pos2.y = sub_80646C8(sprite->data6 >> v6[sprite->data4], sprite->data5); + + sprite->data6++; + + if (sprite->data6 == (v5[sprite->data4] >> 1)) + v2 = 1; + + if (sprite->data6 >= v5[sprite->data4]) + { + sprite->pos2.y = 0; + v2 = -1; + } + + return v2; +} + +u8 sub_806478C(struct Sprite *sprite) +{ + u8 v2; + s16 v5[3]; + u8 v6[3]; + + memcpy(v5, gUnknown_083761E6, 6); + memcpy(v6, gUnknown_083761EC, 3); + + v2 = 0; + + if (sprite->data4 && !(sprite->data6 & 1)) + Step1(sprite, sprite->data3); + + sprite->pos2.y = sub_80646C8(sprite->data6 >> v6[sprite->data4], sprite->data5); + + sprite->data6++; + + if (sprite->data6 == (v5[sprite->data4] >> 1)) + v2 = 1; + + if (sprite->data6 >= v5[sprite->data4]) + { + sprite->pos2.y = 0; + v2 = -1; + } + + return v2; +} + +void sub_8064820(struct Sprite *sprite, u16 a2) +{ + sprite->data3 = a2; +} + +bool8 sub_8064824(struct Sprite *sprite) +{ + sprite->data3--; + + if (sprite->data3 == 0) + return TRUE; + else + return FALSE; +} + +void obj_anim_image_set_and_seek(struct Sprite *sprite, u8 a2, u8 a3) +{ + sprite->animNum = a2; + sprite->animPaused = 0 ; + SeekSpriteAnim(sprite, a3); +} + +bool8 sub_8064864(struct Sprite *sprite) +{ + if (sprite->animEnded) + return TRUE; + else + return FALSE; +} + +void sub_806487C(struct Sprite *sprite, bool8 invisible) +{ + u16 x, y; + s16 x2, y2; + + sprite->invisible = invisible; + + if (sprite->coordOffsetEnabled) + { + x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX; + y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY; + } + else + { + x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX; + y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY; + } + + x2 = x - (sprite->centerToCornerVecX >> 1); + y2 = y - (sprite->centerToCornerVecY >> 1); + + if ((s16)x > 255 || x2 < -16) + sprite->invisible = 1; + if ((s16)y > 175 || y2 < -16) + sprite->invisible = 1; +} + +void sub_8064970(struct Sprite *sprite) +{ + SetObjectSubpriorityByZCoord(sprite->data1, sprite, 1); + sub_806487C(sprite, 0); +} + +void sub_8064990(u8 a1, u8 dir) +{ + u8 i; + for (i = 0; i < MAX_SPRITES; i++) + { + struct Sprite *sprite = &gSprites[i]; + if (sprite->inUse && sprite->callback == sub_8064970 && (u8)sprite->data0 == a1) + { + u8 animNum = FieldObjectDirectionToImageAnimId(dir); + StartSpriteAnim(sprite, animNum); + break; + } + } +} + +u32 oe_exec_and_other_stuff(u8 fieldEffectId, struct MapObject *mapObject) +{ + FieldObjectGetLocalIdAndMap(mapObject, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + return FieldEffectStart(fieldEffectId); +} + +void DoShadowFieldEffect(struct MapObject *mapObject) +{ + if (!mapObject->mapobj_bit_22) + { + mapObject->mapobj_bit_22 = 1; + oe_exec_and_other_stuff(FLDEFF_SHADOW, mapObject); + } +} + +void DoRippleFieldEffect(struct MapObject *mapObject, struct Sprite *sprite) +{ + const struct MapObjectGraphicsInfo *gfxInfo = GetFieldObjectGraphicsInfo(mapObject->graphicsId); + gFieldEffectArguments[0] = sprite->pos1.x; + gFieldEffectArguments[1] = sprite->pos1.y + (gfxInfo->height >> 1) - 2; + gFieldEffectArguments[2] = 151; + gFieldEffectArguments[3] = 3; + FieldEffectStart(FLDEFF_RIPPLE); +} diff --git a/src/field/field_message_box.c b/src/field/field_message_box.c new file mode 100644 index 000000000..35aac7ac9 --- /dev/null +++ b/src/field/field_message_box.c @@ -0,0 +1,155 @@ +#include "global.h" +#include "field_message_box.h" +#include "menu.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "text_window.h" + +static EWRAM_DATA struct Window gFieldMessageBoxWindow = {0}; + +static u8 sMessageBoxMode; + +static void Task_FieldMessageBox(u8 taskId); +static void CreateFieldMessageBoxTask(void); +static void DestroyFieldMessageBoxTask(void); +static void PrintFieldMessage(const u8 *message); +static void PrintFieldMessageFromStringVar4(void); + +void InitFieldMessageBox(void) +{ + sMessageBoxMode = FIELD_MESSAGE_BOX_HIDDEN; + SetMessageBoxBaseTileNum(gMenuTextWindowContentTileOffset); + InitWindowFromConfig(&gFieldMessageBoxWindow, &gWindowConfig_81E6CE4); +} + +static void Task_FieldMessageBox(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + switch (task->data[0]) + { + case 0: + LoadMessageBoxTiles(&gFieldMessageBoxWindow); + task->data[0]++; + break; + case 1: + DrawStandardMessageBox(&gFieldMessageBoxWindow); + task->data[0]++; + break; + case 2: + switch (sMessageBoxMode) + { + case FIELD_MESSAGE_BOX_NORMAL: + if (!sub_80035AC(&gFieldMessageBoxWindow)) + return; + break; + case FIELD_MESSAGE_BOX_AUTO_SCROLL: + if (!sub_8003778(&gFieldMessageBoxWindow)) + return; + break; + } + sMessageBoxMode = FIELD_MESSAGE_BOX_HIDDEN; + DestroyTask(taskId); + } +} + +static void CreateFieldMessageBoxTask(void) +{ + CreateTask(Task_FieldMessageBox, 80); +} + +static void DestroyFieldMessageBoxTask(void) +{ + u8 taskId = FindTaskIdByFunc(Task_FieldMessageBox); + if (taskId != 0xFF) + DestroyTask(taskId); +} + +bool8 ShowFieldMessage(const u8 *message) +{ + if (sMessageBoxMode != FIELD_MESSAGE_BOX_HIDDEN) + { + return FALSE; + } + else + { + PrintFieldMessage(message); + sMessageBoxMode = FIELD_MESSAGE_BOX_NORMAL; + return TRUE; + } +} + +bool8 ShowFieldAutoScrollMessage(const u8 *message) +{ + if (sMessageBoxMode != FIELD_MESSAGE_BOX_HIDDEN) + { + return FALSE; + } + else + { + sMessageBoxMode = FIELD_MESSAGE_BOX_AUTO_SCROLL; + PrintFieldMessage(message); + return TRUE; + } +} + +bool8 unref_sub_8064BB8(const u8 *message) +{ + sMessageBoxMode = FIELD_MESSAGE_BOX_AUTO_SCROLL; + PrintFieldMessage(message); + return TRUE; +} + +bool8 unref_sub_8064BD0(const u8 *message) +{ + if (sMessageBoxMode != FIELD_MESSAGE_BOX_HIDDEN) + { + return FALSE; + } + else + { + sMessageBoxMode = FIELD_MESSAGE_BOX_NORMAL; + PrintFieldMessageFromStringVar4(); + return TRUE; + } +} + +static void PrintFieldMessage(const u8 *message) +{ + StringExpandPlaceholders(gStringVar4, message); + sub_8002EB0(&gFieldMessageBoxWindow, gStringVar4, gMenuTextTileOffset, 2, 15); + CreateFieldMessageBoxTask(); +} + +static void PrintFieldMessageFromStringVar4(void) +{ + sub_8002EB0(&gFieldMessageBoxWindow, gStringVar4, gMenuTextTileOffset, 2, 15); + CreateFieldMessageBoxTask(); +} + +void HideFieldMessageBox(void) +{ + DestroyFieldMessageBoxTask(); + ClearStandardMessageBox(&gFieldMessageBoxWindow); + sMessageBoxMode = FIELD_MESSAGE_BOX_HIDDEN; +} + +u8 GetFieldMessageBoxMode(void) +{ + return sMessageBoxMode; +} + +bool8 IsFieldMessageBoxHidden(void) +{ + if (sMessageBoxMode == FIELD_MESSAGE_BOX_HIDDEN) + return TRUE; + else + return FALSE; +} + +void unref_sub_8064CA0(void) +{ + DestroyFieldMessageBoxTask(); + DrawStandardMessageBox(&gFieldMessageBoxWindow); + sMessageBoxMode = FIELD_MESSAGE_BOX_HIDDEN; +} diff --git a/src/field/field_player_avatar.c b/src/field/field_player_avatar.c new file mode 100644 index 000000000..6c1c9123a --- /dev/null +++ b/src/field/field_player_avatar.c @@ -0,0 +1,1757 @@ +#include "global.h" +#include "field_player_avatar.h" +#include "bike.h" +#include "event_data.h" +#include "field_effect.h" +#include "field_effect_helpers.h" +#include "field_ground_effect.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "fieldmap.h" +#include "main.h" +#include "map_object_constants.h" +#include "menu.h" +#include "metatile_behavior.h" +#include "party_menu.h" +#include "rng.h" +#include "overworld.h" +#include "rotating_gate.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "strings2.h" +#include "task.h" +#include "tv.h" +#include "wild_encounter.h" + +EWRAM_DATA struct PlayerAvatar gPlayerAvatar = {0}; + +//Functions +static bool8 sub_8058854(struct MapObject *, u8); +static void npc_clear_strange_bits(struct MapObject *a); +static void MovePlayerAvatarUsingKeypadInput(u8 a, u16 b, u16 c); +static void PlayerAllowForcedMovementIfMovingSameDirection(void); +static u8 TryDoMetatileBehaviorForcedMovement(void); +static u8 GetForcedMovementByMetatileBehavior(void); +static void MovePlayerNotOnBike(u8 a, u16 b); +static u8 CheckMovementInputNotOnBike(u8 a); +static u8 CheckForPlayerAvatarCollision(u8 a); +static u8 sub_8058EF0(s16 a, s16 b, u8 c); +static bool8 ShouldJumpLedge(s16 a, s16 b, u8 c); +static u8 sub_8058F6C(s16 a, s16 b, u8 c); +static void check_acro_bike_metatile(int unused1, int unused2, u8 c, u8 *d); +static void DoPlayerAvatarTransition(void); +static bool8 player_is_anim_in_certain_ranges(void); +static bool8 sub_80592A4(void); +static bool8 PlayerIsAnimActive(void); +static bool8 PlayerCheckIfAnimFinishedOrInactive(void); +static void PlayerNotOnBikeCollide(u8 a); +static void PlayCollisionSoundIfNotFacingWarp(u8 a); +static void sub_8059D60(struct MapObject *a); +static void StartStrengthAnim(u8 a, u8 b); +static void sub_8059F94(void); +static void sub_805A06C(void); + +static bool8 (*const gUnknown_0830FB58[])(u8) = +{ + MetatileBehavior_IsTrickHouseSlipperyFloor, + MetatileBehavior_IsIce_2, + MetatileBehavior_IsWalkSouth, + MetatileBehavior_IsWalkNorth, + MetatileBehavior_IsWalkWest, + MetatileBehavior_IsWalkEast, + MetatileBehavior_IsSouthwardCurrent, + MetatileBehavior_IsNorthwardCurrent, + MetatileBehavior_IsWestwardCurrent, + MetatileBehavior_IsEastwardCurrent, + MetatileBehavior_IsSlideSouth, + MetatileBehavior_IsSlideNorth, + MetatileBehavior_IsSlideWest, + MetatileBehavior_IsSlideEast, + MetatileBehavior_IsWaterfall, + MetatileBehavior_0xBB, + MetatileBehavior_0xBC, + MetatileBehavior_IsMuddySlope, +}; +static u8 (*const gUnknown_0830FBA0[])(void) = +{ + ForcedMovement_None, + ForcedMovement_Slip, + ForcedMovement_Slip, + sub_8058AAC, + sub_8058AC4, + sub_8058ADC, + sub_8058AF4, + sub_8058B0C, + sub_8058B24, + sub_8058B3C, + sub_8058B54, + ForcedMovement_SlideSouth, + ForcedMovement_SlideNorth, + ForcedMovement_SlideWest, + ForcedMovement_SlideEast, + sub_8058B0C, + sub_8058C04, + sub_8058C10, + ForcedMovement_MuddySlope, +}; +static void (*const gUnknown_0830FBEC[])(u8, u16) = +{ + PlayerNotOnBikeNotMoving, + PlayerNotOnBikeTurningInPlace, + sub_8058D0C, +}; +static bool8 (*const gUnknown_0830FBF8[])(u8) = +{ + MetatileBehavior_IsBumpySlope, + MetatileBehavior_IsIsolatedVerticalRail, + MetatileBehavior_IsIsolatedHorizontalRail, + MetatileBehavior_IsVerticalRail, + MetatileBehavior_IsHorizontalRail, +}; +static const u8 gUnknown_0830FC0C[] = {9, 10, 11, 12, 13}; +static void (*const gUnknown_0830FC14[])(struct MapObject *) = +{ + PlayerAvatarTransition_Normal, + PlayerAvatarTransition_MachBike, + PlayerAvatarTransition_AcroBike, + PlayerAvatarTransition_Surfing, + PlayerAvatarTransition_Underwater, + sub_80591F4, + nullsub_49, + nullsub_49, +}; +static bool8 (*const gUnknown_0830FC34[])(u8) = +{ + MetatileBehavior_IsSouthArrowWarp, + MetatileBehavior_IsNorthArrowWarp, + MetatileBehavior_IsWestArrowWarp, + MetatileBehavior_IsEastArrowWarp, +}; +static const u8 sRivalAvatarGfxIds[][2] = +{ + {MAP_OBJ_GFX_RIVAL_BRENDAN_NORMAL, MAP_OBJ_GFX_RIVAL_MAY_NORMAL}, + {MAP_OBJ_GFX_RIVAL_BRENDAN_MACH_BIKE, MAP_OBJ_GFX_RIVAL_MAY_MACH_BIKE}, + {MAP_OBJ_GFX_RIVAL_BRENDAN_ACRO_BIKE, MAP_OBJ_GFX_RIVAL_MAY_ACRO_BIKE}, + {MAP_OBJ_GFX_RIVAL_BRENDAN_SURFING, MAP_OBJ_GFX_RIVAL_MAY_SURFING}, + {MAP_OBJ_GFX_BRENDAN_UNDERWATER, MAP_OBJ_GFX_MAY_UNDERWATER}, + {MAP_OBJ_GFX_RIVAL_BRENDAN_FIELD_MOVE, MAP_OBJ_GFX_RIVAL_MAY_FIELD_MOVE}, + {MAP_OBJ_GFX_BRENDAN_FISHING, MAP_OBJ_GFX_MAY_FISHING}, + {MAP_OBJ_GFX_BRENDAN_WATERING, MAP_OBJ_GFX_MAY_WATERING}, +}; +static const u8 sPlayerAvatarGfxIds[][2] = +{ + {MAP_OBJ_GFX_BRENDAN_NORMAL, MAP_OBJ_GFX_MAY_NORMAL}, + {MAP_OBJ_GFX_BRENDAN_MACH_BIKE, MAP_OBJ_GFX_MAY_MACH_BIKE}, + {MAP_OBJ_GFX_BRENDAN_ACRO_BIKE, MAP_OBJ_GFX_MAY_ACRO_BIKE}, + {MAP_OBJ_GFX_BRENDAN_SURFING, MAP_OBJ_GFX_MAY_SURFING}, + {MAP_OBJ_GFX_BRENDAN_UNDERWATER, MAP_OBJ_GFX_MAY_UNDERWATER}, + {MAP_OBJ_GFX_BRENDAN_FIELD_MOVE, MAP_OBJ_GFX_MAY_FIELD_MOVE}, + {MAP_OBJ_GFX_BRENDAN_FISHING, MAP_OBJ_GFX_MAY_FISHING}, + {MAP_OBJ_GFX_BRENDAN_WATERING, MAP_OBJ_GFX_MAY_WATERING}, +}; +static const u8 gUnknown_0830FC64[2][5][2] = +{ + //male + { + {MAP_OBJ_GFX_BRENDAN_NORMAL, 1}, + {MAP_OBJ_GFX_BRENDAN_MACH_BIKE, 2}, + {MAP_OBJ_GFX_BRENDAN_ACRO_BIKE, 4}, + {MAP_OBJ_GFX_BRENDAN_SURFING, 8}, + {MAP_OBJ_GFX_BRENDAN_UNDERWATER, 16}, + }, + //female + { + {MAP_OBJ_GFX_MAY_NORMAL, 1}, + {MAP_OBJ_GFX_MAY_MACH_BIKE, 2}, + {MAP_OBJ_GFX_MAY_ACRO_BIKE, 4}, + {MAP_OBJ_GFX_MAY_SURFING, 8}, + {MAP_OBJ_GFX_MAY_UNDERWATER, 16}, + } +}; +static bool8 (*const gUnknown_0830FC78[])(u8) = //Duplicate of gUnknown_0830FC34 +{ + MetatileBehavior_IsSouthArrowWarp, + MetatileBehavior_IsNorthArrowWarp, + MetatileBehavior_IsWestArrowWarp, + MetatileBehavior_IsEastArrowWarp, +}; +static u8 (*const gUnknown_0830FC88[])(struct Task *, struct MapObject *, struct MapObject *) = +{ + sub_8059E84, + sub_8059EA4, + sub_8059F40, +}; +static u8 (*const gUnknown_0830FC94[])(struct Task *, struct MapObject *) = +{ + sub_805A000, +}; +static u8 (*const gUnknown_0830FC98[])(struct Task *, struct MapObject *) = +{ + sub_805A0D8, + sub_805A100, + sub_805A178, + sub_805A1B8, +}; + +fieldmap_object_null_cb(sub_80587B4, sub_80587D8); + +void player_step(u8 direction, u16 newKeys, u16 heldKeys) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + sub_8059D60(playerMapObj); + if (gPlayerAvatar.unk6 == 0) + { + sub_80E5B38(newKeys, heldKeys); + if (!sub_8058854(playerMapObj, direction)) + { + npc_clear_strange_bits(playerMapObj); + DoPlayerAvatarTransition(); + if (TryDoMetatileBehaviorForcedMovement() == 0) + { + MovePlayerAvatarUsingKeypadInput(direction, newKeys, heldKeys); + PlayerAllowForcedMovementIfMovingSameDirection(); + } + } + } +} + +static bool8 sub_8058854(struct MapObject *playerMapObj, u8 direction) +{ + if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(playerMapObj) + && !FieldObjectClearAnimIfSpecialAnimFinished(playerMapObj)) + { + u8 specialAnim = FieldObjectGetSpecialAnim(playerMapObj); + + if (specialAnim > 24 && specialAnim < 29 && direction != DIR_NONE && playerMapObj->placeholder18 != direction) + { + FieldObjectClearAnim(playerMapObj); + return FALSE; + } + else + { + return TRUE; + } + } + return FALSE; +} + +static void npc_clear_strange_bits(struct MapObject *a) +{ + a->mapobj_bit_12 = 0; + a->mapobj_bit_10 = 0; + a->mapobj_bit_9 = 0; + gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_DASH; +} + +static void MovePlayerAvatarUsingKeypadInput(u8 direction, u16 newKeys, u16 heldKeys) +{ + if ((gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_MACH_BIKE) + || (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_ACRO_BIKE)) + MovePlayerOnBike(direction, newKeys, heldKeys); + else + MovePlayerNotOnBike(direction, heldKeys); +} + +static void PlayerAllowForcedMovementIfMovingSameDirection(void) +{ + if (gPlayerAvatar.running2 == 2) + gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_5; +} + +static u8 TryDoMetatileBehaviorForcedMovement(void) +{ + return gUnknown_0830FBA0[GetForcedMovementByMetatileBehavior()](); +} + +static u8 GetForcedMovementByMetatileBehavior(void) +{ + u8 i; + + if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_5)) + { + u8 r5 = gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E; + + for (i = 0; i < 18; i++) + { + if (gUnknown_0830FB58[i](r5)) + return i + 1; + } + } + return 0; +} + +u8 ForcedMovement_None(void) +{ + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_6) + { + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + playerMapObj->mapobj_bit_9 = 0; + playerMapObj->mapobj_bit_11 = 1; + FieldObjectSetDirection(playerMapObj, playerMapObj->mapobj_unk_18); + gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_6; + } + return 0; +} + +static u8 DoForcedMovement(u8 direction, void (*b)(u8)) +{ + struct PlayerAvatar *playerAvatar = &gPlayerAvatar; + u8 collisionType = CheckForPlayerAvatarCollision(direction); + + playerAvatar->flags |= PLAYER_AVATAR_FLAG_6; + if (collisionType != 0) + { + ForcedMovement_None(); + if (collisionType <= 4) + { + return 0; + } + else + { + if (collisionType == COLLISION_LEDGE_JUMP) + PlayerJumpLedge(direction); + playerAvatar->flags |= PLAYER_AVATAR_FLAG_6; + playerAvatar->running2 = 2; + return 1; + } + } + else + { + playerAvatar->running2 = 2; + b(direction); + return 1; + } +} + +static u8 DoForcedMovementInCurrentDirection(void (*a)(u8)) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + playerMapObj->mapobj_bit_10 = 1; + return DoForcedMovement(playerMapObj->placeholder18, a); +} + +u8 ForcedMovement_Slip(void) +{ + return DoForcedMovementInCurrentDirection(sub_80593C4); +} + +u8 sub_8058AAC(void) +{ + return DoForcedMovement(1, PlayerGoSpeed0); +} + +u8 sub_8058AC4(void) +{ + return DoForcedMovement(2, PlayerGoSpeed0); +} + +u8 sub_8058ADC(void) +{ + return DoForcedMovement(3, PlayerGoSpeed0); +} + +u8 sub_8058AF4(void) +{ + return DoForcedMovement(4, PlayerGoSpeed0); +} + +u8 sub_8058B0C(void) +{ + return DoForcedMovement(1, npc_use_some_d2s); +} + +u8 sub_8058B24(void) +{ + return DoForcedMovement(2, npc_use_some_d2s); +} + +u8 sub_8058B3C(void) +{ + return DoForcedMovement(3, npc_use_some_d2s); +} + +u8 sub_8058B54(void) +{ + return DoForcedMovement(4, npc_use_some_d2s); +} + +static u8 ForcedMovement_Slide(u8 direction, void (*b)(u8)) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + playerMapObj->mapobj_bit_10 = 1; + playerMapObj->mapobj_bit_9 = 1; + return DoForcedMovement(direction, b); +} + +u8 ForcedMovement_SlideSouth(void) +{ + return ForcedMovement_Slide(1, sub_80593C4); +} + +u8 ForcedMovement_SlideNorth(void) +{ + return ForcedMovement_Slide(2, sub_80593C4); +} + +u8 ForcedMovement_SlideWest(void) +{ + return ForcedMovement_Slide(3, sub_80593C4); +} + +u8 ForcedMovement_SlideEast(void) +{ + return ForcedMovement_Slide(4, sub_80593C4); +} + +u8 sub_8058C04(void) +{ + sub_8059F94(); + return 1; +} + +u8 sub_8058C10(void) +{ + sub_805A06C(); + return 1; +} + +u8 ForcedMovement_MuddySlope(void) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (playerMapObj->placeholder18 != 2 || GetPlayerSpeed() <= 3) + { + sub_80E6010(0); + playerMapObj->mapobj_bit_9 = 1; + return DoForcedMovement(1, sub_80593C4); + } + else + { + return 0; + } +} + +static void MovePlayerNotOnBike(u8 direction, u16 heldKeys) +{ + gUnknown_0830FBEC[CheckMovementInputNotOnBike(direction)](direction, heldKeys); +} + +static u8 CheckMovementInputNotOnBike(u8 direction) +{ + if (direction == DIR_NONE) + { + gPlayerAvatar.running2 = 0; + return 0; + } + else if (direction != player_get_direction_upper_nybble() && gPlayerAvatar.running2 != 2) + { + gPlayerAvatar.running2 = 1; + return 1; + } + else + { + gPlayerAvatar.running2 = 2; + return 2; + } +} + +void PlayerNotOnBikeNotMoving(u8 direction, u16 heldKeys) +{ + PlayerFaceDirection(player_get_direction_lower_nybble()); +} + +void PlayerNotOnBikeTurningInPlace(u8 direction, u16 heldKeys) +{ + PlayerTurnInPlace(direction); +} + +void sub_8058D0C(u8 direction, u16 heldKeys) +{ + u8 r1 = CheckForPlayerAvatarCollision(direction); + + switch (r1) + { + case 6: + PlayerJumpLedge(direction); + return; + default: + if (r1 > 8 || r1 < 5) + PlayerNotOnBikeCollide(direction); + return; + case 0: + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) + { + sub_80593C4(direction); + return; + } + if (!(gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_4) && (heldKeys & B_BUTTON) && FlagGet(SYS_B_DASH) + && IsRunningDisallowed(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E) == 0) + { + sub_805940C(direction); + gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_DASH; + } + else + { + PlayerGoSpeed0(direction); + } + } +} + +static u8 CheckForPlayerAvatarCollision(u8 direction) +{ + s16 x, y; + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + x = playerMapObj->coords2.x; + y = playerMapObj->coords2.y; + MoveCoords(direction, &x, &y); + return CheckForFieldObjectCollision(playerMapObj, x, y, direction, MapGridGetMetatileBehaviorAt(x, y)); +} + +u8 CheckForFieldObjectCollision(struct MapObject *a, s16 x, s16 y, u8 direction, u8 e) +{ + u8 collision; + + collision = npc_block_way(a, x, y, direction); + if (collision == 3 && sub_8058EF0(x, y, direction)) + return 5; + if (ShouldJumpLedge(x, y, direction)) + { + IncrementGameStat(0x2B); + return COLLISION_LEDGE_JUMP; + } + if (collision == 4 && sub_8058F6C(x, y, direction)) + return 7; + + if (collision == 0) + { + if (CheckForRotatingGatePuzzleCollision(direction, x, y)) + return 8; + check_acro_bike_metatile(x, y, e, &collision); + } + return collision; +} + +static u8 sub_8058EF0(s16 a, s16 b, u8 c) +{ + if ((gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) + && MapGridGetZCoordAt(a, b) == 3 + && GetFieldObjectIdByXYZ(a, b, 3) == 16) + { + sub_805A20C(c); + return 1; + } + else + { + return 0; + } +} + +static bool8 ShouldJumpLedge(s16 a, s16 b, u8 c) +{ + if (GetLedgeJumpDirection(a, b, c) != 0) + return 1; + else + return 0; +} + +static u8 sub_8058F6C(s16 a, s16 b, u8 c) +{ + if (FlagGet(SYS_USE_STRENGTH)) + { + u8 mapObjectId = GetFieldObjectIdByXY(a, b); + + if (mapObjectId != 16) + { + if (gMapObjects[mapObjectId].graphicsId == 0x57) + { + a = gMapObjects[mapObjectId].coords2.x; + b = gMapObjects[mapObjectId].coords2.y; + MoveCoords(c, &a, &b); + if (npc_block_way(&gMapObjects[mapObjectId], a, b, c) == 0 + && MetatileBehavior_IsNonAnimDoor(MapGridGetMetatileBehaviorAt(a, b)) == 0) + { + StartStrengthAnim(mapObjectId, c); + return 1; + } + } + } + } + return 0; +} + +static void check_acro_bike_metatile(int unused1, int unused2, u8 c, u8 *d) +{ + u8 i; + + for (i = 0; i < 5; i++) + { + if (gUnknown_0830FBF8[i](c)) + { + *d = gUnknown_0830FC0C[i]; + return; + } + } +} + +void SetPlayerAvatarTransitionFlags(u16 a) +{ + gPlayerAvatar.bike |= a; + DoPlayerAvatarTransition(); +} + +static void DoPlayerAvatarTransition(void) +{ + u8 i; + u32 flags = gPlayerAvatar.bike; + + if (flags != 0) + { + for (i = 0; i < 8; i++, flags >>= 1) + { +#ifdef NONMATCHING + if (flags & 1) + { + gUnknown_0830FC14[i](&gMapObjects[gPlayerAvatar.mapObjectId]); + } +#else + if (flags & 1) + { + register void (*const *funcs)(struct MapObject *) asm("r0") = gUnknown_0830FC14; + funcs[i](&gMapObjects[gPlayerAvatar.mapObjectId]); + } +#endif + } + gPlayerAvatar.bike = 0; + } +} + +void nullsub_49(struct MapObject *a) +{ +} + +void PlayerAvatarTransition_Normal(struct MapObject *a) +{ + sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(0)); + FieldObjectTurn(a, a->placeholder18); + SetPlayerAvatarStateMask(1); +} + +void PlayerAvatarTransition_MachBike(struct MapObject *a) +{ + sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(1)); + FieldObjectTurn(a, a->placeholder18); + SetPlayerAvatarStateMask(2); + BikeClearState(0, 0); +} + +void PlayerAvatarTransition_AcroBike(struct MapObject *a) +{ + sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(2)); + FieldObjectTurn(a, a->placeholder18); + SetPlayerAvatarStateMask(4); + BikeClearState(0, 0); + sub_80E6084(); +} + +void PlayerAvatarTransition_Surfing(struct MapObject *a) +{ + u8 unk; + + sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(3)); + FieldObjectTurn(a, a->placeholder18); + SetPlayerAvatarStateMask(8); + gFieldEffectArguments[0] = a->coords2.x; + gFieldEffectArguments[1] = a->coords2.y; + gFieldEffectArguments[2] = gPlayerAvatar.mapObjectId; + unk = FieldEffectStart(FLDEFF_SURF_BLOB); + a->mapobj_unk_1A = unk; + sub_8127ED0(unk, 1); +} + +void PlayerAvatarTransition_Underwater(struct MapObject *a) +{ + sub_805B980(a, GetPlayerAvatarGraphicsIdByStateId(4)); + FieldObjectTurn(a, a->placeholder18); + SetPlayerAvatarStateMask(16); + a->mapobj_unk_1A = sub_8128124(a->spriteId); +} + +void sub_80591F4(struct MapObject *a) +{ + gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_5; +} + +void sub_8059204(void) +{ + gPlayerAvatar.running1 = 0; + if (PlayerIsAnimActive()) + { + if (!PlayerCheckIfAnimFinishedOrInactive()) + { + if (!player_is_anim_in_certain_ranges()) + gPlayerAvatar.running1 = 1; + } + else + { + if (!sub_80592A4()) + gPlayerAvatar.running1 = 2; + } + } +} + +static bool8 player_is_anim_in_certain_ranges(void) +{ + u8 unk = gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1C; + + if (unk < 4 + || (unk >= 16 && unk < 0x15) + || (unk >= 25 && unk < 41) + || (unk >= 98 && unk < 110) + || (unk >= 122 && unk < 126)) + return TRUE; + else + return FALSE; +} + +static bool8 sub_80592A4(void) +{ + if (player_is_anim_in_certain_ranges() && gPlayerAvatar.running2 != 1) + return TRUE; + else + return FALSE; +} + +static bool8 PlayerIsAnimActive(void) +{ + return FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(&gMapObjects[gPlayerAvatar.mapObjectId]); +} + +static bool8 PlayerCheckIfAnimFinishedOrInactive(void) +{ + return FieldObjectCheckIfSpecialAnimFinishedOrInactive(&gMapObjects[gPlayerAvatar.mapObjectId]); +} + +static void player_set_x22(u8 a) +{ + gMapObjects[gPlayerAvatar.mapObjectId].animId = a; +} + +u8 player_get_x22(void) +{ + return gMapObjects[gPlayerAvatar.mapObjectId].animId; +} + +static void sub_8059348(u8 a) +{ + FieldObjectForceSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], a); +} + +void PlayerSetAnimId(u8 animId, u8 b) +{ + if (!PlayerIsAnimActive()) + { + player_set_x22(b); + FieldObjectSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], animId); + } +} + +void PlayerGoSpeed0(u8 a) +{ + PlayerSetAnimId(GetGoSpeed0AnimId(a), 2); +} + +void sub_80593C4(u8 a) +{ + PlayerSetAnimId(sub_8060744(a), 2); +} + +void npc_use_some_d2s(u8 a) +{ + PlayerSetAnimId(d2s_08064034(a), 2); +} + +void sub_80593F4(u8 a) +{ + PlayerSetAnimId(sub_806079C(a), 2); +} + +void sub_805940C(u8 a) +{ + PlayerSetAnimId(sub_80607F4(a), 2); +} + +void PlayerOnBikeCollide(u8 a) +{ + PlayCollisionSoundIfNotFacingWarp(a); + PlayerSetAnimId(GetStepInPlaceDelay16AnimId(a), 2); +} + +static void PlayerNotOnBikeCollide(u8 a) +{ + PlayCollisionSoundIfNotFacingWarp(a); + PlayerSetAnimId(GetStepInPlaceDelay32AnimId(a), 2); +} + +void PlayerFaceDirection(u8 direction) +{ + PlayerSetAnimId(GetFaceDirectionAnimId(direction), 1); +} + +void PlayerTurnInPlace(u8 direction) +{ + PlayerSetAnimId(GetStepInPlaceDelay8AnimId(direction), 1); +} + +void PlayerJumpLedge(u8 direction) +{ + PlaySE(SE_DANSA); + PlayerSetAnimId(GetJumpLedgeAnimId(direction), 8); +} + +void sub_80594C0(void) +{ + if (gPlayerAvatar.running1 == 2 || gPlayerAvatar.running1 == 0) + { + if (player_should_look_direction_be_enforced_upon_movement()) + sub_8059348(GetFaceDirectionAnimId(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_18)); + } +} + +void sub_8059504(u8 a) +{ + PlayerSetAnimId(sub_80609D8(a), 1); +} + +//normal to wheelie +void PlayerStartWheelie(u8 a) +{ + PlayerSetAnimId(sub_8060A04(a), 1); +} + +void sub_8059534(u8 a) +{ + PlayerSetAnimId(sub_8060A30(a), 1); +} + +void sub_805954C(u8 a) +{ + PlaySE(SE_JITE_PYOKO); + PlayerSetAnimId(sub_8060A5C(a), 1); +} + +void sub_8059570(u8 a) +{ + PlaySE(SE_JITE_PYOKO); + PlayerSetAnimId(sub_8060A88(a), 2); +} + +void sub_8059594(u8 a) +{ + PlaySE(SE_JITE_PYOKO); + PlayerSetAnimId(sub_8060AB4(a), 8); +} + +void sub_80595B8(u8 direction) +{ + PlaySE(SE_JITE_PYOKO); + PlayerSetAnimId(sub_8060878(direction), 1); +} + +void sub_80595DC(u8 direction) +{ + PlaySE(SE_WALL_HIT); + PlayerSetAnimId(sub_8060AE0(direction), 2); +} + +void sub_8059600(u8 a) +{ + PlayerSetAnimId(sub_8060B0C(a), 2); +} + +void sub_8059618(u8 a) +{ + PlayerSetAnimId(sub_8060B38(a), 2); +} + +void sub_8059630(u8 a) +{ + PlayerSetAnimId(sub_8060B64(a), 2); +} + +static void PlayCollisionSoundIfNotFacingWarp(u8 a) +{ + s16 x, y; + u8 unk = gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1E; + + if (!gUnknown_0830FC34[a - 1](unk)) + { + if (a == 2) + { + PlayerGetDestCoords(&x, &y); + MoveCoords(2, &x, &y); + if (MetatileBehavior_IsWarpDoor(MapGridGetMetatileBehaviorAt(x, y))) + return; + } + PlaySE(SE_WALL_HIT); + } +} + +void GetXYCoordsOneStepInFrontOfPlayer(s16 *x, s16 *y) +{ + *x = gMapObjects[gPlayerAvatar.mapObjectId].coords2.x; + *y = gMapObjects[gPlayerAvatar.mapObjectId].coords2.y; + MoveCoords(player_get_direction_lower_nybble(), x, y); +} + +void PlayerGetDestCoords(s16 *x, s16 *y) +{ + *x = gMapObjects[gPlayerAvatar.mapObjectId].coords2.x; + *y = gMapObjects[gPlayerAvatar.mapObjectId].coords2.y; +} + +u8 player_get_direction_lower_nybble(void) +{ + return gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_18; +} + +u8 player_get_direction_upper_nybble(void) +{ + return gMapObjects[gPlayerAvatar.mapObjectId].placeholder18; +} + +u8 PlayerGetZCoord(void) +{ + return gMapObjects[gPlayerAvatar.mapObjectId].elevation; +} + +void unref_sub_8059790(s16 a, s16 b) +{ + sub_805C058(&gMapObjects[gPlayerAvatar.mapObjectId], a, b); +} + +u8 TestPlayerAvatarFlags(u8 a) +{ + return gPlayerAvatar.flags & a; +} + +u8 sub_80597D0(void) +{ + return gPlayerAvatar.flags; +} + +u8 GetPlayerAvatarObjectId(void) +{ + return gPlayerAvatar.spriteId; +} + +void sub_80597E8(void) +{ + ForcedMovement_None(); +} + +void sub_80597F4(void) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + npc_clear_strange_bits(playerMapObj); + FieldObjectSetDirection(playerMapObj, playerMapObj->mapobj_unk_18); + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) + { + sub_80E6084(); + sub_80E6010(0); + } +} + +u8 GetRivalAvatarGraphicsIdByStateIdAndGender(u8 state, u8 gender) +{ + return sRivalAvatarGfxIds[state][gender]; +} + +static u8 GetPlayerAvatarGraphicsIdByStateIdAndGender(u8 state, u8 gender) +{ + return sPlayerAvatarGfxIds[state][gender]; +} + +u8 GetPlayerAvatarGraphicsIdByStateId(u8 state) +{ + return GetPlayerAvatarGraphicsIdByStateIdAndGender(state, gPlayerAvatar.gender); +} + +u8 unref_GetRivalAvatarGenderByGraphcsId(u8 gfxId) +{ + switch (gfxId) + { + case MAP_OBJ_GFX_RIVAL_MAY_NORMAL: + case MAP_OBJ_GFX_RIVAL_MAY_MACH_BIKE: + case MAP_OBJ_GFX_RIVAL_MAY_ACRO_BIKE: + case MAP_OBJ_GFX_RIVAL_MAY_SURFING: + case MAP_OBJ_GFX_RIVAL_MAY_FIELD_MOVE: + case MAP_OBJ_GFX_MAY_UNDERWATER: + case MAP_OBJ_GFX_MAY_FISHING: + case MAP_OBJ_GFX_MAY_WATERING: + return FEMALE; + default: + return MALE; + } +} + +u8 GetPlayerAvatarGenderByGraphicsId(u8 gfxId) +{ + switch (gfxId) + { + case MAP_OBJ_GFX_MAY_NORMAL: + case MAP_OBJ_GFX_MAY_MACH_BIKE: + case MAP_OBJ_GFX_MAY_ACRO_BIKE: + case MAP_OBJ_GFX_MAY_SURFING: + case MAP_OBJ_GFX_MAY_FIELD_MOVE: + case MAP_OBJ_GFX_MAY_UNDERWATER: + case MAP_OBJ_GFX_MAY_FISHING: + case MAP_OBJ_GFX_MAY_WATERING: + return FEMALE; + default: + return MALE; + } +} + +bool8 PartyHasMonWithSurf(void) +{ + u8 i; + + if (!TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + { + for (i = 0; i < 6; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) == 0) + break; + if (pokemon_has_move(&gPlayerParty[i], 0x39)) + return TRUE; + } + } + return FALSE; +} + +bool8 IsPlayerSurfingNorth(void) +{ + if (player_get_direction_upper_nybble() == DIR_NORTH && TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + return TRUE; + else + return FALSE; +} + +bool8 IsPlayerFacingSurfableFishableWater(void) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + s16 x = playerMapObj->coords2.x; + s16 y = playerMapObj->coords2.y; + + MoveCoords(playerMapObj->mapobj_unk_18, &x, &y); + if (npc_block_way(playerMapObj, x, y, playerMapObj->mapobj_unk_18) == 3 && PlayerGetZCoord() == 3 + && MetatileBehavior_IsSurfableFishableWater(MapGridGetMetatileBehaviorAt(x, y))) + return TRUE; + else + return FALSE; +} + +void ClearPlayerAvatarInfo(void) +{ + //TODO: 0x24 should be the size of gPlayerAvatar + memset(&gPlayerAvatar, 0, sizeof(struct PlayerAvatar)); +} + +void SetPlayerAvatarStateMask(u8 a) +{ + gPlayerAvatar.flags &= 0xE0; + gPlayerAvatar.flags |= a; +} + +static u8 GetPlayerAvatarStateTransitionByGraphicsId(u8 a, u8 gender) +{ + u8 i; + + for (i = 0; i < 5; i++) + { + if (gUnknown_0830FC64[gender][i][0] == a) + return gUnknown_0830FC64[gender][i][1]; + } + return 1; +} + +u8 GetPlayerAvatarGraphicsIdByCurrentState(void) +{ + u8 i; + u8 r5 = gPlayerAvatar.flags; + + for (i = 0; i < 5; i++) + { + if (gUnknown_0830FC64[gPlayerAvatar.gender][i][1] & r5) + return gUnknown_0830FC64[gPlayerAvatar.gender][i][0]; + } + return 0; +} + +void SetPlayerAvatarExtraStateTransition(u8 a, u8 b) +{ + u8 unk = GetPlayerAvatarStateTransitionByGraphicsId(a, gPlayerAvatar.gender); + + gPlayerAvatar.bike |= unk | b; + DoPlayerAvatarTransition(); +} + +void InitPlayerAvatar(s16 x, s16 y, u8 direction, u8 gender) +{ + struct MapObjectTemplate playerMapObjTemplate; + u8 mapObjectId; + struct MapObject *mapObject; + + playerMapObjTemplate.localId = 0xFF; + playerMapObjTemplate.graphicsId = GetPlayerAvatarGraphicsIdByStateIdAndGender(0, gender); + playerMapObjTemplate.x = x - 7; + playerMapObjTemplate.y = y - 7; + playerMapObjTemplate.elevation = 0; + playerMapObjTemplate.movementType = 11; + playerMapObjTemplate.unkA_0 = 0; + playerMapObjTemplate.unkA_4 = 0; + playerMapObjTemplate.unkC = 0; + playerMapObjTemplate.unkE = 0; + playerMapObjTemplate.script = NULL; + playerMapObjTemplate.flagId = 0; + mapObjectId = SpawnSpecialFieldObject(&playerMapObjTemplate); + mapObject = &gMapObjects[mapObjectId]; + mapObject->mapobj_bit_16 = 1; + mapObject->mapobj_unk_1B = sub_8126B54(); + FieldObjectTurn(mapObject, direction); + ClearPlayerAvatarInfo(); + gPlayerAvatar.running2 = 0; + gPlayerAvatar.running1 = 0; + gPlayerAvatar.mapObjectId = mapObjectId; + gPlayerAvatar.spriteId = mapObject->spriteId; + gPlayerAvatar.gender = gender; + SetPlayerAvatarStateMask(0x21); +} + +void sub_8059B88(u8 a) +{ + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = a; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + gSprites[gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1A].invisible = a; +} + +void sub_8059BF4(void) +{ + sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByStateId(5)); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], 0); +} + +void sub_8059C3C(u8 a) +{ + sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByStateId(6)); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FDE8(a)); +} + +void sub_8059C94(u8 a) +{ + sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByStateId(2)); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FD98(a)); + SeekSpriteAnim(&gSprites[gPlayerAvatar.spriteId], 1); +} + +void sub_8059D08(u8 a) +{ + sub_805B980(&gMapObjects[gPlayerAvatar.mapObjectId], GetPlayerAvatarGraphicsIdByStateId(7)); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], FieldObjectDirectionToImageAnimId(a)); +} + +static void sub_8059D60(struct MapObject *a) +{ + s16 x; + s16 y; + u8 r6; + u8 r8 = a->mapobj_unk_1E; + + for (x = 0, r6 = 1; x < 4; x++, r6++) + { + if (gUnknown_0830FC78[x](r8) && r6 == a->placeholder18) + { + x = a->coords2.x; + y = a->coords2.y; + MoveCoords(r6, &x, &y); + sub_8126BC4(a->mapobj_unk_1B, r6, x, y); + return; + } + } + objid_set_invisible(a->mapobj_unk_1B); +} + +/* Strength */ + +static void sub_8059E2C(u8 taskId); + +static void StartStrengthAnim(u8 a, u8 b) +{ + u8 taskId = CreateTask(sub_8059E2C, 0xFF); + + gTasks[taskId].data[1] = a; + gTasks[taskId].data[2] = b; + sub_8059E2C(taskId); +} + +static void sub_8059E2C(u8 taskId) +{ + while (gUnknown_0830FC88[gTasks[taskId].data[0]](&gTasks[taskId], + &gMapObjects[gPlayerAvatar.mapObjectId], + &gMapObjects[gTasks[taskId].data[1]])) + ; +} + +u8 sub_8059E84(struct Task *task, struct MapObject *b, struct MapObject *c) +{ + ScriptContext2_Enable(); + gPlayerAvatar.unk6 = 1; + task->data[0]++; + return 0; +} + +u8 sub_8059EA4(struct Task *task, struct MapObject *b, struct MapObject *c) +{ + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(b) + && !FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(c)) + { + FieldObjectClearAnimIfSpecialAnimFinished(b); + FieldObjectClearAnimIfSpecialAnimFinished(c); + FieldObjectSetSpecialAnim(b, GetStepInPlaceDelay16AnimId((u8)task->data[2])); + FieldObjectSetSpecialAnim(c, GetSimpleGoAnimId((u8)task->data[2])); + gFieldEffectArguments[0] = c->coords2.x; + gFieldEffectArguments[1] = c->coords2.y; + gFieldEffectArguments[2] = c->elevation; + gFieldEffectArguments[3] = gSprites[c->spriteId].oam.priority; + FieldEffectStart(FLDEFF_DUST); + PlaySE(SE_W070); + task->data[0]++; + } + return 0; +} + +u8 sub_8059F40(struct Task *task, struct MapObject *b, struct MapObject *c) +{ + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(b) + && FieldObjectCheckIfSpecialAnimFinishedOrInactive(c)) + { + FieldObjectClearAnimIfSpecialAnimFinished(b); + FieldObjectClearAnimIfSpecialAnimFinished(c); + gPlayerAvatar.unk6 = 0; + ScriptContext2_Disable(); + DestroyTask(FindTaskIdByFunc(sub_8059E2C)); + } + return 0; +} + +/* Some field effect */ + +static void sub_8059FB4(u8 taskId); + +static void sub_8059F94(void) +{ + u8 taskId = CreateTask(sub_8059FB4, 0xFF); + + sub_8059FB4(taskId); +} + +static void sub_8059FB4(u8 taskId) +{ + while (gUnknown_0830FC94[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId])) + ; +} + +u8 sub_805A000(struct Task *task, struct MapObject *mapObject) +{ + gPlayerAvatar.unk6 = 1; + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + PlaySE(SE_DANSA); + FieldObjectSetSpecialAnim(mapObject, sub_806084C(mapObject->mapobj_unk_18)); + task->data[1]++; + if (task->data[1] > 1) + { + gPlayerAvatar.unk6 = 0; + gPlayerAvatar.bike |= 0x20; + DestroyTask(FindTaskIdByFunc(sub_8059FB4)); + } + } + return 0; +} + +/* Some field effect */ + +static void sub_805A08C(u8 taskId); + +static void sub_805A06C(void) +{ + u8 taskId = CreateTask(sub_805A08C, 0xFF); + + sub_805A08C(taskId); +} + +static void sub_805A08C(u8 taskId) +{ + while (gUnknown_0830FC98[gTasks[taskId].data[0]](&gTasks[taskId], &gMapObjects[gPlayerAvatar.mapObjectId])) + ; +} + +u8 sub_805A0D8(struct Task *task, struct MapObject *mapObject) +{ + task->data[0]++; + task->data[1] = mapObject->placeholder18; + gPlayerAvatar.unk6 = 1; + ScriptContext2_Enable(); + PlaySE(SE_TK_WARPIN); + return 1; +} + +u8 sub_805A100(struct Task *task, struct MapObject *mapObject) +{ + u8 directions[] = {DIR_WEST, DIR_EAST, DIR_NORTH, DIR_SOUTH}; + + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + u8 direction; + + FieldObjectSetSpecialAnim(mapObject, GetFaceDirectionAnimId(direction = directions[mapObject->placeholder18 - 1])); + if (direction == (u8)task->data[1]) + task->data[2]++; + task->data[0]++; + if (task->data[2] > 3 && direction == GetOppositeDirection(task->data[1])) + task->data[0]++; + } + return 0; +} + +u8 sub_805A178(struct Task *task, struct MapObject *mapObject) +{ + const u8 arr[] = {16, 16, 17, 18, 19}; + + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + FieldObjectSetSpecialAnim(mapObject, arr[task->data[2]]); + task->data[0] = 1; + } + return 0; +} + +u8 sub_805A1B8(struct Task *task, struct MapObject *mapObject) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(mapObject)) + { + FieldObjectSetSpecialAnim(mapObject, GetSimpleGoAnimId(GetOppositeDirection(task->data[1]))); + ScriptContext2_Disable(); + gPlayerAvatar.unk6 = 0; + DestroyTask(FindTaskIdByFunc(sub_805A08C)); + } + return 0; +} + +/* Some Field effect */ + +static void taskFF_0805D1D4(u8 taskId); +static void sub_805A2D0(u8 taskId); + +void sub_805A20C(u8 a) +{ + u8 taskId; + + ScriptContext2_Enable(); + Overworld_ClearSavedMusic(); + Overworld_ChangeMusicToDefault(); + gPlayerAvatar.flags &= ~PLAYER_AVATAR_FLAG_SURFING; + gPlayerAvatar.flags |= PLAYER_AVATAR_FLAG_ON_FOOT; + gPlayerAvatar.unk6 = 1; + taskId = CreateTask(taskFF_0805D1D4, 0xFF); + gTasks[taskId].data[0] = a; + taskFF_0805D1D4(taskId); +} + +static void taskFF_0805D1D4(u8 taskId) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(playerMapObj)) + { + if (!FieldObjectClearAnimIfSpecialAnimFinished(playerMapObj)) + return; + } + sub_8127ED0(playerMapObj->mapobj_unk_1A, 2); + FieldObjectSetSpecialAnim(playerMapObj, sub_80608D0((u8)gTasks[taskId].data[0])); + gTasks[taskId].func = sub_805A2D0; +} + +static void sub_805A2D0(u8 taskId) +{ + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (FieldObjectClearAnimIfSpecialAnimFinished(playerMapObj)) + { + sub_805B980(playerMapObj, GetPlayerAvatarGraphicsIdByStateId(0)); + FieldObjectSetSpecialAnim(playerMapObj, GetFaceDirectionAnimId(playerMapObj->mapobj_unk_18)); + gPlayerAvatar.unk6 = 0; + ScriptContext2_Disable(); + DestroySprite(&gSprites[playerMapObj->mapobj_unk_1A]); + DestroyTask(taskId); + } +} + +/* Fishing */ + +static u8 (*const sFishingStateFuncs[])(struct Task *) = +{ + Fishing1, + Fishing2, + Fishing3, + Fishing4, + Fishing5, + Fishing6, + Fishing7, + Fishing8, + Fishing9, + Fishing10, + Fishing11, + Fishing12, + Fishing13, + Fishing14, + Fishing15, + Fishing16, +}; + +static void Task_Fishing(u8 taskId); +static void sub_805A954(void); + +#define tStep data[0] +#define tFrameCounter data[1] +#define tNumDots data[2] +#define tDotsRequired data[3] +#define tRoundsPlayed data[12] +#define tMinRoundsRequired data[13] +#define tPlayerGfxId data[14] +#define tFishingRod data[15] + +#define FISHING_START_ROUND 3 +#define FISHING_GOT_BITE 6 +#define FISHING_ON_HOOK 9 +#define FISHING_NO_BITE 11 +#define FISHING_GOT_AWAY 12 +#define FISHING_SHOW_RESULT 13 + +void StartFishing(u8 rod) +{ + u8 taskId = CreateTask(Task_Fishing, 0xFF); + + gTasks[taskId].tFishingRod = rod; + Task_Fishing(taskId); +} + +static void Task_Fishing(u8 taskId) +{ + while (sFishingStateFuncs[gTasks[taskId].tStep](&gTasks[taskId])) + ; +} + +u8 Fishing1(struct Task *task) +{ + ScriptContext2_Enable(); + gPlayerAvatar.unk6 = 1; + task->tStep++; + return 0; +} + +u8 Fishing2(struct Task *task) +{ + struct MapObject *playerMapObj; + const s16 arr1[] = {1, 1, 1}; + const s16 arr2[] = {1, 3, 6}; + + task->tRoundsPlayed = 0; + task->tMinRoundsRequired = arr1[task->tFishingRod] + (Random() % arr2[task->tFishingRod]); + task->tPlayerGfxId = gMapObjects[gPlayerAvatar.mapObjectId].graphicsId; + playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + FieldObjectClearAnimIfSpecialAnimActive(playerMapObj); + playerMapObj->mapobj_bit_11 = 1; + sub_8059C3C(playerMapObj->mapobj_unk_18); + task->tStep++; + return 0; +} + +u8 Fishing3(struct Task *task) +{ + sub_805A954(); + + // Wait one second before starting dot game + task->tFrameCounter++; + if (task->tFrameCounter >= 60) + task->tStep++; + return 0; +} + +u8 Fishing4(struct Task *task) +{ + u32 randVal; + + MenuDisplayMessageBox(); + task->tStep++; + task->tFrameCounter = 0; + task->tNumDots = 0; + randVal = Random(); + randVal %= 10; + task->tDotsRequired = randVal + 1; + if (task->tRoundsPlayed == 0) + task->tDotsRequired = randVal + 4; + if (task->tDotsRequired >= 10) + task->tDotsRequired = 10; + return 1; +} + +// Play a round of the dot game +u8 Fishing5(struct Task *task) +{ + const u8 dot[] = _("·"); + + sub_805A954(); + task->tFrameCounter++; + if (gMain.newKeys & A_BUTTON) + { + task->tStep = FISHING_NO_BITE; + if (task->tRoundsPlayed != 0) + task->tStep = FISHING_GOT_AWAY; + return 1; + } + else + { + if (task->tFrameCounter >= 20) + { + task->tFrameCounter = 0; + if (task->tNumDots >= task->tDotsRequired) + { + task->tStep++; + if (task->tRoundsPlayed != 0) + task->tStep++; + task->tRoundsPlayed++; + } + else + { + MenuPrint(dot, task->tNumDots + 4, 15); + task->tNumDots++; + } + } + return 0; + } +} + +// Determine if fish bites +u8 Fishing6(struct Task *task) +{ + sub_805A954(); + task->tStep++; + if (!DoesCurrentMapHaveFishingMons() || (Random() & 1)) + task->tStep = FISHING_NO_BITE; + else + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FE08(player_get_direction_lower_nybble())); + return 1; +} + +// Oh! A Bite! +u8 Fishing7(struct Task *task) +{ + sub_805A954(); + MenuPrint(gOtherText_OhABite, 4, 17); + task->tStep++; + task->tFrameCounter = 0; + return 0; +} + +// We have a bite. Now, wait for the player to press A, or the timer to expire. +u8 Fishing8(struct Task *task) +{ + const s16 reelTimeouts[3] = {36, 33, 30}; + + sub_805A954(); + task->tFrameCounter++; + if (task->tFrameCounter >= reelTimeouts[task->tFishingRod]) + task->tStep = FISHING_GOT_AWAY; + else if (gMain.newKeys & A_BUTTON) + task->tStep++; + return 0; +} + +// Determine if we're going to play the dot game again +u8 Fishing9(struct Task *task) +{ + const s16 arr[][2] = + { + {0, 0}, + {40, 10}, + {70, 30} + }; + + sub_805A954(); + task->tStep++; + if (task->tRoundsPlayed < task->tMinRoundsRequired) + { + task->tStep = FISHING_START_ROUND; + } + else if (task->tRoundsPlayed < 2) + { + // probability of having to play another round + s16 probability = Random() % 100; + + if (arr[task->tFishingRod][task->tRoundsPlayed] > probability) + task->tStep = FISHING_START_ROUND; + } + return 0; +} + +u8 Fishing10(struct Task *task) +{ + sub_805A954(); + MenuPrintMessageDefaultCoords(gOtherText_PokeOnHook); + MenuDisplayMessageBox(); + task->tStep++; + task->tFrameCounter = 0; + return 0; +} + +u8 Fishing11(struct Task *task) +{ + if (task->tFrameCounter == 0) + sub_805A954(); + + if (task->tFrameCounter == 0) + { + if (MenuUpdateWindowText()) + { + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + sub_805B980(playerMapObj, task->tPlayerGfxId); + FieldObjectTurn(playerMapObj, playerMapObj->placeholder18); + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) + sub_8127F28(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1A, 0, 0); + gSprites[gPlayerAvatar.spriteId].pos2.x = 0; + gSprites[gPlayerAvatar.spriteId].pos2.y = 0; + MenuZeroFillScreen(); + task->tFrameCounter++; + return 0; + } + } + + if (task->tFrameCounter != 0) + { + gPlayerAvatar.unk6 = 0; + ScriptContext2_Disable(); + FishingWildEncounter(task->tFishingRod); + sub_80BE97C(1); + DestroyTask(FindTaskIdByFunc(Task_Fishing)); + } + return 0; +} + +// Not even a nibble +u8 Fishing12(struct Task *task) +{ + sub_805A954(); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FDF8(player_get_direction_lower_nybble())); + MenuPrintMessageDefaultCoords(gOtherText_NotEvenANibble); + task->tStep = FISHING_SHOW_RESULT; + return 1; +} + +// It got away +u8 Fishing13(struct Task *task) +{ + sub_805A954(); + StartSpriteAnim(&gSprites[gPlayerAvatar.spriteId], sub_805FDF8(player_get_direction_lower_nybble())); + MenuPrintMessageDefaultCoords(gOtherText_ItGotAway); + task->tStep++; + return 1; +} + +// Display the message +u8 Fishing14(struct Task *task) +{ + sub_805A954(); + MenuDisplayMessageBox(); + task->tStep++; + return 0; +} + +u8 Fishing15(struct Task *task) +{ + sub_805A954(); + if (gSprites[gPlayerAvatar.spriteId].animEnded) + { + struct MapObject *playerMapObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + sub_805B980(playerMapObj, task->tPlayerGfxId); + FieldObjectTurn(playerMapObj, playerMapObj->placeholder18); + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) + sub_8127F28(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1A, 0, 0); + gSprites[gPlayerAvatar.spriteId].pos2.x = 0; + gSprites[gPlayerAvatar.spriteId].pos2.y = 0; + task->tStep++; + } + return 0; +} + +u8 Fishing16(struct Task *task) +{ + if (MenuUpdateWindowText()) + { + gPlayerAvatar.unk6 = 0; + ScriptContext2_Disable(); + UnfreezeMapObjects(); + MenuZeroFillScreen(); + sub_80BE97C(0); + DestroyTask(FindTaskIdByFunc(Task_Fishing)); + } + return 0; +} + +#undef tStep +#undef tFrameCounter +#undef tFishingRod + +static void sub_805A954(void) +{ + struct Sprite *playerSprite = &gSprites[gPlayerAvatar.spriteId]; + u8 animCmdIndex; + u8 animType; + + AnimateSprite(playerSprite); + playerSprite->pos2.x = 0; + playerSprite->pos2.y = 0; + animCmdIndex = playerSprite->animCmdIndex; + if (playerSprite->anims[playerSprite->animNum][animCmdIndex].type == -1) + { + animCmdIndex--; + } + else + { + playerSprite->animDelayCounter++; + if (playerSprite->anims[playerSprite->animNum][animCmdIndex].type == -1) + animCmdIndex--; + } + animType = playerSprite->anims[playerSprite->animNum][animCmdIndex].type; + if (animType == 1 || animType == 2 || animType == 3) + { + playerSprite->pos2.x = 8; + if (player_get_direction_lower_nybble() == 3) + playerSprite->pos2.x = -8; + } + if (animType == 5) + playerSprite->pos2.y = -8; + if (animType == 10 || animType == 11) + playerSprite->pos2.y = 8; + if (gPlayerAvatar.flags & PLAYER_AVATAR_FLAG_SURFING) + sub_8127F28(gMapObjects[gPlayerAvatar.mapObjectId].mapobj_unk_1A, 1, playerSprite->pos2.y); +} diff --git a/src/field/field_poison.c b/src/field/field_poison.c new file mode 100644 index 000000000..1244b9c62 --- /dev/null +++ b/src/field/field_poison.c @@ -0,0 +1,143 @@ +#include "global.h" +#include "field_poison.h" +#include "field_message_box.h" +#include "fldeff_80C5CD4.h" +#include "pokemon.h" +#include "pokemon_summary_screen.h" +#include "script.h" +#include "string_util.h" +#include "task.h" +#include "text.h" + +extern u16 gScriptResult; +extern u8 fieldPoisonText_PokemonFainted[]; + +bool32 CheckMonIsValid(struct Pokemon *pkmn) +{ + // UB: Too few arguments for function 'GetMonData' + u16 species2 = GetMonData(pkmn, MON_DATA_SPECIES2); + + if (species2 == 0 || species2 == 0x19C) + return FALSE; + else + return TRUE; +} + +bool32 AllMonsFainted(void) +{ + struct Pokemon *pkmn = &gPlayerParty[0]; + int i; + + for (i = 0; i < 6; i++, pkmn++) + { + // UB: Too few arguments for function 'GetMonData' + if (CheckMonIsValid(pkmn) && GetMonData(pkmn, MON_DATA_HP) != 0) + return FALSE; + } + return TRUE; +} + +void MonFaintFromPoisonOnField(u8 partyMember) +{ + struct Pokemon *pkmn = &gPlayerParty[partyMember]; + u32 val = 0; + + AdjustFriendship(pkmn, 7); + SetMonData(pkmn, MON_DATA_STATUS, (u8*)&val); + GetMonData(pkmn, MON_DATA_NICKNAME, gStringVar1); + StringGetEnd10(gStringVar1); +} + +bool32 CheckMonFaintedFromPoison(u8 partyMember) +{ + struct Pokemon *pkmn = &gPlayerParty[partyMember]; + + // UB: Too few arguments for function 'GetMonData' + if (CheckMonIsValid(pkmn) && GetMonData(pkmn, MON_DATA_HP) == 0 + && pokemon_ailments_get_primary(GetMonData(pkmn, MON_DATA_STATUS)) == 1) + return TRUE; + else + return FALSE; +} + +//Task data +enum +{ + TD_STATE, + TD_PARTY_MEMBER, +}; + +void Task_WhiteOut(u8 taskId) +{ + s16 *taskData = gTasks[taskId].data; + + switch (taskData[TD_STATE]) + { + case 0: //Check if Pokemon have fainted due to poison + while (taskData[TD_PARTY_MEMBER] < 6) + { + if (CheckMonFaintedFromPoison(taskData[TD_PARTY_MEMBER])) + { + MonFaintFromPoisonOnField(taskData[TD_PARTY_MEMBER]); + ShowFieldMessage(fieldPoisonText_PokemonFainted); + taskData[TD_STATE]++; + return; + } + taskData[TD_PARTY_MEMBER]++; + } + taskData[TD_STATE] = 2; + break; + case 1: //Wait for message box to disappear + if (IsFieldMessageBoxHidden()) + taskData[TD_STATE]--; //Check next party member + break; + case 2: //Done checking Pokemon + if (AllMonsFainted()) + gScriptResult = 1; + else + gScriptResult = 0; + EnableBothScriptContexts(); + DestroyTask(taskId); + break; + } +} + +void ExecuteWhiteOut(void) +{ + CreateTask(Task_WhiteOut, 0x50); + ScriptContext1_Stop(); +} + +s32 DoPoisonFieldEffect(void) +{ + struct Pokemon *pkmn = &gPlayerParty[0]; + u32 numPoisoned = 0; + u32 numFainting = 0; + int i; + + for (i = 0; i < 6; i++) + { + u32 hp; + + // UB: Too few arguments for function 'GetMonData' + if (GetMonData(pkmn, MON_DATA_SANITY_BIT2) != 0 + && pokemon_ailments_get_primary(GetMonData(pkmn, MON_DATA_STATUS)) == 1) + { + hp = GetMonData(pkmn, MON_DATA_HP); + if (hp != 0) + hp--; + if (hp == 0) + numFainting++; //Pokemon will now faint due to poison + SetMonData(pkmn, MON_DATA_HP, (u8 *)&hp); + numPoisoned++; + } + pkmn++; + } + if (numFainting != 0 || numPoisoned != 0) + DoFieldPoisonEffect(); + if (numFainting != 0) + return 2; + if (numPoisoned != 0) + return 1; + return 0; +} diff --git a/src/field/field_region_map.c b/src/field/field_region_map.c new file mode 100644 index 000000000..7cb22e5df --- /dev/null +++ b/src/field/field_region_map.c @@ -0,0 +1,125 @@ +#include "global.h" +#include "field_region_map.h" +#include "main.h" +#include "menu.h" +#include "palette.h" +#include "region_map.h" +#include "sprite.h" +#include "strings2.h" +#include "text.h" + +struct RegionMapStruct +{ + u8 str[0x16]; + u8 unk16; + u8 filler[0x869]; +}; + +struct UnkStruct +{ + MainCallback callback; + u8 filler[4]; + // This should be RegionMap, but I can't do that because it overlaps unk888. + struct RegionMapStruct unk8; + u16 unk888; +}; + +extern u8 ewram[]; +#define unk_2000000 (*(struct UnkStruct *)(ewram)) + +void FieldInitRegionMap(MainCallback callback) +{ + SetVBlankCallback(NULL); + unk_2000000.unk888 = 0; + unk_2000000.callback = callback; + SetMainCallback2(CB2_FieldInitRegionMap); +} + +void CB2_FieldInitRegionMap(void) +{ + REG_DISPCNT = 0; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG2HOFS = 0; + REG_BG2VOFS = 0; + REG_BG3HOFS = 0; + REG_BG3VOFS = 0; + ResetSpriteData(); + FreeAllSpritePalettes(); + // TODO: remove this cast + InitRegionMap((void *)&unk_2000000.unk8, 0); + CreateRegionMapPlayerIcon(0, 0); + CreateRegionMapCursor(1, 1); + SetUpWindowConfig(&gWindowConfig_81E709C); + InitMenuWindow(&gWindowConfig_81E709C); + MenuZeroFillScreen(); + REG_BG0CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(31) | BGCNT_16COLOR | BGCNT_TXT256x256; + MenuDrawTextWindow(21, 0, 29, 3); + sub_8072BD8(gOtherText_Hoenn, 0x16, 1, 0x38); + MenuDrawTextWindow(16, 16, 29, 19); + sub_813F0C8(); + SetMainCallback2(CB2_FieldRegionMap); + SetVBlankCallback(VBlankCB_FieldRegionMap); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); +} + +void VBlankCB_FieldRegionMap(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void CB2_FieldRegionMap(void) +{ + sub_813EFDC(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +void sub_813EFDC(void) +{ + switch (unk_2000000.unk888) + { + case 0: + REG_DISPCNT = DISPCNT_MODE_1 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON; + unk_2000000.unk888++; + break; + case 1: + if (!gPaletteFade.active) + unk_2000000.unk888++; + break; + case 2: + switch (sub_80FAB60()) + { + case 3: + sub_813F0C8(); + break; + case 4: + case 5: + unk_2000000.unk888++; + } + break; + case 3: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0); + unk_2000000.unk888++; + break; + case 4: + if (!gPaletteFade.active) + { + FreeRegionMapIconResources(); + SetMainCallback2(unk_2000000.callback); + } + break; + } +} + +void sub_813F0C8(void) +{ + MenuFillWindowRectWithBlankTile(17, 17, 28, 18); + if (unk_2000000.unk8.unk16) + MenuPrint(unk_2000000.unk8.str, 17, 17); +} diff --git a/src/field/field_screen_effect.c b/src/field/field_screen_effect.c new file mode 100644 index 000000000..0c76d254d --- /dev/null +++ b/src/field/field_screen_effect.c @@ -0,0 +1,341 @@ +#include "global.h" +#include "event_data.h" +#include "field_camera.h" +#include "menu.h" +#include "palette.h" +#include "overworld.h" +#include "script.h" +#include "task.h" +#include "text.h" +#include "unknown_task.h" + +struct UnknownStruct1 +{ + u8 filler0[0x14]; + u8 unk14; + u8 filler15[0xB]; +}; +extern struct UnknownStruct1 gUnknown_03004DC0; + +extern u16 gUnknown_03004DE0[][0x3C0]; + +const static u16 gUnknown_0839ACDC[] = { 0xC8, 0x48, 0x38, 0x28, 0x18, 0x0 }; + +const s32 gMaxFlashLevel = 4; + +const static struct UnknownTaskStruct gUnknown_0839ACEC = +{ + (void *)REG_ADDR_WIN0H, + ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1, + 1 +}; + +static void sub_808136C(u16 *dest, u32 a2, s32 a3, s32 a4) +{ + if (a2 <= 0xA0) + { + if (a3 < 0) + a3 = 0; + if (a3 > 255) + a3 = 255; + if (a4 < 0) + a4 = 0; + if (a4 > 255) + a4 = 255; + dest[a2] = (a3 << 8) | a4; + } +} + +static void sub_8081398(u16 *dest, s32 a2, s32 a3, s32 a4) +{ + s32 v1 = a4; + s32 v2 = a4; + s32 v3 = 0; + while (v1 >= v3) + { + sub_808136C(dest, a3 - v3, a2 - v1, a2 + v1); + sub_808136C(dest, a3 + v3, a2 - v1, a2 + v1); + sub_808136C(dest, a3 - v1, a2 - v3, a2 + v3); + sub_808136C(dest, a3 + v1, a2 - v3, a2 + v3); + v2 -= (v3 * 2) - 1; + v3++; + if (v2 < 0) + { + v2 += 2 * (v1 - 1); + v1--; + } + } +} + +static void sub_8081424(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (data[0]) + { + case 0: + sub_8081398(&gUnknown_03004DE0[gUnknown_03004DC0.unk14][0], data[1], data[2], data[3]); + data[0] = 1; + break; + case 1: + sub_8081398(&gUnknown_03004DE0[gUnknown_03004DC0.unk14][0], data[1], data[2], data[3]); + data[0] = 0; + data[3] += data[5]; + if (data[3] > data[4]) + { + if (data[6] == 1) + { + remove_some_task(); + data[0] = 2; + } + else + { + DestroyTask(taskId); + } + } + break; + case 2: + dp12_8087EA4(); + DestroyTask(taskId); + break; + } +} + +static void sub_80814E8(u8 taskId) +{ + if (!FuncIsActiveTask(sub_8081424)) + { + EnableBothScriptContexts(); + DestroyTask(taskId); + } +} + +static void sub_8081510(void) +{ + if (!FuncIsActiveTask(sub_80814E8)) + CreateTask(sub_80814E8, 80); +} + +static u8 sub_8081534(s32 a1, s32 a2, s32 a3, s32 a4, s32 a5, u8 a6) +{ + u8 taskId = CreateTask(sub_8081424, 80); + s16 *data = gTasks[taskId].data; + + data[3] = a3; + data[4] = a4; + data[1] = a1; + data[2] = a2; + data[6] = a5; + + if (a3 < a4) + data[5] = a6; + else + data[5] = -a6; + + return taskId; +} + +void sub_8081594(u8 a1) +{ + u8 flashLevel = Overworld_GetFlashLevel(); + u8 value = 0; + if (!a1) + value = 1; + sub_8081534(120, 80, gUnknown_0839ACDC[flashLevel], gUnknown_0839ACDC[a1], value, 1); + sub_8081510(); + ScriptContext2_Enable(); +} + +void sub_80815E0(u8 a1) +{ + if (a1) + { + sub_8081398(&gUnknown_03004DE0[0][0], 120, 80, gUnknown_0839ACDC[a1]); + CpuFastSet(&gUnknown_03004DE0[0], &gUnknown_03004DE0[1], 480); + } +} + +static void sub_808161C(u8 a1) +{ + int i; + u16 color[1]; + + if (!a1) + color[0] = 0x1F; + else + color[0] = 0x7C00; + + for (i = 0; i < 16; i++) + { + LoadPalette(color, 0xF0 + i, 2); + } +} + +static bool8 sub_8081658(u16 a1) +{ + u8 lo = REG_BLDALPHA & 0xFF; + u8 hi = REG_BLDALPHA >> 8; + + if (a1) + { + if (lo) + { + lo--; + } + } + else + { + if (hi < 0x10) + { + hi++; + } + } + + REG_BLDALPHA = (hi << 8) | lo; + + if (lo == 0 && hi == 0x10) + { + return TRUE; + } + + return FALSE; +} + +static void sub_80816A8(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (data[0]) + { + case 0: + data[6] = REG_DISPCNT; + data[7] = REG_BLDCNT; + data[8] = REG_BLDALPHA; + data[9] = REG_WININ; + data[10] = REG_WINOUT; + REG_DISPCNT &= 0xBFFF; + REG_BLDCNT |= gUnknown_081E29E8[0]; + REG_BLDALPHA = 1804; + REG_WININ = 63; + REG_WINOUT = 30; + sub_8081398(&gUnknown_03004DE0[0][0], data[2], data[3], 1); + CpuFastSet(&gUnknown_03004DE0[0], &gUnknown_03004DE0[1], 480); + //sub_80895F8(gUnknown_0839ACEC[0], gUnknown_0839ACEC[1], gUnknown_0839ACEC[2]); + sub_80895F8(gUnknown_0839ACEC); + data[0] = 1; + break; + case 1: + MenuFillWindowRectWithBlankTile(0, 0, 29, 19); + sub_808161C(data[1]); + sub_8081534(data[2], data[3], 1, 160, 1, 2); + data[0] = 2; + break; + case 2: + if (!FuncIsActiveTask(sub_8081424)) + { + EnableBothScriptContexts(); + data[0] = 3; + } + break; + case 3: + InstallCameraPanAheadCallback(); + SetCameraPanningCallback(NULL); + data[5] = 0; + data[4] = 4; + data[0] = 4; + break; + case 4: + data[4]--; + if (!data[4]) + { + s32 panning; + data[4] = 4; + data[5] ^= 1; + if (data[5]) + panning = 4; + else + panning = -4; + SetCameraPanning(0, panning); + } + break; + case 6: + InstallCameraPanAheadCallback(); + data[4] = 8; + data[0] = 7; + break; + case 7: + data[4]--; + if (!data[4]) + { + data[4] = 8; + data[5] ^= 1; + if (sub_8081658(data[5]) == TRUE) + data[0] = 5; + } + break; + case 5: + MenuZeroFillWindowRect(0, 0, 29, 19); + LoadFontDefaultPalette(&gWindowConfig_81E6CE4); + REG_WIN0H = 255; + REG_DISPCNT = data[6]; + REG_BLDCNT = data[7]; + REG_BLDALPHA = data[8]; + REG_WININ = data[9]; + REG_WINOUT = data[10]; + EnableBothScriptContexts(); + DestroyTask(taskId); + break; + } +} + +void sub_80818A4(void) +{ + u8 taskId = CreateTask(sub_80816A8, 80); + s16 *data = gTasks[taskId].data; + + if (gScriptResult == 0) + { + data[1] = 0; + data[2] = 104; + } + else if (gScriptResult == 1) + { + data[1] = 1; + data[2] = 104; + } + else if (gScriptResult == 2) + { + data[1] = 0; + data[2] = 120; + } + else + { + data[1] = 1; + data[2] = 120; + } + + data[3] = 80; +} + +void sub_80818FC(void) +{ + u8 taskId = FindTaskIdByFunc(sub_80816A8); + gTasks[taskId].data[0] = 6; +} + +static void task50_0807F0C8(u8); + +void sub_8081924(void) +{ + Overworld_FadeOutMapMusic(); + CreateTask(task50_0807F0C8, 80); +} + +static void task50_0807F0C8(u8 taskId) +{ + if (sub_8054034() == TRUE) + { + DestroyTask(taskId); + EnableBothScriptContexts(); + } +} diff --git a/src/field/field_special_scene.c b/src/field/field_special_scene.c new file mode 100644 index 000000000..d4b59c8a2 --- /dev/null +++ b/src/field/field_special_scene.c @@ -0,0 +1,349 @@ +#include "global.h" +#include "field_special_scene.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_fadetransition.h" +#include "field_map_obj.h" +#include "field_specials.h" +#include "fieldmap.h" +#include "main.h" +#include "palette.h" +#include "overworld.h" +#include "script.h" +#include "script_movement.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" + +#define SECONDS(value) ((signed) (60.0 * value + 0.5)) + +// porthole states +enum +{ + INIT_PORTHOLE, + IDLE_CHECK, + EXECUTE_MOVEMENT, + EXIT_PORTHOLE, +}; + +extern s8 gTruckCamera_HorizontalTable[]; + +extern u8 gUnknown_083D295F[]; +extern u8 gUnknown_083D2961[]; + +s32 GetTruckCameraBobbingY(int a1) +{ + if (!(a1 % 120)) + return -1; + else if ((a1 % 10) <= 4) + return 1; + + return 0; +} + +s32 GetTruckBoxMovement(int a1) // for the box movement? +{ + if (!((a1 + 120) % 180)) + return -1; + + return 0; +} + +void Task_Truck1(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + s16 cameraYpan; + s16 box1 = 0; + s16 box2 = 0; + s16 box3 = 0; + u8 mapNum, mapGroup; + register s16 zero asm("r4"); + + box1 = GetTruckBoxMovement(data[0] + 30) * 4; // top box. + sub_805BD90(1, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 3, box1 + 3); + box2 = GetTruckBoxMovement(data[0]) * 2; // bottom left box. + sub_805BD90(2, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 0, box2 - 3); + box3 = GetTruckBoxMovement(data[0]) * 4; // bottom right box. + mapNum = gSaveBlock1.location.mapNum; + mapGroup = gSaveBlock1.location.mapGroup; + zero = 0; + sub_805BD90(3, mapNum, mapGroup, -3, box3); + + if (++data[0] == SECONDS(500)) // this will never run + data[0] = zero; // reset the timer if it gets stuck. + + cameraYpan = GetTruckCameraBobbingY(data[0]); + SetCameraPanning(0, cameraYpan); +} + +void Task_Truck2(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + s16 cameraYpan; + s16 cameraXpan; + s16 box1; + s16 box2; + s16 box3; + + data[0]++; + data[2]++; + + if (data[0] > 5) + { + data[0] = 0; + data[1]++; + } + if ((u16)data[1] == 19) + { + DestroyTask(taskId); + } + else + { + if (gTruckCamera_HorizontalTable[data[1]] == 2) + gTasks[taskId].func = Task_Truck3; + + cameraXpan = gTruckCamera_HorizontalTable[data[1]]; + cameraYpan = GetTruckCameraBobbingY(data[2]); + SetCameraPanning(cameraXpan, cameraYpan); + box1 = GetTruckBoxMovement(data[2] + 30) * 4; + sub_805BD90(1, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 3 - cameraXpan, box1 + 3); + box2 = GetTruckBoxMovement(data[2]) * 2; + sub_805BD90(2, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -cameraXpan, box2 - 3); + box3 = GetTruckBoxMovement(data[2]) * 4; + sub_805BD90(3, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -3 - cameraXpan, box3); + } +} + +void Task_Truck3(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + s16 cameraXpan; + s16 cameraYpan; + + data[0]++; + + if (data[0] > 5) + { + data[0] = 0; + data[1]++; + } + + if ((u16)data[1] == 19) + { + DestroyTask(taskId); + } + else + { + cameraXpan = gTruckCamera_HorizontalTable[data[1]]; + cameraYpan = 0; + SetCameraPanning(cameraXpan, 0); + sub_805BD90(1, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 3 - cameraXpan, cameraYpan + 3); + sub_805BD90(2, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -cameraXpan, cameraYpan - 3); + sub_805BD90(3, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -3 - cameraXpan, cameraYpan); + } +} + +void Task_HandleTruckSequence(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + switch (data[0]) + { + /* + Each case has a timer which is handled with data[1], incrementing + until it reaches the if function's condition, which sets the next task up. + */ + case 0: + data[1]++; + if (data[1] == SECONDS(1.5)) + { + SetCameraPanningCallback(0); + data[1] = 0; // reset the timer. + data[2] = CreateTask(Task_Truck1, 0xA); + data[0] = 1; // run the next case. + PlaySE(SE_TRACK_MOVE); + } + break; + case 1: + data[1]++; + if (data[1] == SECONDS(2.5)) + { + pal_fill_black(); + data[1] = 0; + data[0] = 2; + } + break; + case 2: + data[1]++; + if (!gPaletteFade.active && data[1] > SECONDS(5)) + { + data[1] = 0; + DestroyTask(data[2]); + data[3] = CreateTask(Task_Truck2, 0xA); + data[0] = 3; + PlaySE(SE_TRACK_STOP); + } + break; + case 3: + if (!gTasks[data[3]].isActive) // is Truck2 no longer active (is Truck3 active?) + { + InstallCameraPanAheadCallback(); + data[1] = 0; + data[0] = 4; + } + break; + case 4: + data[1]++; + if (data[1] == 90) + { + PlaySE(SE_TRACK_HAIK); + data[1] = 0; + data[0] = 5; + } + break; + case 5: + data[1]++; + if (data[1] == 120) + { + MapGridSetMetatileIdAt(11, 8, 520); + MapGridSetMetatileIdAt(11, 9, 528); + MapGridSetMetatileIdAt(11, 10, 536); + DrawWholeMapView(); + PlaySE(SE_TRACK_DOOR); + DestroyTask(taskId); + ScriptContext2_Disable(); + } + break; + } +} + +void ExecuteTruckSequence(void) +{ + MapGridSetMetatileIdAt(11, 8, 525); + MapGridSetMetatileIdAt(11, 9, 533); + MapGridSetMetatileIdAt(11, 10, 541); + DrawWholeMapView(); + ScriptContext2_Enable(); + CpuFastFill(0, gPlttBufferFaded, 0x400); + CreateTask(Task_HandleTruckSequence, 0xA); +} + +void EndTruckSequence(u8 taskId) +{ + if (!FuncIsActiveTask(Task_HandleTruckSequence)) + { + sub_805BD90(1, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 3, 3); + sub_805BD90(2, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, 0, -3); + sub_805BD90(3, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, -3, 0); + } +} + +bool8 sub_80C7754(void) +{ + s8 mapGroup, mapNum; + s16 x, y; + + if (GetSSTidalLocation(&mapGroup, &mapNum, &x, &y)) + { + return FALSE; + } + else + { + Overworld_SetWarpDestination(mapGroup, mapNum, -1, x, y); + return TRUE; + } +} + +void Task_HandlePorthole(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + u16 *var = GetVarPointer(VAR_PORTHOLE); + struct WarpData *location = &gSaveBlock1.location; + + switch (data[0]) + { + case INIT_PORTHOLE: // finish fading before making porthole finish. + if (!gPaletteFade.active) + { + data[1] = 0; + data[0] = EXECUTE_MOVEMENT; // execute movement before checking if should be exited. strange? + } + break; + case IDLE_CHECK: // idle and move. + if (gMain.newKeys & A_BUTTON) + data[1] = 1; + if (!ScriptMovement_IsObjectMovementFinished(0xFF, location->mapNum, location->mapGroup)) + return; + if (CountSSTidalStep(1) == TRUE) + { + if (*var == 2) + *var = 9; + else + *var = 10; + data[0] = 3; + return; + } + data[0] = 2; + case EXECUTE_MOVEMENT: // execute movement. + if (data[1]) + { + data[0] = EXIT_PORTHOLE; // exit porthole. + return; + } + // run this once. + if (*var == 2) // which direction? + { + ScriptMovement_StartObjectMovementScript(0xFF, location->mapNum, location->mapGroup, gUnknown_083D295F); + data[0] = IDLE_CHECK; // run case 1. + } + else + { + ScriptMovement_StartObjectMovementScript(0xFF, location->mapNum, location->mapGroup, gUnknown_083D2961); + data[0] = IDLE_CHECK; // run case 1. + } + break; + case EXIT_PORTHOLE: // exit porthole. + FlagClear(0x4001); + FlagClear(0x4000); + copy_saved_warp2_bank_and_enter_x_to_warp1(0); + sp13E_warp_to_last_warp(); + DestroyTask(taskId); + break; + } +} + +void sub_80C78A0(void) +{ + u8 spriteId = AddPseudoFieldObject(0x8C, SpriteCallbackDummy, 112, 80, 0); + + gSprites[spriteId].coordOffsetEnabled = FALSE; + + if (VarGet(0x40B4) == 2) + { + StartSpriteAnim(&gSprites[spriteId], FieldObjectDirectionToImageAnimId(4)); + } + else + { + StartSpriteAnim(&gSprites[spriteId], FieldObjectDirectionToImageAnimId(3)); + } +} + +void sub_80C791C(void) +{ + sub_80C78A0(); + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_13 = TRUE; + pal_fill_black(); + CreateTask(Task_HandlePorthole, 80); + ScriptContext2_Enable(); +} + +void sub_80C7958(void) +{ + FlagSet(SYS_CRUISE_MODE); + FlagSet(0x4001); + FlagSet(0x4000); + saved_warp2_set(0, gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum, -1); + sub_80C7754(); + sub_8080F9C(); +} diff --git a/src/field/field_specials.c b/src/field/field_specials.c new file mode 100644 index 000000000..36362d098 --- /dev/null +++ b/src/field/field_specials.c @@ -0,0 +1,2383 @@ +#include "global.h" +#include "field_specials.h" +#include "diploma.h" +#include "fieldmap.h" +#include "event_data.h" +#include "battle_tower.h" +#include "field_map_obj.h" +#include "region_map.h" +#include "field_region_map.h" +#include "field_message_box.h" +#include "field_camera.h" +#include "field_player_avatar.h" +#include "main.h" +#include "map_constants.h" +#include "overworld.h" +#include "script.h" +#include "songs.h" +#include "string_util.h" +#include "strings.h" +#include "pokeblock.h" +#include "species.h" +#include "abilities.h" +#include "moves.h" +#include "text.h" +#include "wallclock.h" +#include "tv.h" +#include "rtc.h" +#include "link.h" +#include "songs.h" +#include "sound.h" +#include "menu.h" +#include "starter_choose.h" +#include "menu_helpers.h" +#include "battle_tower.h" +#include "field_weather.h" +#include "pokemon_summary_screen.h" +#include "rng.h" + +#if ENGLISH +#define CHAR_DECIMAL_SEPARATOR CHAR_PERIOD +#elif GERMAN +#define CHAR_DECIMAL_SEPARATOR CHAR_COMMA +#endif + +extern struct WarpData gUnknown_020297F0; +extern u8 gBattleOutcome; +extern u16 gSpecialVar_0x8004; +extern u16 gSpecialVar_0x8005; +extern u16 gScriptResult; + +EWRAM_DATA u8 gUnknown_02039250 = 0; +EWRAM_DATA u8 gUnknown_02039251 = 0; +EWRAM_DATA u32 gUnknown_02039254 = 0; +EWRAM_DATA u8 gUnknown_02039258 = 0; +EWRAM_DATA u8 gUnknown_02039259 = 0; +EWRAM_DATA u8 gUnknown_0203925A = 0; +EWRAM_DATA u8 gUnknown_0203925B = 0; +EWRAM_DATA u8 gUnknown_0203925C = 0; + +static void RecordCyclingRoadResults(u32, u8); + +static struct ElevatorMenu gUnknown_03000760[20]; + +void ScrSpecial_ShowDiploma(void) +{ + SetMainCallback2(CB2_ShowDiploma); + ScriptContext2_Enable(); +} + +void ScrSpecial_ViewWallClock(void) +{ + gMain.savedCallback = c2_exit_to_overworld_2_switch; + SetMainCallback2(CB2_ViewWallClock); + ScriptContext2_Enable(); +} + +void ResetCyclingRoadChallengeData(void) +{ + gUnknown_02039250 = 0; + gUnknown_02039251 = 0; + gUnknown_02039254 = 0; +} + +void ScrSpecial_BeginCyclingRoadChallenge(void) +{ + gUnknown_02039250 = 1; + gUnknown_02039251 = 0; + gUnknown_02039254 = gMain.vblankCounter1; +} + +u16 GetPlayerAvatarBike(void) +{ + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_ACRO_BIKE)) + return 1; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE)) + return 2; + return 0; +} + +static void DetermineCyclingRoadResults(u32 arg0, u8 arg1) +{ + u8 result; + + if (arg1 <= 99) + { + ConvertIntToDecimalStringN(gStringVar1, arg1, STR_CONV_MODE_LEFT_ALIGN, 2); + StringAppend(gStringVar1, gOtherText_Times); + } + else + { + StringCopy(gStringVar1, gOtherText_99Times); + } + + if (arg0 < 3600) + { + ConvertIntToDecimalStringN(gStringVar2, arg0 / 60, STR_CONV_MODE_RIGHT_ALIGN, 2); + gStringVar2[2] = CHAR_DECIMAL_SEPARATOR; + ConvertIntToDecimalStringN(&gStringVar2[3], ((arg0 % 60) * 100) / 60, STR_CONV_MODE_LEADING_ZEROS, 2); + StringAppend(gStringVar2, gOtherText_Seconds); + } + else + { + StringCopy(gStringVar2, gOtherText_1Minute); + } + + result = 0; + if (arg1 == 0) + { + result = 5; + } + else if (arg1 < 4) + { + result = 4; + } + else if (arg1 < 10) + { + result = 3; + } + else if (arg1 < 20) + { + result = 2; + } + else if (arg1 < 100) + { + result = 1; + } + + if (arg0 / 60 <= 10) + { + result += 5; + } + else if (arg0 / 60 <= 15) + { + result += 4; + } + else if (arg0 / 60 <= 20) + { + result += 3; + } + else if (arg0 / 60 <= 40) + { + result += 2; + } + else if (arg0 / 60 < 60) + { + result += 1; + } + + + gScriptResult = result; +} + +void FinishCyclingRoadChallenge(void) { + const u32 time = gMain.vblankCounter1 - gUnknown_02039254; + + DetermineCyclingRoadResults(time, gUnknown_02039251); + RecordCyclingRoadResults(time, gUnknown_02039251); +} + +static void RecordCyclingRoadResults(u32 arg0, u8 arg1) { + u16 high = VarGet(0x4028); + u16 low = VarGet(0x4029); + u32 record = high + (low << 16); + + if (record > arg0 || record == 0) + { + VarSet(0x4028, arg0); + VarSet(0x4029, arg0 >> 16); + VarSet(0x4027, arg1); + } +} + +u16 GetRecordedCyclingRoadResults(void) { + u16 high = VarGet(0x4028); + u16 low = VarGet(0x4029); + u32 record = high + (low << 16); + + if (record == 0) + { + return FALSE; + } + + DetermineCyclingRoadResults(record, VarGet(0x4027)); + return TRUE; +} + +void UpdateCyclingRoadState(void) { + if (gUnknown_020297F0.mapNum == MAP_ID_ROUTE110_SEASIDE_CYCLING_ROAD_NORTH_ENTRANCE && gUnknown_020297F0.mapGroup == MAP_GROUP_ROUTE110_SEASIDE_CYCLING_ROAD_NORTH_ENTRANCE) + { + return; + } + + if (VarGet(0x40a9) == 2 || VarGet(0x40a9) == 3) + { + VarSet(0x40a9, 0); + Overworld_SetSavedMusic(SE_STOP); + } +} + +void SetSSTidalFlag(void) +{ + FlagSet(SYS_CRUISE_MODE); + *GetVarPointer(VAR_CRUISE_STEP_COUNT) = 0; +} + +void ResetSSTidalFlag(void) +{ + FlagClear(SYS_CRUISE_MODE); +} + +bool32 CountSSTidalStep(u16 delta) +{ + if (!FlagGet(SYS_CRUISE_MODE) || (*GetVarPointer(VAR_CRUISE_STEP_COUNT) += delta) <= 0xcc) + { + return FALSE; + } + return TRUE; +} + +u8 GetSSTidalLocation(s8 *mapGroup, s8 *mapNum, s16 *x, s16 *y) +{ + u16 *varCruiseStepCount = GetVarPointer(VAR_CRUISE_STEP_COUNT); + switch (*GetVarPointer(VAR_PORTHOLE)) + { + case 1: + case 8: + return 1; + case 3: + case 9: + return 4; + case 4: + case 5: + return 2; + case 6: + case 10: + return 3; + case 2: + if (*varCruiseStepCount < 60) + { + *mapNum = MAP_ID_ROUTE134; + *x = *varCruiseStepCount + 19; + } + else if (*varCruiseStepCount < 140) + { + *mapNum = MAP_ID_ROUTE133; + *x = *varCruiseStepCount - 60; + } + else + { + *mapNum = MAP_ID_ROUTE132; + *x = *varCruiseStepCount - 140; + } + break; + case 7: + if (*varCruiseStepCount < 66) + { + *mapNum = MAP_ID_ROUTE132; + *x = 65 - *varCruiseStepCount; + } + else if (*varCruiseStepCount < 146) { + *mapNum = MAP_ID_ROUTE133; + *x = 145 - *varCruiseStepCount; + } + else + { + *mapNum = MAP_ID_ROUTE134; + *x = 224 - *varCruiseStepCount; + } + break; + } + *mapGroup = MAP_GROUP_ROUTE132; + *y = 20; + return 0; +} + +u8 GetLinkPartnerNames(void) +{ + u8 i; + u8 j = 0; + u8 myLinkPlayerNumber = sub_8008218(); + u8 nLinkPlayers = sub_800820C(); + for (i=0; i<nLinkPlayers; i++) + { + if (myLinkPlayerNumber != i) + { + StringCopy(gUnknown_083D1464[j], gLinkPlayers[i].name); + j++; + } + } + return nLinkPlayers; +} + +const u8 gUnknown_083F8358[4] = {7, 9, 8, 10}; +const s8 gUnknown_083F835C[4][2] = { + { 0, 1}, + { 1, 0}, + { 0, -1}, + {-1, 0} +}; + +void SpawnBerryBlenderLinkPlayerSprites(void) +{ + u8 unknown_083F8358[4]; + u8 unknown_083F835C[4][2]; + u8 myLinkPlayerNumber; + u8 playerDirectionLowerNybble; + u8 rivalAvatarGraphicsId; + u8 i; + u8 j = 0; + s16 x = 0; + s16 y = 0; + + memcpy(unknown_083F8358, gUnknown_083F8358, sizeof gUnknown_083F8358); + memcpy(unknown_083F835C, gUnknown_083F835C, sizeof gUnknown_083F835C); + myLinkPlayerNumber = sub_8008218(); + playerDirectionLowerNybble = player_get_direction_lower_nybble(); + switch (playerDirectionLowerNybble) + { + case DIR_WEST: + j = 2; + x = gSaveBlock1.pos.x - 1; + y = gSaveBlock1.pos.y; + break; + case DIR_NORTH: + j = 1; + x = gSaveBlock1.pos.x; + y = gSaveBlock1.pos.y - 1; + break; + case DIR_EAST: + x = gSaveBlock1.pos.x + 1; + y = gSaveBlock1.pos.y; + break; + case DIR_SOUTH: + j = 3; + x = gSaveBlock1.pos.x; + y = gSaveBlock1.pos.y + 1; + } + for (i=0; i<gSpecialVar_0x8004; i++) + { + if (myLinkPlayerNumber != i) + { + rivalAvatarGraphicsId = GetRivalAvatarGraphicsIdByStateIdAndGender(0, gLinkPlayers[i].gender); + SpawnSpecialFieldObjectParametrized(rivalAvatarGraphicsId, unknown_083F8358[j], 0xf0 - i, (s8)unknown_083F835C[j][0] + x + 7, (s8)unknown_083F835C[j][1] + y + 7, 0); + j++; + if (j == 4) + { + j = 0; + } + } + } +} + +struct Coords8 { + u8 x; + u8 y; +}; + +const struct Coords8 gUnknown_083F8364[3] = { + { 7, 16}, + {15, 18}, + {11, 22} +}; + +void MauvilleGymSpecial1(void) +{ + u8 i; + for (i=0; i<3; i++) + { + if (i == gSpecialVar_0x8004) + { + MapGridSetMetatileIdAt(gUnknown_083F8364[i].x, gUnknown_083F8364[i].y, 0x206); + } + else + { + MapGridSetMetatileIdAt(gUnknown_083F8364[i].x, gUnknown_083F8364[i].y, 0x205); + } + } +} + +void MauvilleGymSpecial2(void) +{ + int x, y; + for (y=12; y<24; y++) + { + for (x=7; x<16; x++) + { + switch (MapGridGetMetatileIdAt(x, y)) + { + case 0x220: + MapGridSetMetatileIdAt(x, y, 0x230); + break; + case 0x221: + MapGridSetMetatileIdAt(x, y, 0x231); + break; + case 0x228: + MapGridSetMetatileIdAt(x, y, 0x238); + break; + case 0x229: + MapGridSetMetatileIdAt(x, y, 0x239); + break; + case 0x230: + MapGridSetMetatileIdAt(x, y, 0x220); + break; + case 0x231: + MapGridSetMetatileIdAt(x, y, 0x221); + break; + case 0x238: + MapGridSetMetatileIdAt(x, y, 0xe28); + break; + case 0x239: + MapGridSetMetatileIdAt(x, y, 0xe29); + break; + case 0x222: + MapGridSetMetatileIdAt(x, y, 0x232); + break; + case 0x223: + MapGridSetMetatileIdAt(x, y, 0x233); + break; + case 0x22a: + MapGridSetMetatileIdAt(x, y, 0x23a); + break; + case 0x22b: + MapGridSetMetatileIdAt(x, y, 0x23b); + break; + case 0x232: + MapGridSetMetatileIdAt(x, y, 0x222); + break; + case 0x233: + MapGridSetMetatileIdAt(x, y, 0x223); + break; + case 0x23a: + MapGridSetMetatileIdAt(x, y, 0xe2a); + break; + case 0x23b: + MapGridSetMetatileIdAt(x, y, 0xe2b); + break; + case 0x240: + MapGridSetMetatileIdAt(x, y, 0xe42); + break; + case 0x248: + MapGridSetMetatileIdAt(x, y, 0x21a); + break; + case 0x241: + MapGridSetMetatileIdAt(x, y, 0xe43); + break; + case 0x249: + MapGridSetMetatileIdAt(x, y, 0x21a); + break; + case 0x242: + MapGridSetMetatileIdAt(x, y, 0xe40); + break; + case 0x21a: + if (MapGridGetMetatileIdAt(x, y - 1) == 0x240) + { + MapGridSetMetatileIdAt(x, y, 0xe48); + } + else + { + MapGridSetMetatileIdAt(x, y, 0xe49); + } + break; + case 0x243: + MapGridSetMetatileIdAt(x, y, 0xe41); + break; + case 0x251: + MapGridSetMetatileIdAt(x, y, 0xe50); + break; + case 0x250: + MapGridSetMetatileIdAt(x, y, 0x251); + break; + } + } + } +} + +void MauvilleGymSpecial3(void) +{ + int i, x, y; + const struct Coords8 *switchCoords = gUnknown_083F8364; + for (i=ARRAY_COUNT(gUnknown_083F8364)-1; i>=0; i--) + { + MapGridSetMetatileIdAt(switchCoords->x, switchCoords->y, 0x206); + switchCoords++; + } + for (y=12; y<24; y++) + { + for (x=7; x<16; x++) + { + switch (MapGridGetMetatileIdAt(x, y)) + { + case 0x220: + MapGridSetMetatileIdAt(x, y, 0x230); + break; + case 0x221: + MapGridSetMetatileIdAt(x, y, 0x231); + break; + case 0x228: + MapGridSetMetatileIdAt(x, y, 0x238); + break; + case 0x229: + MapGridSetMetatileIdAt(x, y, 0x239); + break; + case 0x222: + MapGridSetMetatileIdAt(x, y, 0x232); + break; + case 0x223: + MapGridSetMetatileIdAt(x, y, 0x233); + break; + case 0x22a: + MapGridSetMetatileIdAt(x, y, 0x23a); + break; + case 0x22b: + MapGridSetMetatileIdAt(x, y, 0x23b); + break; + case 0x240: + MapGridSetMetatileIdAt(x, y, 0xe42); + break; + case 0x241: + MapGridSetMetatileIdAt(x, y, 0xe43); + break; + case 0x248: + case 0x249: + MapGridSetMetatileIdAt(x, y, 0x21a); + break; + case 0x250: + MapGridSetMetatileIdAt(x, y, 0x251); + break; + } + } + } +} + +static void Task_PetalburgGym(u8); +static void PetalburgGymFunc(u8, u16); +const u8 gUnknown_083F8370[] = {0, 1, 1, 1, 1}; +const u16 gUnknown_083F8376[] = {0x218, 0x219, 0x21a, 0x21b, 0x21c}; + +void PetalburgGymSpecial1(void) +{ + gUnknown_02039258 = 0; + gUnknown_02039259 = 0; + PlaySE(SE_KI_GASYAN); + CreateTask(Task_PetalburgGym, 8); +} + +static void Task_PetalburgGym(u8 taskId) +{ + if (gUnknown_083F8370[gUnknown_02039259] == gUnknown_02039258) + { + PetalburgGymFunc(gSpecialVar_0x8004, gUnknown_083F8376[gUnknown_02039259]); + gUnknown_02039258 = 0; + if ((++gUnknown_02039259) == 5) + { + DestroyTask(taskId); + EnableBothScriptContexts(); + } + } + else + { + gUnknown_02039258++; + } +} + +static void PetalburgGymFunc(u8 a0, u16 a1) +{ + u16 x[4]; + u16 y[4]; + u8 i; + u8 nDoors = 0; + switch (a0) + { + case 1: + nDoors = 2; + x[0] = 1; + x[1] = 7; + y[0] = 0x68; + y[1] = 0x68; + break; + case 2: + nDoors = 2; + x[0] = 1; + x[1] = 7; + y[0] = 0x4e; + y[1] = 0x4e; + break; + case 3: + nDoors = 2; + x[0] = 1; + x[1] = 7; + y[0] = 0x5b; + y[1] = 0x5b; + break; + case 4: + nDoors = 1; + x[0] = 7; + y[0] = 0x27; + break; + case 5: + nDoors = 2; + x[0] = 1; + x[1] = 7; + y[0] = 0x34; + y[1] = 0x34; + break; + case 6: + nDoors = 1; + x[0] = 1; + y[0] = 0x41; + break; + case 7: + nDoors = 1; + x[0] = 7; + y[0] = 0xd; + break; + case 8: + nDoors = 1; + x[0] = 1; + y[0] = 0x1a; + break; + } + for (i=0; i<nDoors; i++) + { + MapGridSetMetatileIdAt(x[i] + 7, y[i] + 7, a1 | 0xc00); + MapGridSetMetatileIdAt(x[i] + 7, y[i] + 8, (a1 + 8) | 0xc00); + } + DrawWholeMapView(); +} + +void PetalburgGymSpecial2(void) +{ + PetalburgGymFunc(gSpecialVar_0x8004, gUnknown_083F8376[4]); +} + +void ShowFieldMessageStringVar4(void) +{ + ShowFieldMessage(gStringVar4); +} + +void StorePlayerCoordsInVars(void) +{ + gSpecialVar_0x8004 = gSaveBlock1.pos.x; + gSpecialVar_0x8005 = gSaveBlock1.pos.y; +} + +u8 GetPlayerTrainerIdOnesDigit(void) +{ + return (u16)((gSaveBlock2.playerTrainerId[1] << 8) | gSaveBlock2.playerTrainerId[0]) % 10; +} + +void GetPlayerBigGuyGirlString(void) +{ + if (gSaveBlock2.playerGender == MALE) + { + StringCopy(gStringVar1, gOtherText_BigGuy); + } + else + { + StringCopy(gStringVar1, gOtherText_BigGirl); + } +} + +void GetRivalSonDaughterString(void) +{ + if (gSaveBlock2.playerGender == MALE) + { + StringCopy(gStringVar1, gOtherText_Daughter); + } + else + { + StringCopy(gStringVar1, gOtherText_Son); + } +} + +u8 sub_810E300(void) +{ + return gBattleOutcome; +} + +void CableCarWarp(void) +{ + if (gSpecialVar_0x8004 != 0) + { + Overworld_SetWarpDestination(MAP_GROUP_ROUTE112_CABLE_CAR_STATION, MAP_ID_ROUTE112_CABLE_CAR_STATION, -1, 6, 4); + } + else + { + Overworld_SetWarpDestination(MAP_GROUP_MT_CHIMNEY_CABLE_CAR_STATION, MAP_ID_MT_CHIMNEY_CABLE_CAR_STATION, -1, 6, 4); + } +} + +void SetFlagInVar(void) +{ + FlagSet(gSpecialVar_0x8004); +} + +u16 GetWeekCount(void) +{ + u16 weekCount = gLocalTime.days / 7; + if (weekCount > 9999) + { + weekCount = 9999; + } + return weekCount; +} + +u8 GetLeadMonFriendshipScore(void) +{ + struct Pokemon *pokemon = &gPlayerParty[GetLeadMonIndex()]; + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) == 255) + { + return 6; + } + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 200) + { + return 5; + } + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 150) + { + return 4; + } + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 100) + { + return 3; + } + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 50) + { + return 2; + } + if (GetMonData(pokemon, MON_DATA_FRIENDSHIP) >= 1) + { + return 1; + } + return 0; +} + +void CB2_FieldShowRegionMap(void) +{ + FieldInitRegionMap(c2_exit_to_overworld_1_continue_scripts_restart_music); +} + +void FieldShowRegionMap(void) +{ + SetMainCallback2(CB2_FieldShowRegionMap); +} + +static void Task_PCTurnOnEffect(u8); +static void PCTurnOffEffect_0(struct Task *); +static void PCTurnOffEffect_1(s16, s8, s8); +static void PCTurnOffEffect(void); + +void DoPCTurnOnEffect(void) +{ + if (FuncIsActiveTask(Task_PCTurnOnEffect) != TRUE) + { + u8 taskId = CreateTask(Task_PCTurnOnEffect, 8); + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = taskId; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = 0; + } +} + +static void Task_PCTurnOnEffect(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + if (task->data[0] == 0) + { + PCTurnOffEffect_0(task); + } +} + +static void PCTurnOffEffect_0(struct Task *task) +{ + u8 playerDirectionLowerNybble; + s8 dx = 0; + s8 dy = 0; + if (task->data[3] == 6) + { + task->data[3] = 0; + playerDirectionLowerNybble = player_get_direction_lower_nybble(); + switch (playerDirectionLowerNybble) + { + case DIR_NORTH: + dx = 0; + dy = -1; + break; + case DIR_WEST: + dx = -1; + dy = -1; + break; + case DIR_EAST: + dx = 1; + dy = -1; + break; + } + PCTurnOffEffect_1(task->data[4], dx, dy); + DrawWholeMapView(); + task->data[4] ^= 1; + if ((++task->data[2]) == 5) + { + DestroyTask(task->data[1]); + } + } + task->data[3]++; +} + +static void PCTurnOffEffect_1(s16 flag, s8 dx, s8 dy) +{ + u16 tileId = 0; + if (flag != 0) + { + if (gSpecialVar_0x8004 == 0) + { + tileId = 0x4; + } + else if (gSpecialVar_0x8004 == 1) + { + tileId = 0x25a; + } + else if (gSpecialVar_0x8004 == 2) + { + tileId = 0x259; + } + } + else + { + if (gSpecialVar_0x8004 == 0) + { + tileId = 0x5; + } + else if (gSpecialVar_0x8004 == 1) + { + tileId = 0x27f; + } + else if (gSpecialVar_0x8004 == 2) + { + tileId = 0x27e; + } + } + MapGridSetMetatileIdAt(gSaveBlock1.pos.x + dx + 7, gSaveBlock1.pos.y + dy + 7, tileId | 0xc00); +} + +void DoPCTurnOffEffect(void) +{ + PCTurnOffEffect(); +} + +static void PCTurnOffEffect(void) +{ + s8 dx = 0; + s8 dy = 0; + u16 tileId = 0; + u8 playerDirectionLowerNybble = player_get_direction_lower_nybble(); + switch (playerDirectionLowerNybble) + { + case DIR_NORTH: + dx = 0; + dy = -1; + break; + case DIR_WEST: + dx = -1; + dy = -1; + break; + case DIR_EAST: + dx = 1; + dy = -1; + break; + } + if (gSpecialVar_0x8004 == 0) + { + tileId = 0x4; + } + else if (gSpecialVar_0x8004 == 1) + { + tileId = 0x25a; + } + else if (gSpecialVar_0x8004 == 2) + { + tileId = 0x259; + } + MapGridSetMetatileIdAt(gSaveBlock1.pos.x + dx + 7, gSaveBlock1.pos.y + dy + 7, tileId | 0xc00); + DrawWholeMapView(); +} + +static void Task_LotteryCornerComputerEffect(u8); +static void LotteryCornerComputerEffect(struct Task *); + +void DoLotteryCornerComputerEffect(void) +{ + if (FuncIsActiveTask(Task_LotteryCornerComputerEffect) != TRUE) + { + u8 taskId = CreateTask(Task_LotteryCornerComputerEffect, 8); + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = taskId; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = 0; + } +} + +static void Task_LotteryCornerComputerEffect(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + if (task->data[0] == 0) + { + LotteryCornerComputerEffect(task); + } +} + +static void LotteryCornerComputerEffect(struct Task *task) +{ + if (task->data[3] == 6) + { + task->data[3] = 0; + if (task->data[4] != 0) + { + MapGridSetMetatileIdAt(18, 8, 0xe9d); + MapGridSetMetatileIdAt(18, 9, 0xea5); + } + else + { + MapGridSetMetatileIdAt(18, 8, 0xe58); + MapGridSetMetatileIdAt(18, 9, 0xe60); + } + DrawWholeMapView(); + task->data[4] ^= 1; + if ((++task->data[2]) == 5) + { + DestroyTask(task->data[1]); + } + } + task->data[3]++; +} + +void EndLotteryCornerComputerEffect(void) +{ + MapGridSetMetatileIdAt(18, 8, 0xe9d); + MapGridSetMetatileIdAt(18, 9, 0xea5); + DrawWholeMapView(); +} + +static void sub_810E874(void); +void sub_810E944(void); +void sub_810E984(u8); +bool8 sub_810EAC8(u8, u8); +void sub_810EB90(u8, u8); +void sub_810EBEC(void); +void sub_810EC34(u8); +void sub_810EC9C(u8); +void sub_810ECB0(void); +void sub_810ECD4(void); +void sub_810ECFC(void); +void sub_810ED40(u8); +void sub_810ED60(struct Task *); +void sub_810EEDC(void); + +const u8 *const gUnknown_083F8380[] = { + OtherText_1F, + OtherText_2F, + OtherText_3F, + OtherText_4F, + OtherText_5F, + OtherText_6F, + OtherText_7F, + OtherText_8F, + OtherText_9F, + OtherText_10F, + OtherText_11F, + OtherText_B1F, + OtherText_B2F, + OtherText_B3F, + OtherText_B4F, + OtherText_Rooftop +}; + +void SetDepartmentStoreFloorVar(void) +{ + u8 deptStoreFloor; + switch (gSaveBlock1.warp2.mapNum) + { + case MAP_ID_LILYCOVE_CITY_DEPARTMENT_STORE_1F: + deptStoreFloor = 0; + break; + case MAP_ID_LILYCOVE_CITY_DEPARTMENT_STORE_2F: + deptStoreFloor = 1; + break; + case MAP_ID_LILYCOVE_CITY_DEPARTMENT_STORE_3F: + deptStoreFloor = 2; + break; + case MAP_ID_LILYCOVE_CITY_DEPARTMENT_STORE_4F: + deptStoreFloor = 3; + break; + case MAP_ID_LILYCOVE_CITY_DEPARTMENT_STORE_5F: + deptStoreFloor = 4; + break; + case MAP_ID_LILYCOVE_CITY_DEPARTMENT_STORE_ROOFTOP: + deptStoreFloor = 15; + break; + default: + deptStoreFloor = 0; + break; + } + VarSet(VAR_DEPT_STORE_FLOOR, deptStoreFloor); +} + +void ScriptAddElevatorMenuItem(u8 a0, u8 a1, u8 a2, u8 a3) +{ + u8 i; + if (gSpecialVar_0x8004 == 0) + { + for (i=0; i<20; i++) + { + gUnknown_03000760[i].var0 = 16; + } + } + gUnknown_03000760[gSpecialVar_0x8004].var0 = a0; + gUnknown_03000760[gSpecialVar_0x8004].var1 = a1; + gUnknown_03000760[gSpecialVar_0x8004].var2 = a2; + gUnknown_03000760[gSpecialVar_0x8004].var3 = a3; + gSpecialVar_0x8004++; +} + +void ScriptShowElevatorMenu(void) +{ + u8 i = 0; + gUnknown_0203925A = 0; + gUnknown_0203925B = 0; + ScriptAddElevatorMenuItem(16, 0, 0, 0); + while (gUnknown_03000760[i].var0 != 16) + { + gUnknown_0203925A++; + i++; + } + sub_810E874(); +} + +static void sub_810E874(void) +{ + u8 i; + ScriptContext2_Enable(); + if (gUnknown_0203925A > 5) + { + MenuDrawTextWindow(0, 0, 8, 11); + InitMenu(0, 1, 1, 5, 0, 7); + gUnknown_0203925C = 0; + sub_80F944C(); + LoadScrollIndicatorPalette(); + sub_810ECD4(); + } + else + { + MenuDrawTextWindow(0, 0, 8, 2 * gUnknown_0203925A + 1); + InitMenu(0, 1, 1, gUnknown_0203925A, 0, 7); + } + for (i = 0; i < 5 && gUnknown_03000760[i].var0 != 16; i ++) + { + MenuPrint(gUnknown_083F8380[gUnknown_03000760[i].var0], 1, 2 * i + 1); + } + sub_810E944(); + CreateTask(sub_810E984, 8); +} + +void sub_810E944(void) +{ + MenuDrawTextWindow(20, 0, 29, 5); + sub_8072BD8(gOtherText_NowOn, 21, 1, 64); + sub_8072BD8(gUnknown_083F8380[gSpecialVar_0x8005], 21, 3, 64); +} + +void sub_810E984(u8 taskId) +{ + u8 curMenuPos; + if (gMain.newKeys == DPAD_UP && gUnknown_0203925B != 0) + { + gUnknown_0203925B--; + curMenuPos = GetMenuCursorPos(); + MoveMenuCursorNoWrap(-1); + sub_810EAC8(curMenuPos, DPAD_UP); + } + if (gMain.newKeys == DPAD_DOWN && gUnknown_0203925B != gUnknown_0203925A - 1) + { + gUnknown_0203925B++; + curMenuPos = GetMenuCursorPos(); + MoveMenuCursorNoWrap(+1); + sub_810EAC8(curMenuPos, DPAD_DOWN); + } + if (gMain.newKeys & A_BUTTON) + { + saved_warp2_set_2(0, gUnknown_03000760[gUnknown_0203925B].var1, gUnknown_03000760[gUnknown_0203925B].var2, -1, 2, 1); + if (gSpecialVar_0x8005 == gUnknown_0203925B) + { + gScriptResult = 0; + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(0, 0, 29, 12); + sub_810EC9C(taskId); + } + else + { + gScriptResult = 1; + gSpecialVar_0x8005 = gUnknown_0203925B; + sub_810EBEC(); + FieldObjectTurnByLocalIdAndMap(gScriptLastTalked, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, DIR_SOUTH); + sub_810EEDC(); + MenuZeroFillScreen(); + DestroyTask(taskId); + } + } + else if (gMain.newKeys & B_BUTTON) + { + gScriptResult = 0; + PlaySE(SE_SELECT); + sub_810EEDC(); + MenuZeroFillWindowRect(0, 0, 29, 12); + sub_810EC9C(taskId); + } +} + +// This function, as written, swaps the roles of r4 and r5 throughout. +#ifdef NONMATCHING +bool8 sub_810EAC8(u8 prevMenuPos, u8 dpadInput) +{ + u8 i; + bool8 flag = 0; + u8 newPos = 0; + if (gUnknown_0203925A < 5) + { + return FALSE; + } + if (dpadInput == DPAD_UP) + { + if (prevMenuPos == 0) + { + newPos = gUnknown_0203925B; + flag = 1; + } + } + else if (dpadInput == DPAD_DOWN) + { + if (prevMenuPos == 4) + { + newPos = gUnknown_0203925B - 4; + flag = 1; + } + } + if (flag) + { + sub_810EB90(newPos, 5); + MenuFillWindowRectWithBlankTile(2, 1, 7, 10); + for (i=0; i<5 && gUnknown_03000760[newPos].var0 != 16; newPos++, i++) + { + MenuPrint(gUnknown_083F8380[gUnknown_03000760[newPos].var0], 1, i * 2 + 1); + } + } + return flag; +} +#else +__attribute__((naked)) +bool8 sub_810EAC8(u8 prevMenuPos, u8 dpadInput) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r8\n" + "\tpush {r7}\n" + "\tlsls r0, 24\n" + "\tlsrs r2, r0, 24\n" + "\tadds r5, r2, 0\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tadds r3, r1, 0\n" + "\tmovs r7, 0\n" + "\tmovs r4, 0\n" + "\tldr r0, _0810EAEC @ =gUnknown_0203925A\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x4\n" + "\tbhi _0810EAF0\n" + "\tmovs r0, 0\n" + "\tb _0810EB78\n" + "\t.align 2, 0\n" + "_0810EAEC: .4byte gUnknown_0203925A\n" + "_0810EAF0:\n" + "\tcmp r1, 0x40\n" + "\tbne _0810EB04\n" + "\tcmp r2, 0\n" + "\tbne _0810EB18\n" + "\tldr r0, _0810EB00 @ =gUnknown_0203925B\n" + "\tldrb r4, [r0]\n" + "\tmovs r7, 0x1\n" + "\tb _0810EB1C\n" + "\t.align 2, 0\n" + "_0810EB00: .4byte gUnknown_0203925B\n" + "_0810EB04:\n" + "\tcmp r3, 0x80\n" + "\tbne _0810EB18\n" + "\tcmp r5, 0x4\n" + "\tbne _0810EB18\n" + "\tldr r0, _0810EB84 @ =gUnknown_0203925B\n" + "\tldrb r0, [r0]\n" + "\tsubs r0, 0x4\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tmovs r7, 0x1\n" + "_0810EB18:\n" + "\tcmp r7, 0\n" + "\tbeq _0810EB76\n" + "_0810EB1C:\n" + "\tadds r0, r4, 0\n" + "\tmovs r1, 0x5\n" + "\tbl sub_810EB90\n" + "\tmovs r0, 0x2\n" + "\tmovs r1, 0x1\n" + "\tmovs r2, 0x7\n" + "\tmovs r3, 0xA\n" + "\tbl MenuFillWindowRectWithBlankTile\n" + "\tmovs r5, 0\n" + "\tldr r2, _0810EB88 @ =gUnknown_03000760\n" + "\tlsls r1, r4, 2\n" + "\tadds r0, r1, r2\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x10\n" + "\tbeq _0810EB76\n" + "\tldr r0, _0810EB8C @ =gUnknown_083F8380\n" + "\tmov r8, r0\n" + "\tadds r6, r2, 0\n" + "_0810EB44:\n" + "\tadds r0, r1, r6\n" + "\tldrb r0, [r0]\n" + "\tlsls r0, 2\n" + "\tadd r0, r8\n" + "\tldr r0, [r0]\n" + "\tlsls r2, r5, 1\n" + "\tadds r2, 0x1\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tmovs r1, 0x1\n" + "\tbl MenuPrint\n" + "\tadds r0, r4, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r5, r0, 24\n" + "\tcmp r5, 0x4\n" + "\tbhi _0810EB76\n" + "\tlsls r1, r4, 2\n" + "\tadds r0, r1, r6\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x10\n" + "\tbne _0810EB44\n" + "_0810EB76:\n" + "\tadds r0, r7, 0\n" + "_0810EB78:\n" + "\tpop {r3}\n" + "\tmov r8, r3\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1\n" + "\t.align 2, 0\n" + "_0810EB84: .4byte gUnknown_0203925B\n" + "_0810EB88: .4byte gUnknown_03000760\n" + "_0810EB8C: .4byte gUnknown_083F8380"); +} +#endif + +void sub_810EB90(u8 newPos, u8 maxItems) +{ + if (newPos == 0) + { + gUnknown_0203925C ^= 0x02; + DestroyVerticalScrollIndicator(0); + } + else + { + sub_810ECB0(); + } + if (newPos + maxItems < gUnknown_0203925A) + { + sub_810ECD4(); + } + else if (newPos + maxItems == gUnknown_0203925A) + { + gUnknown_0203925C ^= 0x01; + DestroyVerticalScrollIndicator(1); + } +} + +void sub_810EBEC(void) +{ + u8 taskId = CreateTask(sub_810EC34, 9); + gTasks[taskId].data[0] = 1; + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = 1; + gTasks[taskId].data[5] = 3; + SetCameraPanningCallback(NULL); + sub_810ECFC(); + PlaySE(SE_ELEBETA); +} + +void sub_810EC34(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + task->data[1] ++; + if (task->data[1] % task->data[5] == 0) + { + task->data[1] = 0; + task->data[2] ++; + if (task->data[3] == 0) + { + task->data[4] = -task->data[4]; + SetCameraPanning(0, task->data[4]); + if (task->data[2] == 23) + { + PlaySE(SE_PINPON); + sub_810EC9C(taskId); + InstallCameraPanAheadCallback(); + } + } + } +} + +void sub_810EC9C(u8 taskId) +{ + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +void sub_810ECB0(void) +{ + if (gUnknown_0203925C >> 1 != 1) + { + gUnknown_0203925C |= 0x2; + CreateVerticalScrollIndicators(0, 0x24, 0x08); + } +} + +void sub_810ECD4(void) +{ + if ((gUnknown_0203925C & 1) == 0) + { + gUnknown_0203925C |= 0x1; + CreateVerticalScrollIndicators(1, 0x24, 0x48); + } +} + +void sub_810ECFC(void) +{ + if (FuncIsActiveTask(sub_810ED40) != TRUE) + { + u8 taskId = CreateTask(sub_810ED40, 8); + gTasks[taskId].data[0] = 0; + gTasks[taskId].data[1] = taskId; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = 0; + } +} + +void sub_810ED40(u8 taskId) +{ + sub_810ED60(&gTasks[taskId]); +} + +void sub_810ED60(struct Task *task) +{ + if (task->data[3] == 8) + { + task->data[3] = 0; + if (task->data[4] != 0) + { + MapGridSetMetatileIdAt( 7, 7, 0xe68); + MapGridSetMetatileIdAt( 8, 7, 0xe69); + MapGridSetMetatileIdAt( 9, 7, 0xe69); + MapGridSetMetatileIdAt(10, 7, 0xe6a); + MapGridSetMetatileIdAt( 7, 8, 0xe70); + MapGridSetMetatileIdAt( 8, 8, 0xe71); + MapGridSetMetatileIdAt( 9, 8, 0xe71); + MapGridSetMetatileIdAt(10, 8, 0xe72); + MapGridSetMetatileIdAt( 7, 9, 0xe78); + MapGridSetMetatileIdAt( 8, 9, 0xe79); + MapGridSetMetatileIdAt( 9, 9, 0xe79); + MapGridSetMetatileIdAt(10, 9, 0xe7a); + } + else + { + MapGridSetMetatileIdAt( 7, 7, 0xe6b); + MapGridSetMetatileIdAt( 8, 7, 0xe6c); + MapGridSetMetatileIdAt( 9, 7, 0xe6c); + MapGridSetMetatileIdAt(10, 7, 0xe6d); + MapGridSetMetatileIdAt( 7, 8, 0xe73); + MapGridSetMetatileIdAt( 8, 8, 0xe74); + MapGridSetMetatileIdAt( 9, 8, 0xe74); + MapGridSetMetatileIdAt(10, 8, 0xe75); + MapGridSetMetatileIdAt( 7, 9, 0xe7b); + MapGridSetMetatileIdAt( 8, 9, 0xe7c); + MapGridSetMetatileIdAt( 9, 9, 0xe7c); + MapGridSetMetatileIdAt(10, 9, 0xe7d); + } + DrawWholeMapView(); + task->data[4] ^= 1; + task->data[2]++; + if (task->data[2] == 8) + { + DestroyTask(task->data[1]); + } + } + task->data[3]++; +} + +void sub_810EEDC(void) +{ + if ((gUnknown_0203925C & 1) != 0) + { + DestroyVerticalScrollIndicator(1); + } + if ((gUnknown_0203925C >> 1) == 1) + { + DestroyVerticalScrollIndicator(0); + } + BuyMenuFreeMemory(); +} + +void SetTrickHouseEndRoomFlag(void) +{ + u16 *specVar = &gSpecialVar_0x8004; + u16 flag = 0x259; + *specVar = flag; + FlagSet(flag); +} + +void ResetTrickHouseEndRoomFlag(void) +{ + u16 *specVar = &gSpecialVar_0x8004; + u16 flag = 0x259; + *specVar = flag; + FlagClear(flag); +} + +bool8 CheckLeadMonCool(void) +{ + if (GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_COOL) < 200) + { + return FALSE; + } + return TRUE; +} + +bool8 CheckLeadMonBeauty(void) +{ + if (GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_BEAUTY) < 200) + { + return FALSE; + } + return TRUE; +} + +bool8 CheckLeadMonCute(void) +{ + if (GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_CUTE) < 200) + { + return FALSE; + } + return TRUE; +} + +bool8 CheckLeadMonSmart(void) +{ + if (GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SMART) < 200) + { + return FALSE; + } + return TRUE; +} + +bool8 CheckLeadMonTough(void) +{ + if (GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_TOUGH) < 200) + { + return FALSE; + } + return TRUE; +} + +void IsGrassTypeInParty(void) +{ + u8 i; + u16 species; + struct Pokemon *pokemon; + for (i=0; i<PARTY_SIZE; i++) + { + pokemon = &gPlayerParty[i]; + if (GetMonData(pokemon, MON_DATA_SANITY_BIT2) && !GetMonData(pokemon, MON_DATA_IS_EGG)) + { + species = GetMonData(pokemon, MON_DATA_SPECIES); + if (gBaseStats[species].type1 == TYPE_GRASS || gBaseStats[species].type2 == TYPE_GRASS) + { + gScriptResult = TRUE; + return; + } + } + } + gScriptResult = FALSE; +} + +const u8 *const gUnknown_083F83C0[] = { + OtherText_BlueFlute, + OtherText_YellowFlute, + OtherText_RedFlute, + OtherText_WhiteFlute, + OtherText_BlackFlute, + OtherText_PrettyChair, + OtherText_PrettyDesk, + gOtherText_CancelNoTerminator +}; + +void sub_810F118(u8); +bool8 sub_810F1F4(u8, u8); +void sub_810F2B4(void); +void GlassWorkshopUpdateScrollIndicators(u8, u8); + +void ShowGlassWorkshopMenu(void) +{ + u8 i; + ScriptContext2_Enable(); + MenuDrawTextWindow(0, 0, 10, 11); + InitMenu(0, 1, 1, 5, 0, 9); + gUnknown_0203925C = 0; + sub_80F944C(); + LoadScrollIndicatorPalette(); + sub_810F2B4(); + for (i=0; i<5; i++) + { + MenuPrint(gUnknown_083F83C0[i], 1, 2 * i + 1); + } + gUnknown_0203925B = 0; + gUnknown_0203925A = ARRAY_COUNT(gUnknown_083F83C0); + CreateTask(sub_810F118, 8); +} + +void sub_810F118(u8 taskId) +{ + u8 prevCursorPos; + if (gMain.newKeys == DPAD_UP && gUnknown_0203925B != 0) + { + gUnknown_0203925B--; + prevCursorPos = GetMenuCursorPos(); + MoveMenuCursorNoWrap(-1); + sub_810F1F4(prevCursorPos, DPAD_UP); + } + if (gMain.newKeys == DPAD_DOWN && gUnknown_0203925B != gUnknown_0203925A - 1) + { + gUnknown_0203925B++; + prevCursorPos = GetMenuCursorPos(); + MoveMenuCursorNoWrap(1); + sub_810F1F4(prevCursorPos, DPAD_DOWN); + } + if (gMain.newKeys & A_BUTTON) + { + HandleDestroyMenuCursors(); + gScriptResult = gUnknown_0203925B; + PlaySE(SE_SELECT); + sub_810EEDC(); + MenuZeroFillWindowRect(0, 0, 29, 12); + sub_810EC9C(taskId); + } + if (gMain.newKeys & B_BUTTON) + { + HandleDestroyMenuCursors(); + gScriptResult = 0x7f; + PlaySE(SE_SELECT); + sub_810EEDC(); + MenuZeroFillWindowRect(0, 0, 29, 12); + sub_810EC9C(taskId); + } +} + +// Second verse, same as the first +#ifdef NONMATCHING +bool8 sub_810F1F4(u8 prevCursorPos, u8 dpadInput) +{ + u8 i; + u8 flag = 0; + u8 newPos = 0; + if (gUnknown_0203925A < 5) + { + return FALSE; + } + if (dpadInput == DPAD_UP) + { + if (prevCursorPos == 0) + { + newPos = gUnknown_0203925B; + flag = TRUE; + } + } + else if (dpadInput == DPAD_DOWN) + { + if (prevCursorPos == 4) + { + newPos = gUnknown_0203925B - 4; + flag = TRUE; + } + } + if (flag) + { + GlassWorkshopUpdateScrollIndicators(newPos, 5); + MenuFillWindowRectWithBlankTile(2, 1, 9, 10); + for (i=0; i<5; newPos++, i++) + { + MenuPrint(gUnknown_083F83C0[newPos], 1, 2 * i + 1); + } + } + return flag; +} +#else +__attribute__((naked)) +bool8 sub_810F1F4(u8 prevCursorPos, u8 dpadInput) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tlsls r0, 24\n" + "\tlsrs r2, r0, 24\n" + "\tadds r5, r2, 0\n" + "\tlsls r1, 24\n" + "\tlsrs r1, 24\n" + "\tadds r3, r1, 0\n" + "\tmovs r6, 0\n" + "\tmovs r4, 0\n" + "\tldr r0, _0810F214 @ =gUnknown_0203925A\n" + "\tldrb r0, [r0]\n" + "\tcmp r0, 0x4\n" + "\tbhi _0810F218\n" + "\tmovs r0, 0\n" + "\tb _0810F282\n" + "\t.align 2, 0\n" + "_0810F214: .4byte gUnknown_0203925A\n" + "_0810F218:\n" + "\tcmp r1, 0x40\n" + "\tbne _0810F22C\n" + "\tcmp r2, 0\n" + "\tbne _0810F240\n" + "\tldr r0, _0810F228 @ =gUnknown_0203925B\n" + "\tldrb r4, [r0]\n" + "\tmovs r6, 0x1\n" + "\tb _0810F244\n" + "\t.align 2, 0\n" + "_0810F228: .4byte gUnknown_0203925B\n" + "_0810F22C:\n" + "\tcmp r3, 0x80\n" + "\tbne _0810F240\n" + "\tcmp r5, 0x4\n" + "\tbne _0810F240\n" + "\tldr r0, _0810F288 @ =gUnknown_0203925B\n" + "\tldrb r0, [r0]\n" + "\tsubs r0, 0x4\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tmovs r6, 0x1\n" + "_0810F240:\n" + "\tcmp r6, 0\n" + "\tbeq _0810F280\n" + "_0810F244:\n" + "\tadds r0, r4, 0\n" + "\tmovs r1, 0x5\n" + "\tbl GlassWorkshopUpdateScrollIndicators\n" + "\tmovs r0, 0x2\n" + "\tmovs r1, 0x1\n" + "\tmovs r2, 0x9\n" + "\tmovs r3, 0xA\n" + "\tbl MenuFillWindowRectWithBlankTile\n" + "\tmovs r5, 0\n" + "\tldr r7, _0810F28C @ =gUnknown_083F83C0\n" + "_0810F25C:\n" + "\tlsls r0, r4, 2\n" + "\tadds r0, r7\n" + "\tldr r0, [r0]\n" + "\tlsls r2, r5, 1\n" + "\tadds r2, 0x1\n" + "\tlsls r2, 24\n" + "\tlsrs r2, 24\n" + "\tmovs r1, 0x1\n" + "\tbl MenuPrint\n" + "\tadds r0, r4, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r4, r0, 24\n" + "\tadds r0, r5, 0x1\n" + "\tlsls r0, 24\n" + "\tlsrs r5, r0, 24\n" + "\tcmp r5, 0x4\n" + "\tbls _0810F25C\n" + "_0810F280:\n" + "\tadds r0, r6, 0\n" + "_0810F282:\n" + "\tpop {r4-r7}\n" + "\tpop {r1}\n" + "\tbx r1\n" + "\t.align 2, 0\n" + "_0810F288: .4byte gUnknown_0203925B\n" + "_0810F28C: .4byte gUnknown_083F83C0"); +} +#endif + +void sub_810F290(void) +{ + if (gUnknown_0203925C >> 1 != 1) + { + gUnknown_0203925C |= 0x02; + CreateVerticalScrollIndicators(0, 0x2c, 0x08); + } +} + +void sub_810F2B4(void) +{ + if (!(gUnknown_0203925C & 0x01)) + { + gUnknown_0203925C |= 0x01; + CreateVerticalScrollIndicators(1, 0x2c, 0x58); + } +} + +void GlassWorkshopUpdateScrollIndicators(u8 newPos, u8 maxItems) +{ + if (newPos == 0) + { + gUnknown_0203925C ^= 0x02; + DestroyVerticalScrollIndicator(0); + } + else + { + sub_810F290(); + } + if (newPos + maxItems < gUnknown_0203925A) + { + sub_810F2B4(); + } + else if (newPos + maxItems == gUnknown_0203925A) + { + gUnknown_0203925C ^= 0x01; + DestroyVerticalScrollIndicator(1); + } +} + +void SpawnCameraDummy(void) +{ + u8 mapObjectId = SpawnSpecialFieldObjectParametrized(7, 8, 0x7f, gSaveBlock1.pos.x + 7, gSaveBlock1.pos.y + 7, 3); + gMapObjects[mapObjectId].mapobj_bit_13 = 1; + CameraObjectSetFollowedObjectId(gMapObjects[mapObjectId].spriteId); +} + +void RemoveCameraDummy(void) +{ + CameraObjectSetFollowedObjectId(GetPlayerAvatarObjectId()); + RemoveFieldObjectByLocalIdAndMap(0x7f, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); +} + +u8 GetPokeblockNameByMonNature(void) +{ + return sub_810CB68(GetNature(&gPlayerParty[GetLeadMonIndex()]), gStringVar1); +} + +void GetSecretBaseNearbyMapName(void) +{ + GetMapSectionName(gStringVar1, VarGet(VAR_SECRET_BASE_MAP), 0); +} + +u16 sub_810F404(void) +{ + return GetGameStat(GAME_STAT_BATTLE_TOWER_BEST_STREAK); +} + +void sub_810F414(void) +{ + sub_8135FF4(gStringVar1); +} + +const u8 gUnknown_083F83E0[] = {12, 2, 4, 5, 1, 8, 7, 11, 3, 10, 9, 6}; +const u8 gUnknown_083F83EC[] = {0, 1, 1, 2, 2, 2, 3, 3, 3, 4, 4, 5}; +const u8 gUnknown_083F83F8[] = {3, 3, 3, 3, 3, 3, 4, 4, 4, 4, 5, 5}; + +u8 sub_810F424(void) +{ + u32 v0 = gSaveBlock1.easyChatPairs[0].unk0_0 + gSaveBlock1.easyChatPairs[0].unk2 + gUnknown_083F83E0[gSpecialVar_0x8004]; + if (GetPriceReduction(2)) + { + return gUnknown_083F83F8[v0 % 12]; + } + return gUnknown_083F83EC[v0 % 12]; +} + +bool8 sub_810F488(void) +{ + u16 *specVar = &gSpecialVar_0x8004; + u16 flag = 0x277; + *specVar = flag; + if (!FlagGet(flag)) + { + return FALSE; + } + return TRUE; +} + +bool8 sub_810F4B0(void) +{ + u16 *specVar = &gSpecialVar_0x8004; + u16 flag = 0x278; + *specVar = flag; + if (!FlagGet(flag)) + { + return FALSE; + } + return TRUE; +} + +bool8 sub_810F4D4(void) +{ + u16 *specVar = &gSpecialVar_0x8004; + u16 flag = 0x279; + *specVar = flag; + if (!FlagGet(flag)) + { + return FALSE; + } + return TRUE; +} + +bool8 sub_810F4FC(void) +{ + u16 *specVar = &gSpecialVar_0x8004; + u16 flag = 0x27a; + *specVar = flag; + if (!FlagGet(flag)) + { + return FALSE; + } + return TRUE; +} + +bool8 LeadMonHasEffortRibbon(void) +{ + return GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_EFFORT_RIBBON, NULL); +} + +void GivLeadMonEffortRibbon(void) +{ + bool8 ribbonSet; + IncrementGameStat(GAME_STAT_RECEIVED_RIBBONS); + FlagSet(SYS_RIBBON_GET); + ribbonSet = TRUE; + SetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_EFFORT_RIBBON, &ribbonSet); +} + +bool8 ScrSpecial_AreLeadMonEVsMaxedOut(void) +{ + if (GetMonEVCount(&gPlayerParty[GetLeadMonIndex()]) >= 510) + { + return TRUE; + } + return FALSE; +} + +u8 sub_810F5BC(void) +{ + if (!FlagGet(0xc7) && gSaveBlock1.location.mapGroup == MAP_GROUP_RUSTURF_TUNNEL && gSaveBlock1.location.mapNum == MAP_ID_RUSTURF_TUNNEL) + { + if (FlagGet(0x3a3)) + { + VarSet(VAR_0x409a, 4); + return TRUE; + } + else if (FlagGet(0x3a4)) + { + VarSet(VAR_0x409a, 5); + return TRUE; + } + } + return FALSE; +} + +void SetShoalItemFlag(u16 v0) +{ + FlagSet(0x85f); +} + +void PutZigzagoonInPlayerParty(void) +{ + u16 monData; + CreateMon(&gPlayerParty[0], SPECIES_ZIGZAGOON, 7, 0x20, FALSE, 0, FALSE, 0); + monData = TRUE; + SetMonData(&gPlayerParty[0], MON_DATA_ALT_ABILITY, (u8 *)&monData); + monData = MOVE_TACKLE; + SetMonData(&gPlayerParty[0], MON_DATA_MOVE1, (u8 *)&monData); + monData = MOVE_NONE; + SetMonData(&gPlayerParty[0], MON_DATA_MOVE2, (u8 *)&monData); + SetMonData(&gPlayerParty[0], MON_DATA_MOVE3, (u8 *)&monData); + SetMonData(&gPlayerParty[0], MON_DATA_MOVE4, (u8 *)&monData); +} + +bool8 IsStarterInParty(void) +{ + u8 i; + u16 starter = GetStarterPokemon(VarGet(VAR_FIRST_POKE)); + u8 partyCount = CalculatePlayerPartyCount(); + for (i = 0; i < partyCount; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) == starter) + { + return TRUE; + } + } + return FALSE; +} + +bool8 CheckFreePokemonStorageSpace(void) +{ + u16 i, j; + for (i=0; i<14; i++) + { + for (j=0; j<30; j++) + { + if (GetBoxMonData(&gPokemonStorage.boxes[i][j], MON_DATA_SPECIES, NULL) == SPECIES_NONE) + { + return TRUE; + } + } + } + return FALSE; +} + +bool8 IsPokerusInParty(void) +{ + if (!CheckPartyPokerus(gPlayerParty, 0x3f)) + { + return FALSE; + } + return TRUE; +} + +static void sub_810F7A8(u8); +static void sub_810F814(u8); + +void sub_810F758(void) +{ + u8 taskId = CreateTask(sub_810F7A8, 9); + gTasks[taskId].data[0] = gSpecialVar_0x8005; + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = 0; + gTasks[taskId].data[3] = 0; + gTasks[taskId].data[4] = gSpecialVar_0x8004; + gTasks[taskId].data[5] = 5; + SetCameraPanningCallback(NULL); + PlaySE(SE_W070); +} + +static void sub_810F7A8(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + task->data[1]++; + if ((task->data[1] % task->data[5]) == 0) + { + task->data[1] = 0; + task->data[2]++; + if (task->data[3] == 0) + { + task->data[0] = -task->data[0]; + task->data[4] = -task->data[4]; + SetCameraPanning(task->data[0], task->data[4]); + if (task->data[2] == 8) + { + sub_810F814(taskId); + InstallCameraPanAheadCallback(); + } + } + } +} + +static void sub_810F814(u8 taskId) +{ + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +bool8 sub_810F828(void) +{ + return FlagGet(0x2b8); +} + +void SetRoute119Weather(void) +{ + if (is_map_type_1_2_3_5_or_6(get_map_type_from_warp0()) != TRUE) + { + SetSav1Weather(0x14); + } +} + +void SetRoute123Weather(void) +{ + if (is_map_type_1_2_3_5_or_6(get_map_type_from_warp0()) != TRUE) + { + SetSav1Weather(0x15); + } +} + +u8 GetLeadMonIndex(void) +{ + u8 i; + u8 partyCount = CalculatePlayerPartyCount(); + for (i=0; i<partyCount; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != SPECIES_EGG && GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2, NULL) != 0) + { + return i; + } + } + return 0; +} + +u16 ScriptGetPartyMonSpecies(void) +{ + return GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPECIES2, NULL); +} + +void sub_810F8FC(void) +{ + sub_805ADDC(6); +} + +u16 sub_810F908(void) +{ + u16 var40c2 = VarGet(VAR_0x40C2); + if (gLocalTime.days - var40c2 >= 7) + { + return 0; + } + else if (gLocalTime.days < 0) + { + return 8; + } + return 7 - (gLocalTime.days - var40c2); +} + +u16 sub_810F950(void) +{ + VarSet(VAR_0x40C2, gLocalTime.days); + return gLocalTime.days; +} + +bool8 sub_810F96C(void) +{ + GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_OT_NAME, gStringVar1); + if (!StringCompareWithoutExtCtrlCodes(gSaveBlock2.playerName, gStringVar1)) + { + return FALSE; + } + return TRUE; +} + +void sub_810F9AC(void) +{ + if (gScriptResult >= 10000) + { + sub_80BF088(0, gScriptResult); + } + else if (gScriptResult >= 1000) + { + gStringVar1[0] = CHAR_0; + ConvertIntToDecimalStringN(gStringVar1 + 1, gScriptResult, 0, sub_80BF0B8(gScriptResult)); + } + else if (gScriptResult >= 100) + { + gStringVar1[0] = CHAR_0; + gStringVar1[1] = CHAR_0; + ConvertIntToDecimalStringN(gStringVar1 + 2, gScriptResult, 0, sub_80BF0B8(gScriptResult)); + } + else if (gScriptResult >= 10) + { + gStringVar1[0] = CHAR_0; + gStringVar1[1] = CHAR_0; + gStringVar1[2] = CHAR_0; + ConvertIntToDecimalStringN(gStringVar1 + 3, gScriptResult, 0, sub_80BF0B8(gScriptResult)); + } + else + { + gStringVar1[0] = CHAR_0; + gStringVar1[1] = CHAR_0; + gStringVar1[2] = CHAR_0; + gStringVar1[3] = CHAR_0; + ConvertIntToDecimalStringN(gStringVar1 + 4, gScriptResult, 0, sub_80BF0B8(gScriptResult)); + } +} + +const u8 gUnknown_083F8404[] = {2, 1, 2, 1}; +const u8 gUnknown_083F8408[] = {8, 9, 10, 11, 12, 13, 14, 15}; +const u8 gUnknown_083F8410[] = {8, 13, 14, 11, 10, 12, 15, 9}; + +bool8 sub_810FF30(void); +void sub_810FCE8(void); +void sub_810FF48(void); +void sub_810FD80(void); +u16 sub_810FCB0(void); +int sub_810FB9C(void); + +void ResetFanClub(void) +{ + gSaveBlock1.vars[0x41] = 0; + gSaveBlock1.vars[0x42] = 0; +} + +void sub_810FA74(void) +{ + if (sub_810FF30()) + { + sub_810FCE8(); + gSaveBlock1.vars[0x42] = gSaveBlock2.playTimeHours; + } +} + +void sub_810FAA0(void) +{ + if (!((gSaveBlock1.vars[0x41] >> 7) & 1)) + { + sub_810FF48(); + sub_810FD80(); + gSaveBlock1.vars[0x42] = gSaveBlock2.playTimeHours; + FlagClear(0x315); + FlagClear(0x316); + FlagClear(0x317); + FlagClear(0x318); + VarSet(VAR_0x4095, 1); + } +} + +u8 sub_810FB10(u8 a0) +{ + if (VarGet(VAR_0x4095) == 2) + { + if ((gSaveBlock1.vars[0x41] & 0x7f) + gUnknown_083F8404[a0] >= 20) + { + if (sub_810FCB0() < 3) + { + sub_810FB9C(); + gSaveBlock1.vars[0x41] &= 0xff80; + } + else + { + gSaveBlock1.vars[0x41] = (gSaveBlock1.vars[0x41] & 0xff80) | 20; + } + } + else + { + gSaveBlock1.vars[0x41] += gUnknown_083F8404[a0]; + } + } + return gSaveBlock1.vars[0x41] & 0x7f; +} + +int sub_810FB9C(void) +{ + u8 i; + int retval = 0; + for (i=0; i<8; i++) + { + if (!((gSaveBlock1.vars[0x41] >> gUnknown_083F8408[i]) & 0x01)) + { + retval = i; + if (Random() & 1) + { + gSaveBlock1.vars[0x41] |= (1 << gUnknown_083F8408[i]); + return retval; + } + } + } + gSaveBlock1.vars[0x41] |= (1 << gUnknown_083F8408[retval]); + return retval; +} + +int sub_810FC18(void) +{ + u8 i; + int retval = 0; + if (sub_810FCB0() == TRUE) + { + return 0; + } + for (i=0; i<8; i++) + { + if ((gSaveBlock1.vars[0x41] >> gUnknown_083F8410[i]) & 1) + { + retval = i; + if (Random() & 1) + { + gSaveBlock1.vars[0x41] ^= (1 << gUnknown_083F8410[i]); + return retval; + } + } + } + if ((gSaveBlock1.vars[0x41] >> gUnknown_083F8410[retval]) & 1) + { + gSaveBlock1.vars[0x41] ^= (1 << gUnknown_083F8410[retval]); + } + return retval; +} + +u16 sub_810FCB0(void) +{ + u8 i; + u8 retval = 0; + for (i=0; i<8; i++) + { + if ((gSaveBlock1.vars[0x41] >> (i + 8)) & 1) + { + retval ++; + } + } + return retval; +} + +void sub_810FCE8(void) +{ + u8 i = 0; + if (gSaveBlock2.playTimeHours < 999) + { + while (1) + { + if (sub_810FCB0() < 5) + { + gSaveBlock1.vars[0x42] = gSaveBlock2.playTimeHours; + break; + } + else if (i == 8) + { + break; + } + else if (gSaveBlock2.playTimeHours - gSaveBlock1.vars[0x42] < 12) + { + return; + } + sub_810FC18(); + gSaveBlock1.vars[0x42] += 12; + i++; + } + } +} + +bool8 sub_810FD60(void) +{ + return (gSaveBlock1.vars[0x41] >> gSpecialVar_0x8004) & 0x01; +} + +void sub_810FD80(void) +{ + gSaveBlock1.vars[0x41] |= 0x2000; + gSaveBlock1.vars[0x41] |= 0x100; + gSaveBlock1.vars[0x41] |= 0x400; +} + +void sub_810FE1C(void *, u8, u8); + +void sub_810FDAC(void) +{ + u8 a = 0; + u8 b = 0; + switch (gSpecialVar_0x8004) + { + case 8: + break; + case 9: + break; + case 10: + a = 0; + b = 3; + break; + case 11: + a = 0; + b = 1; + break; + case 12: + a = 1; + b = 0; + break; + case 13: + a = 0; + b = 4; + break; + case 14: + a = 1; + b = 5; + break; + case 15: + break; + } + sub_810FE1C(gSaveBlock1.linkBattleRecords, a, b); +} + +void sub_810FE1C(void *linkRecords, u8 a, u8 b) +{ + u8 *curRecord = (linkRecords + 16 * a); + if (*curRecord == EOS) + { + switch (b) + { + case 0: + StringCopy(gStringVar1, gOtherText_Wallace); + break; + case 1: + StringCopy(gStringVar1, gOtherText_Steven); + break; + case 2: + StringCopy(gStringVar1, gOtherText_Brawly); + break; + case 3: + StringCopy(gStringVar1, gOtherText_Winona); + break; + case 4: + StringCopy(gStringVar1, gOtherText_Phoebe); + break; + case 5: + StringCopy(gStringVar1, gOtherText_Glacia); + break; + default: + StringCopy(gStringVar1, gOtherText_Wallace); + break; + } + } + else + { + StringCopyN(gStringVar1, curRecord, 7); + gStringVar1[7] = EOS; + if (gStringVar1[0] == 0xfc && gStringVar1[1] == 0x15) + { + ConvertInternationalString(gStringVar1, 1); + } + } +} + +void sub_810FEFC(void) +{ + if (VarGet(VAR_0x4095) == 2) + { + sub_810FA74(); + if (gBattleOutcome == 1) + { + sub_810FB9C(); + } + else + { + sub_810FC18(); + } + } +} + +bool8 sub_810FF30(void) +{ + return (gSaveBlock1.vars[0x41] >> 7) & 0x01; +} + +void sub_810FF48(void) +{ + gSaveBlock1.vars[0x41] |= 0x80; +} + +u8 sub_810FF60(void) +{ + return sub_810FB10(gSpecialVar_0x8004); +} diff --git a/src/field/field_tasks.c b/src/field/field_tasks.c new file mode 100644 index 000000000..da6f162c2 --- /dev/null +++ b/src/field/field_tasks.c @@ -0,0 +1,868 @@ +// + +// + +#include "global.h" +#include "task.h" +#include "main.h" +#include "vars.h" +#include "bike.h" +#include "item.h" +#include "items.h" +#include "event_data.h" +#include "overworld.h" +#include "clock.h" +#include "script.h" +#include "field_special_scene.h" +#include "field_effect_helpers.h" +#include "secret_base.h" +#include "metatile_behavior.h" +#include "fieldmap.h" +#include "field_player_avatar.h" +#include "field_camera.h" +#include "songs.h" +#include "sound.h" +#include "field_tasks.h" + +void DummyPerStepCallback(u8); +void PerStepCallback_8069F64(u8); +void PerStepCallback_8069AA0(u8); +void PerStepCallback_8069864(u8); +void PerStepCallback_8069DD4(u8); +void PerStepCallback_806A07C(u8); + +void (*const gUnknown_08376364[])(u8) = { + DummyPerStepCallback, + PerStepCallback_8069F64, + PerStepCallback_8069AA0, + PerStepCallback_8069864, + PerStepCallback_8069DD4, + EndTruckSequence, + sub_80BCF1C, + PerStepCallback_806A07C +}; + +void Task_RunPerStepCallback(u8 taskId) +{ + int idx = gTasks[taskId].data[0]; + gUnknown_08376364[idx](taskId); +} + +#define tState data[0] +#define tAmbientCryState data[1] +#define tAmbientCryDelay data[2] + +static void RunTimeBasedEvents(s16 *data) +{ + switch (tState) + { + case 0: + if (gMain.vblankCounter1 & 0x1000) + { + DoTimeBasedEvents(); + tState++; + } + break; + case 1: + if (!(gMain.vblankCounter1 & 0x1000)) + { + tState--; + } + break; + } +} + +void Task_RunTimeBasedEvents(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + if (!ScriptContext2_IsEnabled()) + { + RunTimeBasedEvents(data); + UpdateAmbientCry(&tAmbientCryState, &tAmbientCryDelay); + } +} + +#undef tState +#undef tAmbientCryState +#undef tAmbientCryDelay + +void Task_MuddySlope(u8); + +void SetUpFieldTasks(void) +{ + if (!FuncIsActiveTask(Task_RunPerStepCallback)) + { + u8 taskId = CreateTask(Task_RunPerStepCallback, 0x50); + gTasks[taskId].data[0] = 0; + } + if (!FuncIsActiveTask(Task_MuddySlope)) + { + CreateTask(Task_MuddySlope, 0x50); + } + if (!FuncIsActiveTask(Task_RunTimeBasedEvents)) + { + CreateTask(Task_RunTimeBasedEvents, 0x50); + } +} + +void ActivatePerStepCallback(u8 callback) +{ + s16 *dataPointer; + s16 *dataStart; + s16 zero; + u8 taskId = FindTaskIdByFunc(Task_RunPerStepCallback); + if (taskId != 0xff) + { + dataStart = gTasks[taskId].data; + zero = 0; + dataPointer = &dataStart[15]; + do + { + *dataPointer-- = zero; + } while ((int)dataPointer >= (int)dataStart); + if (callback >= ARRAY_COUNT(gUnknown_08376364)) + { + *dataStart = 0; + } + else + { + *dataStart = callback; + } + } +} + +void ResetFieldTasksArgs(void) +{ + u8 taskId; + s16 *taskData; + taskId = FindTaskIdByFunc(Task_RunPerStepCallback); + if (taskId != 0xff) + { + taskData = gTasks[taskId].data; + } + taskId = FindTaskIdByFunc(Task_RunTimeBasedEvents); + if (taskId != 0xff) + { + taskData = gTasks[taskId].data; + taskData[1] = 0; + taskData[2] = 0; + } +} + +const struct MetatileOffset gUnknown_08376384[][2] = { + {{ 0, 0,0x259}, { 0, 1,0x261}}, + {{ 0, -1,0x259}, { 0, 0,0x261}}, + {{ 0, 0,0x252}, { 1, 0,0x253}}, + {{ -1, 0,0x252}, { 0, 0,0x253}} +}; + +const struct MetatileOffset gUnknown_083763A4[][2] = { + {{ 0, 0,0x25A}, { 0, 1,0x262}}, + {{ 0, -1,0x25A}, { 0, 0,0x262}}, + {{ 0, 0,0x254}, { 1, 0,0x255}}, + {{ -1, 0,0x254}, { 0, 0,0x255}} +}; + +const struct MetatileOffset gUnknown_083763C4[][2] = { + {{ 0, 0,0x258}, { 0, 1,0x260}}, + {{ 0, -1,0x258}, { 0, 0,0x260}}, + {{ 0, 0,0x250}, { 1, 0,0x251}}, + {{ -1, 0,0x250}, { 0, 0,0x251}} +}; + +void DummyPerStepCallback(u8 taskId) {} + +const struct MetatileOffset *sub_80695E0(const struct MetatileOffset a0[][2], s8 a1) +{ + if (sub_80576A0(a1)) + { + return a0[0]; + } + else if (sub_80576B4(a1)) + { + return a0[1]; + } + else if (sub_80576C8(a1)) + { + return a0[2]; + } + else if (sub_80576DC(a1)) + { + return a0[3]; + } + else + { + return NULL; + } +} + +#ifdef NONMATCHING +void sub_8069638(const struct MetatileOffset offsets[][2], s16 x, s16 y, bool32 flag) +{ + const struct MetatileOffset *offsetData = sub_80695E0(offsets, MapGridGetMetatileBehaviorAt(x, y)); + const struct MetatileOffset *offsetData2 = offsetData; + if (offsetData != NULL) + { + MapGridSetMetatileIdAt(x + offsetData[0].x, y + offsetData[0].y, offsetData[0].tileId); + if (flag) + { + CurrentMapDrawMetatileAt(x + offsetData[0].x, y + offsetData[0].y); + } + MapGridSetMetatileIdAt(x + offsetData2[1].x, y + offsetData2[1].y, offsetData2[1].tileId); + if (flag) + { + CurrentMapDrawMetatileAt(x + offsetData2[1].x, y + offsetData2[1].y); + } + } +} +#else +__attribute__((naked)) +void sub_8069638(const struct MetatileOffset offsets[][2], s16 x, s16 y, bool32 flag) +{ + asm_unified("\tpush {r4-r7,lr}\n" + "\tmov r7, r8\n" + "\tpush {r7}\n" + "\tadds r5, r0, 0\n" + "\tmov r8, r3\n" + "\tlsls r1, 16\n" + "\tasrs r6, r1, 16\n" + "\tlsls r2, 16\n" + "\tasrs r7, r2, 16\n" + "\tadds r0, r6, 0\n" + "\tadds r1, r7, 0\n" + "\tbl MapGridGetMetatileBehaviorAt\n" + "\tadds r1, r0, 0\n" + "\tlsls r1, 16\n" + "\tlsrs r1, 16\n" + "\tadds r0, r5, 0\n" + "\tbl sub_80695E0\n" + "\tadds r4, r0, 0\n" + "\tadds r5, r4, 0\n" + "\tcmp r4, 0\n" + "\tbeq _080696B6\n" + "\tmovs r0, 0\n" + "\tldrsb r0, [r4, r0]\n" + "\tadds r0, r6, r0\n" + "\tmovs r1, 0x1\n" + "\tldrsb r1, [r4, r1]\n" + "\tadds r1, r7, r1\n" + "\tldrh r2, [r4, 0x2]\n" + "\tbl MapGridSetMetatileIdAt\n" + "\tmov r0, r8\n" + "\tcmp r0, 0\n" + "\tbeq _0806968E\n" + "\tmovs r0, 0\n" + "\tldrsb r0, [r4, r0]\n" + "\tadds r0, r6, r0\n" + "\tmovs r1, 0x1\n" + "\tldrsb r1, [r4, r1]\n" + "\tadds r1, r7, r1\n" + "\tbl CurrentMapDrawMetatileAt\n" + "_0806968E:\n" + "\tmovs r0, 0x4\n" + "\tldrsb r0, [r5, r0]\n" + "\tadds r0, r6, r0\n" + "\tmovs r1, 0x5\n" + "\tldrsb r1, [r5, r1]\n" + "\tadds r1, r7, r1\n" + "\tldrh r2, [r5, 0x6]\n" + "\tbl MapGridSetMetatileIdAt\n" + "\tmov r0, r8\n" + "\tcmp r0, 0\n" + "\tbeq _080696B6\n" + "\tmovs r0, 0x4\n" + "\tldrsb r0, [r5, r0]\n" + "\tadds r0, r6, r0\n" + "\tmovs r1, 0x5\n" + "\tldrsb r1, [r5, r1]\n" + "\tadds r1, r7, r1\n" + "\tbl CurrentMapDrawMetatileAt\n" + "_080696B6:\n" + "\tpop {r3}\n" + "\tmov r8, r3\n" + "\tpop {r4-r7}\n" + "\tpop {r0}\n" + "\tbx r0"); +} +#endif + +void sub_80696C0(s16 x, s16 y, bool32 flag) +{ + sub_8069638(gUnknown_08376384, x, y, flag); +} + +void sub_80696E4(s16 x, s16 y, bool32 flag) +{ + sub_8069638(gUnknown_083763A4, x, y, flag); +} + +void sub_8069708(s16 x, s16 y, bool32 flag) +{ + sub_8069638(gUnknown_083763C4, x, y, flag); +} + +bool32 sub_806972C(s16 x1, s16 y1, s16 x2, s16 y2) +{ + s8 metatileBehavior = MapGridGetMetatileBehaviorAt(x2, y2); + if (sub_80576A0(metatileBehavior)) + { + if (y1 > y2) + { + return FALSE; + } + } + else if (sub_80576B4(metatileBehavior)) + { + if (y1 < y2) + { + return FALSE; + } + } + else if (sub_80576C8(metatileBehavior)) + { + if (x1 > x2) + { + return FALSE; + } + } + else if (sub_80576DC(metatileBehavior)) + { + if (x1 < x2) + { + return FALSE; + } + } + return TRUE; +} + +bool32 sub_80697C8(s16 x1, s16 y1, s16 x2, s16 y2) +{ + s8 metatileBehavior = MapGridGetMetatileBehaviorAt(x1, y1); + if (sub_80576A0(metatileBehavior)) + { + if (y1 < y2) + { + return FALSE; + } + } + else if (sub_80576B4(metatileBehavior)) + { + if (y1 > y2) + { + return FALSE; + } + } + else if (sub_80576C8(metatileBehavior)) + { + if (x1 < x2) + { + return FALSE; + } + } + else if (sub_80576DC(metatileBehavior)) + { + if (x1 > x2) + { + return FALSE; + } + } + return TRUE; +} + +void PerStepCallback_8069864(u8 taskId) +{ + s16 *data; + s16 x, y; + data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + switch (data[1]) + { + case 0: + data[2] = x; + data[3] = y; + sub_80696E4(x, y, TRUE); + data[1] = 1; + break; + case 1: + if (x != data[2] || y != data[3]) + { + if (sub_806972C(x, y, data[2], data[3])) + { + sub_80696C0(data[2], data[3], TRUE); + sub_8069708(data[2], data[3], FALSE); + data[4] = data[2]; + data[5] = data[3]; + data[1] = 2; + data[6] = 8; + } + else + { + data[4] = -1; + data[5] = -1; + } + if (sub_80697C8(x, y, data[2], data[3])) + { + sub_80696C0(x, y, TRUE); + data[1] = 2; + data[6] = 8; + } + data[2] = x; + data[3] = y; + if (MetatileBehavior_IsPacifidlogLog(MapGridGetMetatileBehaviorAt(x, y))) + { + PlaySE(SE_MIZU); + } + } + break; + case 2: + if ((--data[6]) == 0) + { + sub_80696E4(x, y, TRUE); + if (data[4] != -1 && data[5] != -1) + { + sub_8069708(data[4], data[5], TRUE); + } + data[1] = 1; + } + break; + } +} + +void sub_80699D8(s16 x, s16 y) +{ + u8 z = PlayerGetZCoord(); + if (!(z & 0x01)) + { + switch (MapGridGetMetatileIdAt(x, y)) + { + case 0x24e: + MapGridSetMetatileIdAt(x, y, 0x24f); + break; + case 0x256: + MapGridSetMetatileIdAt(x, y, 0x257); + break; + } + } +} + +void sub_8069A3C(s16 x, s16 y) +{ + u8 z = PlayerGetZCoord(); + if (!(z & 0x01)) + { + switch (MapGridGetMetatileIdAt(x, y)) + { + case 0x24f: + MapGridSetMetatileIdAt(x, y, 0x24e); + break; + case 0x257: + MapGridSetMetatileIdAt(x, y, 0x256); + break; + } + } +} + +void PerStepCallback_8069AA0(u8 taskId) +{ + bool8 isFortreeBridgeCur; + bool8 isFortreeBridgePrev; + u8 z, flag; + s16 x, y, x2, y2; + s16 *data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + switch (data[1]) + { + default: + break; + case 0: + data[2] = x; + data[3] = y; + if (MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x, y))) + { + sub_80699D8(x, y); + CurrentMapDrawMetatileAt(x, y); + } + data[1] = 1; + break; + case 1: + x2 = data[2]; + y2 = data[3]; + if (x == x2 && y == y2) + { + break; + } + isFortreeBridgeCur = MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x, y)); + isFortreeBridgePrev = MetatileBehavior_IsFortreeBridge(MapGridGetMetatileBehaviorAt(x2, y2)); + z = PlayerGetZCoord(); + flag = 0; + if ((u8)(z & 1) == 0) + { + flag = 1; + } + if (flag && (isFortreeBridgeCur == 1 || isFortreeBridgePrev == 1)) + { + PlaySE(SE_HASHI); + } + if (isFortreeBridgePrev) + { + sub_8069A3C(x2, y2); + CurrentMapDrawMetatileAt(x2, y2); + sub_80699D8(x, y); + CurrentMapDrawMetatileAt(x, y); + } + data[4] = x2; + data[5] = y2; + data[2] = x; + data[3] = y; + if (!isFortreeBridgePrev) + { + break; + } + data[6] = 16; + data[1] = 2; + // fallthrough + case 2: + data[6]--; + x2 = data[4]; + y2 = data[5]; + switch (data[6] % 7) + { + case 0: + CurrentMapDrawMetatileAt(x2, y2); + case 1: + case 2: + case 3: + break; + case 4: + sub_80699D8(x2, y2); + CurrentMapDrawMetatileAt(x2, y2); + sub_8069A3C(x2, y2); + case 5: + case 6: + case 7: + break; + } + if (data[6] == 0) + { + data[1] = 1; + } + break; + } +} + +const u16 gUnknown_083763E4[] = { + 0, + 0, + 0, + 0, + 0, + 0, + VAR_0x4001, + VAR_0x4002, + VAR_0x4003, + VAR_0x4004, + 0, + 0, + VAR_0x4005, + VAR_0x4006, + VAR_0x4007, + 0, + 0, + VAR_0x4008, + VAR_0x4009, + VAR_0x400A, + 0, + 0, + 0, + 0, + 0, + 0 +}; + +bool32 sub_8069CB8(s16 x, s16 y) +{ + if ((u16)(x - 3) < 11 && (u16)(y - 6) < 14 && gUnknown_083763E4[y]) + { + return TRUE; + } + return FALSE; +} + +void sub_8069CFC(s16 x, s16 y) +{ + if (sub_8069CB8(x, y)) + { + *GetVarPointer(gUnknown_083763E4[y]) |= (1 << (x - 3)); + } +} + +bool32 sub_8069D34(s16 x, s16 y) +{ + u32 var; + if (!sub_8069CB8(x, y)) + { + return FALSE; + } + var = VarGet(gUnknown_083763E4[y]) << 16; + if (((1 << 16) << (x - 3)) & var) + { + return TRUE; + } + return FALSE; +} + +void sub_8069D78(void) +{ + s32 x, y; + s32 width = gMapHeader.mapData->width; + s32 height = gMapHeader.mapData->height; + for (x=0; x<width; x++) + { + for (y=0; y<height; y++) + { + if (sub_8069D34(x, y) == TRUE) + { + MapGridSetMetatileIdAt(x + 7, y + 7, 0x20e); + } + } + } +} + +void PerStepCallback_8069DD4(u8 taskId) +{ + s16 x, y; + u16 tileBehavior; + u16 *var; + s16 *data = gTasks[taskId].data; + switch (data[1]) + { + case 0: + PlayerGetDestCoords(&x, &y); + data[2] = x; + data[3] = y; + data[1] = 1; + break; + case 1: + PlayerGetDestCoords(&x, &y); + if (x != data[2] || y != data[3]) + { + data[2] = x; + data[3] = y; + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + var = GetVarPointer(VAR_ICE_STEP_COUNT); + if (MetatileBehavior_IsThinIce(tileBehavior) == TRUE) + { + (*var)++; + data[6] = 4; + data[1] = 2; + data[4] = x; + data[5] = y; + } + else if (MetatileBehavior_IsCrackedIce(tileBehavior) == TRUE) + { + *var = 0; + data[6] = 4; + data[1] = 3; + data[4] = x; + data[5] = y; + } + } + break; + case 2: + if (data[6] != 0) + { + data[6]--; + } + else + { + x = data[4]; + y = data[5]; + PlaySE(SE_RU_BARI); + MapGridSetMetatileIdAt(x, y, 0x20e); + CurrentMapDrawMetatileAt(x, y); + sub_8069CFC(x - 7, y - 7); + data[1] = 1; + } + break; + case 3: + if (data[6] != 0) + { + data[6]--; + } + else + { + x = data[4]; + y = data[5]; + PlaySE(SE_RU_GASYAN); + MapGridSetMetatileIdAt(x, y, 0x206); + CurrentMapDrawMetatileAt(x, y); + data[1] = 1; + } + break; + } +} + +void PerStepCallback_8069F64(u8 taskId) +{ + s16 x, y; + u16 *var; + s16 *data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + if (x != data[1] || y != data[2]) + { + data[1] = x; + data[2] = y; + if (MetatileBehavior_IsAshGrass(MapGridGetMetatileBehaviorAt(x, y))) + { + if (MapGridGetMetatileIdAt(x, y) == 0x20a) + { + ash(x, y, 0x212, 4); + } + else + { + ash(x, y, 0x206, 4); + } + if (CheckBagHasItem(ITEM_SOOT_SACK, 1)) + { + var = GetVarPointer(VAR_ASH_GATHER_COUNT); + if (*var < 9999) + { + (*var)++; + } + } + } + } +} + +void sub_806A040(s16 x, s16 y) +{ + MapGridSetMetatileIdAt(x, y, MapGridGetMetatileIdAt(x, y) == 0x22f ? 0x206 : 0x237); + CurrentMapDrawMetatileAt(x, y); +} + +void PerStepCallback_806A07C(u8 taskId) +{ + s16 x, y; + u16 behavior; + s16 *data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + behavior = MapGridGetMetatileBehaviorAt(x, y); + if (data[4] != 0 && (--data[4]) == 0) + { + sub_806A040(data[5], data[6]); + } + if (data[7] != 0 && (--data[7]) == 0) + { + sub_806A040(data[8], data[9]); + } + if (MetatileBehavior_IsCrackedFloorHole(behavior)) + { + VarSet(VAR_ICE_STEP_COUNT, 0); // this var does double duty + } + if ((x != data[2] || y != data[3])) + { + data[2] = x; + data[3] = y; + if (MetatileBehavior_IsCrackedFloor(behavior)) + { + if (GetPlayerSpeed() != 4) + { + VarSet(VAR_ICE_STEP_COUNT, 0); // this var does double duty + } + if (data[4] == 0) + { + data[4] = 3; + data[5] = x; + data[6] = y; + } + else if (data[7] == 0) + { + data[7] = 3; + data[8] = x; + data[9] = y; + } + } + } +} + +const u16 gUnknown_08376418[] = {0xe8, 0xeb, 0xea, 0xe9}; + +void sub_806A18C(s16 *data, s16 x, s16 y) +{ + u16 tile; + if ((--data[0]) == 0) + { + tile = 0xe8; + } + else + { + tile = gUnknown_08376418[data[0] / 8]; + } + MapGridSetMetatileIdAt(x, y, tile); + CurrentMapDrawMetatileAt(x, y); + MapGridSetMetatileIdAt(x, y, 0xe8); +} + +void Task_MuddySlope(u8 taskId) +{ + s16 x, y, x2, y2; + int i; + u16 mapIndices; + s16 *data = gTasks[taskId].data; + PlayerGetDestCoords(&x, &y); + mapIndices = (gSaveBlock1.location.mapGroup << 8) | gSaveBlock1.location.mapNum; + switch (data[1]) + { + case 0: + data[0] = mapIndices; + data[2] = x; + data[3] = y; + data[1] = 1; + data[4] = 0; + data[7] = 0; + data[10] = 0; + data[13] = 0; + break; + case 1: + if (data[2] != x || data[3] != y) + { + data[2] = x; + data[3] = y; + if (MetatileBehavior_IsMuddySlope(MapGridGetMetatileBehaviorAt(x, y))) + { + for (i=4; i<14; i+=3) + { + if (data[i] == 0) + { + data[i] = 32; + data[i + 1] = x; + data[i + 2] = y; + break; + } + } + } + } + break; + } + if (gCamera.field_0 && mapIndices != data[0]) + { + data[0] = mapIndices; + x2 = gCamera.x; + y2 = gCamera.y; + } + else + { + x2 = 0; + y2 = 0; + } + for (i=4; i<14; i+=3) + { + if (data[i]) + { + data[i + 1] -= x2; + data[i + 2] -= y2; + sub_806A18C(&data[i], data[i + 1], data[i + 2]); + } + } +} diff --git a/src/field/field_weather.c b/src/field/field_weather.c new file mode 100644 index 000000000..443a38357 --- /dev/null +++ b/src/field/field_weather.c @@ -0,0 +1,367 @@ +#include "global.h" +#include "field_weather.h" +#include "palette.h" +#include "sprite.h" +#include "task.h" + +struct Weather +{ + u8 filler_000[0x200]; + u8 unknown_200[2][32]; + u8 filler_240[0x480]; + s8 unknown_6C0; + s8 unknown_6C1; + u8 unknown_6C2; + u8 unknown_6C3; + u16 unknown_6C4; + u8 unknown_6C6; + u8 unknown_6C7; + u8 unknown_6C8; + u8 unknown_6C9; + u8 unknown_6CA; + u8 unknown_6CB; + u8 filler_6CC[2]; + u16 unknown_6CE; + u8 unknown_6D0; + u8 unknown_6D1; + u8 filler_6D2[1]; + u8 unknown_6D3; + u8 unknown_6D4; + u8 unknown_6D5; + u8 filler_6D6[2]; + u8 unknown_6D8; + u8 filler_6D9[1]; + u8 unknown_6DA; + u8 filler_6DB[3]; + u8 unknown_6DE; + u8 filler_6DF[5]; + u8 unknown_6E4; + u8 filler_6E5[0x15]; + u8 unknown_6FA; + u8 unknown_6FB; + u8 filler_6FC[4]; + u8 unknown_700; + u8 filler_701[0x15]; + u8 unknown_716; + u8 unknown_717; + u8 filler_718[0xc]; + u8 unknown_724; + u8 filler_725[9]; + u8 unknown_72E; +}; + +#define gWeather gUnknown_0202F7E8 +extern struct Weather gWeather; +extern u8 *gUnknown_083970E8; +extern u8 (*gUnknown_08396FC8[][4])(void); +extern u8 (*gUnknown_083970B8[])(void); +IWRAM_DATA u8 *gUnknown_030006DC; +extern u8 gUnknown_083970C8; +extern u8 (*gUnknown_0202FC48)[32]; +extern u8 gUnknown_0202F9E8[32]; + + +void sub_807C828(void) +{ + u8 index; + if (!FuncIsActiveTask(&sub_807CA34)) + { + index = AllocSpritePalette(0x1200); + CpuCopy32(&gUnknown_083970E8, &gPlttBufferUnfaded[0x100 + index * 16], 32); + sub_807CB10(); + gWeather.unknown_6D5 = index; + gWeather.unknown_6D4 = AllocSpritePalette(0x1201); + gWeather.unknown_6DA = 0; + gWeather.unknown_6D8 = 0; + gWeather.unknown_6DE = 0; + gWeather.unknown_6E4 = 0; + gWeather.unknown_700 = 0; + gWeather.unknown_6FB = 0; + gWeather.unknown_724 = 0; + gWeather.unknown_716 = 0; + gWeather.unknown_717 = 0; + gWeather.unknown_72E = 0; + gWeather.unknown_6FA = 0; + sub_807DB64(16, 0); + gWeather.unknown_6D0 = 0; + gWeather.unknown_6C6 = 3; + gWeather.unknown_6C8 = 0; + gWeather.unknown_6D3 = 1; + gWeather.unknown_6C9 = CreateTask(&sub_807C9E4, 80); + } +} + +void DoWeatherEffect(u8 effect) +{ + if (effect != 3 && effect != 5 && effect != 13) + { + PlayRainSoundEffect(); + } + if (gWeather.unknown_6D1 != effect && gWeather.unknown_6D0 == effect) + { + gUnknown_08396FC8[effect][0](); + } + gWeather.unknown_6D3 = 0; + gWeather.unknown_6D1 = effect; + gWeather.unknown_6CE = 0; +} + +void sub_807C988(u8 effect) +{ + PlayRainSoundEffect(); + gWeather.unknown_6D0 = effect; + gWeather.unknown_6D1 = effect; +} + +void sub_807C9B4(u8 effect) +{ + PlayRainSoundEffect(); + gWeather.unknown_6D0 = effect; + gWeather.unknown_6D1 = effect; + gWeather.unknown_6C8 = 1; +} + +void sub_807C9E4(u8 task) +{ + if (gWeather.unknown_6C8) + { + gUnknown_08396FC8[gWeather.unknown_6D0][2](); + gTasks[task].func = &sub_807CA34; + } +} + +void sub_807CA34(u8 task) +{ + u8 v1; + if (gWeather.unknown_6D0 != gWeather.unknown_6D1) + { + v1 = gUnknown_08396FC8[gWeather.unknown_6D0][3](); + if (!v1) + { + gUnknown_08396FC8[gWeather.unknown_6D1][0](); + gWeather.unknown_6C3 = 0; // compiler reuses v1 + gWeather.unknown_6C6 = 0; // compiler reuses v1 + gWeather.unknown_6D0 = gWeather.unknown_6D1; + gWeather.unknown_6D3 = 1; + } + } + else + { + gUnknown_08396FC8[gWeather.unknown_6D0][1](); + } + gUnknown_083970B8[gWeather.unknown_6C6](); +} + +void sub_807CAE8(void) +{ + gWeather.unknown_6C1 = 0; + gWeather.unknown_6C2 = 0; +} + +void nullsub_38(void) +{ +} + +u32 sub_807CB0C(void) +{ + return 0; +} + +void sub_807CB10(void) +{ + u16 v0; + u8(*v1)[32]; + u16 v2; + u16 v4; + u16 v5; + u16 v6; + u16 v9; + u32 v10; + u16 v11; + s16 dunno; + + gUnknown_030006DC = &gUnknown_083970C8; + for (v0 = 0; v0 <= 1; v0++) + { + if (v0 == 0) + { + v1 = &gUnknown_0202F9E8; + } + else + { + v1 = &gUnknown_0202F9E8 + 19; + } + for (v2 = 0; (u16)v2 <= 0x1f; v2++) + { + v4 = v2 << 8; + if (v0 == 0) + { + v5 = (v2 << 8) / 16; + } + else + { + v5 = 0; + } + v6 = 0; + for (; v6 <= 2; v6++) + { + v4 = (v4 - v5); + v1[v6][v2] = v4 >> 8; + } + v9 = v4; + v10 = 0x1f00 - v4; + if ((0x1f00 - v4) < 0) + { + v10 += 0xf; + } + v11 = v10 >> 4; + if (v2 <= 0xb) + { + for (; v6 <= 0x12; v6++) + { + v4 += v11; + dunno = v4 - v9; + if (dunno > 0) + { + v4 -= (dunno + ((u16)dunno >> 15)) >> 1; + } + v1[v6][v2] = v4 >> 8; + if (v1[v6][v2] > 0x1f) + { + v1[v6][v2] = 0x1f; + } + } + } + else + { + for (; v6 <= 0x12; v6++) + { + v4 += v11; + v1[v6][v2] = v4 >> 8; + if (v1[v6][v2] > 0x1f) + { + v1[v6][v2] = 0x1f; + } + } + } + } + } +} + +void sub_807CC24(void) +{ + if (gWeather.unknown_6C0 == gWeather.unknown_6C1) + { + gWeather.unknown_6C6 = 3; + } + else + { + if (++gWeather.unknown_6C3 >= gWeather.unknown_6C2) + { + gWeather.unknown_6C3 = 0; + if (gWeather.unknown_6C0 < gWeather.unknown_6C1) + { + gWeather.unknown_6C0++; + } + else + { + gWeather.unknown_6C0--; + } + sub_807CEBC(0, 0x20, gWeather.unknown_6C0); + } + } +} + +void sub_807CCAC(void) +{ + if (++gWeather.unknown_6CB > 1) + { + gWeather.unknown_6CA = 0; + } + switch (gWeather.unknown_6D0) + { + case 3: + case 4: + case 5: + case 11: + case 13: + if (sub_807CDC4() == 0) + { + gWeather.unknown_6C0 = 3; + gWeather.unknown_6C6 = 3; + } + break; + case 12: + if (sub_807CE24() == 0) + { + gWeather.unknown_6C0 = -6; + gWeather.unknown_6C6 = 3; + } + break; + case 6: + if (sub_807CE7C() == 0) + { + gWeather.unknown_6C0 = 0; + gWeather.unknown_6C6 = 3; + } + break; + case 7: + case 8: + case 9: + case 10: + default: + if (!gPaletteFade.active) + { + gWeather.unknown_6C0 = gWeather.unknown_6C1; + gWeather.unknown_6C6 = 3; + } + break; + } +} + +u8 sub_807CDC4(void) +{ + if (gWeather.unknown_6C7 == 0x10) + { + return 0; + } + if (++gWeather.unknown_6C7 >= 0x10) + { + sub_807CEBC(0, 0x20, 3); + gWeather.unknown_6C7 = 0x10; + return 0; + } + sub_807D1BC(0, 0x20, 3, 0x10 - gWeather.unknown_6C7, gWeather.unknown_6C4); + return 1; +} + +u8 sub_807CE24(void) +{ + if (gWeather.unknown_6C7 == 0x10) + { + return 0; + } + if (++gWeather.unknown_6C7 >= 0x10) + { + sub_807CEBC(0, 0x20, -6); + gWeather.unknown_6C7 = 0x10; + return 0; + } + sub_807D304(-6, 0x10 - gWeather.unknown_6C7, gWeather.unknown_6C4); + return 1; +} + +u8 sub_807CE7C(void) +{ + if (gWeather.unknown_6C7 == 0x10) + { + return 0; + } + ++gWeather.unknown_6C7; + sub_807D424(0x10 - gWeather.unknown_6C7, gWeather.unknown_6C4); + return 1; +} + +void nullsub_39(void) +{ +} diff --git a/src/field/fieldmap.c b/src/field/fieldmap.c new file mode 100644 index 000000000..7a31ae720 --- /dev/null +++ b/src/field/fieldmap.c @@ -0,0 +1,955 @@ +#include "global.h" +#include "fieldmap.h" +#include "palette.h" +#include "overworld.h" +#include "script.h" +#include "secret_base.h" +#include "tv.h" + +struct ConnectionFlags +{ + u8 south:1; + u8 north:1; + u8 west:1; + u8 east:1; +}; + +struct Coords32 +{ + s32 x; + s32 y; +}; + +EWRAM_DATA static u16 gUnknown_02029828[0x2800] = {0}; +EWRAM_DATA struct MapHeader gMapHeader = {0}; +EWRAM_DATA struct Camera gCamera = {0}; +EWRAM_DATA static struct ConnectionFlags gUnknown_0202E850 = {0}; + +struct BackupMapData gUnknown_03004870; + +static const struct ConnectionFlags sDummyConnectionFlags = {0}; + +struct MapHeader *mapconnection_get_mapheader(struct MapConnection *connection) +{ + return Overworld_GetMapHeaderByGroupAndId(connection->mapGroup, connection->mapNum); +} + +void not_trainer_hill_battle_pyramid(void) +{ + mapheader_copy_mapdata_with_padding(&gMapHeader); + sub_80BB970(gMapHeader.events); + mapheader_run_script_with_tag_x1(); +} + +void sub_8055FC0(void) +{ + mapheader_copy_mapdata_with_padding(&gMapHeader); + sub_80BBCCC(0); + sub_80BB970(gMapHeader.events); + sub_8056670(); + mapheader_run_script_with_tag_x1(); + UpdateTVScreensOnMap(gUnknown_03004870.width, gUnknown_03004870.height); +} + +void mapheader_copy_mapdata_with_padding(struct MapHeader *mapHeader) +{ + struct MapData *mapData; + int width; + int height; + mapData = mapHeader->mapData; + CpuFastFill16(0x03ff, gUnknown_02029828, sizeof(gUnknown_02029828)); + gUnknown_03004870.map = gUnknown_02029828; + width = mapData->width + 15; + gUnknown_03004870.width = width; + height = mapData->height + 14; + gUnknown_03004870.height = height; + if (width * height <= 0x2800) + { + map_copy_with_padding(mapData->map, mapData->width, mapData->height); + sub_80560AC(mapHeader); + } +} + +void map_copy_with_padding(u16 *map, u16 width, u16 height) +{ + u16 *dest; + int y; + dest = gUnknown_03004870.map; + dest += gUnknown_03004870.width * 7 + 7; + for (y = 0; y < height; y++) + { + CpuCopy16(map, dest, width * 2); + dest += width + 0xf; + map += width; + } +} + +void sub_80560AC(struct MapHeader *mapHeader) +{ + int i; + struct MapConnection *connection; + struct MapHeader *cMap; + u32 offset; + int count; + count = mapHeader->connections->count; + connection = mapHeader->connections->connections; + gUnknown_0202E850 = sDummyConnectionFlags; + for (i = 0; i < count; i++, connection++) + { + cMap = mapconnection_get_mapheader(connection); + offset = connection->offset; + switch (connection->direction) + { + case CONNECTION_SOUTH: + fillSouthConnection(mapHeader, cMap, offset); + gUnknown_0202E850.south = 1; + break; + case CONNECTION_NORTH: + fillNorthConnection(mapHeader, cMap, offset); + gUnknown_0202E850.north = 1; + break; + case CONNECTION_WEST: + fillWestConnection(mapHeader, cMap, offset); + gUnknown_0202E850.west = 1; + break; + case CONNECTION_EAST: + fillEastConnection(mapHeader, cMap, offset); + gUnknown_0202E850.east = 1; + break; + } + } +} + +void sub_8056134(int x, int y, struct MapHeader *mapHeader, int x2, int y2, int width, int height) +{ + int i; + u16 *src; + u16 *dest; + int mapWidth; + + mapWidth = mapHeader->mapData->width; + src = &mapHeader->mapData->map[mapWidth * y2 + x2]; + dest = &gUnknown_03004870.map[gUnknown_03004870.width * y + x]; + + for (i = 0; i < height; i++) + { + CpuCopy16(src, dest, width * 2); + dest += gUnknown_03004870.width; + src += mapWidth; + } +} + +void fillSouthConnection(struct MapHeader *mapHeader, struct MapHeader *connectedMapHeader, s32 offset) +{ + int x, y; + int x2; + int width; + int cWidth; + + if (connectedMapHeader) + { + cWidth = connectedMapHeader->mapData->width; + x = offset + 7; + y = mapHeader->mapData->height + 7; + if (x < 0) + { + x2 = -x; + x += cWidth; + if (x < gUnknown_03004870.width) + { + width = x; + } + else + { + width = gUnknown_03004870.width; + } + x = 0; + } + else + { + x2 = 0; + if (x + cWidth < gUnknown_03004870.width) + { + width = cWidth; + } + else + { + width = gUnknown_03004870.width - x; + } + } + sub_8056134( + x, y, + connectedMapHeader, + x2, /*y2*/ 0, + width, /*height*/ 7); + } +} + +void fillNorthConnection(struct MapHeader *mapHeader, struct MapHeader *connectedMapHeader, s32 offset) +{ + int x; + int x2, y2; + int width; + int cWidth, cHeight; + + if (connectedMapHeader) + { + cWidth = connectedMapHeader->mapData->width; + cHeight = connectedMapHeader->mapData->height; + x = offset + 7; + y2 = cHeight - 7; + if (x < 0) + { + x2 = -x; + x += cWidth; + if (x < gUnknown_03004870.width) + { + width = x; + } + else + { + width = gUnknown_03004870.width; + } + x = 0; + } + else + { + x2 = 0; + if (x + cWidth < gUnknown_03004870.width) + { + width = cWidth; + } + else + { + width = gUnknown_03004870.width - x; + } + } + + sub_8056134( + x, /*y*/ 0, + connectedMapHeader, + x2, y2, + width, /*height*/ 7); + + } +} + + +void fillWestConnection(struct MapHeader *mapHeader, struct MapHeader *connectedMapHeader, s32 offset) +{ + int y; + int x2, y2; + int height; + int cWidth, cHeight; + if (connectedMapHeader) + { + cWidth = connectedMapHeader->mapData->width; + cHeight = connectedMapHeader->mapData->height; + y = offset + 7; + x2 = cWidth - 7; + if (y < 0) + { + y2 = -y; + if (y + cHeight < gUnknown_03004870.height) + { + height = y + cHeight; + } + else + { + height = gUnknown_03004870.height; + } + y = 0; + } + else + { + y2 = 0; + if (y + cHeight < gUnknown_03004870.height) + { + height = cHeight; + } + else + { + height = gUnknown_03004870.height - y; + } + } + + sub_8056134( + /*x*/ 0, y, + connectedMapHeader, + x2, y2, + /*width*/ 7, height); + } +} + +void fillEastConnection(struct MapHeader *mapHeader, struct MapHeader *connectedMapHeader, s32 offset) +{ + int x, y; + int y2; + int height; + int cHeight; + if (connectedMapHeader) + { + cHeight = connectedMapHeader->mapData->height; + x = mapHeader->mapData->width + 7; + y = offset + 7; + if (y < 0) + { + y2 = -y; + if (y + cHeight < gUnknown_03004870.height) + { + height = y + cHeight; + } + else + { + height = gUnknown_03004870.height; + } + y = 0; + } + else + { + y2 = 0; + if (y + cHeight < gUnknown_03004870.height) + { + height = cHeight; + } + else + { + height = gUnknown_03004870.height - y; + } + } + + sub_8056134( + x, y, + connectedMapHeader, + /*x2*/ 0, y2, + /*width*/ 8, height); + } +} + +union Block +{ + struct + { + u16 block:10; + u16 collision:2; + u16 elevation:4; + } block; + u16 value; +}; + +u8 MapGridGetZCoordAt(int x, int y) +{ + u16 block; + int i; + u16 *border; + + if (x >= 0 && x < gUnknown_03004870.width + && y >= 0 && y < gUnknown_03004870.height) + { + block = gUnknown_03004870.map[x + gUnknown_03004870.width * y]; + } + else + { + border = gMapHeader.mapData->border; + i = (x + 1) & 1; + i += ((y + 1) & 1) * 2; + block = gMapHeader.mapData->border[i]; + block |= 0xc00; + } + if (block == 0x3ff) + { + return 0; + } + return block >> 12; +} + +u8 MapGridIsImpassableAt(int x, int y) +{ + u16 block; + int i; + u16 *border; + + if (x >= 0 && x < gUnknown_03004870.width + && y >= 0 && y < gUnknown_03004870.height) + { + block = gUnknown_03004870.map[x + gUnknown_03004870.width * y]; + } + else + { + border = gMapHeader.mapData->border; + i = (x + 1) & 1; + i += ((y + 1) & 1) * 2; + block = gMapHeader.mapData->border[i]; + block |= 0xc00; + } + if (block == 0x3ff) + { + return 1; + } + return (block & 0xc00) >> 10; +} + +u32 MapGridGetMetatileIdAt(int x, int y) +{ + u16 block; + int i; + int j; + struct MapData *mapData; + u16 *border; + u16 block2; + + if (x >= 0 && x < gUnknown_03004870.width + && y >= 0 && y < gUnknown_03004870.height) + { + block = gUnknown_03004870.map[x + gUnknown_03004870.width * y]; + } + else + { + mapData = gMapHeader.mapData; + i = (x + 1) & 1; + i += ((y + 1) & 1) * 2; + block = mapData->border[i] | 0xc00; + } + if (block == 0x3ff) + { + border = gMapHeader.mapData->border; + j = (x + 1) & 1; + j += ((y + 1) & 1) * 2; + block2 = gMapHeader.mapData->border[j]; + block2 |= 0xc00; + return block2 & block; + } + return block & 0x3ff; +} + +u32 MapGridGetMetatileBehaviorAt(int x, int y) +{ + u16 metatile; + metatile = MapGridGetMetatileIdAt(x, y); + return GetBehaviorByMetatileId(metatile) & 0xff; +} + +u8 MapGridGetMetatileLayerTypeAt(int x, int y) +{ + u16 metatile; + metatile = MapGridGetMetatileIdAt(x, y); + return (GetBehaviorByMetatileId(metatile) & 0xf000) >> 12; +} + +void MapGridSetMetatileIdAt(int x, int y, u16 metatile) +{ + int i; + if (x >= 0 && x < gUnknown_03004870.width + && y >= 0 && y < gUnknown_03004870.height) + { + i = x + y * gUnknown_03004870.width; + gUnknown_03004870.map[i] = (gUnknown_03004870.map[i] & 0xf000) | (metatile & 0xfff); + } +} + +void MapGridSetMetatileEntryAt(int x, int y, u16 metatile) +{ + int i; + if (x >= 0 && x < gUnknown_03004870.width + && y >= 0 && y < gUnknown_03004870.height) + { + i = x + gUnknown_03004870.width * y; + gUnknown_03004870.map[i] = metatile; + } +} + +u32 GetBehaviorByMetatileId(u16 metatile) +{ + u16 *attributes; + if (metatile <= 0x1ff) + { + attributes = gMapHeader.mapData->primaryTileset->metatileAttributes; + return attributes[metatile]; + } + else if (metatile <= 0x3ff) + { + attributes = gMapHeader.mapData->secondaryTileset->metatileAttributes; + return attributes[metatile - 0x200]; + } + else + { + return 0xff; + } +} + +void save_serialize_map(void) +{ + int i, j; + int x, y; + u16 *mapView; + int width; + mapView = gSaveBlock1.mapView; + width = gUnknown_03004870.width; + x = gSaveBlock1.pos.x; + y = gSaveBlock1.pos.y; + for (i = y; i < y + 14; i++) + { + for (j = x; j < x + 15; j++) + { + *mapView++ = gUnknown_02029828[width * i + j]; + } + } +} + +int sub_8056618(void) +{ + u16 i; + u32 r2; + r2 = 0; + for (i = 0; i < 0x200; i++) + { + r2 |= gSaveBlock1.mapView[i]; + } + if (r2 == 0) + { + return 1; + } + return 0; +} + +void sav2_mapdata_clear(void) +{ + CpuFill16(0, gSaveBlock1.mapView, sizeof(gSaveBlock1.mapView)); +} + +void sub_8056670(void) +{ + int i, j; + int x, y; + u16 *mapView; + int width; + mapView = gSaveBlock1.mapView; + if (!sub_8056618()) + { + width = gUnknown_03004870.width; + x = gSaveBlock1.pos.x; + y = gSaveBlock1.pos.y; + for (i = y; i < y + 14; i++) + { + for (j = x; j < x + 15; j++) + { + gUnknown_02029828[width * i + j] = *mapView++; + } + } + sav2_mapdata_clear(); + } +} + +void sub_80566F0(u8 a1) +{ + u16 *mapView; + int width; + int x0, y0; + int x2, y2; + u16 *src, *dest; + int srci, desti; + int r9, r8; + int x, y; + int i, j; + mapView = gSaveBlock1.mapView; + width = gUnknown_03004870.width; + r9 = 0; + r8 = 0; + x0 = gSaveBlock1.pos.x; + y0 = gSaveBlock1.pos.y; + x2 = 15; + y2 = 14; + switch (a1) + { + case CONNECTION_NORTH: + y0 += 1; + y2 = 13; + break; + case CONNECTION_SOUTH: + r8 = 1; + y2 = 13; + break; + case CONNECTION_WEST: + x0 += 1; + x2 = 14; + break; + case CONNECTION_EAST: + r9 = 1; + x2 = 14; + break; + } + for (y = 0; y < y2; y++) + { + i = 0; + j = 0; + for (x = 0; x < x2; x++) + { + desti = width * (y + y0); + srci = (y + r8) * 15 + r9; + src = &mapView[srci + i]; + dest = &gUnknown_02029828[x0 + desti + j]; + *dest = *src; + i++; + j++; + } + } + sav2_mapdata_clear(); +} + +int GetMapBorderIdAt(int x, int y) +{ + struct MapData *mapData; + u16 block, block2; + int i, j; + if (x >= 0 && x < gUnknown_03004870.width + && y >= 0 && y < gUnknown_03004870.height) + { + i = gUnknown_03004870.width; + i *= y; + block = gUnknown_03004870.map[x + i]; + if (block == 0x3ff) + { + goto fail; + } + } + else + { + mapData = gMapHeader.mapData; + j = (x + 1) & 1; + j += ((y + 1) & 1) * 2; + block2 = 0xc00 | mapData->border[j]; + if (block2 == 0x3ff) + { + goto fail; + } + } + goto success; +fail: + return -1; +success: + + if (x >= (gUnknown_03004870.width - 8)) + { + if (!gUnknown_0202E850.east) + { + return -1; + } + return CONNECTION_EAST; + } + else if (x < 7) + { + if (!gUnknown_0202E850.west) + { + return -1; + } + return CONNECTION_WEST; + } + else if (y >= (gUnknown_03004870.height - 7)) + { + if (!gUnknown_0202E850.south) + { + return -1; + } + return CONNECTION_SOUTH; + } + else if (y < 7) + { + if (!gUnknown_0202E850.north) + { + return -1; + } + return CONNECTION_NORTH; + } + else + { + return 0; + } +} + +int GetPostCameraMoveMapBorderId(int x, int y) +{ + return GetMapBorderIdAt(gSaveBlock1.pos.x + 7 + x, gSaveBlock1.pos.y + 7 + y); +} + +int CanCameraMoveInDirection(int direction) +{ + int x, y; + x = gSaveBlock1.pos.x + 7 + gUnknown_0821664C[direction].x; + y = gSaveBlock1.pos.y + 7 + gUnknown_0821664C[direction].y; + if (GetMapBorderIdAt(x, y) == -1) + { + return 0; + } + return 1; +} + +void sub_8056918(struct MapConnection *connection, int direction, int x, int y) +{ + struct MapHeader *mapHeader; + mapHeader = mapconnection_get_mapheader(connection); + switch (direction) + { + case CONNECTION_EAST: + gSaveBlock1.pos.x = -x; + gSaveBlock1.pos.y -= connection->offset; + break; + case CONNECTION_WEST: + gSaveBlock1.pos.x = mapHeader->mapData->width; + gSaveBlock1.pos.y -= connection->offset; + break; + case CONNECTION_SOUTH: + gSaveBlock1.pos.x -= connection->offset; + gSaveBlock1.pos.y = -y; + break; + case CONNECTION_NORTH: + gSaveBlock1.pos.x -= connection->offset; + gSaveBlock1.pos.y = mapHeader->mapData->height; + break; + } +} + +bool8 CameraMove(int x, int y) +{ + unsigned int direction; + struct MapConnection *connection; + int old_x, old_y; + gCamera.field_0 = FALSE; + direction = GetPostCameraMoveMapBorderId(x, y); + if (direction + 1 <= 1) + { + gSaveBlock1.pos.x += x; + gSaveBlock1.pos.y += y; + } + else + { + save_serialize_map(); + old_x = gSaveBlock1.pos.x; + old_y = gSaveBlock1.pos.y; + connection = sub_8056A64(direction, gSaveBlock1.pos.x, gSaveBlock1.pos.y); + sub_8056918(connection, direction, x, y); + sub_80538F0(connection->mapGroup, connection->mapNum); + gCamera.field_0 = TRUE; + gCamera.x = old_x - gSaveBlock1.pos.x; + gCamera.y = old_y - gSaveBlock1.pos.y; + gSaveBlock1.pos.x += x; + gSaveBlock1.pos.y += y; + sub_80566F0(direction); + } + return gCamera.field_0; +} + +struct MapConnection *sub_8056A64(u8 direction, int x, int y) +{ + int count; + struct MapConnection *connection; + int i; + count = gMapHeader.connections->count; + connection = gMapHeader.connections->connections; + for (i = 0; i < count; i++, connection++) + { + if (connection->direction == direction) + { + if (sub_8056ABC(direction, x, y, connection) == TRUE) + { + return connection; + } + } + } + return NULL; +} + +bool8 sub_8056ABC(u8 direction, int x, int y, struct MapConnection *connection) +{ + struct MapHeader *mapHeader; + mapHeader = mapconnection_get_mapheader(connection); + switch (direction) + { + case CONNECTION_SOUTH: + case CONNECTION_NORTH: + return sub_8056B20(x, gMapHeader.mapData->width, mapHeader->mapData->width, connection->offset); + case CONNECTION_WEST: + case CONNECTION_EAST: + return sub_8056B20(y, gMapHeader.mapData->height, mapHeader->mapData->height, connection->offset); + } + return FALSE; +} + +bool8 sub_8056B20(int x, int src_width, int dest_width, int offset) +{ + int offset2; + offset2 = offset; + if (offset2 < 0) + { + offset2 = 0; + } + if (dest_width + offset < src_width) + { + src_width = dest_width + offset; + } + if (offset2 <= x && x <= src_width) + { + return TRUE; + } + return FALSE; +} + +int sub_8056B4C(int x, int width) +{ + if (x >= 0 && x < width) + { + return TRUE; + } + return FALSE; +} + +int sub_8056B60(struct MapConnection *connection, int x, int y) +{ + struct MapHeader *mapHeader; + mapHeader = mapconnection_get_mapheader(connection); + switch (connection->direction) + { + case CONNECTION_SOUTH: + case CONNECTION_NORTH: + return sub_8056B4C(x - connection->offset, mapHeader->mapData->width); + case CONNECTION_WEST: + case CONNECTION_EAST: + return sub_8056B4C(y - connection->offset, mapHeader->mapData->height); + } + return FALSE; +} + +struct MapConnection *sub_8056BA0(s16 x, s16 y) +{ + int count; + struct MapConnection *connection; + int i; + u8 direction; + if (!gMapHeader.connections) + { + return NULL; + } + else + { + count = gMapHeader.connections->count; + connection = gMapHeader.connections->connections; + for (i = 0; i < count; i++, connection++) + { + direction = connection->direction; + if ((direction == CONNECTION_DIVE || direction == CONNECTION_EMERGE) + || (direction == CONNECTION_NORTH && y > 6) + || (direction == CONNECTION_SOUTH && y < gMapHeader.mapData->height + 7) + || (direction == CONNECTION_WEST && x > 6) + || (direction == CONNECTION_EAST && x < gMapHeader.mapData->width + 7)) + { + continue; + } + if (sub_8056B60(connection, x - 7, y - 7) == TRUE) + { + return connection; + } + } + } + return NULL; +} + +void sub_8056C50(u16 x, u16 y) +{ + gSaveBlock1.pos.x = x - 7; + gSaveBlock1.pos.y = y - 7; +} + +void sav1_camera_get_focus_coords(u16 *x, u16 *y) +{ + *x = gSaveBlock1.pos.x + 7; + *y = gSaveBlock1.pos.y + 7; +} + +void unref_sub_8056C7C(u16 x, u16 y) +{ + gSaveBlock1.pos.x = x; + gSaveBlock1.pos.y = y; +} + +void GetCameraCoords(u16 *x, u16 *y) +{ + *x = gSaveBlock1.pos.x; + *y = gSaveBlock1.pos.y; +} + +void sub_8056C98(struct Tileset *tileset, void *src) +{ + if (tileset) + { + if (!tileset->isCompressed) + { + CpuFastSet(tileset->tiles, src, 0x1000); + } + else + { + LZ77UnCompVram(tileset->tiles, src); + } + } +} + +void sub_8056CBC(struct Tileset *tileset, int offset, int size) +{ + u16 black; + if (tileset) + { + if (tileset->isSecondary == FALSE) + { + black = 0; + LoadPalette(&black, offset, 2); + LoadPalette(tileset->palettes + 2, offset + 1, size - 2); + } + else if (tileset->isSecondary == TRUE) + { + LoadPalette(tileset->palettes + 0xc0, offset, size); + } + else + { + LZ77UnCompVram(tileset->palettes, (void*)0x2000000); + LoadPalette((void*)0x2000000, offset, size); + } + } +} + +void sub_8056D28(struct MapData *mapData) +{ + void *src = (void*)(BG_VRAM); + sub_8056C98(mapData->primaryTileset, src); +} + +void sub_8056D38(struct MapData *mapData) +{ + void *src = (void*)(BG_VRAM + 0x4000); + sub_8056C98(mapData->secondaryTileset, src); +} + +void apply_map_tileset1_palette(struct MapData *mapData) +{ + sub_8056CBC(mapData->primaryTileset, 0, 0xc0); +} + +void apply_map_tileset2_palette(struct MapData *mapData) +{ + sub_8056CBC(mapData->secondaryTileset, 0x60, 0xc0); +} + +void copy_map_tileset1_tileset2_to_vram(struct MapData *mapData) +{ + if (mapData) + { + sub_8056D28(mapData); + sub_8056D38(mapData); + } +} + +void apply_map_tileset1_tileset2_palette(struct MapData *mapData) +{ + if (mapData) + { + apply_map_tileset1_palette(mapData); + apply_map_tileset2_palette(mapData); + } +} diff --git a/src/field/fldeff_cut.c b/src/field/fldeff_cut.c new file mode 100644 index 000000000..00643a979 --- /dev/null +++ b/src/field/fldeff_cut.c @@ -0,0 +1,287 @@ +#include "global.h" +#include "fldeff_cut.h" +#include "field_camera.h" +#include "field_effect.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "map_obj_lock.h" +#include "metatile_behavior.h" +#include "metatile_behaviors.h" +#include "pokemon_menu.h" +#include "overworld.h" +#include "rom6.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "trig.h" + +extern u8 gCutGrassSpriteArray[8]; // seems to be an array of 8 sprite IDs + +extern void (*gFieldCallback)(void); +extern void (*gUnknown_03005CE4)(void); + +extern struct SpriteTemplate gSpriteTemplate_CutGrass; + +extern struct MapPosition gUnknown_0203923C; + +extern u8 gLastFieldPokeMenuOpened; + +extern u8 S_UseCut[]; + +bool8 SetUpFieldMove_Cut(void) +{ + s16 x, y; + u8 i, j; + u8 tileBehavior; + + if(npc_before_player_of_type(0x52) == TRUE) // is in front of tree? + { + gFieldCallback = FieldCallback_Teleport; + gUnknown_03005CE4 = sub_80A2634; + return TRUE; + } + else // is in ash or grass to cut? + { + PlayerGetDestCoords(&gUnknown_0203923C.x, &gUnknown_0203923C.y); + for(i = 0; i < 3; i++) + { + y = i - 1 + gUnknown_0203923C.y; + for(j = 0; j < 3; j++) + { + x = j - 1 + gUnknown_0203923C.x; + if(MapGridGetZCoordAt(x, y) == (s8)gUnknown_0203923C.height) + { + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + if(MetatileBehavior_IsPokeGrass(tileBehavior) == TRUE + || MetatileBehavior_IsAshGrass(tileBehavior) == TRUE) + { + gFieldCallback = FieldCallback_Teleport; + gUnknown_03005CE4 = sub_80A25E8; + return TRUE; + } + } + } + } + return FALSE; // do not use cut + } +} + +void sub_80A25E8(void) +{ + FieldEffectStart(FLDEFF_USE_CUT_ON_GRASS); + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; +} + +bool8 FldEff_UseCutOnGrass(void) +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)sub_80A2684 >> 16; + gTasks[taskId].data[9] = (u32)sub_80A2684; + IncrementGameStat(0x12); + return FALSE; +} + +void sub_80A2634(void) +{ + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; + ScriptContext1_SetupScript(S_UseCut); +} + +bool8 FldEff_UseCutOnTree(void) +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)sub_80A2B00 >> 16; + gTasks[taskId].data[9] = (u32)sub_80A2B00; + IncrementGameStat(0x12); + return FALSE; +} + +void sub_80A2684(void) +{ + FieldEffectActiveListRemove(FLDEFF_USE_CUT_ON_GRASS); + FieldEffectStart(FLDEFF_CUT_GRASS); +} + +bool8 FldEff_CutGrass(void) +{ + s16 x, y; + u8 tileBehavior; + u8 i, j; // not in for loop? + + for(i = 0, PlaySE(SE_W015), PlayerGetDestCoords(&gUnknown_0203923C.x, &gUnknown_0203923C.y); i < 3; i++) + { + y = i - 1 + gUnknown_0203923C.y; + for(j = 0; j < 3; j++) + { + x = j - 1 + gUnknown_0203923C.x; + if(MapGridGetZCoordAt(x, y) == (s8)gUnknown_0203923C.height) + { + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + if(MetatileBehavior_IsCuttableGrass(tileBehavior) == TRUE) + { + sub_80A27A8(x, y); + sub_805BCC0(x, y); + } + } + } + } + sub_80A28F4(gUnknown_0203923C.x - 1, gUnknown_0203923C.y - 2); + DrawWholeMapView(); + + // populate sprite ID array + for(i = 0; i < 8; i++) + { + gCutGrassSpriteArray[i] = CreateSprite((struct SpriteTemplate *)&gSpriteTemplate_CutGrass, + gSprites[gPlayerAvatar.spriteId].oam.x + 8, gSprites[gPlayerAvatar.spriteId].oam.y + 20, 0); + gSprites[gCutGrassSpriteArray[i]].data2 = 32 * i; + } + return 0; +} + +// set map grid metatile depending on x, y +// TODO: enum for metatile IDs +void sub_80A27A8(s16 x, s16 y) +{ + int metatileId = MapGridGetMetatileIdAt(x, y); + + switch(metatileId) + { + case 0x208: + case 0x15: + case 0xD: + MapGridSetMetatileIdAt(x, y, 0x1); + break; + case 0x1C6: + MapGridSetMetatileIdAt(x, y, 0x1CE); + break; + case 0x1C7: + MapGridSetMetatileIdAt(x, y, 0x1CF); + break; + case 0x281: + MapGridSetMetatileIdAt(x, y, 0x279); + break; + case 0x282: + MapGridSetMetatileIdAt(x, y, 0x27A); + break; + case 0x283: + MapGridSetMetatileIdAt(x, y, 0x27B); + break; + case 0x206: + case 0x207: + MapGridSetMetatileIdAt(x, y, 0x271); + break; + case 0x212: + case 0x20A: + MapGridSetMetatileIdAt(x, y, 0x218); + break; + case 0x25: + MapGridSetMetatileIdAt(x, y, 0xE); + break; + } +} + +s32 sub_80A28A0(s16 x, s16 y) +{ + u16 metatileId = MapGridGetMetatileIdAt(x, y); + + if(metatileId == 1) + return 1; + else if(metatileId == 633) + return 2; + else if(metatileId == 634) + return 3; + else if(metatileId == 635) + return 4; + else + return 0; +} + +void sub_80A28F4(s16 x, s16 y) +{ + s16 i; + u16 lowerY = y + 3; + + for(i = 0; i < 3; i++) + { + u16 currentX = x + i; + s16 currentXsigned = x + i; + if(MapGridGetMetatileIdAt(currentXsigned, y) == 21) + { + switch((u8)sub_80A28A0(currentXsigned, y + 1)) + { + case 1: + MapGridSetMetatileIdAt(currentXsigned, y + 1, 0x208); + break; + case 2: + MapGridSetMetatileIdAt(currentXsigned, y + 1, 0x281); + break; + case 3: + MapGridSetMetatileIdAt(currentXsigned, y + 1, 0x282); + break; + case 4: + MapGridSetMetatileIdAt(currentXsigned, y + 1, 0x283); + break; + } + } + if(MapGridGetMetatileIdAt((s16)currentX, (s16)lowerY) == 1) + { + if(MapGridGetMetatileIdAt((s16)currentX, (s16)lowerY + 1) == 0x208) + MapGridSetMetatileIdAt((s16)currentX, (s16)lowerY + 1, 0x1); + if(MapGridGetMetatileIdAt((s16)currentX, (s16)lowerY + 1) == 0x281) + MapGridSetMetatileIdAt((s16)currentX, (s16)lowerY + 1, 0x279); + if(MapGridGetMetatileIdAt((s16)currentX, (s16)lowerY + 1) == 0x282) + MapGridSetMetatileIdAt((s16)currentX, (s16)lowerY + 1, 0x27A); + if(MapGridGetMetatileIdAt((s16)currentX, (s16)lowerY + 1) == 0x283) + MapGridSetMetatileIdAt((s16)currentX, (s16)lowerY + 1, 0x27B); + } + } +} + +void sub_80A2A48(struct Sprite *sprite) +{ + sprite->data0 = 8; + sprite->data1 = 0; + sprite->data3 = 0; + sprite->callback = (void *)objc_8097BBC; +} + +void objc_8097BBC(struct Sprite *sprite) +{ + u16 tempdata; + u16 tempdata2; + + sprite->pos2.x = Sin(sprite->data2, sprite->data0); + sprite->pos2.y = Cos(sprite->data2, sprite->data0); + + sprite->data2 = (sprite->data2 + 8) & 0xFF; + sprite->data0 += ((tempdata2 = sprite->data3) << 16 >> 18) + 1; // what? + sprite->data3 = tempdata2 + 1; + + tempdata = sprite->data1; + if((s16)tempdata != 28) // done rotating the grass, execute clean up function + sprite->data1++; + else + sprite->callback = (void *)sub_80A2AB8; +} + +void sub_80A2AB8(void) +{ + u8 i; + + for (i = 1; i < 8; i++) + DestroySprite(&gSprites[gCutGrassSpriteArray[i]]); + FieldEffectStop(&gSprites[gCutGrassSpriteArray[0]], FLDEFF_CUT_GRASS); + sub_8064E2C(); + ScriptContext2_Disable(); +} + +void sub_80A2B00(void) +{ + PlaySE(SE_W015); + FieldEffectActiveListRemove(FLDEFF_USE_CUT_ON_TREE); + EnableBothScriptContexts(); +} diff --git a/src/field/fldeff_flash.c b/src/field/fldeff_flash.c new file mode 100644 index 000000000..1ee8a8f05 --- /dev/null +++ b/src/field/fldeff_flash.c @@ -0,0 +1,306 @@ +#include "global.h" +#include "event_data.h" +#include "field_effect.h" +#include "main.h" +#include "palette.h" +#include "pokemon_menu.h" +#include "overworld.h" +#include "rom6.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" + +struct FlashStruct +{ + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; + void (*func)(void); +}; + +extern struct FlashStruct gUnknown_083F7FC4[]; +extern u16 gCaveTransitionPalette_White[]; +extern u16 gCaveTransitionPalette_Black[]; +extern u16 gUnknown_083F808C[]; +extern u16 gUnknown_083F809C[]; +extern u16 gCaveTransitionTilemap[]; +extern u8 gCaveTransitionTiles[]; + +extern u8 gLastFieldPokeMenuOpened; +extern void (*gUnknown_03005CE4)(void); + +extern u8 gUnknown_081B694A[]; + +void sub_810CBFC(void); +void sub_810CC34(void); +bool8 sub_810CD5C(void); +void sub_810CE5C(u8); +void sub_810CE78(u8); +void sub_810CF18(u8); +void sub_810CF5C(u8); +void sub_810CFC4(u8); +void sub_810D00C(u8); +void sub_810D028(u8); +void sub_810D0C4(u8); +void sub_810D128(u8); + +bool8 SetUpFieldMove_Flash(void) +{ + if (gMapHeader.cave == TRUE && !FlagGet(SYS_USE_FLASH)) + { + gFieldCallback = FieldCallback_Teleport; + gUnknown_03005CE4 = sub_810CBFC; + return TRUE; + } + + return FALSE; +} + +void sub_810CBFC(void) +{ + u8 taskId = oei_task_add(); + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; + gTasks[taskId].data[8] = (uintptr_t)sub_810CC34 >> 16; + gTasks[taskId].data[9] = (uintptr_t)sub_810CC34; +} + +void sub_810CC34(void) +{ + PlaySE(SE_W115); + FlagSet(SYS_USE_FLASH); + ScriptContext1_SetupScript(gUnknown_081B694A); +} + +void sub_810CC54(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void VBlankCB(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +void sub_810CC80(void) +{ + u16 ime; + + SetVBlankCallback(NULL); + REG_DISPCNT = 0; + REG_BG2CNT = 0; + REG_BG1CNT = 0; + REG_BG0CNT = 0; + REG_BG2HOFS = 0; + REG_BG2VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + DmaFill16(3, 0, (void *)VRAM, VRAM_SIZE); + DmaFill32(3, 0, (void *)OAM, OAM_SIZE); + DmaFill16(3, 0, (void *)(PLTT + 2), PLTT_SIZE - 2); + ResetPaletteFade(); + ResetTasks(); + ResetSpriteData(); + ime = REG_IME; + REG_IME = 0; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = ime; + SetVBlankCallback(VBlankCB); + SetMainCallback2(sub_810CC54); + if (!sub_810CD5C()) + SetMainCallback2(gMain.savedCallback); +} + +bool8 sub_810CD5C(void) +{ + u8 i; + u8 v0 = get_map_type_from_warp0(); + u8 v1 = Overworld_GetMapTypeOfSaveblockLocation(); + + for (i = 0; gUnknown_083F7FC4[i].unk0; i++) + { + if (gUnknown_083F7FC4[i].unk0 == v0 && gUnknown_083F7FC4[i].unk1 == v1) + { + gUnknown_083F7FC4[i].func(); + return TRUE; + } + } + + return FALSE; +} + +u8 sub_810CDB8(u8 a1, u8 a2) +{ + u8 i; + u8 v0 = a1; + u8 v1 = a2; + + for (i = 0; gUnknown_083F7FC4[i].unk0; i++) + { + if (gUnknown_083F7FC4[i].unk0 == v0 && gUnknown_083F7FC4[i].unk1 == v1) + { + return gUnknown_083F7FC4[i].unk2; + } + } + + return FALSE; +} + +u8 fade_type_for_given_maplight_pair(u8 a1, u8 a2) +{ + u8 i; + u8 v0 = a1; + u8 v1 = a2; + + for (i = 0; gUnknown_083F7FC4[i].unk0; i++) + { + if (gUnknown_083F7FC4[i].unk0 == v0 && gUnknown_083F7FC4[i].unk1 == v1) + { + return gUnknown_083F7FC4[i].unk3; + } + } + + return FALSE; +} + +void sub_810CE48(void) +{ + CreateTask(sub_810CE5C, 0); +} + +void sub_810CE5C(u8 taskId) +{ + gTasks[taskId].func = sub_810CE78; +} + +void sub_810CE78(u8 taskId) +{ + REG_DISPCNT = 0; + LZ77UnCompVram(gCaveTransitionTiles, (void *)0x600C000); + LZ77UnCompVram(gCaveTransitionTilemap, (void *)0x600F800); + LoadPalette(gCaveTransitionPalette_White, 0xE0, 0x20); + LoadPalette(gUnknown_083F809C, 0xE0, 0x10); + REG_BLDCNT = 15937; + REG_BLDALPHA = 0; + REG_BLDY = 0; + REG_BG0CNT = 7948; + REG_DISPCNT = 4416; + gTasks[taskId].func = sub_810CF18; + gTasks[taskId].data[0] = 16; + gTasks[taskId].data[1] = 0; +} + +void sub_810CF18(u8 taskId) +{ + u16 count = gTasks[taskId].data[1]; + u16 blend = count + 0x1000; + REG_BLDALPHA = blend; + if (count <= 0x10) + { + gTasks[taskId].data[1]++; + } + else + { + gTasks[taskId].data[2] = 0; + gTasks[taskId].func = sub_810CF5C; + } +} + +void sub_810CF5C(u8 taskId) +{ + u16 count; + + REG_BLDALPHA = 4112; + + count = gTasks[taskId].data[2]; + + if (count < 8) + { + gTasks[taskId].data[2]++; + LoadPalette(&gUnknown_083F809C[count], 0xE0, 16 - 2 * count); + } + else + { + LoadPalette(gCaveTransitionPalette_White, 0, 0x20); + gTasks[taskId].func = sub_810CFC4; + gTasks[taskId].data[2] = 8; + } +} + +void sub_810CFC4(u8 taskId) +{ + if (gTasks[taskId].data[2]) + gTasks[taskId].data[2]--; + else + SetMainCallback2(gMain.savedCallback); +} + +void sub_810CFF8(void) +{ + CreateTask(sub_810D00C, 0); +} + +void sub_810D00C(u8 taskId) +{ + gTasks[taskId].func = sub_810D028; +} + +void sub_810D028(u8 taskId) +{ + REG_DISPCNT = 0; + LZ77UnCompVram(gCaveTransitionTiles, (void *)0x600C000); + LZ77UnCompVram(gCaveTransitionTilemap, (void *)0x600F800); + REG_BLDCNT = 0; + REG_BLDALPHA = 0; + REG_BLDY = 0; + REG_BG0CNT = 7948; + REG_DISPCNT = 4416; + LoadPalette(gCaveTransitionPalette_White, 0xE0, 0x20); + LoadPalette(gCaveTransitionPalette_Black, 0, 0x20); + gTasks[taskId].func = sub_810D0C4; + gTasks[taskId].data[0] = 16; + gTasks[taskId].data[1] = 0; + gTasks[taskId].data[2] = 0; +} + +void sub_810D0C4(u8 taskId) +{ + u16 count = gTasks[taskId].data[2]; + if (count < 16) + { + gTasks[taskId].data[2]++; + gTasks[taskId].data[2]++; + LoadPalette(&gUnknown_083F808C[15 - count], 0xE0, 2 * (count + 1)); + } + else + { + REG_BLDALPHA = 4112; + REG_BLDCNT = 15937; + gTasks[taskId].func = sub_810D128; + } +} + +void sub_810D128(u8 taskId) +{ + u16 count = 16 - gTasks[taskId].data[1]; + u16 blend = count + 0x1000; + REG_BLDALPHA = blend; + if (count) + { + gTasks[taskId].data[1]++; + } + else + { + LoadPalette(gCaveTransitionPalette_Black, 0, 0x20); + SetMainCallback2(gMain.savedCallback); + } +} diff --git a/src/field/fldeff_softboiled.c b/src/field/fldeff_softboiled.c new file mode 100644 index 000000000..cb26d9966 --- /dev/null +++ b/src/field/fldeff_softboiled.c @@ -0,0 +1,153 @@ +#include "global.h" +#include "fldeff_softboiled.h" +#include "menu.h" +#include "party_menu.h" +#include "pokemon.h" +#include "pokemon_menu.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "strings.h" +#include "task.h" + +struct Struct2001000 { + u8 unk0; + u8 unk1; + u8 unk2; + u8 filler3[9]; + void *unkC; +}; + +struct Struct201C000 { + struct Pokemon *unk0; + u8 filler4[1]; + u8 unk5; + u16 unk6; + u8 filler8[4]; + s32 unkC; + void* unk10; + u8 filler14[26]; + s16 unk2E; +}; + +#if ENGLISH +#define WINDOW_LEFT 3 +#define WINDOW_RIGHT 26 +#elif GERMAN +#define WINDOW_LEFT 0 +#define WINDOW_RIGHT 29 +#endif + +#define EWRAM_1000 (*(struct Struct2001000 *)(unk_2000000 + 0x1000)) +#define EWRAM_1B000_2 (*(struct Struct201B000 *)(unk_2000000 + 0x1B000)) +#define EWRAM_1C000 (*(struct Struct201C000 *)(unk_2000000 + 0x1C000)) + +// extern +extern u8 gUnknown_0202E8F6; +extern u8 gLastFieldPokeMenuOpened; + +extern u8 unk_2000000[]; +extern u8 gUnknown_0202E8F4; + +// Static +static void sub_8133D50(u8 taskId); +static void sub_8133E74(u8 taskId); +static void sub_8133EB8(u8 taskId); +static void sub_8133EF8(void); + +bool8 SetUpFieldMove_SoftBoiled(void) { + u16 maxHp; + u16 hp; + u16 minHp; + + maxHp = GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_MAX_HP); + hp = GetMonData(&gPlayerParty[gLastFieldPokeMenuOpened], MON_DATA_HP); + + minHp = (maxHp / 5); + if (hp >= minHp) + { + return TRUE; + } + + return FALSE; +} + +void sub_8133D28(u8 taskid) { + EWRAM_1000.unkC = sub_8133D50; + EWRAM_1B000_2.unk272 = 3; + sub_808A004(taskid); +} + +static void sub_8133D50(u8 taskId) { + u8 unk1, unk2; + u16 hp; + struct Pokemon *pokemon; + //struct Task *task; + + struct Sprite *sprites = gSprites; + + + unk1 = sprites[EWRAM_1000.unk1].data0; + unk2 = sprites[EWRAM_1000.unk2].data0; + + if (unk1 > 5 || unk2 > 5) + { + sub_806CD44(taskId); + return; + } + + EWRAM_1C000.unk0 = &gPlayerParty[sprites[EWRAM_1000.unk2].data0]; + hp = GetMonData(EWRAM_1C000.unk0, MON_DATA_HP); + + if (hp == 0 || unk1 == unk2 || GetMonData(EWRAM_1C000.unk0, MON_DATA_MAX_HP) == hp) + { + sub_8133EB8(taskId); + return; + } + + PlaySE(SE_KAIFUKU); + + EWRAM_1C000.unk5 = gSprites[EWRAM_1000.unk1].data0; + + pokemon = &gPlayerParty[EWRAM_1C000.unk5]; + EWRAM_1C000.unk0 = pokemon; + EWRAM_1C000.unk6 = 0; + EWRAM_1C000.unkC = -0x8000; + EWRAM_1C000.unk10 = sub_8133EF8; + + + gTasks[taskId].data[10] = GetMonData(EWRAM_1C000.unk0, MON_DATA_MAX_HP); + gTasks[taskId].data[11] = GetMonData(EWRAM_1C000.unk0, MON_DATA_HP); + gTasks[taskId].data[12] = gTasks[taskId].data[10] / 5; + + sub_806D5A4(); + gTasks[taskId].func = sub_806FA18; + EWRAM_1B000_2.unk282 = gTasks[taskId].data[11]; +} + +static void sub_8133E74(u8 taskId) { + if (gUnknown_0202E8F6) + { + return; + } + + MenuZeroFillWindowRect(WINDOW_LEFT, 14, WINDOW_RIGHT, 19); + sub_806D538(3, 0); + gTasks[taskId].func = sub_806CB74; +} + +static void sub_8133EB8(u8 taskId) { + gUnknown_0202E8F4 = 0; + sub_806D5A4(); + sub_806E834(gOtherText_CantUseOnPoke, 1); + gTasks[taskId].func = sub_8133E74; +} + +static void sub_8133EF8(void) { + sub_806CCE4(); + EWRAM_1B000_2.unk261 = 2; + DestroySprite(&gSprites[EWRAM_1000.unk1]); + MenuZeroFillWindowRect(WINDOW_LEFT, 14, WINDOW_RIGHT, 19); + sub_806D538(0, 0); + SwitchTaskToFollowupFunc(EWRAM_1000.unk0); +} diff --git a/src/field/fldeff_strength.c b/src/field/fldeff_strength.c new file mode 100644 index 000000000..d9603d094 --- /dev/null +++ b/src/field/fldeff_strength.c @@ -0,0 +1,76 @@ +#include "global.h" +#include "braille_puzzles.h" +#include "field_effect.h" +#include "party_menu.h" +#include "pokemon.h" +#include "pokemon_menu.h" +#include "rom6.h" +#include "script.h" +#include "task.h" +#include "text.h" + +static void sub_811AA18(void); +static void sub_811AA38(void); +static void sub_811AA9C(void); + +extern u8 gLastFieldPokeMenuOpened; +extern u16 gScriptResult; +extern void (*gFieldCallback)(void); +extern void (*gUnknown_03005CE4)(void); + +extern u8 S_UseStrength[]; + +bool8 SetUpFieldMove_Strength(void) +{ + if (ShouldDoBrailleStrengthEffect()) + { + gScriptResult = gLastFieldPokeMenuOpened; + gFieldCallback = FieldCallback_Teleport; + gUnknown_03005CE4 = sub_811AA38; + } + else + { + if (npc_before_player_of_type(87) != TRUE) + return 0; + gScriptResult = gLastFieldPokeMenuOpened; + gFieldCallback = FieldCallback_Teleport; + gUnknown_03005CE4 = sub_811AA18; + } + + return TRUE; +} + +static void sub_811AA18(void) +{ + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; + ScriptContext1_SetupScript(S_UseStrength); +} + +static void sub_811AA38(void) +{ + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; + FieldEffectStart(FLDEFF_USE_STRENGTH); +} + +bool8 FldEff_UseStrength(void) +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)sub_811AA9C >> 16; + gTasks[taskId].data[9] = (u32)sub_811AA9C; + GetMonNickname(&gPlayerParty[gFieldEffectArguments[0]], gStringVar1); + return FALSE; +} + +static void sub_811AA9C(void) +{ + if (ShouldDoBrailleStrengthEffect()) + { + DoBrailleStrengthEffect(); + } + else + { + FieldEffectActiveListRemove(40); + EnableBothScriptContexts(); + } +} diff --git a/src/field/fldeff_sweetscent.c b/src/field/fldeff_sweetscent.c new file mode 100644 index 000000000..b9dbf619d --- /dev/null +++ b/src/field/fldeff_sweetscent.c @@ -0,0 +1,88 @@ +#include "global.h" +#include "field_effect.h" +#include "field_player_avatar.h" +#include "palette.h" +#include "pokemon_menu.h" +#include "rom6.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "wild_encounter.h" + +static void sub_812BFD4(void); +static void sub_812C01C(void); +static void sub_812C084(u8); +static void sub_812C118(u8); + +extern u8 gLastFieldPokeMenuOpened; +extern void (*gFieldCallback)(void); +extern void (*gUnknown_03005CE4)(void); + +extern u8 SweetScentNothingHereScript[]; + +bool8 SetUpFieldMove_SweetScent(void) +{ + gFieldCallback = FieldCallback_Teleport; + gUnknown_03005CE4 = sub_812BFD4; + return TRUE; +} + +static void sub_812BFD4(void) +{ + FieldEffectStart(FLDEFF_SWEET_SCENT); + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; +} + +bool8 FldEff_SweetScent() +{ + u8 taskId = oei_task_add(); + + gTasks[taskId].data[8] = (u32)sub_812C01C >> 16; + gTasks[taskId].data[9] = (u32)sub_812C01C; + return FALSE; +} + +static void sub_812C01C(void) +{ + u8 taskId; + + PlaySE(0xEC); + BeginNormalPaletteFade(~(1 << (gSprites[GetPlayerAvatarObjectId()].oam.paletteNum + 16)), 4, 0, 8, 0x1F); + taskId = CreateTask(sub_812C084, 0); + gTasks[taskId].data[0] = 0; + FieldEffectActiveListRemove(FLDEFF_SWEET_SCENT); +} + +static void sub_812C084(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gTasks[taskId].data[0] == 64) + { + gTasks[taskId].data[0] = 0; + if (SweetScentWildEncounter() == TRUE) + { + DestroyTask(taskId); + } + else + { + gTasks[taskId].func = sub_812C118; + BeginNormalPaletteFade(~(1 << (gSprites[GetPlayerAvatarObjectId()].oam.paletteNum + 16)), 4, 8, 0, 0x1F); + } + } + else + { + gTasks[taskId].data[0]++; + } + } +} + +static void sub_812C118(u8 taskId) +{ + if (!gPaletteFade.active) + { + ScriptContext1_SetupScript(SweetScentNothingHereScript); + DestroyTask(taskId); + } +} diff --git a/src/field/fldeff_teleport.c b/src/field/fldeff_teleport.c new file mode 100644 index 000000000..af48fb414 --- /dev/null +++ b/src/field/fldeff_teleport.c @@ -0,0 +1,46 @@ +#include "global.h" +#include "fldeff_teleport.h" +#include "field_effect.h" +#include "field_player_avatar.h" +#include "pokemon_menu.h" +#include "overworld.h" +#include "rom6.h" +#include "task.h" + +extern void (*gFieldCallback)(void); +extern u8 gLastFieldPokeMenuOpened; +extern void (*gUnknown_03005CE4)(void); + +bool8 SetUpFieldMove_Teleport(void) +{ + if (Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE) + { + gFieldCallback = FieldCallback_Teleport; + gUnknown_03005CE4 = hm_teleport_run_dp02scr; + return TRUE; + } + + return FALSE; +} + +void hm_teleport_run_dp02scr(void) +{ + Overworld_ResetStateAfterTeleport(); + FieldEffectStart(FLDEFF_USE_TELEPORT); + gFieldEffectArguments[0] = gLastFieldPokeMenuOpened; +} + +bool8 FldEff_UseTeleport(void) +{ + u8 taskId = oei_task_add(); + gTasks[taskId].data[8] = (u32)sub_814A404 >> 16; + gTasks[taskId].data[9] = (u32)sub_814A404; + SetPlayerAvatarTransitionFlags(1); + return 0; +} + +void sub_814A404(void) +{ + FieldEffectActiveListRemove(FLDEFF_USE_TELEPORT); + sub_8087BA8(); +} diff --git a/src/field/heal_location.c b/src/field/heal_location.c new file mode 100644 index 000000000..42bc18567 --- /dev/null +++ b/src/field/heal_location.c @@ -0,0 +1,63 @@ +#include "global.h" +#include "heal_location.h" +#include "map_constants.h" + +#define NUM_HEAL_LOCATIONS 22 + +static const struct HealLocation sHealLocations[] = +{ + {MAP_GROUP_LITTLEROOT_TOWN_BRENDANS_HOUSE_2F, MAP_ID_LITTLEROOT_TOWN_BRENDANS_HOUSE_2F, 4, 2}, + {MAP_GROUP_LITTLEROOT_TOWN_MAYS_HOUSE_2F, MAP_ID_LITTLEROOT_TOWN_MAYS_HOUSE_2F, 4, 2}, + {MAP_GROUP_PETALBURG_CITY, MAP_ID_PETALBURG_CITY, 20, 17}, + {MAP_GROUP_SLATEPORT_CITY, MAP_ID_SLATEPORT_CITY, 19, 20}, + {MAP_GROUP_MAUVILLE_CITY, MAP_ID_MAUVILLE_CITY, 22, 6}, + {MAP_GROUP_RUSTBORO_CITY, MAP_ID_RUSTBORO_CITY, 16, 39}, + {MAP_GROUP_FORTREE_CITY, MAP_ID_FORTREE_CITY, 5, 7}, + {MAP_GROUP_LILYCOVE_CITY, MAP_ID_LILYCOVE_CITY, 24, 15}, + {MAP_GROUP_MOSSDEEP_CITY, MAP_ID_MOSSDEEP_CITY, 28, 17}, + {MAP_GROUP_SOOTOPOLIS_CITY, MAP_ID_SOOTOPOLIS_CITY, 43, 32}, + {MAP_GROUP_EVER_GRANDE_CITY, MAP_ID_EVER_GRANDE_CITY, 27, 49}, + {MAP_GROUP_LITTLEROOT_TOWN, MAP_ID_LITTLEROOT_TOWN, 5, 9}, + {MAP_GROUP_LITTLEROOT_TOWN, MAP_ID_LITTLEROOT_TOWN, 14, 9}, + {MAP_GROUP_OLDALE_TOWN, MAP_ID_OLDALE_TOWN, 6, 17}, + {MAP_GROUP_DEWFORD_TOWN, MAP_ID_DEWFORD_TOWN, 2, 11}, + {MAP_GROUP_LAVARIDGE_TOWN, MAP_ID_LAVARIDGE_TOWN, 9, 7}, + {MAP_GROUP_FALLARBOR_TOWN, MAP_ID_FALLARBOR_TOWN, 14, 8}, + {MAP_GROUP_VERDANTURF_TOWN, MAP_ID_VERDANTURF_TOWN, 16, 4}, + {MAP_GROUP_PACIFIDLOG_TOWN, MAP_ID_PACIFIDLOG_TOWN, 8, 16}, + {MAP_GROUP_EVER_GRANDE_CITY, MAP_ID_EVER_GRANDE_CITY, 18, 6}, + {MAP_GROUP_BATTLE_TOWER_OUTSIDE, MAP_ID_BATTLE_TOWER_OUTSIDE, 14, 9}, + {MAP_GROUP_SOUTHERN_ISLAND_EXTERIOR, MAP_ID_SOUTHERN_ISLAND_EXTERIOR, 15, 20}, +}; + +u32 GetHealLocationIndexByMap(u16 mapGroup, u16 mapNum) +{ + u32 i; + + for (i = 0; i < NUM_HEAL_LOCATIONS; i++) + { + if (sHealLocations[i].group == mapGroup && sHealLocations[i].map == mapNum) + return i + 1; + } + return 0; +} + +const struct HealLocation *GetHealLocationByMap(u16 mapGroup, u16 mapNum) +{ + u32 index = GetHealLocationIndexByMap(mapGroup, mapNum); + + if (index == 0) + return NULL; + else + return &sHealLocations[index - 1]; +} + +const struct HealLocation *GetHealLocation(u32 index) +{ + if (index == 0) + return NULL; + else if (index > NUM_HEAL_LOCATIONS) + return NULL; + else + return &sHealLocations[index - 1]; +} diff --git a/src/field/hof_pc.c b/src/field/hof_pc.c new file mode 100644 index 000000000..267ed4274 --- /dev/null +++ b/src/field/hof_pc.c @@ -0,0 +1,42 @@ +#include "global.h" +#include "hall_of_fame.h" +#include "main.h" +#include "palette.h" +#include "overworld.h" +#include "script.h" +#include "script_menu.h" +#include "task.h" + +extern void (*gFieldCallback)(void); +extern void (*gUnknown_0300485C)(void); + +static void ReshowPCMenuAfterHallOfFamePC(void); +static void Task_WaitForPaletteFade(u8); + +void AccessHallOfFamePC(void) +{ + SetMainCallback2(sub_81428CC); + ScriptContext2_Enable(); +} + +void ReturnFromHallOfFamePC(void) +{ + SetMainCallback2(c2_exit_to_overworld_2_switch); + gFieldCallback = ReshowPCMenuAfterHallOfFamePC; +} + +static void ReshowPCMenuAfterHallOfFamePC(void) +{ + ScriptContext2_Enable(); + Overworld_PlaySpecialMapMusic(); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, 0); + ScrSpecial_CreatePCMenu(); + ScriptMenu_DisplayPCStartupPrompt(); + CreateTask(Task_WaitForPaletteFade, 10); +} + +static void Task_WaitForPaletteFade(u8 taskId) +{ + if (!gPaletteFade.active) + DestroyTask(taskId); +} diff --git a/src/field/item.c b/src/field/item.c new file mode 100644 index 000000000..fd49f5c39 --- /dev/null +++ b/src/field/item.c @@ -0,0 +1,674 @@ +#include "global.h" +#include "hold_effects.h" +#include "item.h" +#include "items.h" +#include "item_use.h" +#include "berry.h" +#include "string_util.h" +#include "strings.h" + +extern u8 gUnknown_02038560; + +// These constants are used in gItems +enum +{ + POCKET_NONE, + POCKET_ITEMS, + POCKET_POKE_BALLS, + POCKET_TM_HM, + POCKET_BERRIES, + POCKET_KEY_ITEMS, +}; + +enum +{ + ITEMS_POCKET, + BALLS_POCKET, + TMHM_POCKET, + BERRIES_POCKET, + KEYITEMS_POCKET +}; + +#if ENGLISH +#include "../data/item_descriptions_en.h" +#include "../data/items_en.h" +#elif GERMAN +#include "../data/item_descriptions_de.h" +#include "../data/items_de.h" +#endif + +static void CompactPCItems(void); + +void CopyItemName(u16 itemId, u8 *string) +{ + if (itemId == ITEM_ENIGMA_BERRY) + { + StringCopy(string, GetBerryInfo(0x2B)->name); // berry 0x2b = enigma berry + StringAppend(string, gOtherText_Berry2); + } + else + StringCopy(string, ItemId_GetItem(itemId)->name); +} + +//Unreferenced +s8 CountUsedBagPocketSlots(u8 pocket) +{ + u8 i; + + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (gBagPockets[pocket].itemSlots[i].itemId == 0) + return i; + } + return -1; +} + +bool8 IsBagPocketNonEmpty(u8 pocket) +{ + u8 i; + + for (i = 0; i < gBagPockets[pocket - 1].capacity; i++) + { + if (gBagPockets[pocket - 1].itemSlots[i].itemId != 0) + return TRUE; + } + return FALSE; +} + +bool8 CheckBagHasItem(u16 itemId, u16 count) +{ + u8 i; + u8 pocket; + + if (ItemId_GetPocket(itemId) == 0) + return FALSE; + pocket = ItemId_GetPocket(itemId) - 1; + //Check for item slots that contain the item + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (gBagPockets[pocket].itemSlots[i].itemId == itemId) + { + //Does this item slot contain enough of the item? + if (gBagPockets[pocket].itemSlots[i].quantity >= count) + return TRUE; + count -= gBagPockets[pocket].itemSlots[i].quantity; + //Does this item slot and all previous slots contain enough of the item? + if (count == 0) + return TRUE; + } + } + return FALSE; +} + +bool8 CheckBagHasSpace(u16 itemId, u16 count) +{ + u8 i; + u8 pocket; + u16 slotCapacity; + + if (ItemId_GetPocket(itemId) == 0) + return FALSE; + pocket = ItemId_GetPocket(itemId) - 1; + if (pocket != BERRIES_POCKET) + slotCapacity = 99; + else + slotCapacity = 999; + + //Check space in any existing item slots that already contain this item + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (gBagPockets[pocket].itemSlots[i].itemId == itemId) + { + if (gBagPockets[pocket].itemSlots[i].quantity + count <= slotCapacity) + return TRUE; + if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET) + return FALSE; + count -= slotCapacity - gBagPockets[pocket].itemSlots[i].quantity; + if (count == 0) + return TRUE; + } + } + + //Check space in empty item slots + if (count > 0) + { + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (gBagPockets[pocket].itemSlots[i].itemId == 0) + { + if (count <= slotCapacity) + return TRUE; + else + count -= slotCapacity; + } + } + if (count > 0) + return FALSE; //No more item slots. The bag is full + } + + return TRUE; +} + +// This function matches if gBagPockets is declared non-const, +// but it should be fixed anyway. +#ifdef NONMATCHING +bool8 AddBagItem(u16 itemId, u16 count) +{ + u8 i; + u8 pocket; + u16 slotCapacity; + struct ItemSlot newItems[64]; + + if (ItemId_GetPocket(itemId) == 0) + return FALSE; + pocket = ItemId_GetPocket(itemId) - 1; + //Copy the bag pocket + memcpy(newItems, gBagPockets[pocket].itemSlots, gBagPockets[pocket].capacity * sizeof(struct ItemSlot)); + if (pocket != BERRIES_POCKET) + slotCapacity = 99; + else + slotCapacity = 999; + + //Use any item slots that already contain this item + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (newItems[i].itemId == itemId) + { + if (newItems[i].quantity + count <= slotCapacity) + { + newItems[i].quantity += count; + //Copy pocket back into the bag. + memcpy(gBagPockets[pocket].itemSlots, newItems, gBagPockets[pocket].capacity * sizeof(struct ItemSlot)); + return TRUE; + } + if (pocket == TMHM_POCKET || pocket == BERRIES_POCKET) + return FALSE; + count -= slotCapacity - newItems[i].quantity; + newItems[i].quantity = slotCapacity; + if (count == 0) + goto copy_items; + } + } + + //Put any remaining items into new item slots. + if (count > 0) + { + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (newItems[i].itemId == 0) + { + newItems[i].itemId = itemId; + if (count <= slotCapacity) + { + newItems[i].quantity = count; + goto copy_items; + } + count -= slotCapacity; + newItems[i].quantity = slotCapacity; + } + } + if (count > 0) + return FALSE; //No more empty item slots. The bag is full. + } + + copy_items: + //Copy pocket back into the bag. + memcpy(gBagPockets[pocket].itemSlots, newItems, gBagPockets[pocket].capacity * sizeof(struct ItemSlot)); + return TRUE; +} +#else +__attribute__((naked)) +bool8 AddBagItem(u16 itemId, u16 count) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r9\n\ + mov r6, r8\n\ + push {r6,r7}\n\ + sub sp, 0x100\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + mov r8, r0\n\ + lsls r1, 16\n\ + lsrs r4, r1, 16\n\ + bl ItemId_GetPocket\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080A9510\n\ + mov r0, r8\n\ + bl ItemId_GetPocket\n\ + subs r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r6, r0, 24\n\ + ldr r1, _080A94F8 @ =gBagPockets\n\ + lsls r0, r6, 3\n\ + adds r5, r0, r1\n\ + ldr r1, [r5]\n\ + ldrb r2, [r5, 0x4]\n\ + lsls r2, 2\n\ + mov r0, sp\n\ + bl memcpy\n\ + ldr r7, _080A94FC @ =0x000003e7\n\ + cmp r6, 0x3\n\ + beq _080A9468\n\ + movs r7, 0x63\n\ +_080A9468:\n\ + movs r1, 0\n\ + ldrb r0, [r5, 0x4]\n\ + cmp r1, r0\n\ + bcs _080A94B2\n\ + subs r0, r6, 0x2\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r12, r0\n\ +_080A9478:\n\ + lsls r0, r1, 2\n\ + mov r2, sp\n\ + adds r3, r2, r0\n\ + ldrh r0, [r3]\n\ + cmp r0, r8\n\ + bne _080A94A6\n\ + ldrh r2, [r3, 0x2]\n\ + adds r0, r2, r4\n\ + cmp r0, r7\n\ + ble _080A9500\n\ + mov r0, r12\n\ + cmp r0, 0x1\n\ + bls _080A9510\n\ + subs r0, r7, r2\n\ + subs r0, r4, r0\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + strh r7, [r3, 0x2]\n\ + ldr r2, _080A94F8 @ =gBagPockets\n\ + mov r9, r2\n\ + lsls r3, r6, 3\n\ + cmp r4, 0\n\ + beq _080A9516\n\ +_080A94A6:\n\ + adds r0, r1, 0x1\n\ + lsls r0, 24\n\ + lsrs r1, r0, 24\n\ + ldrb r0, [r5, 0x4]\n\ + cmp r1, r0\n\ + bcc _080A9478\n\ +_080A94B2:\n\ + ldr r2, _080A94F8 @ =gBagPockets\n\ + mov r9, r2\n\ + lsls r3, r6, 3\n\ + cmp r4, 0\n\ + beq _080A9516\n\ + movs r1, 0\n\ + adds r0, r3, r2\n\ + ldrb r0, [r0, 0x4]\n\ + cmp r1, r0\n\ + bcs _080A94F2\n\ + mov r6, r9\n\ + adds r5, r3, r6\n\ +_080A94CA:\n\ + lsls r0, r1, 2\n\ + mov r6, sp\n\ + adds r2, r6, r0\n\ + ldrh r0, [r2]\n\ + cmp r0, 0\n\ + bne _080A94E6\n\ + mov r0, r8\n\ + strh r0, [r2]\n\ + cmp r4, r7\n\ + bls _080A9514\n\ + subs r0, r4, r7\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + strh r7, [r2, 0x2]\n\ +_080A94E6:\n\ + adds r0, r1, 0x1\n\ + lsls r0, 24\n\ + lsrs r1, r0, 24\n\ + ldrb r2, [r5, 0x4]\n\ + cmp r1, r2\n\ + bcc _080A94CA\n\ +_080A94F2:\n\ + cmp r4, 0\n\ + beq _080A9516\n\ + b _080A9510\n\ + .align 2, 0\n\ +_080A94F8: .4byte gBagPockets\n\ +_080A94FC: .4byte 0x000003e7\n\ +_080A9500:\n\ + strh r0, [r3, 0x2]\n\ + ldr r0, _080A950C @ =gBagPockets\n\ + lsls r1, r6, 3\n\ + adds r1, r0\n\ + b _080A951A\n\ + .align 2, 0\n\ +_080A950C: .4byte gBagPockets\n\ +_080A9510:\n\ + movs r0, 0\n\ + b _080A9528\n\ +_080A9514:\n\ + strh r4, [r2, 0x2]\n\ +_080A9516:\n\ + mov r6, r9\n\ + adds r1, r3, r6\n\ +_080A951A:\n\ + ldr r0, [r1]\n\ + ldrb r2, [r1, 0x4]\n\ + lsls r2, 2\n\ + mov r1, sp\n\ + bl memcpy\n\ + movs r0, 0x1\n\ +_080A9528:\n\ + add sp, 0x100\n\ + pop {r3,r4}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .syntax divided\n"); +} +#endif + +bool8 RemoveBagItem(u16 itemId, u16 count) +{ + u8 i; + u8 pocket; + u16 totalQuantity = 0; + + if (ItemId_GetPocket(itemId) == 0 || itemId == 0) + return FALSE; + pocket = ItemId_GetPocket(itemId) - 1; + + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (gBagPockets[pocket].itemSlots[i].itemId == itemId) + totalQuantity += gBagPockets[pocket].itemSlots[i].quantity; + } + if (totalQuantity < count) + return FALSE; //We don't have enough of the item + + if (gBagPockets[pocket].capacity > gUnknown_02038560 + && gBagPockets[pocket].itemSlots[gUnknown_02038560].itemId == itemId) + { + if (gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity >= count) + { + gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity -= count; + count = 0; + } + else + { + count -= gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity; + gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity = 0; + } + if (gBagPockets[pocket].itemSlots[gUnknown_02038560].quantity == 0) + gBagPockets[pocket].itemSlots[gUnknown_02038560].itemId = 0; + if (count == 0) + return TRUE; + } + + for (i = 0; i < gBagPockets[pocket].capacity; i++) + { + if (gBagPockets[pocket].itemSlots[i].itemId == itemId) + { + if (gBagPockets[pocket].itemSlots[i].quantity >= count) + { + gBagPockets[pocket].itemSlots[i].quantity -= count; + count = 0; + } + else + { + count -= gBagPockets[pocket].itemSlots[i].quantity; + gBagPockets[pocket].itemSlots[i].quantity = 0; + } + if (gBagPockets[pocket].itemSlots[i].quantity == 0) + gBagPockets[pocket].itemSlots[i].itemId = 0; + if (count == 0) + return TRUE; + } + } + return TRUE; +} + +u8 GetPocketByItemId(u16 itemId) +{ + return ItemId_GetPocket(itemId); +} + +void ClearItemSlots(struct ItemSlot *itemSlots, u8 b) +{ + u16 i; + + for (i = 0; i < b; i++) + { + itemSlots[i].itemId = 0; + itemSlots[i].quantity = 0; + } +} + +static s32 FindFreePCItemSlot(void) +{ + s8 i; + + for (i = 0; i < 50; i++) + { + if (gSaveBlock1.pcItems[i].itemId == 0) + return i; + } + return -1; +} + +u8 CountUsedPCItemSlots(void) +{ + u8 usedSlots = 0; + u8 i; + + for (i = 0; i < 50; i++) + { + if (gSaveBlock1.pcItems[i].itemId != 0) + usedSlots++; + } + return usedSlots; +} + +bool8 CheckPCHasItem(u16 itemId, u16 count) +{ + u8 i; + + for (i = 0; i < 50; i++) + { + if (gSaveBlock1.pcItems[i].itemId == itemId && gSaveBlock1.pcItems[i].quantity >= count) + return TRUE; + } + return FALSE; +} + +bool8 AddPCItem(u16 itemId, u16 count) +{ + u8 i; + s8 freeSlot; + struct ItemSlot newItems[50]; + + //Copy PC items + memcpy(newItems, gSaveBlock1.pcItems, sizeof(newItems)); + + //Use any item slots that already contain this item + for (i = 0; i < 50; i++) + { + if (newItems[i].itemId == itemId) + { + if (newItems[i].quantity + count <= 999) + { + newItems[i].quantity += count; + memcpy(gSaveBlock1.pcItems, newItems, sizeof(gSaveBlock1.pcItems)); + return TRUE; + } + count += newItems[i].quantity - 999; + newItems[i].quantity = 999; + if (count == 0) + { + memcpy(gSaveBlock1.pcItems, newItems, sizeof(gSaveBlock1.pcItems)); + return TRUE; + } + } + } + + //Put any remaining items into a new item slot. + if (count > 0) + { + freeSlot = FindFreePCItemSlot(); + if (freeSlot == -1) + return FALSE; + newItems[freeSlot].itemId = itemId; + newItems[freeSlot].quantity = count; + } + + //Copy items back to the PC + memcpy(gSaveBlock1.pcItems, newItems, sizeof(gSaveBlock1.pcItems)); + return TRUE; +} + +void RemovePCItem(u8 index, u16 count) +{ + gSaveBlock1.pcItems[index].quantity -= count; + if (gSaveBlock1.pcItems[index].quantity == 0) + { + gSaveBlock1.pcItems[index].itemId = 0; + CompactPCItems(); + } +} + +static void CompactPCItems(void) +{ + u16 i; + u16 j; + + for (i = 0; i < 49; i++) + { + for (j = i + 1; j <= 49; j++) + { + if (gSaveBlock1.pcItems[i].itemId == 0) + { + struct ItemSlot temp = gSaveBlock1.pcItems[i]; + gSaveBlock1.pcItems[i] = gSaveBlock1.pcItems[j]; + gSaveBlock1.pcItems[j] = temp; + } + } + } +} + +void SwapRegisteredBike(void) +{ + switch (gSaveBlock1.registeredItem) + { + case 0x103: + gSaveBlock1.registeredItem = 0x110; + break; + case 0x110: + gSaveBlock1.registeredItem = 0x103; + break; + } +} + +static u16 SanitizeItemId(u16 itemId) +{ + if (itemId > 0x15C) + return 0; + else + return itemId; +} + +const struct Item *ItemId_GetItem(u16 itemId) +{ + return &gItems[SanitizeItemId(itemId)]; +} + +u16 ItemId_GetId(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].itemId; +} + +u16 ItemId_GetPrice(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].price; +} + +u8 ItemId_GetHoldEffect(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].holdEffect; +} + +u8 ItemId_GetHoldEffectParam(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].holdEffectParam; +} + +const u8 *ItemId_GetDescription(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].description; +} + +bool32 ItemId_CopyDescription(u8 *a, u32 itemId, u32 c) +{ + u32 r5 = c + 1; + const u8 *description = gItems[SanitizeItemId(itemId)].description; + u8 *str = a; + + for (;;) + { + if (*description == 0xFF || *description == 0xFE) + { + r5--; + if (r5 == 0) + { + *str = 0xFF; + return TRUE; + } + if (*description == 0xFF) + return FALSE; + str = a; + description++; + } + else + *(str++) = *(description++); + } +} + +u8 ItemId_GetImportance(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].importance; +} + +u8 ItemId_GetUnknownValue(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].unk19; +} + +u8 ItemId_GetPocket(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].pocket; +} + +u8 ItemId_GetType(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].type; +} + +ItemUseFunc ItemId_GetFieldFunc(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].fieldUseFunc; +} + +u8 ItemId_GetBattleUsage(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].battleUsage; +} + +ItemUseFunc ItemId_GetBattleFunc(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].battleUseFunc; +} + +u8 ItemId_GetSecondaryId(u16 itemId) +{ + return gItems[SanitizeItemId(itemId)].secondaryId; +} diff --git a/src/field/item_menu.c b/src/field/item_menu.c new file mode 100644 index 000000000..c508bcacf --- /dev/null +++ b/src/field/item_menu.c @@ -0,0 +1,4575 @@ +#include "global.h" +#include "berry.h" +#include "berry_tag_screen.h" +#include "data2.h" +#include "decompress.h" +#include "field_effect.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "graphics.h" +#include "item.h" +#include "items.h" +#include "item_menu.h" +#include "item_use.h" +#include "link.h" +#include "mail_data.h" +#include "main.h" +#include "map_name_popup.h" +#include "menu.h" +#include "menu_cursor.h" +#include "menu_helpers.h" +#include "money.h" +#include "palette.h" +#include "party_menu.h" +#include "player_pc.h" +#include "pokemon_menu.h" +#include "overworld.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "strings.h" +#include "strings2.h" +#include "string_util.h" +#include "task.h" +#include "text.h" +#include "unknown_task.h" + +// External stuff +extern u8 ewram[]; +extern void gpu_pal_allocator_reset__manage_upper_four(void); +extern void sub_80F9020(void); +extern void sub_80F9988(); +extern void sub_809D104(u16 *, u16, u16, const u8 *, u16, u16, u16, u16); +extern void PauseVerticalScrollIndicator(); +extern u8 sub_80F9284(void); +extern void sub_808B5B4(); +extern u8 sub_80F92F4(); +extern void sub_80C9C7C(u8); +extern void pal_fill_black(void); +extern bool8 sub_807D770(void); +extern u8 sub_80F931C(); +extern void sub_808A3F8(u8); +extern void sub_80B3050(void); +extern void sub_80546B8(u8); +extern void sub_804E990(u8); +extern void sub_802E424(u8); +extern void sub_8064E2C(void); + +struct UnknownStruct2 +{ + u8 unk0; + u8 textLine; + u8 unk2; +}; + +struct UnknownStruct3 +{ + u8 unk0; + u8 unk1; + u8 unk2; +}; + +struct UnknownStruct4 +{ + u8 unk0; + u8 unk1; + u16 unk2; + const u8 *unk4; + TaskFunc unk8; +}; + +struct UnknownStruct5 +{ + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; +}; + +struct UnknownStruct6 +{ + u8 unk0; +}; + +enum +{ + BAG_POCKET_ITEMS, // 0 + BAG_POCKET_POKE_BALLS, // 1 + BAG_POCKET_TMs_HMs, // 2 + BAG_POCKET_BERRIES, // 3 + BAG_POCKET_KEY_ITEMS, // 4 +}; + +enum +{ + RETURN_TO_FIELD_0, + RETURN_TO_BATTLE, + RETURN_TO_PKMN_LIST, + RETURN_TO_SHOP, + RETURN_TO_FIELD_4, + RETURN_TO_FIELD_5, + RETURN_TO_PC, + RETURN_TO_WALLY_BATTLE, +}; + +enum +{ + ITEM_ACTION_USE_0, // 0 + ITEM_ACTION_TOSS, // 1 + ITEM_ACTION_CANCEL_2, // 2 + ITEM_ACTION_REGISTER, // 3 + ITEM_ACTION_USE_4, // 4 + ITEM_ACTION_CANCEL_5, // 5 + ITEM_ACTION_GIVE, // 6 + ITEM_ACTION_CHECK_TAG, // 7 + ITEM_ACTION_NONE, // 8 + ITEM_ACTION_CONFIRM, // 9 +}; + +// ewram +EWRAM_DATA static struct UnknownStruct2 gUnknown_0203853C = {0}; +EWRAM_DATA static struct UnknownStruct3 gUnknown_02038540 = {0}; +EWRAM_DATA static struct UnknownStruct4 gUnknown_02038544 = {0}; +EWRAM_DATA static struct UnknownStruct5 gUnknown_02038550 = {0}; +EWRAM_DATA static struct UnknownStruct6 gUnknown_02038554 = {0}; // There are 3 bytes of padding after this, so I assume it's a struct +EWRAM_DATA static u8 gUnknown_02038558 = 0; +EWRAM_DATA static s8 sCurrentBagPocket = 0; +EWRAM_DATA static u8 gUnknown_0203855A = 0; +EWRAM_DATA static s8 gUnknown_0203855B = 0; +EWRAM_DATA static s8 gUnknown_0203855C = 0; +EWRAM_DATA u16 gScriptItemId = 0; +EWRAM_DATA u8 gUnknown_02038560 = 0; +EWRAM_DATA u8 gUnknown_02038561 = 0; +EWRAM_DATA static u8 gUnknown_02038562 = 0; +EWRAM_DATA static u8 gUnknown_02038563 = 0; +EWRAM_DATA static u8 gUnknown_02038564 = 0; +EWRAM_DATA static u8 sPokeballSpriteId ALIGNED(4) = 0; // HACK: why is there a space before this variable? + +// bss +static u8 sPopupMenuSelection; +static u8 sReturnLocation; +static const u8 *sPopupMenuActionList; + +// common +void (*gFieldItemUseCallback)(u8) = NULL; +extern u16 gUnknown_030041B4; +extern struct PocketScrollState gBagPocketScrollStates[]; +extern struct ItemSlot *gCurrentBagPocketItemSlots; // selected pocket item slots +extern const u8 Event_NoRegisteredItem[]; + +#define ewramBerryPic (ewram + 0) +#define ewramBerryPicTemp (ewram + 0x1000) +#define ewramSavedItemsPocket ((struct ItemSlot *)(ewram + 0x1E000)) // saved items pocket (for Wally battle) +#define ewramSavedPokeballsPocket ((struct ItemSlot *)(ewram + 0x1F000)) // saved Pokeballs pocket (for Wally battle) +#define ewramBagSetupStep (ewram[0x1FFFF]) + +extern const struct CompressedSpriteSheet sMaleBagSpriteSheet; +extern const struct CompressedSpriteSheet sFemaleBagSpriteSheet; +extern const struct CompressedSpritePalette sBagSpritePalette; + +const struct BagPocket gBagPockets[NUM_BAG_POCKETS] = +{ + {gSaveBlock1.bagPocket_Items, 20}, + {gSaveBlock1.bagPocket_PokeBalls, 16}, + {gSaveBlock1.bagPocket_TMHM, 64}, + {gSaveBlock1.bagPocket_Berries, 46}, + {gSaveBlock1.bagPocket_KeyItems, 20}, +}; + +static void HandlePopupMenuAction_UseOnField(u8); +static void HandlePopupMenuAction_Toss(u8); +static void sub_80A5F80(u8); +static void HandlePopupMenuAction_Register(u8); +static void HandlePopupMenuAction_UseInBattle(u8); +static void sub_80A7124(u8); +static void HandlePopupMenuAction_Give(u8); +static void HandlePopupMenuAction_CheckTag(u8); +static void HandlePopupMenuAction_Confirm(u8); + +static const struct MenuAction2 sItemPopupMenuActions[] = +{ + {OtherText_Use, HandlePopupMenuAction_UseOnField}, + {OtherText_Toss, HandlePopupMenuAction_Toss}, + {gOtherText_CancelNoTerminator, sub_80A5F80}, + {OtherText_Register, HandlePopupMenuAction_Register}, + {OtherText_Use, HandlePopupMenuAction_UseInBattle}, + {gOtherText_CancelNoTerminator, sub_80A7124}, + {OtherText_Give2, HandlePopupMenuAction_Give}, + {OtherText_CheckTag, HandlePopupMenuAction_CheckTag}, + {gOtherText_CancelWithTerminator, NULL}, + {OtherText_Confirm, HandlePopupMenuAction_Confirm}, +}; + +static const u8 sItemPopupMenuChoicesTable[][6] = +{ + [BAG_POCKET_ITEMS] = + { + ITEM_ACTION_USE_0, + ITEM_ACTION_TOSS, + ITEM_ACTION_GIVE, + ITEM_ACTION_CANCEL_2, + }, + + [BAG_POCKET_POKE_BALLS] = + { + ITEM_ACTION_GIVE, + ITEM_ACTION_TOSS, + ITEM_ACTION_NONE, + ITEM_ACTION_CANCEL_2, + }, + + [BAG_POCKET_TMs_HMs] = + { + ITEM_ACTION_USE_0, + ITEM_ACTION_NONE, + ITEM_ACTION_GIVE, + ITEM_ACTION_CANCEL_2, + }, + + [BAG_POCKET_BERRIES] = + { + ITEM_ACTION_CHECK_TAG, + ITEM_ACTION_USE_0, + ITEM_ACTION_TOSS, + ITEM_ACTION_NONE, + ITEM_ACTION_GIVE, + ITEM_ACTION_CANCEL_2 + }, + + [BAG_POCKET_KEY_ITEMS] = + { + ITEM_ACTION_USE_0, + ITEM_ACTION_NONE, + ITEM_ACTION_REGISTER, + ITEM_ACTION_CANCEL_2, + }, +}; + +const u8 gUnknown_083C16AE[][2] = +{ + {6, 2}, + {6, 2}, + {6, 2}, + {6, 2}, + {2, 0}, +}; + +const u8 gUnknown_083C16B8[] = {7, 9, 8, 2}; + +static void OnItemSelect_Field05(u8); +static void OnBagClose_Field0(u8); +static void OnBagClose_PkmnList(u8); +static void OnItemSelect_PkmnList(u8); +static void OnBagClose_Shop(u8); +static void OnItemSelect_Shop(u8); +static void OnBagClose_Field4(u8); +static void OnItemSelect_Field4(u8); +static void OnBagClose_Field5(u8); +static void OnBagClose_PC(u8); +static void OnItemSelect_PC(u8); +static void OnItemSelect_Battle(u8); +static void OnBagClose_Battle(u8); + +static const struct {TaskFunc onItemSelect; TaskFunc onBagClose;} gUnknown_083C16BC[] = +{ + [RETURN_TO_FIELD_0] = {OnItemSelect_Field05, OnBagClose_Field0}, + [RETURN_TO_BATTLE] = {OnItemSelect_Battle, OnBagClose_Battle}, + [RETURN_TO_PKMN_LIST] = {OnItemSelect_PkmnList, OnBagClose_PkmnList}, + [RETURN_TO_SHOP] = {OnItemSelect_Shop, OnBagClose_Shop}, + [RETURN_TO_FIELD_4] = {OnItemSelect_Field4, OnBagClose_Field4}, + [RETURN_TO_FIELD_5] = {OnItemSelect_Field05, OnBagClose_Field5}, + [RETURN_TO_PC] = {OnItemSelect_PC, OnBagClose_PC}, +}; + +static void sub_80A5E60(u8); +static void sub_80A5E90(u8); + +static const struct YesNoFuncTable gUnknown_083C16F4 = {sub_80A5E60, sub_80A5E90}; + +static void sub_80A65AC(u8); +static void sub_80A6618(u8); + +const struct YesNoFuncTable gUnknown_083C16FC = {sub_80A65AC, sub_80A6618}; + +void sub_80A34E8(void); +static bool8 LoadBagGraphicsMultistep(void); +static void sub_80A362C(void); +static void sub_80A3740(void); +static void sub_80A396C(u16 *, u8, u8, u8); +static void sub_80A39B8(u16 *, u8); +static void sub_80A39E4(u16 *, u8, u8, s8); +static void DrawPocketIndicatorDots(u16 *, u8); +static void SortItemSlots(struct BagPocket); +static void UpdateAllBagPockets(void); +static void sub_80A3D24(u8); +static void sub_80A3D40(void); +static void RemoveSelectIconFromRegisteredItem(void); +static void sub_80A48E8(u16, int, int); +static void ItemListMenu_InitDescription(s16); +static void ItemListMenu_ChangeDescription(s16, int); +static void sub_80A4F68(u8); +static void sub_80A50C8(u8); +static void sub_80A5AE4(u8); +static void sub_80A5BF8(u8); +static void Task_CallItemUseOnFieldCallback(u8); +static void sub_80A6444(u8); +static void sub_80A648C(u8); +static void Task_BuyHowManyDialogueHandleInput(u8); +static void BuyMenuPrintItemQuantityAndPrice(u8); +static void BuyMenuDisplayMessage(u16, u16); +static void sub_80A683C(void); +static void sub_80A6870(u16, u8); +static void sub_80A699C(void); +static void sub_80A7230(u8); +static void ItemListMenu_InitMenu(void); +static void sub_80A73C0(void); +static void sub_80A73F0(void); +static void sub_80A73FC(void); +static void sub_80A740C(void); +static void sub_80A7420(void); +static void sub_80A751C(void); +static void sub_80A7528(u8); +static void sub_80A7590(void); +static void sub_80A75E4(void); +static void sub_80A7630(void); +static void sub_80A763C(void); +static void sub_80A76A0(void); +static void sub_80A770C(void); +static void DisplayCannotUseItemMessage(int, const u8 *, TaskFunc, int); +static void sub_80A7768(void); +static void sub_80A7828(void); +static void sub_80A7834(int, int); +static bool32 sub_80A78A0(void); +static void sub_80A78B8(void); +static bool32 sub_80A78C4(void); +static void sub_80A78E8(void); +static int sub_80A78F4(void); +static void sub_80A7918(void); +static int sub_80A7924(void); +static int sub_80A7958(void); +static void sub_80A7970(void); +static void sub_80A797C(void); +static int sub_80A7988(void); +static void sub_80A79B4(struct Sprite *); +static void sub_80A79EC(struct Sprite *); +static void sub_80A7A94(struct Sprite *); +static void sub_80A7AE4(struct Sprite *); +static void CreateBagSprite(void); +static void sub_80A7B6C(struct Sprite *); +static void CreateBagPokeballSprite(u8); +static void sub_80A7C64(void); + +static void sub_80A3118(void) +{ + AnimateSprites(); + BuildOamBuffer(); + RunTasks(); + sub_80A740C(); + UpdatePaletteFade(); +} + +static void sub_80A3134(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); + + { + const void *src = gBGTilemapBuffers[1]; + void *dst = (void *)(VRAM + 0x2000); + + DmaCopy16(3, src, dst, 0x800); + } + + { + const void *src = gBGTilemapBuffers[2]; + void *dst = (void *)(VRAM + 0x6000); + + DmaCopy16(3, src, dst, 0x800); + } +} + +static bool8 SetupBagMultistep(void) +{ + u32 index; + u16 savedIme; + + switch (gMain.state) + { + case 0: + sub_80F9438(); + sub_80A34E8(); + gMain.state++; + break; + case 1: + remove_some_task(); + gMain.state++; + break; + case 2: + gpu_pal_allocator_reset__manage_upper_four(); + gMain.state++; + break; + case 3: + sub_80F9020(); + ewramBagSetupStep = 0; + gMain.state++; + break; + case 4: + ResetPaletteFade(); + gPaletteFade.bufferTransferDisabled = TRUE; + gMain.state++; + break; + case 5: + ResetSpriteData(); + gMain.state++; + break; + case 6: + if (LoadBagGraphicsMultistep() == FALSE) + break; + gMain.state++; + break; + case 7: + SetUpWindowConfig(&gWindowConfig_81E6DFC); + gMain.state++; + break; + case 8: + MultistepInitMenuWindowBegin(&gWindowConfig_81E6DFC); + gMain.state++; + break; + case 9: + if (!MultistepInitMenuWindowContinue()) + break; + gMain.state++; + break; + case 10: + sub_80F944C(); + LoadScrollIndicatorPalette(); + CreateVerticalScrollIndicators(0, 172, 12); + CreateVerticalScrollIndicators(1, 172, 148); + CreateVerticalScrollIndicators(2, 28, 88); + CreateVerticalScrollIndicators(3, 100, 88); + sub_80F9988(0, 2); + sub_80F9988(1, 2); + sub_80F9988(2, 2); + sub_80F9988(3, 2); + if (sReturnLocation == RETURN_TO_FIELD_4 || sReturnLocation == RETURN_TO_FIELD_5) + { + sub_80F979C(2, 1); + sub_80F979C(3, 1); + } + gMain.state++; + break; + case 11: + gUnknown_0203855A = 16; + sub_80A39B8(gBGTilemapBuffers[2], sCurrentBagPocket + 1); + DrawPocketIndicatorDots(gBGTilemapBuffers[2], sCurrentBagPocket); + UpdateAllBagPockets(); + SortItemSlots(gBagPockets[2]); + SortItemSlots(gBagPockets[3]); + sub_80A3D40(); + gCurrentBagPocketItemSlots = gBagPockets[sCurrentBagPocket].itemSlots; + sub_80A362C(); + gMain.state++; + break; + case 12: + sub_80A48E8(0xFFFF, 0, 7); + index = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos; + ItemListMenu_InitDescription(gCurrentBagPocketItemSlots[index].itemId); + ItemListMenu_InitMenu(); + gUnknown_0203855B = sCurrentBagPocket + 1; + gUnknown_0203855C = 0; + gMain.state++; + break; + case 13: + CreateBagSprite(); + CreateBagPokeballSprite(0); + sub_80A3740(); + gMain.state++; + break; + case 14: + savedIme = REG_IME; + REG_IME = 0; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = savedIme; + REG_DISPSTAT |= DISPSTAT_VBLANK_INTR; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0); + gPaletteFade.bufferTransferDisabled = FALSE; + gMain.state++; + break; + case 15: + if (sub_8055870() == TRUE) + break; + gMain.state++; + break; + case 16: + SetVBlankCallback(sub_80A3134); + SetMainCallback2(sub_80A3118); + sub_80A751C(); + sub_80A7630(); + sub_80A770C(); + sub_80A7828(); + sub_80A78B8(); + return TRUE; + } + return FALSE; +} + +static bool8 sub_80A34B4(void) +{ + while (1) + { + if (SetupBagMultistep() == TRUE) + { + sPopupMenuSelection = 0; + ResetTasks(); + return TRUE; + } + if (sub_80F9344() == TRUE) + break; + } + return FALSE; +} + + +void sub_80A34E8(void) +{ + sub_80F9368(); + REG_BG2CNT = BGCNT_PRIORITY(2) | BGCNT_CHARBASE(1) | BGCNT_SCREENBASE(12) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_BG1CNT = BGCNT_PRIORITY(1) | BGCNT_CHARBASE(1) | BGCNT_SCREENBASE(4) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG1_ON | DISPCNT_BG2_ON | DISPCNT_OBJ_ON; + REG_BLDCNT = 0; +} + +static bool8 LoadBagGraphicsMultistep(void) +{ + switch (ewramBagSetupStep) + { + case 0: + LZDecompressVram(gBagScreen_Gfx, (void *)(VRAM + 0x4000)); + ewramBagSetupStep++; + break; + case 1: + CpuCopy16(gUnknown_08E77004, gBGTilemapBuffers[2], 0x800); + ewramBagSetupStep++; + break; + case 2: + if (gSaveBlock2.playerGender == MALE || sReturnLocation == RETURN_TO_WALLY_BATTLE) + LoadCompressedPalette(gBagScreenMale_Pal, 0, 64); + else + LoadCompressedPalette(gBagScreenFemale_Pal, 0, 64); + ewramBagSetupStep++; + break; + case 3: + if (gSaveBlock2.playerGender == MALE || sReturnLocation == RETURN_TO_WALLY_BATTLE) + LoadCompressedObjectPic(&sMaleBagSpriteSheet); + else + LoadCompressedObjectPic(&sFemaleBagSpriteSheet); + ewramBagSetupStep++; + break; + case 4: + LoadCompressedObjectPalette(&sBagSpritePalette); + ewramBagSetupStep = 0; + return TRUE; + } + return FALSE; +} + +static void sub_80A362C(void) +{ + u8 i; + + for (i = 0; i < 5; i++) + { + u8 r3; + + if (sReturnLocation == RETURN_TO_FIELD_5) + r3 = gBagPocketScrollStates[i].numSlots - 1; + else + r3 = gBagPocketScrollStates[i].numSlots; + + if (gBagPocketScrollStates[i].scrollTop != 0) + { + if (gBagPocketScrollStates[i].scrollTop + gBagPocketScrollStates[i].cursorMax > r3) + gBagPocketScrollStates[i].scrollTop = r3 - gBagPocketScrollStates[i].cursorMax; + } + else + { + if (gBagPocketScrollStates[i].cursorPos > r3) + gBagPocketScrollStates[i].cursorPos = r3; + } + } +} + +void ResetBagScrollPositions(void) +{ + u16 i; + + for (i = 0; i < NUM_BAG_POCKETS; i++) + { + gBagPocketScrollStates[i].cursorPos = 0; + gBagPocketScrollStates[i].scrollTop = 0; + gBagPocketScrollStates[i].numSlots = 0; + gBagPocketScrollStates[i].cursorMax = 0; + } + sCurrentBagPocket = 0; +} + +static void sub_80A36B8(u16 *a, u8 b, u8 c, u8 d, u8 e) +{ + u16 i; + u16 j; + + for (i = c; i <= c + e; i++) + { + for (j = b; j <= b + d; j++) + { + u32 index = j + i * 32; + + a[index] = 0; + } + } +} + +void ClearBag(void) +{ + u16 i; + + for (i = 0; i < NUM_BAG_POCKETS; i++) + ClearItemSlots(gBagPockets[i].itemSlots, gBagPockets[i].capacity); + ResetBagScrollPositions(); +} + +static void sub_80A3740(void) +{ + const u16 colors[2] = {RGB(14, 15, 16), RGB_WHITE}; + + LoadPalette(&colors[1], 0xD1, sizeof(colors[1])); + LoadPalette(&colors[0], 0xD8, sizeof(colors[0])); +} + +static void sub_80A3770(void) +{ + if (sReturnLocation == RETURN_TO_FIELD_0) + { + sPopupMenuActionList = sItemPopupMenuChoicesTable[sCurrentBagPocket]; + if (sCurrentBagPocket != BAG_POCKET_BERRIES) + gUnknown_02038564 = 4; + else + gUnknown_02038564 = 6; + } +} + +static void sub_80A37C0(u8 taskId) +{ + gTasks[taskId].func = sub_80A50C8; + StartVerticalScrollIndicators(0); + StartVerticalScrollIndicators(1); + StartVerticalScrollIndicators(2); + StartVerticalScrollIndicators(3); +} + +static void sub_80A37F8(u8 taskId) +{ + u8 r5 = gUnknown_0203855A; + + if (r5 < 16) + { + gUnknown_0203855A++; + sub_80A396C(gBGTilemapBuffers[2], r5, gUnknown_0203855A, 0x4F); + sub_80A39E4(gBGTilemapBuffers[2], sCurrentBagPocket + 1, gUnknown_0203855A / 2, gTasks[taskId].data[5]); + gUnknown_02038558 = 1; + sub_80A48E8(taskId, r5 / 2, gUnknown_0203855A / 2 - 1); + gUnknown_02038558 = 0; + return; + } + + if (gLinkOpen == TRUE) + { + u32 index = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos; + + ItemListMenu_ChangeDescription(gCurrentBagPocketItemSlots[index].itemId, gUnknown_02038562); + gUnknown_02038562++; + } + else + { + while (gUnknown_02038562 < 3) + { + u32 index = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos; + + ItemListMenu_ChangeDescription(gCurrentBagPocketItemSlots[index].itemId, gUnknown_02038562); + gUnknown_02038562++; + } + } + if (gUnknown_02038562 == 3) + { + gUnknown_0203855A = 16; + gUnknown_0203855B = sCurrentBagPocket + 1; + sub_80A37C0(FindTaskIdByFunc(sub_80A4F68)); + DestroyTask(taskId); + ItemListMenu_InitMenu(); + sub_80F979C(2, 0); + sub_80F979C(3, 0); + } +} + +static void sub_80A3954(u16 *a) +{ + CpuCopy16(gUnknown_08E77004, a, 0x800); +} + +static void sub_80A396C(u16 *a, u8 b, u8 c, u8 d) +{ + u16 *dst = a + 14 + (b + 2) * 32; + u16 i; + + while (c > b++) + { + for (i = 0; i < 15; i++) + dst[i] = d; + dst += 32; + } +} + +static void sub_80A39B8(u16 *a, u8 b) +{ + u8 var = b * 2; + + sub_809D104(a, 4, 10, gUnknown_08E96EC8, 0, var, 8, 2); +} + +static void sub_80A39E4(u16 *a, u8 b, u8 c, s8 d) +{ + u16 r2 = b * 2; + u16 r7; + + if (d == -1) + { + r7 = (b + 1) * 2; + if (b == 5) + r7 = 2; + + sub_809D104(a, 4, 10, gUnknown_08E96EC8, 8 - c, r2, c, 2); + sub_809D104(a, c + 4, 10, gUnknown_08E96EC8, 0, r7, 8 - c, 2); + } + else if (d == 1) + { + r7 = (b - 1) * 2; + if (b == 1) + r7 = 10; + + sub_809D104(a, 4, 10, gUnknown_08E96EC8, c, r7, 8 - c, 2); + sub_809D104(a, 12 - c, 10, gUnknown_08E96EC8, 0, r2, c, 2); + } +} + +// Draws dots under the bag sprite, showing which pocket is selected +static void DrawPocketIndicatorDots(u16 *tileMapBuffer, u8 selectedPocket) +{ + u8 i; + + for (i = 0; i < NUM_BAG_POCKETS; i++) + { + if (i == selectedPocket) + tileMapBuffer[0x125 + i] = 0x107D; + else + tileMapBuffer[0x125 + i] = 0x107C; + } +} + +static void ChangePocket(u16 *tileMapBuffer, s8 delta) +{ + u8 taskId; + + sCurrentBagPocket += delta; + // Wrap around + if (sCurrentBagPocket >= NUM_BAG_POCKETS) + sCurrentBagPocket = 0; + if (sCurrentBagPocket < 0) + sCurrentBagPocket = NUM_BAG_POCKETS - 1; + + sub_80A76A0(); + sub_80A7590(); + gCurrentBagPocketItemSlots = gBagPockets[sCurrentBagPocket].itemSlots; + sub_80A3D24(sCurrentBagPocket); + gUnknown_0203855A = 0; + sub_80A3954(tileMapBuffer); + sub_80A396C(tileMapBuffer, 0, 16, 3); + sub_80A39B8(tileMapBuffer, 0); + gUnknown_0203855B = 6; + gUnknown_02038562 = 0; + taskId = FindTaskIdByFunc(sub_80A37F8); + if (taskId == 0xFF) + taskId = CreateTask(sub_80A37F8, 8); + gTasks[taskId].data[5] = delta; +} + +static void SwapItemSlots(struct ItemSlot *a, struct ItemSlot *b) +{ + struct ItemSlot temp = *a; + + *a = *b; + *b = temp; +} + +static void RemoveEmptyItemSlots(struct BagPocket pocket) +{ + u16 i; + u16 j; + + for (i = 0; i < pocket.capacity - 1; i++) + { + for (j = i + 1; j < pocket.capacity; j++) + { + if (pocket.itemSlots[i].quantity == 0) + SwapItemSlots(&pocket.itemSlots[i], &pocket.itemSlots[j]); + } + } +} + +static void SortItemSlots(struct BagPocket pocket) +{ + u16 i; + u16 j; + + for (i = 0; i < pocket.capacity; i++) + { + for (j = i + 1; j < pocket.capacity; j++) + { + if (pocket.itemSlots[i].quantity != 0 && pocket.itemSlots[j].quantity != 0 + && pocket.itemSlots[i].itemId > pocket.itemSlots[j].itemId) + SwapItemSlots(&pocket.itemSlots[i], &pocket.itemSlots[j]); + } + } +} + +static void UpdateBagPocket(u8 pocketNum) +{ + u16 i; + + gBagPocketScrollStates[pocketNum].numSlots = 0; + for (i = 0; i < gBagPockets[pocketNum].capacity; i++) + { + if (gBagPockets[pocketNum].itemSlots[i].quantity != 0) + gBagPocketScrollStates[pocketNum].numSlots++; + } + RemoveEmptyItemSlots(gBagPockets[pocketNum]); +} + +static void UpdateAllBagPockets(void) +{ + u8 i; + + for (i = 0; i < NUM_BAG_POCKETS; i++) + UpdateBagPocket(i); +} + +static void sub_80A3D24(u8 pocketNum) +{ + if (gBagPocketScrollStates[pocketNum].numSlots >= 7) + gBagPocketScrollStates[pocketNum].cursorMax = 7; + else + gBagPocketScrollStates[pocketNum].cursorMax = gBagPocketScrollStates[pocketNum].numSlots; +} + +static void sub_80A3D40(void) +{ + u8 i; + + for (i = 0; i < NUM_BAG_POCKETS; i++) + sub_80A3D24(i); +} + +static void sub_80A3D5C(u8 taskId) +{ + u32 index = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos; + + gCurrentBagPocketItemSlots[index].quantity -= gTasks[taskId].data[1]; + if (gCurrentBagPocketItemSlots[index].quantity == 0) // item slot will be removed if the quantity is zero + { + // Un-register the item if registered + if (gSaveBlock1.registeredItem == gCurrentBagPocketItemSlots[index].itemId) + { + RemoveSelectIconFromRegisteredItem(); + gSaveBlock1.registeredItem = ITEM_NONE; + } + + gCurrentBagPocketItemSlots[index].itemId = ITEM_NONE; + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + 7 == gBagPocketScrollStates[sCurrentBagPocket].numSlots + && gBagPocketScrollStates[sCurrentBagPocket].scrollTop != 0) + gBagPocketScrollStates[sCurrentBagPocket].scrollTop--; + UpdateBagPocket(sCurrentBagPocket); + } + sub_80A3D24(sCurrentBagPocket); +} + +void sub_80A3E0C(void) +{ + u32 index = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos; + + if (gCurrentBagPocketItemSlots[index].quantity == 0) + { + gCurrentBagPocketItemSlots[index].itemId = 0; + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + 7 == gBagPocketScrollStates[sCurrentBagPocket].numSlots + && gBagPocketScrollStates[sCurrentBagPocket].scrollTop != 0) + gBagPocketScrollStates[sCurrentBagPocket].scrollTop--; + UpdateBagPocket(sCurrentBagPocket); + } + sub_80A3D24(sCurrentBagPocket); +} + +static void nullsub_16(void) +{ +} + +static void sub_80A3E70(u8 a, u8 b) +{ + struct ItemSlot temp = gCurrentBagPocketItemSlots[a]; + + gCurrentBagPocketItemSlots[a] = gCurrentBagPocketItemSlots[b]; + gCurrentBagPocketItemSlots[b] = temp; +} + +static void sub_80A3E90(u8 taskId) +{ + PlaySE(SE_SELECT); + nullsub_16(); + sub_80A3E70( + gTasks[taskId].data[10] - 1, + gBagPocketScrollStates[sCurrentBagPocket].cursorPos + gBagPocketScrollStates[sCurrentBagPocket].scrollTop); + gTasks[taskId].data[10] = 0; + sub_80A763C(); + sub_80A7528(0); + ItemListMenu_InitMenu(); +} + +static void sub_80A3EF4(u8 taskId) +{ + u8 r2; + + PlaySE(SE_SELECT); + nullsub_16(); + r2 = gTasks[taskId].data[10] - gBagPocketScrollStates[sCurrentBagPocket].scrollTop - 1; + gTasks[taskId].data[10] = 0; + if (r2 < 8) + sub_80A48E8(taskId, r2, r2); + sub_80A7528(0); +} + +static void sub_80A3F50(u8 taskId) +{ + gTasks[taskId].data[10] = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos + 1; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A7528(1); +} + +void sub_80A3FA0(u16 *a, u8 b, u8 c, u8 d, u8 e, u16 f) +{ + s16 i; + s16 j; + + for (i = c; i < c + e; i++) + { + for (j = b; j < b + d; j++) + { + u32 index = j + i * 32; + + a[index] = f; + } + } +} + +static void sub_80A4008(u16 *a, u8 b, u8 c, u8 d, u8 e) +{ + sub_80A3FA0(a, b, c, d, e, 1); +} + +static void DrawSelectIcon(u32 itemPos) +{ + u16 *ptr1 = gBGTilemapBuffers[2] + 0x5A; + + ptr1 += itemPos * 64; + ptr1[0] = 0x5A; + ptr1[1] = 0x5B; + ptr1[2] = 0x5C; + ptr1[32] = 0x6A; + ptr1[33] = 0x6B; + ptr1[34] = 0x6C; +} + +static void MoveSelectIcon(u8 itemPos) +{ + u16 i; + u16 *ptr; + + ptr = gBGTilemapBuffers[2] + 0x5A; + for (i = 0; i < 16; i++) + { + ptr[0] = 0x4F; + ptr[1] = 0x4F; + ptr[2] = 0x4F; + ptr += 32; + } + + ptr = gBGTilemapBuffers[2] + 0x5A + itemPos * 64; + ptr[0] = 0x5A; + ptr[1] = 0x5B; + ptr[2] = 0x5C; + ptr[32] = 0x6A; + ptr[33] = 0x6B; + ptr[34] = 0x6C; +} + +static void EraseSelectIcon(u8 itemPos) +{ + u16 *ptr = gBGTilemapBuffers[2] + 0x5A; + + ptr += itemPos * 64; + ptr[0] = 0x4F; + ptr[1] = 0x4F; + ptr[2] = 0x4F; + ptr[32] = 0x4F; + ptr[33] = 0x4F; + ptr[34] = 0x4F; +} + +static void RemoveSelectIconFromRegisteredItem(void) +{ + u8 i; + + for (i = 0; i < 8; i++) + { + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + i == gBagPocketScrollStates[sCurrentBagPocket].numSlots) + break; + if (gCurrentBagPocketItemSlots[gBagPocketScrollStates[sCurrentBagPocket].scrollTop + i].itemId == gSaveBlock1.registeredItem) + { + EraseSelectIcon(i); + break; + } + } +} + +static void AddSelectIconToRegisteredItem(void) +{ + RemoveSelectIconFromRegisteredItem(); + MoveSelectIcon(gBagPocketScrollStates[sCurrentBagPocket].cursorPos); +} + +void sub_80A4164(u8 *dest, u16 value, enum StringConvertMode mode, u8 digits) +{ + *dest++ = CHAR_MULT_SIGN; + dest[0] = EXT_CTRL_CODE_BEGIN; + dest[1] = 0x14; + dest[2] = 6; + dest += 3; + ConvertIntToDecimalStringN(dest, value, mode, digits); +} + +void sub_80A418C(u16 value, enum StringConvertMode mode, u8 c, u8 d, u8 digits) +{ + sub_80A4164(gStringVar1, value, mode, digits); + MenuPrint(gStringVar1, c, d); +} + +static void sub_80A41D4(u8 taskId) +{ + sub_80A763C(); +} + +static void sub_80A41E0(u8 *a, u16 b, const u8 *c, u16 d, u8 e) +{ + a[0] = EXT_CTRL_CODE_BEGIN; + a[1] = 0x13; + a[2] = 8; + a += 3; + a = ConvertIntToDecimalStringN(a, b, STR_CONV_MODE_LEADING_ZEROS, 2); + a[0] = EXT_CTRL_CODE_BEGIN; + a[1] = 0x13; + a[2] = 0x18; + a += 3; + a = sub_8072C74(a, c, 0x78 - (e + 1) * 6, 0); + *a++ = CHAR_MULT_SIGN; + sub_8072C14(a, d, 0x78, 1); +} + +static u8 *sub_80A425C(u8 taskId, u8 *text, u8 c) +{ + if (gTasks[taskId].data[10] - gBagPocketScrollStates[sCurrentBagPocket].scrollTop - 1 == c) + { + text[0] = EXT_CTRL_CODE_BEGIN; + text[1] = 1; + text[2] = 2; + text += 3; + } + return text; +} + +static bool8 sub_80A42B0(u8 itemPos, int b) +{ + u8 r5; + u16 *ptr; + struct UnknownStruct3 *r8 = &gUnknown_02038540; + + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + itemPos > gBagPocketScrollStates[sCurrentBagPocket].numSlots) + return TRUE; + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + itemPos == gBagPocketScrollStates[sCurrentBagPocket].numSlots) + { + if (sReturnLocation == RETURN_TO_FIELD_5) + return TRUE; + r5 = itemPos * 2 + 2; + sub_8072C74(gStringVar1, gOtherText_CloseBag, 0x78, 0); + MenuPrint(gStringVar1, 14, r5); + ptr = gBGTilemapBuffers[2] + 14 + r5 * 32; + ptr[0] = 0x4F; + ptr[1] = 0x4F; + ptr[32] = 0x4F; + ptr[33] = 0x4F; + if (itemPos == 7) + return TRUE; + if ((b == 1 && r8->unk2 != 0) || b == 2) + MenuFillWindowRectWithBlankTile(14, r5 + 2, 29, 13); + else + MenuFillWindowRectWithBlankTile(14, r5 + 2, 29, 17); + return TRUE; + } + return FALSE; +} + +static void sub_80A4380(u16 a, int b, int c, int d) +{ + u8 i; + + for (i = b; i <= c; i++) + { + u8 r4; + u8 r5; + u8 *text; + + if (sub_80A42B0(i, d) == TRUE) + break; + r4 = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + i; + r5 = i * 2 + 2; + text = gStringVar1; + text = sub_80A425C(a, text, i); + text = sub_8072C74(text, ItemId_GetItem(gCurrentBagPocketItemSlots[r4].itemId)->name, 0x66, 0); + *text++ = CHAR_MULT_SIGN; + sub_8072C14(text, gCurrentBagPocketItemSlots[r4].quantity, 0x78, 1); + MenuPrint(gStringVar1, 14, r5); + } +} + +static void sub_80A444C(u16 a, int b, int c, int d) +{ + u8 i; + + for (i = b; i <= c; i++) + { + u8 r4; + u8 r5; + u8 *text; + + if (sub_80A42B0(i, d) == TRUE) + break; + r4 = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + i; + r5 = i * 2 + 2; + text = gStringVar1; + text = sub_80A425C(a, text, i); +#if ENGLISH + sub_8072C74(text, ItemId_GetItem(gCurrentBagPocketItemSlots[r4].itemId)->name, 0x60, 0); +#else + sub_8072C74(text, ItemId_GetItem(gCurrentBagPocketItemSlots[r4].itemId)->name, 0x63, 0); +#endif + MenuPrint(gStringVar1, 14, r5); + if (gUnknown_02038558 != 0) + { + if (gCurrentBagPocketItemSlots[r4].itemId == gSaveBlock1.registeredItem) + DrawSelectIcon(i); + } + else + { + if (gCurrentBagPocketItemSlots[r4].itemId == gSaveBlock1.registeredItem) + MoveSelectIcon(i); + else + EraseSelectIcon(i); + } + } +} + +// more gBGTilemapBuffers shenanigans +#ifdef NONMATCHING +static void sub_80A4548(u16 a, int b, int c, int d) +{ + u8 i; + + for (i = b; i <= c; i++) + { + u8 r4; + u8 sp10; + u32 r5; + u8 *text; + + if (sub_80A42B0(i, d) == TRUE) + break; + r4 = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + i; + sp10 = i * 2 + 2; + r5 = sp10 * 32 + 14; + text = gStringVar1; + text = sub_80A425C(a, text, i); + if (gCurrentBagPocketItemSlots[r4].itemId < 0x153) + { + const u8 *r2; + + gBGTilemapBuffers[2][r5 + 0] = 0x59; + gBGTilemapBuffers[2][r5 + 1] = 0x4F; + gBGTilemapBuffers[2][r5 + 32] = 0x69; + gBGTilemapBuffers[2][r5 + 33] = 0x4F; + r2 = gMoveNames[ItemIdToBattleMoveId(gCurrentBagPocketItemSlots[r4].itemId)]; + sub_80A41E0(text, gCurrentBagPocketItemSlots[r4].itemId - 288, r2, gCurrentBagPocketItemSlots[r4].quantity, 2); + } + else + { + const u8 *moveName; + + gBGTilemapBuffers[2][r5 + 0] = 0x105D; + gBGTilemapBuffers[2][r5 + 1] = 0x105E; + gBGTilemapBuffers[2][r5 + 32] = 0x106D; + gBGTilemapBuffers[2][r5 + 33] = 0x106E; + text[0] = EXT_CTRL_CODE_BEGIN; + text[1] = 0x13; + text[2] = 0x11; + text += 3; + text = ConvertIntToDecimalString(text, gCurrentBagPocketItemSlots[r4].itemId); + text[0] = EXT_CTRL_CODE_BEGIN; + text[1] = 0x13; + text[2] = 0x18; + text += 3; + moveName = gMoveNames[ItemIdToBattleMoveId(gCurrentBagPocketItemSlots[r4].itemId)]; + sub_8072C74(text, moveName, 0x78, 0); + } + MenuPrint(gStringVar1, 14, sp10); + } +} +#else +__attribute__((naked)) +static void sub_80A4548(u16 a, int b, int c, int d) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x14\n\ + str r2, [sp, 0x8]\n\ + str r3, [sp, 0xC]\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [sp, 0x4]\n\ + lsls r1, 24\n\ + lsrs r1, 24\n\ + mov r8, r1\n\ + ldr r0, _080A456C @ =gBGTilemapBuffers + 0x1000\n\ + mov r9, r0\n\ + b _080A46C2\n\ + .align 2, 0\n\ +_080A456C: .4byte gBGTilemapBuffers + 0x1000\n\ +_080A4570:\n\ + ldr r1, _080A461C @ =gBagPocketScrollStates\n\ + ldr r0, _080A4620 @ =sCurrentBagPocket\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r4, [r0, 0x1]\n\ + add r4, r8\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + mov r1, r8\n\ + lsls r0, r1, 25\n\ + movs r3, 0x80\n\ + lsls r3, 18\n\ + adds r0, r3\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x10]\n\ + lsls r0, 5\n\ + adds r0, 0xE\n\ + adds r5, r0, 0\n\ + ldr r6, _080A4624 @ =gStringVar1\n\ + ldr r1, [sp, 0x4]\n\ + lsls r0, r1, 24\n\ + lsrs r0, 24\n\ + adds r1, r6, 0\n\ + mov r2, r8\n\ + bl sub_80A425C\n\ + adds r6, r0, 0\n\ + ldr r3, _080A4628 @ =gCurrentBagPocketItemSlots\n\ + mov r10, r3\n\ + ldr r0, [r3]\n\ + lsls r7, r4, 2\n\ + adds r3, r7, r0\n\ + ldrh r1, [r3]\n\ + movs r0, 0xA9\n\ + lsls r0, 1\n\ + cmp r1, r0\n\ + bhi _080A4634\n\ + lsls r0, r5, 1\n\ + add r0, r9\n\ + movs r1, 0x59\n\ + strh r1, [r0]\n\ + adds r0, r5, 0x1\n\ + lsls r0, 1\n\ + add r0, r9\n\ + movs r2, 0x4F\n\ + strh r2, [r0]\n\ + adds r0, r5, 0\n\ + adds r0, 0x20\n\ + lsls r0, 1\n\ + add r0, r9\n\ + movs r1, 0x69\n\ + strh r1, [r0]\n\ + adds r0, r5, 0\n\ + adds r0, 0x21\n\ + lsls r0, 1\n\ + add r0, r9\n\ + strh r2, [r0]\n\ + ldrh r0, [r3]\n\ + bl ItemIdToBattleMoveId\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0xD\n\ + adds r2, r0, 0\n\ + muls r2, r1\n\ + ldr r0, _080A462C @ =gMoveNames\n\ + adds r2, r0\n\ + mov r1, r10\n\ + ldr r0, [r1]\n\ + adds r0, r7, r0\n\ + ldr r3, _080A4630 @ =0xfffffee0\n\ + adds r1, r3, 0\n\ + ldrh r3, [r0]\n\ + adds r1, r3\n\ + lsls r1, 16\n\ + lsrs r1, 16\n\ + ldrh r3, [r0, 0x2]\n\ + movs r0, 0x2\n\ + str r0, [sp]\n\ + adds r0, r6, 0\n\ + bl sub_80A41E0\n\ + b _080A46AE\n\ + .align 2, 0\n\ +_080A461C: .4byte gBagPocketScrollStates\n\ +_080A4620: .4byte sCurrentBagPocket\n\ +_080A4624: .4byte gStringVar1\n\ +_080A4628: .4byte gCurrentBagPocketItemSlots\n\ +_080A462C: .4byte gMoveNames\n\ +_080A4630: .4byte 0xfffffee0\n\ +_080A4634:\n\ + lsls r0, r5, 1\n\ + add r0, r9\n\ + ldr r1, _080A46EC @ =0x0000105d\n\ + strh r1, [r0]\n\ + adds r0, r5, 0x1\n\ + lsls r0, 1\n\ + add r0, r9\n\ + adds r1, 0x1\n\ + strh r1, [r0]\n\ + adds r0, r5, 0\n\ + adds r0, 0x20\n\ + lsls r0, 1\n\ + add r0, r9\n\ + adds r1, 0xF\n\ + strh r1, [r0]\n\ + adds r0, r5, 0\n\ + adds r0, 0x21\n\ + lsls r0, 1\n\ + add r0, r9\n\ + adds r1, 0x1\n\ + strh r1, [r0]\n\ + movs r0, 0xFC\n\ + strb r0, [r6]\n\ + movs r4, 0x13\n\ + strb r4, [r6, 0x1]\n\ + movs r0, 0x11\n\ + strb r0, [r6, 0x2]\n\ + adds r6, 0x3\n\ + mov r1, r10\n\ + ldr r0, [r1]\n\ + adds r0, r7, r0\n\ + ldrh r1, [r0]\n\ + ldr r3, _080A46F0 @ =0xfffffeae\n\ + adds r1, r3\n\ + adds r0, r6, 0\n\ + bl ConvertIntToDecimalString\n\ + adds r6, r0, 0\n\ + movs r0, 0xFC\n\ + strb r0, [r6]\n\ + strb r4, [r6, 0x1]\n\ + movs r0, 0x18\n\ + strb r0, [r6, 0x2]\n\ + adds r6, 0x3\n\ + mov r1, r10\n\ + ldr r0, [r1]\n\ + adds r0, r7, r0\n\ + ldrh r0, [r0]\n\ + bl ItemIdToBattleMoveId\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0xD\n\ + muls r1, r0\n\ + ldr r0, _080A46F4 @ =gMoveNames\n\ + adds r1, r0\n\ + adds r0, r6, 0\n\ + movs r2, 0x78\n\ + movs r3, 0\n\ + bl sub_8072C74\n\ +_080A46AE:\n\ + ldr r0, _080A46F8 @ =gStringVar1\n\ + movs r1, 0xE\n\ + ldr r2, [sp, 0x10]\n\ + bl MenuPrint\n\ + mov r0, r8\n\ + adds r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ +_080A46C2:\n\ + ldr r3, [sp, 0x8]\n\ + cmp r8, r3\n\ + bgt _080A46DA\n\ + mov r0, r8\n\ + ldr r1, [sp, 0xC]\n\ + bl sub_80A42B0\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + beq _080A46DA\n\ + b _080A4570\n\ +_080A46DA:\n\ + add sp, 0x14\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080A46EC: .4byte 0x0000105d\n\ +_080A46F0: .4byte 0xfffffeae\n\ +_080A46F4: .4byte gMoveNames\n\ +_080A46F8: .4byte gStringVar1\n\ + .syntax divided\n"); +} +#endif + +static void sub_80A46FC(u16 a, int b, int c, int d) +{ + u8 i; + + for (i = b; i <= c; i++) + { + u8 r4; + u8 r5; + u8 *text; + register int var asm("r0"); + + if (sub_80A42B0(i, d) == TRUE) + break; + r4 = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + i; + r5 = i * 2 + 2; + + var = 14 + r5 * 32; + gBGTilemapBuffers[2][var] = 0x59; + var += 32; + gBGTilemapBuffers[2][var] = 0x69; + + text = gStringVar1; + text = sub_80A425C(a, text, i); + CopyItemName(gCurrentBagPocketItemSlots[r4].itemId, gStringVar2); + sub_80A41E0(text, gCurrentBagPocketItemSlots[r4].itemId - 0x84, gStringVar2, gCurrentBagPocketItemSlots[r4].quantity, 3); + MenuPrint(gStringVar1, 14, r5); + } +} + +static void sub_80A47E8(u16 a, int b, int c, int d) +{ + switch (sCurrentBagPocket) + { + case BAG_POCKET_ITEMS: + case BAG_POCKET_POKE_BALLS: + sub_80A4380(a, b, c, d); + break; + case BAG_POCKET_KEY_ITEMS: + sub_80A444C(a, b, c, d); + break; + case BAG_POCKET_TMs_HMs: + sub_80A4548(a, b, c, d); + break; + case BAG_POCKET_BERRIES: + sub_80A46FC(a, b, c, d); + break; + } + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop != 0) + sub_80F979C(0, 0); + else + sub_80F979C(0, 1); + if ((sReturnLocation != RETURN_TO_FIELD_5 && gBagPocketScrollStates[sCurrentBagPocket].scrollTop + 8 < gBagPocketScrollStates[sCurrentBagPocket].numSlots + 1) + || (sReturnLocation == RETURN_TO_FIELD_5 && gBagPocketScrollStates[sCurrentBagPocket].scrollTop + 8 < gBagPocketScrollStates[sCurrentBagPocket].numSlots)) + sub_80F979C(1, 0); + else + sub_80F979C(1, 1); +} + +static void sub_80A48E8(u16 taskId, int b, int c) +{ + sub_80A47E8(taskId, b, c, 0); +} + +static void sub_80A48F8(u16 taskId) +{ + sub_80A47E8(taskId, 0, 5, 2); +} + +static void ItemListMenu_InitDescription(s16 itemId) +{ + u8 r5; + + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos == gBagPocketScrollStates[sCurrentBagPocket].numSlots) + { + r5 = sub_8072A18(gOtherText_ReturnTo, 4, 0x68, 0x68, 1); + r5 += sub_8072A18(gUnknown_0840E740[sReturnLocation], 4, 0x78, 0x68, 1); + } + else + { + r5 = sub_8072A18(ItemId_GetDescription(itemId), 4, 0x68, 0x68, 1); + } + + if (r5 < 3) + MenuZeroFillWindowRect(0, 13 + r5 * 2, 13, 20); +} + +static void ItemListMenu_ChangeDescription(s16 itemId, int b) +{ + u8 description[100]; + + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos == gBagPocketScrollStates[sCurrentBagPocket].numSlots) + { + if (b == 0) + { + MenuZeroFillWindowRect(0, 13, 13, 20); + MenuPrint_PixelCoords(gOtherText_ReturnTo, 4, 0x68, 0); + } + else if (b == 1) + { + MenuPrint_PixelCoords(gUnknown_0840E740[sReturnLocation], 4, 0x78, 0); + } + } + else + { + if (b == 0) + MenuZeroFillWindowRect(0, 13, 13, 20); + if (ItemId_CopyDescription(description, itemId, b)) + MenuPrint_PixelCoords(description, 4, 104 + b * 16, 0); + } +} + +static bool32 CopyTextLine(u8 *destination, const u8 *source, u32 c) +{ + u32 r4 = c + 1; + const u8 *src = source; + u8 *dst = destination; + + while (1) + { + if (*src == CHAR_NEWLINE || *src == EOS) + { + r4--; + if (r4 == 0) + { + *dst = EOS; + return TRUE; + } + if (*src == EOS) + return FALSE; + // got a new line - reset dst pointer + dst = destination; + src++; + } + else + { + *dst++ = *src++; + } + } +} + +static void sub_80A4A98(const u8 *text, u32 line) +{ + u8 buffer[100]; + + if (line == 0) + MenuZeroFillWindowRect(0, 13, 13, 20); + if (CopyTextLine(buffer, text, line)) + MenuPrint_PixelCoords(buffer, 4, 104 + line * 16, 0); +} + +static void sub_80A4ADC(u8 taskId) +{ + if (gTasks[taskId].data[10] == 0) + sub_80A7528(0); + PlaySE(SE_SELECT); + gUnknown_0203855C = 1; +} + +static void sub_80A4B14(s8 a, u8 b) +{ + gBagPocketScrollStates[sCurrentBagPocket].scrollTop += a; + MoveMenuCursor(0); + sub_80A73C0(); + sub_80A763C(); + sub_80A4ADC(b); +} + +static void sub_80A4B58(s8 delta, u8 b) +{ + gBagPocketScrollStates[sCurrentBagPocket].cursorPos = MoveMenuCursor(delta); + sub_80A73C0(); + sub_80A4ADC(b); +} + +static const u8 *sub_80A4B90(u16 itemId) +{ + if (TestPlayerAvatarFlags(6)) + { + if (itemId == ITEM_MACH_BIKE || itemId == ITEM_ACRO_BIKE) + return gOtherText_Walk; + } + if (ItemIsMail(itemId) == TRUE) + return gOtherText_Check; + return sItemPopupMenuActions[sPopupMenuActionList[0]].text; +} + +static void sub_80A4BF0(u16 *a) +{ + u8 i; + + if (gUnknown_02038564 == 4) + { + MenuDrawTextWindow(0, 7, 13, 12); + sub_80A4008(a, 1, 8, 12, 4); + if (sub_80F9344() == TRUE && sReturnLocation == RETURN_TO_FIELD_5) + { + sub_80A7834(1, 0); + } + else + { + for (i = 0; i < gUnknown_02038564; i++) + { + const u8 *text; + + if (i == 0) + text = sub_80A4B90(gScriptItemId); + else + text = sItemPopupMenuActions[sPopupMenuActionList[i]].text; + MenuPrint(text, 1 + (i / 2) * 6, 8 + (i % 2) * 2); + } + } + if (sReturnLocation == RETURN_TO_FIELD_5) + InitMenu(0, 1, 8, gUnknown_02038564, sPopupMenuSelection, 1); + else + InitMenu(0, 1, 8, gUnknown_02038564, 0, 1); + sub_8072DCC(0x2F); + } + else + { + MenuDrawTextWindow(0, 5, 13, 12); + sub_80A4008(a, 1, 6, 12, 6); + for (i = 0; i < gUnknown_02038564; i++) + MenuPrint(sItemPopupMenuActions[sPopupMenuActionList[i]].text, 1 + (i / 3) * 6, 6 + (i % 3) * 2); + InitMenu(0, 1, 6, gUnknown_02038564, 0, 1); + sub_8072DCC(0x2F); + } + sub_80A7528(2); +} + +static void sub_80A4DA4(u16 *a) +{ + sub_80A73FC(); + sub_80A36B8(a, 0, 6, 13, 6); + MenuZeroFillWindowRect(0, 5, 13, 12); + sub_80A7590(); +} + +static void sub_80A4DD8(u8 taskId, u8 b, u8 c, u8 d, u8 e, u8 digits) +{ + gTasks[taskId].data[1] = 1; + gTasks[taskId].data[2] = b + 2; + gTasks[taskId].data[3] = c + 1; + MenuDrawTextWindow(b, c, b + d, c + e); + sub_80A4008(gBGTilemapBuffers[1], b + 1, c + 1, d - 1, e - 1); + sub_80A418C(1, 1, b + 2, c + 1, digits); +} + +static void sub_80A4E8C(s8 delta, u8 b) +{ + PlaySE(SE_SELECT); + sub_80F979C(0, 1); + sub_80F979C(1, 1); + sub_80F979C(2, 1); + sub_80F979C(3, 1); + PauseVerticalScrollIndicator(0); + PauseVerticalScrollIndicator(1); + PauseVerticalScrollIndicator(2); + PauseVerticalScrollIndicator(3); + ChangePocket(gBGTilemapBuffers[2], delta); + DrawPocketIndicatorDots(gBGTilemapBuffers[2], sCurrentBagPocket); + sub_80A3770(); + sub_80A7C64(); + CreateBagPokeballSprite(b); +} + +static bool8 sub_80A4F0C(void) +{ + if (sReturnLocation == RETURN_TO_FIELD_5 || sReturnLocation == RETURN_TO_FIELD_4) + return FALSE; + if (gMain.newKeys == DPAD_RIGHT || sub_80F9284() == 2) + { + sub_80A4E8C(1, 2); + return TRUE; + } + if (gMain.newKeys == DPAD_LEFT || sub_80F9284() == 1) + { + sub_80A4E8C(-1, 1); + return TRUE; + } + return FALSE; +} + +static void sub_80A4F68(u8 taskId) +{ + sub_80A4F0C(); +} + +static bool8 sub_80A4F74(u8 a) +{ + bool8 retVal = FALSE; + + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP) + { + if (gBagPocketScrollStates[sCurrentBagPocket].cursorPos != 0) + sub_80A4B58(-1, a); + else if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop != 0) + sub_80A4B14(-1, a); + if (gLinkOpen == TRUE && gMain.keyRepeatCounter == 5) + gMain.keyRepeatCounter = 11; + retVal = TRUE; + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN) + { + if (sReturnLocation != RETURN_TO_FIELD_5) + { + if (gBagPocketScrollStates[sCurrentBagPocket].cursorPos == gBagPocketScrollStates[sCurrentBagPocket].cursorMax) + { + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos != gBagPocketScrollStates[sCurrentBagPocket].numSlots) + sub_80A4B14(1, a); + } + else + { + sub_80A4B58(1, a); + } + } + else + { + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos != gBagPocketScrollStates[sCurrentBagPocket].numSlots - 1) + { + if (gBagPocketScrollStates[sCurrentBagPocket].cursorPos != gBagPocketScrollStates[sCurrentBagPocket].cursorMax) + sub_80A4B58(1, a); + else + sub_80A4B14(1, a); + } + } + retVal = TRUE; + if (gLinkOpen == TRUE && gMain.keyRepeatCounter == 5) + gMain.keyRepeatCounter = 11; + } + else + { + if (gTasks[a].data[10] == 0 && sub_80A4F0C() == TRUE) + { + sub_80A73F0(); + gTasks[a].func = sub_80A4F68; + retVal = TRUE; + } + else + { + sub_80A73C0(); + } + } + return retVal; +} + +static void sub_80A50C8(u8 taskId) +{ + s16 *r5 = gTasks[taskId].data; + + if (!gPaletteFade.active) + { + if (sub_80A4F74(taskId) == TRUE) + { + sub_808B5B4(taskId); + return; + } + + if ((gMain.newKeys & SELECT_BUTTON) + && !(sCurrentBagPocket == BAG_POCKET_BERRIES || sCurrentBagPocket == BAG_POCKET_TMs_HMs) + && (sReturnLocation == RETURN_TO_FIELD_0 || sReturnLocation == RETURN_TO_BATTLE)) + { + if (r5[10] == 0) + { + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos != gBagPocketScrollStates[sCurrentBagPocket].numSlots) + { + PlaySE(SE_SELECT); + sub_80A3F50(taskId); + } + sub_808B5B4(taskId); + } + else + { + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos != gBagPocketScrollStates[sCurrentBagPocket].numSlots) + { + PlaySE(SE_SELECT); + sub_80A3E90(taskId); + } + else + { + sub_80A3EF4(taskId); + } + sub_808B5B4(taskId); + } + return; + } + + if (gMain.newKeys & A_BUTTON) + { + if (gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos == gBagPocketScrollStates[sCurrentBagPocket].numSlots) + { + if (r5[10] == 0) + { + gScriptItemId = 0; + gUnknown_083C16BC[sReturnLocation].onBagClose(taskId); + } + else + { + sub_80A3EF4(taskId); + } + sub_808B5B4(taskId); + } + else + { + if (r5[10] == 0) + { + PlaySE(SE_SELECT); + gUnknown_02038560 = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos; + gScriptItemId = gCurrentBagPocketItemSlots[gUnknown_02038560].itemId; + gUnknown_083C16BC[sReturnLocation].onItemSelect(taskId); + sub_80F98A4(0); + sub_80F98A4(1); + sub_80F98A4(2); + sub_80F98A4(3); + sub_80A797C(); + } + else + { + sub_80A3E90(taskId); + } + sub_808B5B4(taskId); + } + return; + } + + if (gMain.newKeys & B_BUTTON) + { + if (r5[10] == 0) + { + if (sReturnLocation != RETURN_TO_FIELD_5) + { + gScriptItemId = 0; + gUnknown_083C16BC[sReturnLocation].onBagClose(taskId); + } + } + else + { + sub_80A3EF4(taskId); + } + sub_808B5B4(taskId); + return; + } + } +} + +bool8 sub_80A52C4(u8 taskId, u16 b) +{ + s16 *taskData = gTasks[taskId].data; + + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP) + { + if (taskData[1] != b) + taskData[1]++; + else + taskData[1] = 1; + return TRUE; + } + + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN) + { + if (taskData[1] != 1) + taskData[1]--; + else + taskData[1] = b; + return TRUE; + } + + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_RIGHT) + { + if (taskData[1] + 10 < b) + taskData[1] += 10; + else + taskData[1] = b; + return TRUE; + } + + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_LEFT) + { + if (taskData[1] > 10) + taskData[1] -= 10; + else + taskData[1] = 1; + return TRUE; + } + + return FALSE; +} + +static bool8 sub_80A5350(u8 taskId) +{ + s16 *taskData = gTasks[taskId].data; + + if (sub_80A52C4(taskId, gCurrentBagPocketItemSlots[gUnknown_02038560].quantity) == TRUE) + { + // if (sCurrentBagPocket == BAG_POCKET_BERRIES) Can't get it to match this way + if (sCurrentBagPocket + 1 == BAG_POCKET_BERRIES + 1) + sub_80A418C(taskData[1], 1, taskData[2], taskData[3], 3); + else + sub_80A418C(taskData[1], 1, taskData[2], taskData[3], 2); + return TRUE; + } + return FALSE; +} + +static void sub_80A53CC(void) +{ + if (sub_80A34B4() == TRUE) + { + sub_80A3770(); + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); + } +} + +void sub_80A53F8(void) +{ + sReturnLocation = RETURN_TO_FIELD_0; + SetMainCallback2(sub_80A53CC); +} + +#ifdef NONMATCHING +static void sub_80A5414(u8 taskId) +{ + TaskFunc r5 = NULL; + + if (sub_80A78A0() != 0) + { + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == 0x40) + { + if ((sPopupMenuSelection & 1) && sPopupMenuActionList[sPopupMenuSelection - 1] == 8) + { + PlaySE(SE_SELECT); + sPopupMenuSelection = MoveMenuCursor3(-1); + } + } + //_080A546C + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == 0x80) + { + if (!(sPopupMenuSelection & 1) && sPopupMenuActionList[sPopupMenuSelection + 1] != 8) + { + PlaySE(SE_SELECT); + sPopupMenuSelection = MoveMenuCursor3(1); + } + } + //_080A549C + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == 0x20) + { + if (sPopupMenuSelection > 1 && sPopupMenuActionList[sPopupMenuSelection - 2] != 8) + { + PlaySE(SE_SELECT); + sPopupMenuSelection = MoveMenuCursor3(-2); + } + } + //_080A54CC + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == 0x10) + { + if (sPopupMenuSelection <= 1 && sPopupMenuActionList[sPopupMenuSelection + 2] != 8) + { + PlaySE(SE_SELECT); + sPopupMenuSelection = MoveMenuCursor3(2); + } + } + //_080A5500 + else if (!(gMain.newKeys & A_BUTTON)) + { + if (gMain.newKeys & B_BUTTON) + { + gTasks[taskId].data[10] = 0; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A4DA4(gBGTilemapBuffers[1]); + r5 = sItemPopupMenuActions[sPopupMenuActionList[3]].func; + r5(taskId); + } + } + else + { + //_080A5590 + gTasks[taskId].data[10] = 0; + sub_80A4DA4(gBGTilemapBuffers[1]); + r5 = sItemPopupMenuActions[sPopupMenuActionList[sPopupMenuSelection]].func; + r5(taskId); + } + } + //_080A5552 + if (r5 == NULL) + { + if (sReturnLocation == RETURN_TO_FIELD_5) + { + if (sPopupMenuSelection == 0) + { + sub_8072DDC(12); + return; + } + //_080A55D4 + //else + //{ + if (sPopupMenuSelection == 0 || sPopupMenuSelection == 1) + sub_8072DCC(0x2F); + else + sub_8072DCC(0x30); + //} + } + //_080A55E0 + else + { + if (sPopupMenuSelection == 0 || sPopupMenuSelection == 1) + sub_8072DCC(0x2F); + else + sub_8072DCC(0x30); + } + } +} +#else +__attribute__((naked)) +static void sub_80A5414(u8 taskId) +{ + asm(".syntax unified\n\ + push {r4,r5,lr}\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + movs r5, 0\n\ + bl sub_80A78A0\n\ + cmp r0, 0\n\ + bne _080A5426\n\ + b _080A5552\n\ +_080A5426:\n\ + ldr r2, _080A5460 @ =gMain\n\ + ldrh r0, [r2, 0x30]\n\ + movs r1, 0xF0\n\ + ands r1, r0\n\ + cmp r1, 0x40\n\ + bne _080A546C\n\ + ldr r4, _080A5464 @ =sPopupMenuSelection\n\ + ldrb r1, [r4]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080A5440\n\ + b _080A5552\n\ +_080A5440:\n\ + ldrb r1, [r4]\n\ + ldr r0, _080A5468 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r1, r0\n\ + subs r1, 0x1\n\ + ldrb r0, [r1]\n\ + cmp r0, 0x8\n\ + bne _080A5452\n\ + b _080A5552\n\ +_080A5452:\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + b _080A54EE\n\ + .align 2, 0\n\ +_080A5460: .4byte gMain\n\ +_080A5464: .4byte sPopupMenuSelection\n\ +_080A5468: .4byte sPopupMenuActionList\n\ +_080A546C:\n\ + cmp r1, 0x80\n\ + bne _080A549C\n\ + ldr r4, _080A5494 @ =sPopupMenuSelection\n\ + ldrb r1, [r4]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080A5552\n\ + ldrb r1, [r4]\n\ + ldr r0, _080A5498 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x1]\n\ + cmp r0, 0x8\n\ + beq _080A5552\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x1\n\ + b _080A54EE\n\ + .align 2, 0\n\ +_080A5494: .4byte sPopupMenuSelection\n\ +_080A5498: .4byte sPopupMenuActionList\n\ +_080A549C:\n\ + cmp r1, 0x20\n\ + bne _080A54CC\n\ + ldr r4, _080A54C4 @ =sPopupMenuSelection\n\ + ldrb r0, [r4]\n\ + cmp r0, 0x1\n\ + bls _080A5552\n\ + adds r1, r0, 0\n\ + ldr r0, _080A54C8 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r1, r0\n\ + subs r1, 0x2\n\ + ldrb r0, [r1]\n\ + cmp r0, 0x8\n\ + beq _080A5552\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x2\n\ + negs r0, r0\n\ + b _080A54EE\n\ + .align 2, 0\n\ +_080A54C4: .4byte sPopupMenuSelection\n\ +_080A54C8: .4byte sPopupMenuActionList\n\ +_080A54CC:\n\ + cmp r1, 0x10\n\ + bne _080A5500\n\ + ldr r4, _080A54F8 @ =sPopupMenuSelection\n\ + ldrb r0, [r4]\n\ + cmp r0, 0x1\n\ + bhi _080A5552\n\ + adds r1, r0, 0\n\ + ldr r0, _080A54FC @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x2]\n\ + cmp r0, 0x8\n\ + beq _080A5552\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x2\n\ +_080A54EE:\n\ + bl MoveMenuCursor3\n\ + strb r0, [r4]\n\ + b _080A5552\n\ + .align 2, 0\n\ +_080A54F8: .4byte sPopupMenuSelection\n\ +_080A54FC: .4byte sPopupMenuActionList\n\ +_080A5500:\n\ + ldrh r1, [r2, 0x2E]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080A5590\n\ + movs r0, 0x2\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080A5552\n\ + ldr r1, _080A5570 @ =gTasks\n\ + lsls r0, r4, 2\n\ + adds r0, r4\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + strh r5, [r0, 0x1C]\n\ + ldr r1, _080A5574 @ =gBagPocketScrollStates\n\ + ldr r0, _080A5578 @ =sCurrentBagPocket\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r2, [r0]\n\ + adds r0, r4, 0\n\ + adds r1, r2, 0\n\ + bl sub_80A48E8\n\ + ldr r0, _080A557C @ =gBGTilemapBuffers + 0x800\n\ + bl sub_80A4DA4\n\ + ldr r1, _080A5580 @ =sItemPopupMenuActions\n\ + ldr r0, _080A5584 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + ldrb r0, [r0, 0x3]\n\ + lsls r0, 3\n\ + adds r1, 0x4\n\ + adds r0, r1\n\ + ldr r5, [r0]\n\ + adds r0, r4, 0\n\ + bl _call_via_r5\n\ +_080A5552:\n\ + cmp r5, 0\n\ + bne _080A55FA\n\ + ldr r0, _080A5588 @ =sReturnLocation\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x5\n\ + bne _080A55E0\n\ + ldr r0, _080A558C @ =sPopupMenuSelection\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + bne _080A55D4\n\ + movs r0, 0xC\n\ + bl sub_8072DDC\n\ + b _080A55FA\n\ + .align 2, 0\n\ +_080A5570: .4byte gTasks\n\ +_080A5574: .4byte gBagPocketScrollStates\n\ +_080A5578: .4byte sCurrentBagPocket\n\ +_080A557C: .4byte gBGTilemapBuffers + 0x800\n\ +_080A5580: .4byte sItemPopupMenuActions\n\ +_080A5584: .4byte sPopupMenuActionList\n\ +_080A5588: .4byte sReturnLocation\n\ +_080A558C: .4byte sPopupMenuSelection\n\ +_080A5590:\n\ + ldr r1, _080A55C0 @ =gTasks\n\ + lsls r0, r4, 2\n\ + adds r0, r4\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + strh r5, [r0, 0x1C]\n\ + ldr r0, _080A55C4 @ =gBGTilemapBuffers + 0x800\n\ + bl sub_80A4DA4\n\ + ldr r1, _080A55C8 @ =sItemPopupMenuActions\n\ + ldr r0, _080A55CC @ =sPopupMenuSelection\n\ + ldrb r2, [r0]\n\ + ldr r0, _080A55D0 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r0, r2\n\ + ldrb r0, [r0]\n\ + lsls r0, 3\n\ + adds r1, 0x4\n\ + adds r0, r1\n\ + ldr r5, [r0]\n\ + adds r0, r4, 0\n\ + bl _call_via_r5\n\ + b _080A5552\n\ + .align 2, 0\n\ +_080A55C0: .4byte gTasks\n\ +_080A55C4: .4byte gBGTilemapBuffers + 0x800\n\ +_080A55C8: .4byte sItemPopupMenuActions\n\ +_080A55CC: .4byte sPopupMenuSelection\n\ +_080A55D0: .4byte sPopupMenuActionList\n\ +_080A55D4:\n\ + cmp r0, 0x1\n\ + bls _080A55E8\n\ + movs r0, 0x30\n\ + bl sub_8072DCC\n\ + b _080A55FA\n\ +_080A55E0:\n\ + ldr r0, _080A55F0 @ =sPopupMenuSelection\n\ + ldrb r0, [r0]\n\ + cmp r0, 0x1\n\ + bhi _080A55F4\n\ +_080A55E8:\n\ + movs r0, 0x2F\n\ + bl sub_8072DCC\n\ + b _080A55FA\n\ + .align 2, 0\n\ +_080A55F0: .4byte sPopupMenuSelection\n\ +_080A55F4:\n\ + movs r0, 0x30\n\ + bl sub_8072DCC\n\ +_080A55FA:\n\ + pop {r4,r5}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided\n"); +} +#endif + +__attribute__((naked)) +static void sub_80A5600(u8 taskId) +{ + asm(".syntax unified\n\ + push {r4,r5,lr}\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + movs r5, 0\n\ + ldr r2, _080A563C @ =gMain\n\ + ldrh r0, [r2, 0x30]\n\ + movs r1, 0xF0\n\ + ands r1, r0\n\ + cmp r1, 0x40\n\ + bne _080A5648\n\ + ldr r4, _080A5640 @ =sPopupMenuSelection\n\ + ldrb r0, [r4]\n\ + cmp r0, 0\n\ + bne _080A561E\n\ + b _080A5736\n\ +_080A561E:\n\ + adds r1, r0, 0\n\ + ldr r0, _080A5644 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r1, r0\n\ + subs r1, 0x1\n\ + ldrb r0, [r1]\n\ + cmp r0, 0x8\n\ + bne _080A5630\n\ + b _080A5736\n\ +_080A5630:\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x1\n\ + negs r0, r0\n\ + b _080A56D2\n\ + .align 2, 0\n\ +_080A563C: .4byte gMain\n\ +_080A5640: .4byte sPopupMenuSelection\n\ +_080A5644: .4byte sPopupMenuActionList\n\ +_080A5648:\n\ + cmp r1, 0x80\n\ + bne _080A5680\n\ + ldr r4, _080A5674 @ =sPopupMenuSelection\n\ + ldrb r1, [r4]\n\ + ldr r0, _080A5678 @ =gUnknown_02038564\n\ + ldrb r0, [r0]\n\ + subs r0, 0x1\n\ + cmp r1, r0\n\ + beq _080A5736\n\ + cmp r1, 0x2\n\ + beq _080A5736\n\ + ldr r0, _080A567C @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r0, r1, r0\n\ + ldrb r0, [r0, 0x1]\n\ + cmp r0, 0x8\n\ + beq _080A5736\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x1\n\ + b _080A56D2\n\ + .align 2, 0\n\ +_080A5674: .4byte sPopupMenuSelection\n\ +_080A5678: .4byte gUnknown_02038564\n\ +_080A567C: .4byte sPopupMenuActionList\n\ +_080A5680:\n\ + cmp r1, 0x20\n\ + bne _080A56B0\n\ + ldr r4, _080A56A8 @ =sPopupMenuSelection\n\ + ldrb r0, [r4]\n\ + cmp r0, 0x2\n\ + bls _080A5736\n\ + adds r1, r0, 0\n\ + ldr r0, _080A56AC @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r1, r0\n\ + subs r1, 0x3\n\ + ldrb r0, [r1]\n\ + cmp r0, 0x8\n\ + beq _080A5736\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x3\n\ + negs r0, r0\n\ + b _080A56D2\n\ + .align 2, 0\n\ +_080A56A8: .4byte sPopupMenuSelection\n\ +_080A56AC: .4byte sPopupMenuActionList\n\ +_080A56B0:\n\ + cmp r1, 0x10\n\ + bne _080A56E4\n\ + ldr r4, _080A56DC @ =sPopupMenuSelection\n\ + ldrb r0, [r4]\n\ + cmp r0, 0x2\n\ + bhi _080A5736\n\ + adds r1, r0, 0\n\ + ldr r0, _080A56E0 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x3]\n\ + cmp r0, 0x8\n\ + beq _080A5736\n\ + movs r0, 0x5\n\ + bl PlaySE\n\ + movs r0, 0x3\n\ +_080A56D2:\n\ + bl MoveMenuCursor3\n\ + strb r0, [r4]\n\ + b _080A5736\n\ + .align 2, 0\n\ +_080A56DC: .4byte sPopupMenuSelection\n\ +_080A56E0: .4byte sPopupMenuActionList\n\ +_080A56E4:\n\ + ldrh r1, [r2, 0x2E]\n\ + movs r0, 0x1\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + bne _080A5768\n\ + movs r0, 0x2\n\ + ands r0, r1\n\ + cmp r0, 0\n\ + beq _080A5736\n\ + ldr r1, _080A574C @ =gTasks\n\ + lsls r0, r4, 2\n\ + adds r0, r4\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + strh r5, [r0, 0x1C]\n\ + ldr r1, _080A5750 @ =gBagPocketScrollStates\n\ + ldr r0, _080A5754 @ =sCurrentBagPocket\n\ + ldrb r0, [r0]\n\ + lsls r0, 24\n\ + asrs r0, 24\n\ + lsls r0, 2\n\ + adds r0, r1\n\ + ldrb r2, [r0]\n\ + adds r0, r4, 0\n\ + adds r1, r2, 0\n\ + bl sub_80A48E8\n\ + ldr r0, _080A5758 @ =gBGTilemapBuffers + 0x800\n\ + bl sub_80A4DA4\n\ + ldr r1, _080A575C @ =sItemPopupMenuActions\n\ + ldr r0, _080A5760 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + ldrb r0, [r0, 0x5]\n\ + lsls r0, 3\n\ + adds r1, 0x4\n\ + adds r0, r1\n\ + ldr r5, [r0]\n\ + adds r0, r4, 0\n\ + bl _call_via_r5\n\ +_080A5736:\n\ + cmp r5, 0\n\ + bne _080A57BE\n\ + ldr r0, _080A5764 @ =sPopupMenuSelection\n\ + ldrb r0, [r0]\n\ + cmp r0, 0\n\ + bne _080A57AC\n\ + movs r0, 0xC\n\ + bl sub_8072DDC\n\ + b _080A57BE\n\ + .align 2, 0\n\ +_080A574C: .4byte gTasks\n\ +_080A5750: .4byte gBagPocketScrollStates\n\ +_080A5754: .4byte sCurrentBagPocket\n\ +_080A5758: .4byte gBGTilemapBuffers + 0x800\n\ +_080A575C: .4byte sItemPopupMenuActions\n\ +_080A5760: .4byte sPopupMenuActionList\n\ +_080A5764: .4byte sPopupMenuSelection\n\ +_080A5768:\n\ + ldr r1, _080A5798 @ =gTasks\n\ + lsls r0, r4, 2\n\ + adds r0, r4\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + strh r5, [r0, 0x1C]\n\ + ldr r0, _080A579C @ =gBGTilemapBuffers + 0x800\n\ + bl sub_80A4DA4\n\ + ldr r1, _080A57A0 @ =sItemPopupMenuActions\n\ + ldr r0, _080A57A4 @ =sPopupMenuSelection\n\ + ldrb r2, [r0]\n\ + ldr r0, _080A57A8 @ =sPopupMenuActionList\n\ + ldr r0, [r0]\n\ + adds r0, r2\n\ + ldrb r0, [r0]\n\ + lsls r0, 3\n\ + adds r1, 0x4\n\ + adds r0, r1\n\ + ldr r5, [r0]\n\ + adds r0, r4, 0\n\ + bl _call_via_r5\n\ + b _080A5736\n\ + .align 2, 0\n\ +_080A5798: .4byte gTasks\n\ +_080A579C: .4byte gBGTilemapBuffers + 0x800\n\ +_080A57A0: .4byte sItemPopupMenuActions\n\ +_080A57A4: .4byte sPopupMenuSelection\n\ +_080A57A8: .4byte sPopupMenuActionList\n\ +_080A57AC:\n\ + cmp r0, 0x2\n\ + bhi _080A57B8\n\ + movs r0, 0x2F\n\ + bl sub_8072DCC\n\ + b _080A57BE\n\ +_080A57B8:\n\ + movs r0, 0x30\n\ + bl sub_8072DCC\n\ +_080A57BE:\n\ + pop {r4,r5}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided\n"); +} + +static void sub_80A57C4(void) +{ + u8 r5; + + sPopupMenuActionList = gUnknown_083C16AE[sCurrentBagPocket]; + if (sCurrentBagPocket == BAG_POCKET_KEY_ITEMS) + { + gUnknown_02038564 = 1; + r5 = 9; + } + else if (sub_80F92F4(gScriptItemId) == 0) + { + sPopupMenuActionList = gUnknown_083C16AE[4]; + gUnknown_02038564 = 1; + r5 = 9; + } + else + { + gUnknown_02038564 = 2; + r5 = 7; + } + sub_80A4008(gBGTilemapBuffers[1], 7, r5 + 1, 6, gUnknown_02038564 * 2); + MenuDrawTextWindow(6, r5, 13, gUnknown_02038564 * 2 + 1 + r5); + sub_80A7834(0, r5); + InitMenu(0, 7, r5 + 1, gUnknown_02038564, 0, 6); +} + +static void sub_80A5888(u8 taskId) +{ + if (sub_80A78A0() != 0) + { + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + if (sPopupMenuSelection != 0) + { + PlaySE(SE_SELECT); + sPopupMenuSelection = MoveMenuCursor(-1); + } + } + else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + if (sPopupMenuSelection != gUnknown_02038564 - 1) + { + PlaySE(SE_SELECT); + sPopupMenuSelection = MoveMenuCursor(1); + } + } + else if (gMain.newKeys & A_BUTTON) + { + gTasks[taskId].data[10] = 0; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A4DA4(gBGTilemapBuffers[1]); + sItemPopupMenuActions[sPopupMenuActionList[sPopupMenuSelection]].func(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + gTasks[taskId].data[10] = 0; + sub_80A4DA4(gBGTilemapBuffers[1]); + sItemPopupMenuActions[2].func(taskId); + } + } +} + +static void OnBagClose_Field0(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)sub_805469C >> 16; + gTasks[taskId].data[9] = (u32)sub_805469C; + gLastFieldPokeMenuOpened = 0; + sub_80A5AE4(taskId); +} + +static void OnItemSelect_Field05(u8 taskId) +{ + sPopupMenuSelection = 0; + if (sReturnLocation == RETURN_TO_FIELD_5) + sPopupMenuSelection = 1; + gTasks[taskId].data[10] = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos + 1; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A73FC(); + if (sub_80F9344() == TRUE && sReturnLocation != RETURN_TO_FIELD_5) + { + sub_80A57C4(); + gTasks[taskId].func = sub_80A5888; + } + else + { + sub_80A4BF0(gBGTilemapBuffers[1]); + if (sCurrentBagPocket != BAG_POCKET_BERRIES || sReturnLocation == RETURN_TO_FIELD_5) + gTasks[taskId].func = sub_80A5414; + else + gTasks[taskId].func = sub_80A5600; + } +} + +static void sub_80A5AAC(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = HandleItemMenuPaletteFade; +} + +static void sub_80A5AE4(u8 taskId) +{ + PlaySE(SE_SELECT); + sub_80A5AAC(taskId); +} + +void HandleItemMenuPaletteFade(u8 taskId) +{ + s16 *taskData = gTasks[taskId].data; + + if (!gPaletteFade.active) + { + MainCallback cb = (MainCallback)((u16)taskData[8] << 16 | (u16)taskData[9]); + + SetMainCallback2(cb); + gpu_pal_allocator_reset__manage_upper_four(); + DestroyTask(taskId); + } +} + +void sub_80A5B40(void) +{ + while (1) + { + if (SetupBagMultistep() == TRUE) + { + ResetTasks(); + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); + break; + } + if (sub_80F9344() == TRUE) + break; + } +} + +static void HandlePopupMenuAction_UseOnField(u8 taskId) +{ + if (ItemId_GetFieldFunc(gScriptItemId) != NULL) + { + PlaySE(SE_SELECT); + if (CalculatePlayerPartyCount() == 0 && ItemId_GetType(gScriptItemId) == 1) + { + sub_80A5BF8(taskId); + } + else + { + gTasks[taskId].data[2] = 0; + if (sCurrentBagPocket != BAG_POCKET_BERRIES) + ItemId_GetFieldFunc(gScriptItemId)(taskId); + else + sub_80C9C7C(taskId); + } + } +} + +static void sub_80A5BF8(u8 taskId) +{ + sub_80A73FC(); + sub_80A7590(); + DisplayCannotUseItemMessage(taskId, gOtherText_NoPokemon, CleanUpItemMenuMessage, 1); +} + +static void sub_80A5C24(u8 taskId) +{ + sub_80A7528(0); + sub_80A41D4(taskId); + ItemListMenu_InitMenu(); + sub_80A37C0(taskId); +} + +void CleanUpItemMenuMessage(u8 taskId) +{ + sub_80A36B8(gBGTilemapBuffers[1], 0, 0, 31, 31); + MenuZeroFillWindowRect(7, 7, 13, 12); + MenuZeroFillWindowRect(0, 14, 29, 19); + gTasks[taskId].func = sub_80A5C24; +} + +void CleanUpOverworldMessage(u8 taskId) +{ + MenuZeroFillWindowRect(0, 13, 29, 19); + DestroyTask(taskId); + sub_8064E2C(); + ScriptContext2_Disable(); +} + +void ExecuteItemUseFromBlackPalette(void) +{ + pal_fill_black(); + CreateTask(Task_CallItemUseOnFieldCallback, 8); +} + +static void Task_CallItemUseOnFieldCallback(u8 taskId) +{ + if (sub_807D770() == TRUE) + gFieldItemUseCallback(taskId); +} + +void sub_80A5D04(void) +{ + while (1) + { + if (SetupBagMultistep() == TRUE) + { + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); + break; + } + if (sub_80F9344() == TRUE) + break; + } +} + +static void sub_80A5D38(u8 taskId) +{ + gTasks[taskId].data[1] = 0; + sub_80A4DA4(gBGTilemapBuffers[1]); + sub_80A7528(0); + sub_80A41D4(taskId); + ItemListMenu_InitMenu(); + sub_80A37C0(taskId); +} + +static void sub_80A5D78(void) +{ + sub_80A4008(gBGTilemapBuffers[1], 8, 8, 5, 4); + DisplayYesNoMenu(7, 7, 1); +} + +static void sub_80A5DA0(u16 itemId, u16 quantity) +{ + CopyItemName(itemId, gStringVar1); + if (quantity >= 100) + ConvertIntToDecimalStringN(gStringVar2, quantity, STR_CONV_MODE_LEFT_ALIGN, 3); + else + ConvertIntToDecimalStringN(gStringVar2, quantity, STR_CONV_MODE_LEFT_ALIGN, 2); + sub_80A4DA4(gBGTilemapBuffers[1]); + sub_80A7528(5); + sub_80A5D78(); +} + +static void sub_80A5DF8(void) +{ + sub_80A4DA4(gBGTilemapBuffers[1]); + MenuZeroFillWindowRect(7, 6, 11, 13); + sub_80A7528(4); +} + +static void sub_80A5E1C(u8 taskId) +{ + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + gTasks[taskId].data[10] = 0; + sub_80A41D4(taskId); + sub_80A5D38(taskId); + } +} + +static void sub_80A5E60(u8 taskId) +{ + sub_80A5DF8(); + sub_80A3D5C(taskId); + gTasks[taskId].func = sub_80A5E1C; +} + +static void sub_80A5E90(u8 taskId) +{ + sub_80A5D38(taskId); +} + +static void sub_80A5EA0(u8 taskId) +{ + if (sub_80A5350(taskId) == TRUE) + return; + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + sub_80A5DA0(gScriptItemId, gTasks[taskId].data[1]); + DoYesNoFuncWithChoice(taskId, &gUnknown_083C16F4); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + sub_80A5D38(taskId); + } +} + +static void HandlePopupMenuAction_Toss(u8 taskId) +{ + PlaySE(SE_SELECT); + gTasks[taskId].func = sub_80A5EA0; + sub_80A7528(3); + // if (sCurrentBagPocket == BAG_POCKET_BERRIES) Can't get it to match this way + if (sCurrentBagPocket + 1 == BAG_POCKET_BERRIES + 1) + sub_80A4DD8(taskId, 6, 9, 7, 3, 3); + else + sub_80A4DD8(taskId, 7, 9, 6, 3, 2); +} + +static void sub_80A5F80(u8 taskId) +{ + PlaySE(SE_SELECT); + sub_80A7528(0); + sub_80A41D4(taskId); + ItemListMenu_InitMenu(); + sub_80A37C0(taskId); +} + +static void HandlePopupMenuAction_Register(u8 taskId) +{ + PlaySE(SE_SELECT); + if (gSaveBlock1.registeredItem == gScriptItemId) + { + // Un-register the registered item + RemoveSelectIconFromRegisteredItem(); + gSaveBlock1.registeredItem = 0; + } + else + { + AddSelectIconToRegisteredItem(); + gSaveBlock1.registeredItem = gScriptItemId; + } + sub_80A7528(0); + sub_80A41D4(taskId); + ItemListMenu_InitMenu(); + sub_80A37C0(taskId); +} + +static void sub_80A6000(u8 taskId) +{ + sub_80A7528(0); + sub_80A41D4(taskId); + ItemListMenu_InitMenu(); + sub_80A37C0(taskId); +} + +static void sub_80A6024(u8 taskId) +{ + if (gMain.newKeys & A_BUTTON) + { + sub_80A36B8(gBGTilemapBuffers[1], 0, 0, 31, 31); + MenuZeroFillWindowRect(0, 14, 29, 19); + gTasks[taskId].func = sub_80A6000; + } +} + +static void DisplayCannotBeHeldMessage(u8 taskId) +{ + sub_80A73FC(); + CopyItemName(gScriptItemId, gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_CantBeHeld); + sub_80A7590(); + DisplayCannotUseItemMessage(taskId, gStringVar4, sub_80A6024, 1); +} + +static void HandlePopupMenuAction_Give(u8 taskId) +{ + PlaySE(SE_SELECT); + if (sub_80F931C(gScriptItemId) == 0) + { + sub_80A73FC(); + sub_80A7590(); + DisplayCannotUseItemMessage(taskId, gOtherText_CantWriteMail, sub_80A6024, 1); + } + else if (ItemId_GetImportance(gScriptItemId) == 0) + { + if (CalculatePlayerPartyCount() == 0) + { + sub_80A5BF8(taskId); + } + else + { + gTasks[taskId].data[8] = (u32)sub_808B020 >> 16; + gTasks[taskId].data[9] = (u32)sub_808B020; + gTasks[taskId].func = HandleItemMenuPaletteFade; + gUnknown_02038561 = 1; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + } + } + else + { + DisplayCannotBeHeldMessage(taskId); + } +} + +static void HandlePopupMenuAction_CheckTag(u8 taskId) +{ + sub_80A5AE4(taskId); + gTasks[taskId].data[8] = (u32)BerryTagScreen_814625C >> 16; + gTasks[taskId].data[9] = (u32)BerryTagScreen_814625C; +} + +static void sub_80A61A8(void) +{ + if (sub_80A34B4() == TRUE) + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); +} + +void sub_80A61D0(void) +{ + sReturnLocation = RETURN_TO_PKMN_LIST; + SetMainCallback2(sub_80A61A8); +} + +static void OnBagClose_PkmnList(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)sub_808A3F8 >> 16; + gTasks[taskId].data[9] = (u32)sub_808A3F8; + sub_80A5AE4(taskId); +} + +static void OnItemSelect_PkmnList(u8 taskId) +{ + u8 r6 = sCurrentBagPocket + 1; + + if (sub_80F931C(gScriptItemId) == 0) + { + sub_80A73FC(); + sub_80A7590(); + DisplayCannotUseItemMessage(taskId, gOtherText_CantWriteMail, sub_80A6024, 1); + } + else if (sub_80F92F4(gScriptItemId) == 0) + { + sub_80A73FC(); + CopyItemName(gScriptItemId, gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_CantBeHeldHere); + sub_80A7590(); + DisplayCannotUseItemMessage(taskId, gStringVar4, sub_80A6024, 1); + } + else if (r6 != 5 && ItemId_GetImportance(gScriptItemId) == 0) + { + gTasks[taskId].data[8] = (u32)sub_808A3F8 >> 16; + gTasks[taskId].data[9] = (u32)sub_808A3F8; + sub_80A5AAC(taskId); + } + else + { + DisplayCannotBeHeldMessage(taskId); + } +} + +static void sub_80A62D8(void) +{ + if (sub_80A34B4() == TRUE) + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); +} + +void sub_80A6300(void) +{ + sReturnLocation = RETURN_TO_SHOP; + SetMainCallback2(sub_80A62D8); +} + +static void OnBagClose_Shop(u8 taskId) +{ + gFieldCallback = sub_80B3050; + gTasks[taskId].data[8] = (u32)c2_exit_to_overworld_2_switch >> 16; + gTasks[taskId].data[9] = (u32)c2_exit_to_overworld_2_switch; + sub_80A5AE4(taskId); +} + +static void OnItemSelect_Shop(u8 taskId) +{ + sub_80A7590(); + gTasks[taskId].data[10] = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos + 1; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A73FC(); + CopyItemName(gScriptItemId, gStringVar2); + if (ItemId_GetPrice(gScriptItemId) == 0) + { + StringExpandPlaceholders(gStringVar4, gOtherText_CantBuyThat); + DisplayCannotUseItemMessage(taskId, gStringVar4, sub_80A6444, 1); + } + else + { + StringExpandPlaceholders(gStringVar4, gOtherText_HowManyToSell); + DisplayCannotUseItemMessage(taskId, gStringVar4, sub_80A648C, 1); + } +} + +static void sub_80A640C(u8 taskId) +{ + gTasks[taskId].data[10] = 0; + sub_80A7528(0); + sub_80A41D4(taskId); + ItemListMenu_InitMenu(); + sub_80A37C0(taskId); +} + +static void sub_80A6444(u8 taskId) +{ + sub_80A36B8(gBGTilemapBuffers[1], 0, 0, 31, 31); + MenuZeroFillWindowRect(0, 14, 29, 19); + gTasks[taskId].func = sub_80A640C; +} + +static void sub_80A648C(u8 taskId) +{ + gTasks[taskId].func = Task_BuyHowManyDialogueHandleInput; + sub_80A4008(gBGTilemapBuffers[1], 1, 11, 12, 2); + MenuDrawTextWindow(0, 10, 13, 13); + gTasks[taskId].data[1] = 1; + gTasks[taskId].data[2] = 1; + gTasks[taskId].data[3] = 11; + // if (sCurrentBagPocket == BAG_POCKET_BERRIES) Can't get it to match this way + if (sCurrentBagPocket + 1 == BAG_POCKET_BERRIES + 1) + sub_80A418C(1, 1, 1, 11, 3); + else + sub_80A418C(1, 1, 1, 11, 2); + BuyMenuDisplayMessage(gScriptItemId, 1); + sub_80A683C(); +} + +static void sub_80A6520(u8 taskId) +{ + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + BuyMenuPrintItemQuantityAndPrice(taskId); + } +} + +static void sub_80A6548(u8 taskId) +{ + sub_80A48F8(taskId); + gTasks[taskId].func = sub_80A6520; +} + +static void sub_80A6574(u8 taskId) +{ + PlaySE(SE_REGI); + sub_80A6870(gScriptItemId, gTasks[taskId].data[1]); + gTasks[taskId].func = sub_80A6548; +} + +static void sub_80A65AC(u8 taskId) +{ + MenuZeroFillWindowRect(7, 6, 13, 12); + sub_80A36B8(gBGTilemapBuffers[1], 7, 6, 6, 6); + CopyItemName(gScriptItemId, gStringVar2); + StringExpandPlaceholders(gStringVar4, gOtherText_SoldItem); + DisplayCannotUseItemMessage(taskId, gStringVar4, sub_80A6574, 1); + sub_80A3D5C(taskId); +} + +static void sub_80A6618(u8 taskId) +{ + MenuZeroFillWindowRect(7, 6, 13, 12); + sub_80A36B8(gBGTilemapBuffers[1], 7, 6, 6, 6); + BuyMenuPrintItemQuantityAndPrice(taskId); +} + +static void sub_80A6650(u8 taskId) +{ + sub_80A5D78(); + DoYesNoFuncWithChoice(taskId, &gUnknown_083C16FC); +} + +static void Task_BuyHowManyDialogueHandleInput(u8 taskId) +{ + if (sub_80A5350(taskId) == TRUE) + { + MenuZeroFillWindowRect(6, 11, 12, 11); + BuyMenuDisplayMessage(gScriptItemId, gTasks[taskId].data[1]); + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(0, 10, 13, 13); + sub_80A36B8(gBGTilemapBuffers[1], 0, 10, 13, 3); + ConvertIntToDecimalStringN(gStringVar1, ItemId_GetPrice(gScriptItemId) / 2 * gTasks[taskId].data[1], STR_CONV_MODE_LEFT_ALIGN, 6); + StringExpandPlaceholders(gStringVar4, gOtherText_CanPay); + DisplayCannotUseItemMessage(taskId, gStringVar4, sub_80A6650, 1); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + BuyMenuPrintItemQuantityAndPrice(taskId); + } +} + +static void sub_80A6760(u8 taskId) +{ + gTasks[taskId].data[10] = 0; + sub_80A7528(0); + sub_80A41D4(taskId); + ItemListMenu_InitMenu(); + sub_80A37C0(taskId); +} + +static void BuyMenuPrintItemQuantityAndPrice(u8 taskId) +{ + sub_80A36B8(gBGTilemapBuffers[1], 0, 0, 31, 31); + CloseMoneyWindow(0, 0); + MenuZeroFillWindowRect(0, 4, 13, 13); + MenuZeroFillWindowRect(0, 14, 29, 19); + gTasks[taskId].func = sub_80A6760; +} + +static void BuyMenuDisplayMessage(u16 itemId, u16 quantity) +{ + PrintMoneyAmount(ItemId_GetPrice(itemId) / 2 * quantity, 6, 6, 11); + ConvertIntToDecimalStringN(gStringVar1, ItemId_GetPrice(itemId) / 2 * quantity, STR_CONV_MODE_LEFT_ALIGN, 6); +} + +static void sub_80A683C(void) +{ + OpenMoneyWindow(gSaveBlock1.money, 0, 0); + sub_80A4008(gBGTilemapBuffers[1], 1, 1, 12, 2); +} + +static void sub_80A6870(u16 itemId, u8 quantity) +{ + AddMoney(&gSaveBlock1.money, ItemId_GetPrice(itemId) / 2 * quantity); + UpdateMoneyWindow(gSaveBlock1.money, 0, 0); +} + +static void sub_80A68A4(void) +{ + if (sub_80A34B4() == TRUE) + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); +} + +void sub_80A68CC(void) +{ + sCurrentBagPocket = BAG_POCKET_BERRIES; + sReturnLocation = RETURN_TO_FIELD_4; + SetMainCallback2(sub_80A68A4); +} + +static void OnBagClose_Field4(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)sub_80546B8 >> 16; + gTasks[taskId].data[9] = (u32)sub_80546B8; + sub_80A5AE4(taskId); +} + +static void OnItemSelect_Field4(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)sub_80546B8 >> 16; + gTasks[taskId].data[9] = (u32)sub_80546B8; + sub_80A5AAC(taskId); +} + +static void sub_80A6940(void) +{ + while (1) + { + if (SetupBagMultistep() == TRUE) + { + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); + sub_80A699C(); + break; + } + if (sub_80F9344() == TRUE) + break; + } +} + +void sub_80A6978(void) +{ + sCurrentBagPocket = BAG_POCKET_BERRIES; + sReturnLocation = RETURN_TO_FIELD_5; + SetMainCallback2(sub_80A6940); +} + +static void sub_80A699C(void) +{ + sPopupMenuActionList = gUnknown_083C16B8; + gUnknown_02038564 = 4; +} + +static void OnBagClose_Field5(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)sub_804E990 >> 16; + gTasks[taskId].data[9] = (u32)sub_804E990; + sub_80A5AE4(taskId); +} + +static void HandlePopupMenuAction_Confirm(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)sub_804E990 >> 16; + gTasks[taskId].data[9] = (u32)sub_804E990; + sub_80A5AAC(taskId); +} + +static void sub_80A6A08(void) +{ + if (sub_80A34B4() == TRUE) + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); +} + +void sub_80A6A30(void) +{ + sReturnLocation = RETURN_TO_PC; + SetMainCallback2(sub_80A6A08); +} + +static void OnBagClose_PC(u8 taskId) +{ + gFieldCallback = ItemStorage_ReturnToMenuAfterDeposit; + gTasks[taskId].data[8] = (u32)c2_exit_to_overworld_2_switch >> 16; + gTasks[taskId].data[9] = (u32)c2_exit_to_overworld_2_switch; + sub_80A5AE4(taskId); +} + +static void sub_80A6A84(u8 taskId) +{ + s16 *taskData = gTasks[taskId].data; + + sub_80A4DA4(gBGTilemapBuffers[1]); + CopyItemName(gScriptItemId, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, taskData[1], STR_CONV_MODE_LEFT_ALIGN, 3); + MenuZeroFillWindowRect(7, 6, 11, 13); + sub_80A7528(7); + sub_80A3D5C(taskId); + gTasks[taskId].func = sub_80A5E1C; +} + +static void sub_80A6B00(u8 taskId) +{ + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + gTasks[taskId].data[10] = 0; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + PlaySE(SE_SELECT); + sub_80A5D38(taskId); + } +} + +static void sub_80A6B64(u8 taskId) +{ + s16 *taskData = gTasks[taskId].data; + + if (ItemId_GetImportance(gScriptItemId) == 2) + { + gTasks[taskId].func = sub_80A6B00; + sub_80A7528(9); + } + else + { + if (AddPCItem(gScriptItemId, taskData[1]) == TRUE) + { + sub_80A6A84(taskId); + } + else + { + gTasks[taskId].func = sub_80A6B00; + sub_80A7528(8); + } + } +} + +static void sub_80A6BE0(u8 taskId) +{ + if (sub_80A5350(taskId) == TRUE) + return; + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + sub_80A4DA4(gBGTilemapBuffers[1]); + sub_80A6B64(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + gTasks[taskId].data[10] = 0; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + PlaySE(SE_SELECT); + sub_80A5D38(taskId); + } +} + +static void OnItemSelect_PC(u8 taskId) +{ + gTasks[taskId].data[10] = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos + 1; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A73FC(); + PlaySE(SE_SELECT); + sub_80A7590(); + if (sCurrentBagPocket != BAG_POCKET_KEY_ITEMS) + { + gTasks[taskId].func = sub_80A6BE0; + sub_80A7528(6); + // if (sCurrentBagPocket == BAG_POCKET_BERRIES) Can't get it to match this way + if (sCurrentBagPocket + 1 == BAG_POCKET_BERRIES + 1) + sub_80A4DD8(taskId, 6, 9, 7, 3, 3); + else + sub_80A4DD8(taskId, 7, 9, 6, 3, 2); + } + else + { + gTasks[taskId].data[1] = 1; + sub_80A6B64(taskId); + } +} + +bool32 sub_80A6D1C(void) +{ + HideMapNamePopup(); + if (gSaveBlock1.registeredItem != 0) + { + if (CheckBagHasItem(gSaveBlock1.registeredItem, 1) == TRUE) + { + u8 taskId; + + ScriptContext2_Enable(); + FreezeMapObjects(); + sub_80594C0(); + sub_80597F4(); + gScriptItemId = gSaveBlock1.registeredItem; + taskId = CreateTask(ItemId_GetFieldFunc(gSaveBlock1.registeredItem), 8); + gTasks[taskId].data[2] = 1; + return TRUE; + } + gSaveBlock1.registeredItem = 0; + } + ScriptContext1_SetupScript(Event_NoRegisteredItem); + return TRUE; +} + +static void sub_80A6D98(void) +{ + while (1) + { + if (SetupBagMultistep() == TRUE) + { + gUnknown_02038563 = CreateTask(sub_80A50C8, 0); + break; + } + if (sub_80F9344() == TRUE) + break; + } +} + +void sub_80A6DCC(void) +{ + sPopupMenuSelection = 0; + sReturnLocation = RETURN_TO_BATTLE; + SetMainCallback2(sub_80A6D98); +} + +static void sub_80A6DF0(u16 *a) +{ + u8 r6 = (gUnknown_02038564 - 1) * 2; + + MenuDrawTextWindow(7, 9 - r6, 13, 12); + sub_80A4008(a, 8, 10 - r6, 5, r6 + 2); + if (gUnknown_02038564 == 1) + { + MenuPrint(sItemPopupMenuActions[sPopupMenuActionList[0]].text, 8, 10); + } + else + { + MenuPrint(sItemPopupMenuActions[sPopupMenuActionList[0]].text, 8, 8); + MenuPrint(sItemPopupMenuActions[sPopupMenuActionList[1]].text, 8, 10); + } + InitMenu(0, 8, 10 - r6, gUnknown_02038564, 0, 5); + sub_80A7528(2); +} + +static void sub_80A6EB8(u8 taskId) +{ + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP) + { + if (sPopupMenuSelection == 1) + { + PlaySE(SE_SELECT); + sPopupMenuSelection = MoveMenuCursor(-1); + } + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN) + { + if (sPopupMenuSelection + 1 < gUnknown_02038564) + { + PlaySE(SE_SELECT); + sPopupMenuSelection = MoveMenuCursor(1); + } + } + else if (gMain.newKeys & A_BUTTON) + { + gTasks[taskId].data[10] = 0; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A4DA4(gBGTilemapBuffers[1]); + sItemPopupMenuActions[sPopupMenuActionList[sPopupMenuSelection]].func(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + gTasks[taskId].data[10] = 0; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A4DA4(gBGTilemapBuffers[1]); + sItemPopupMenuActions[5].func(taskId); + } +} + +static const u8 gUnknown_083C1708[] = {4, 5}; +static const u8 gUnknown_083C170A[] = {5, 0}; + +static void sub_80A6FDC(void) +{ + if (ItemId_GetBattleUsage(gScriptItemId) != 0) + { + sPopupMenuActionList = gUnknown_083C1708; + gUnknown_02038564 = 2; + } + else + { + sPopupMenuActionList = gUnknown_083C170A; + gUnknown_02038564 = 1; + } +} + +static void OnItemSelect_Battle(u8 taskId) +{ + sPopupMenuSelection = 0; + sub_80A6FDC(); + gTasks[taskId].data[10] = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos + 1; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A73FC(); + sub_80A6DF0(gBGTilemapBuffers[1]); + gTasks[taskId].func = sub_80A6EB8; +} + +void sub_80A7094(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)sub_802E424 >> 16; + gTasks[taskId].data[9] = (u32)sub_802E424; + gTasks[taskId].func = HandleItemMenuPaletteFade; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); +} + +static void OnBagClose_Battle(u8 taskId) +{ + PlaySE(SE_SELECT); + sub_80A7094(taskId); +} + +static void HandlePopupMenuAction_UseInBattle(u8 taskId) +{ + if (ItemId_GetBattleFunc(gScriptItemId) != NULL) + { + PlaySE(SE_SELECT); + ItemId_GetBattleFunc(gScriptItemId)(taskId); + } +} + +static void sub_80A7124(u8 taskId) +{ + PlaySE(SE_SELECT); + sub_80A7528(0); + sub_80A41D4(taskId); + ItemListMenu_InitMenu(); + sub_80A37C0(taskId); +} + +static void sub_80A7150(void) +{ + while (1) + { + if (SetupBagMultistep() == TRUE) + { + gUnknown_02038563 = CreateTask(sub_80A7230, 0); + gTasks[gUnknown_02038563].data[15] = 0; + break; + } + if (sub_80F9344() == TRUE) + break; + } +} + +void PrepareBagForWallyTutorial(void) +{ + u8 i; + + sPopupMenuSelection = 0; + sCurrentBagPocket = BAG_POCKET_ITEMS; + for (i = 0; i < 5; i++) + { + gBagPocketScrollStates[i].cursorPos = 0; + gBagPocketScrollStates[i].scrollTop = 0; + } + + // Save player's items + memcpy(ewramSavedItemsPocket, gSaveBlock1.bagPocket_Items, sizeof(gSaveBlock1.bagPocket_Items)); + memcpy(ewramSavedPokeballsPocket, gSaveBlock1.bagPocket_PokeBalls, sizeof(gSaveBlock1.bagPocket_PokeBalls)); + + // Add Wally's items to the bag + ClearItemSlots(gSaveBlock1.bagPocket_Items, ARRAY_COUNT(gSaveBlock1.bagPocket_Items)); + ClearItemSlots(gSaveBlock1.bagPocket_PokeBalls, ARRAY_COUNT(gSaveBlock1.bagPocket_PokeBalls)); + AddBagItem(ITEM_POTION, 1); + AddBagItem(ITEM_POKE_BALL, 1); + + sReturnLocation = RETURN_TO_WALLY_BATTLE; + SetMainCallback2(sub_80A7150); +} + +static void sub_80A7230(u8 taskId) +{ + s16 *taskData = gTasks[taskId].data; + + switch (taskData[15]) + { + case 102: + PlaySE(SE_SELECT); + sub_80A4E8C(1, 2); + break; + case 204: + PlaySE(SE_SELECT); + sub_80F98A4(2); + sub_80F98A4(3); + gScriptItemId = ITEM_POKE_BALL; + sPopupMenuActionList = gUnknown_083C1708; + gUnknown_02038564 = 2; + gTasks[taskId].data[10] = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos + 1; + sub_80A48E8(taskId, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, gBagPocketScrollStates[sCurrentBagPocket].cursorPos); + sub_80A73FC(); + sub_80A6DF0(gBGTilemapBuffers[1]); + break; + case 306: + PlaySE(SE_SELECT); + sub_80A4DA4(gBGTilemapBuffers[1]); + + // Restore player's items + memcpy(gSaveBlock1.bagPocket_Items, ewramSavedItemsPocket, sizeof(gSaveBlock1.bagPocket_Items)); + memcpy(gSaveBlock1.bagPocket_PokeBalls, ewramSavedPokeballsPocket, sizeof(gSaveBlock1.bagPocket_PokeBalls)); + + taskData[8] = (u32)sub_802E424 >> 16; + taskData[9] = (u32)sub_802E424; + gTasks[taskId].func = HandleItemMenuPaletteFade; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + return; + } + taskData[15]++; +} + +static void ItemListMenu_InitMenu(void) +{ + InitMenu(0, 14, 2, gBagPocketScrollStates[sCurrentBagPocket].cursorMax + 1, gBagPocketScrollStates[sCurrentBagPocket].cursorPos, 0); + CreateBlendedOutlineCursor(16, 0xFFFF, 12, 0x2D9F, 15); + sub_80A73C0(); +} + +static void sub_80A73C0(void) +{ + sub_814AD7C(0x70, gBagPocketScrollStates[sCurrentBagPocket].cursorPos * 16 + 16); +} + +static void sub_80A73F0(void) +{ + sub_814ADC8(); +} + +static void sub_80A73FC(void) +{ + HandleDestroyMenuCursors(); + sub_814AD44(); +} + +static void sub_80A740C(void) +{ + sub_80A75E4(); + sub_80A7768(); + sub_80A7420(); +} + +static void sub_80A7420(void) +{ + struct UnknownStruct2 *unkStruct = &gUnknown_0203853C; + int index; + + switch (unkStruct->unk0) + { + case 3: + unkStruct->unk0 = 2; + break; + case 2: + switch (unkStruct->unk2) + { + case 0: + index = gBagPocketScrollStates[sCurrentBagPocket].scrollTop + gBagPocketScrollStates[sCurrentBagPocket].cursorPos; + ItemListMenu_ChangeDescription(gCurrentBagPocketItemSlots[index].itemId, unkStruct->textLine); + break; + case 1: + sub_80A4A98(gOtherText_SwitchWhichItem, unkStruct->textLine); + break; + case 2: + sub_80A4A98(gOtherText_WhatWillYouDo2, unkStruct->textLine); + break; + case 3: + sub_80A4A98(gOtherText_HowManyToToss, unkStruct->textLine); + break; + case 4: + sub_80A4A98(gOtherText_ThrewAwayItem, unkStruct->textLine); + break; + case 5: + sub_80A4A98(gOtherText_OkayToThrowAwayPrompt, unkStruct->textLine); + break; + case 6: + sub_80A4A98(gOtherText_HowManyToDeposit, unkStruct->textLine); + break; + case 7: + sub_80A4A98(gOtherText_DepositedItems, unkStruct->textLine); + break; + case 8: + sub_80A4A98(gOtherText_NoRoomForItems, unkStruct->textLine); + break; + case 9: + sub_80A4A98(gOtherText_CantStoreSomeoneItem, unkStruct->textLine); + break; + } + unkStruct->textLine++; + if (unkStruct->textLine == 3) + { + unkStruct->unk0 = 0; + sub_80A7918(); + } + break; + } +} + +static void sub_80A751C(void) +{ + gUnknown_0203853C.unk0 = 0; +} + +static void sub_80A7528(u8 a) +{ + gUnknown_0203853C.textLine = 0; + gUnknown_0203853C.unk2 = a; + switch (sub_80A78F4()) + { + case 0: + gUnknown_0203853C.unk0 = 2; + while (gUnknown_0203853C.unk0 != 0) + sub_80A7420(); + break; + case 1: + gUnknown_0203853C.unk0 = 3; + break; + case 2: + gUnknown_0203853C.unk0 = 1; + break; + } +} + +static void sub_80A756C(void) +{ + if (gUnknown_0203853C.unk0 == 2 || gUnknown_0203853C.unk0 == 3) + sub_80A7918(); + gUnknown_0203853C.unk0 = 0; +} + +static void sub_80A7590(void) +{ + MenuZeroFillWindowRect(0, 13, 13, 20); + sub_80A756C(); +} + +static void sub_80A75A8(void) +{ + if (gUnknown_0203853C.unk0 == 2 || gUnknown_0203853C.unk0 == 3) + gUnknown_0203853C.unk0 = 1; +} + +static void sub_80A75C4(void) +{ + switch (gUnknown_0203853C.unk0) + { + case 1: + gUnknown_0203853C.unk0 = 3; + break; + case 0: + sub_80A7918(); + break; + } +} + +static void sub_80A75E4(void) +{ + if (gUnknown_02038540.unk0 == 1 && sub_80A7988() == 0) + { + int r1; + + sub_80A47E8(gUnknown_02038563, gUnknown_02038540.unk1, gUnknown_02038540.unk1, 1); + gUnknown_02038540.unk1++; + if (gUnknown_02038540.unk2 != 0) + r1 = 5; + else + r1 = 7; + if (r1 < gUnknown_02038540.unk1) + { + gUnknown_02038540.unk0 = 0; + sub_80A78E8(); + } + } +} + +static void sub_80A7630(void) +{ + gUnknown_02038540.unk0 = 0; +} + +static void sub_80A763C(void) +{ + struct UnknownStruct3 *r4 = &gUnknown_02038540; + + switch (sub_80A78C4()) + { + case FALSE: + sub_80A48E8(gUnknown_02038563, 0, 7); + break; + case TRUE: + r4->unk0 = 1; + r4->unk1 = 0; + r4->unk2 = 0; + break; + } +} + +static void sub_80A7678(void) +{ + if (gUnknown_02038540.unk0 == 1) + sub_80A78E8(); + gUnknown_02038540.unk0 = 0; +} + +static void sub_80A7694(void) +{ + gUnknown_02038540.unk2 = 1; +} + +static void sub_80A76A0(void) +{ + MenuZeroFillWindowRect(14, 2, 29, 18); + sub_80A7678(); +} + +static bool32 sub_80A76B8(void) +{ + struct UnknownStruct3 *s = &gUnknown_02038540; + + return (s->unk0 == 0); +} + +static bool32 sub_80A76D0(void) +{ + struct UnknownStruct3 *s = &gUnknown_02038540; + + return (s->unk1 > 5); +} + +static void sub_80A76E8(void) +{ + if (gUnknown_02038544.unk0 == 1) + { + DisplayItemMessageOnField( + gUnknown_02038544.unk1, + gUnknown_02038544.unk4, + gUnknown_02038544.unk8, + gUnknown_02038544.unk2); + gUnknown_02038544.unk0 = 0; + } +} + +static void sub_80A770C(void) +{ + gUnknown_02038544.unk0 = 0; +} + +static void DisplayCannotUseItemMessage(int a, const u8 *b, TaskFunc func, int d) +{ + struct UnknownStruct4 *r4 = &gUnknown_02038544; + + switch (sub_80A7924()) + { + case 0: + DisplayItemMessageOnField(a, b, func, d); + break; + case 2: + r4->unk0 = 1; + r4->unk1 = a; + r4->unk4 = b; + r4->unk8 = func; + r4->unk2 = d; + break; + } +} + +static void sub_80A7768(void) +{ + struct UnknownStruct5 *r4 = &gUnknown_02038550; + + if (r4->unk0 == 2) + { + if (r4->unk1 != 0) + { + if (r4->unk2 != 1) + { + const u8 *text = sItemPopupMenuActions[sPopupMenuActionList[r4->unk1 - 1]].text; + int var = r4->unk1 - 1; + + MenuPrint(text, 7, var * 2 + 1 + r4->unk3); + } + else + { + const u8 *text; + int var; + + if (r4->unk1 == 1) + text = sub_80A4B90(gScriptItemId); + else + text = sItemPopupMenuActions[sPopupMenuActionList[r4->unk1 - 1]].text; + var = r4->unk1 - 1; + MenuPrint(text, (var >> 1) * 6 + 1, (var & 1) * 2 + 8); + } + if (r4->unk1 == gUnknown_02038564) + { + r4->unk0 = 0; + sub_80A7970(); + } + } + r4->unk1++; + } +} + +static void sub_80A7828(void) +{ + gUnknown_02038550.unk0 = 0; +} + +static void sub_80A7834(int a, int b) +{ + struct UnknownStruct5 *r4 = &gUnknown_02038550; + + switch (sub_80A7958()) + { + case 1: + r4->unk0 = 2; + r4->unk1 = 0; + r4->unk2 = a; + r4->unk3 = b; + break; + case 2: + r4->unk0 = 1; + r4->unk1 = 0; + r4->unk2 = a; + r4->unk3 = b; + break; + } +} + +static void sub_80A7868(void) +{ + if (gUnknown_02038550.unk0 == 2) + gUnknown_02038550.unk0 = 1; +} + +static void sub_80A7880(void) +{ + switch (gUnknown_02038550.unk0) + { + case 1: + gUnknown_02038550.unk0 = 2; + break; + case 0: + sub_80A7970(); + break; + } +} + +static bool32 sub_80A78A0(void) +{ + struct UnknownStruct5 *r0 = &gUnknown_02038550; + + return (r0->unk0 == 0); +} + +static void sub_80A78B8(void) +{ + gUnknown_02038554.unk0 = 0; +} + +static bool32 sub_80A78C4(void) +{ + bool32 retVal; + + if (gLinkOpen == TRUE) + { + sub_80A7868(); + sub_80A75A8(); + retVal = TRUE; + } + else + { + retVal = FALSE; + } + return retVal; +} + +static void sub_80A78E8(void) +{ + sub_80A7880(); +} + +static int sub_80A78F4(void) +{ + int retVal; + + if (gLinkOpen == TRUE) + { + if (sub_80A76B8() != 0) + retVal = 1; + else + retVal = 2; + } + else + { + retVal = 0; + } + return retVal; +} + +static void sub_80A7918(void) +{ + sub_80A76E8(); +} + +static int sub_80A7924(void) +{ + if (gLinkOpen == TRUE && sub_80A76B8() == 0) + { + if (sub_80A76D0() != 0) + { + sub_80A7678(); + return 0; + } + } + else + { + return 0; + } + sub_80A7694(); + return 2; +} + +static int sub_80A7958(void) +{ + if (sub_80A76B8() == 0) + return 2; + sub_80A75A8(); + return 1; +} + +static void sub_80A7970(void) +{ + sub_80A75C4(); +} + +static void sub_80A797C(void) +{ + gUnknown_02038554.unk0 = 1; +} + +static int sub_80A7988(void) +{ + int val = gUnknown_02038554.unk0; + + gUnknown_02038554.unk0 = 0; + return val; +} + +static const u16 gPalette_83C170C[] = INCBIN_U16("graphics/unknown/83C170C.gbapal"); +static const u8 gSpriteImage_83C172C[] = INCBIN_U8("graphics/unknown_sprites/83C172C.4bpp"); + +const u8 gSpriteImage_UnusedCherry[] = INCBIN_U8("graphics/unused/cherry.4bpp"); +const u16 gSpritePalette_UnusedCherry[] = INCBIN_U16("graphics/unused/cherry.gbapal"); + +//------------------------------------------------------------------------------ +// Bag Sprite +//------------------------------------------------------------------------------ + +static const struct OamData sBagSpriteOamData = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 2, + .paletteNum = 7, + .affineParam = 0, +}; + +static const union AnimCmd sBagSpriteAnimSeq0[] = +{ + ANIMCMD_FRAME(0, 4), + ANIMCMD_END, +}; + +static const union AnimCmd sBagSpriteAnimSeq1[] = +{ + ANIMCMD_FRAME(64, 4), + ANIMCMD_END, +}; + +static const union AnimCmd sBagSpriteAnimSeq5[] = +{ + ANIMCMD_FRAME(128, 4), + ANIMCMD_END, +}; + +static const union AnimCmd sBagSpriteAnimSeq2[] = +{ + ANIMCMD_FRAME(192, 4), + ANIMCMD_END, +}; + +static const union AnimCmd sBagSpriteAnimSeq3[] = +{ + ANIMCMD_FRAME(256, 4), + ANIMCMD_END, +}; + +static const union AnimCmd sBagSpriteAnimSeq4[] = +{ + ANIMCMD_FRAME(320, 4), + ANIMCMD_END, +}; + +static const union AnimCmd *const sBagSpriteAnimTable[] = +{ + sBagSpriteAnimSeq0, + sBagSpriteAnimSeq1, + sBagSpriteAnimSeq2, + sBagSpriteAnimSeq3, + sBagSpriteAnimSeq4, + sBagSpriteAnimSeq5, +}; + +static const union AffineAnimCmd sBagSpriteAffineAnimSeq[] = +{ + AFFINEANIMCMD_FRAME(0, 0, -2, 2), + AFFINEANIMCMD_FRAME(0, 0, 2, 4), + AFFINEANIMCMD_FRAME(0, 0, -2, 4), + AFFINEANIMCMD_FRAME(0, 0, 2, 2), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sBagSpriteAffineAnimTable[] = +{ + sBagSpriteAffineAnimSeq, +}; + +static const struct CompressedSpriteSheet sMaleBagSpriteSheet = {gBagMaleTiles, 0x3000, 30000}; +static const struct CompressedSpriteSheet sFemaleBagSpriteSheet = {gBagFemaleTiles, 0x3000, 30000}; +static const struct CompressedSpritePalette sBagSpritePalette = {gBagPalette, 30000}; + +static void sub_80A7998(struct Sprite *sprite) +{ + sprite->animNum = 0; + sprite->data0 = 0; + sprite->data1 = 0; + sprite->data2 = 0; + sprite->data3 = 0; + sprite->data4 = 0; + sprite->callback = sub_80A79B4; +} + +static void sub_80A79B4(struct Sprite *sprite) +{ + if (gUnknown_0203855B != -1) + sub_80A79EC(sprite); + if (gUnknown_0203855C != 0) + sub_80A7A94(sprite); +} + +static void sub_80A79EC(struct Sprite *sprite) +{ + switch (sprite->data3) + { + case 0: + if (gUnknown_0203855B != 6) + { + sprite->animBeginning = TRUE; + sprite->animNum = gUnknown_0203855B; + gUnknown_0203855B = -1; + } + else + { + sprite->animBeginning = TRUE; + sprite->animNum = 0; + sprite->pos1.y -= 4; + sprite->data0 = 4; + sprite->data3 = 1; + sub_80A7AE4(sprite); + } + break; + case 1: + if (sprite->data0 != 0) + { + if (sprite->data1 != 0) + { + sprite->pos1.y++; + sprite->data0--; + } + sprite->data1 = (sprite->data1 + 1) & 1; + } + else + { + gUnknown_0203855B = -1; + sprite->data1 = 0; + sprite->data3 = 0; + } + break; + } +} + +static void sub_80A7A94(struct Sprite *sprite) +{ + switch (sprite->data4) + { + case 0: + sprite->oam.affineMode = 1; + sprite->affineAnims = sBagSpriteAffineAnimTable; + InitSpriteAffineAnim(sprite); + sprite->data4 = 1; + break; + case 1: + sprite->data2++; + if (sprite->data2 == 12) + sub_80A7AE4(sprite); + break; + } +} + +static void sub_80A7AE4(struct Sprite *sprite) +{ + gUnknown_0203855C = 0; + sprite->oam.affineMode = 0; + sprite->data2 = 0; + sprite->data4 = 0; + FreeOamMatrix(sprite->oam.matrixNum); +} + +static const struct SpriteTemplate sBagSpriteTemplate = +{ + .tileTag = 30000, + .paletteTag = 30000, + .oam = &sBagSpriteOamData, + .anims = sBagSpriteAnimTable, + .images = NULL, + .affineAnims = sBagSpriteAffineAnimTable, + .callback = sub_80A7998, +}; + +static void CreateBagSprite(void) +{ + CreateSprite(&sBagSpriteTemplate, 58, 40, 0); +} + +//------------------------------------------------------------------------------ +// Pokeball Sprite +//------------------------------------------------------------------------------ + +static const struct OamData gOamData_83C1CF8 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 4, + .size = 1, + .tileNum = 0, + .priority = 2, + .paletteNum = 8, + .affineParam = 0, +}; + +static const union AffineAnimCmd gSpriteAffineAnim_83C1D00[] = +{ + AFFINEANIMCMD_FRAME(0, 0, 8, 32), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd gSpriteAffineAnim_83C1D10[] = +{ + AFFINEANIMCMD_FRAME(0, 0, -8, 32), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const gSpriteAffineAnimTable_83C1D20[] = +{ + gSpriteAffineAnim_83C1D00, + gSpriteAffineAnim_83C1D10, +}; + +static const struct SpriteFrameImage gSpriteImageTable_83C1D28[] = +{ + {gSpriteImage_83C172C, sizeof(gSpriteImage_83C172C)}, +}; + +static const struct SpritePalette sPokeballSpritePalette = {gPalette_83C170C, 8}; + +static void sub_80A7B28(struct Sprite *sprite) +{ + sprite->data3 = 0; + sprite->data0 = 0; + sub_80A7B6C(sprite); + sprite->callback = sub_80A7B6C; +} + +static void sub_80A7B48(struct Sprite *sprite) +{ + sprite->centerToCornerVecX = sprite->data5 - ((sprite->data0 + 1) & 1); + sprite->centerToCornerVecY = sprite->data6 - ((sprite->data0 + 1) & 1); +} + +static void sub_80A7B6C(struct Sprite *sprite) +{ + if (sprite->data7 != 0) + { + switch (sprite->data3) + { + case 0: + sprite->oam.affineMode = 1; + if (sprite->data7 == 1) + sprite->affineAnims = gSpriteAffineAnimTable_83C1D20; + else + sprite->affineAnims = gSpriteAffineAnimTable_83C1D20 + 1; + InitSpriteAffineAnim(sprite); + sprite->data3 = 1; + sprite->data5 = sprite->centerToCornerVecX; + sprite->data6 = sprite->centerToCornerVecY; + sub_80A7B48(sprite); + break; + case 1: + sprite->data0++; + sub_80A7B48(sprite); + if (sprite->data0 == 32) + { + sprite->data0 = 0; + sprite->data3 = 0; + sprite->centerToCornerVecX = sprite->data5; + sprite->centerToCornerVecY = sprite->data6; + FreeOamMatrix(sprite->oam.matrixNum); + sprite->oam.affineMode = 0; + sprite->callback = SpriteCallbackDummy; + } + break; + } + } +} + +static const struct SpriteTemplate sPokeballSpriteTemplate = +{ + .tileTag = 0xFFFF, + .paletteTag = 8, + .oam = &gOamData_83C1CF8, + .anims = sBagSpriteAnimTable, + .images = gSpriteImageTable_83C1D28, + .affineAnims = gSpriteAffineAnimTable_83C1D20, + .callback = sub_80A7B28, +}; + +static void CreateBagPokeballSprite(u8 a) +{ + LoadSpritePalette(&sPokeballSpritePalette); + sPokeballSpriteId = CreateSprite(&sPokeballSpriteTemplate, 16, 88, 0); + gSprites[sPokeballSpriteId].data7 = a; +} + +static void sub_80A7C64(void) +{ + FreeSpritePaletteByTag(8); + FreeOamMatrix(gSprites[sPokeballSpriteId].oam.matrixNum); + DestroySprite(&gSprites[sPokeballSpriteId]); +} + +static const struct OamData sBerrySpriteOamData = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 1, + .paletteNum = 7, + .affineParam = 0, +}; + +static const struct OamData gOamData_83C1D58 = +{ + .y = 0, + .affineMode = 3, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 0, + .paletteNum = 7, + .affineParam = 0, +}; + +static const union AnimCmd sBerrySpriteAnimSeq[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd *const sBerrySpriteAnimTable[] = +{ + sBerrySpriteAnimSeq, +}; + +static const struct SpriteFrameImage sBerrySpriteImageTable[] = +{ + {ewramBerryPic, 0x800}, +}; + +static void SpriteCB_BerrySprite(struct Sprite *); +static const struct SpriteTemplate sBerrySpriteTemplate = +{ + .tileTag = 0xFFFF, + .paletteTag = 30020, + .oam = &sBerrySpriteOamData, + .anims = sBerrySpriteAnimTable, + .images = sBerrySpriteImageTable, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_BerrySprite, +}; + +static const union AffineAnimCmd gSpriteAffineAnim_83C1D8C[] = +{ + AFFINEANIMCMD_FRAME(-1, -1, -3, 96), + AFFINEANIMCMD_FRAME(0, 0, 0, 16), + AFFINEANIMCMD_FRAME(-2, -2, -1, 64), + AFFINEANIMCMD_FRAME(-8, 0, 0, 16), + AFFINEANIMCMD_FRAME(0, -8, 0, 16), + AFFINEANIMCMD_FRAME(256, 256, 0, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd gSpriteAffineAnim_83C1DC4[] = +{ + AFFINEANIMCMD_FRAME(-1, -1, 3, 96), + AFFINEANIMCMD_FRAME(0, 0, 0, 16), + AFFINEANIMCMD_FRAME(-2, -2, 1, 64), + AFFINEANIMCMD_FRAME(-8, 0, 0, 16), + AFFINEANIMCMD_FRAME(0, -8, 0, 16), + AFFINEANIMCMD_FRAME(256, 256, 0, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd *const gSpriteAffineAnimTable_83C1DFC[] = +{ + gSpriteAffineAnim_83C1D8C, + gSpriteAffineAnim_83C1DC4, +}; + +static const struct SpriteTemplate gSpriteTemplate_83C1E04 = +{ + .tileTag = 0xFFFF, + .paletteTag = 30020, + .oam = &gOamData_83C1D58, + .anims = sBerrySpriteAnimTable, + .images = sBerrySpriteImageTable, + .affineAnims = gSpriteAffineAnimTable_83C1DFC, + .callback = SpriteCallbackDummy, +}; + +static const struct {const u8 *lzPic; const u8 *lzPalette;} sBerryGraphicsTable[] = +{ + {gBerryPic_Cheri, gBerryPalette_Cheri}, + {gBerryPic_Chesto, gBerryPalette_Chesto}, + {gBerryPic_Pecha, gBerryPalette_Pecha}, + {gBerryPic_Rawst, gBerryPalette_Rawst}, + {gBerryPic_Aspear, gBerryPalette_Aspear}, + {gBerryPic_Leppa, gBerryPalette_Leppa}, + {gBerryPic_Oran, gBerryPalette_Oran}, + {gBerryPic_Persim, gBerryPalette_Persim}, + {gBerryPic_Lum, gBerryPalette_Lum}, + {gBerryPic_Sitrus, gBerryPalette_Sitrus}, + {gBerryPic_Figy, gBerryPalette_Figy}, + {gBerryPic_Wiki, gBerryPalette_Wiki}, + {gBerryPic_Mago, gBerryPalette_Mago}, + {gBerryPic_Aguav, gBerryPalette_Aguav}, + {gBerryPic_Iapapa, gBerryPalette_Iapapa}, + {gBerryPic_Razz, gBerryPalette_Razz}, + {gBerryPic_Bluk, gBerryPalette_Bluk}, + {gBerryPic_Nanab, gBerryPalette_Nanab}, + {gBerryPic_Wepear, gBerryPalette_Wepear}, + {gBerryPic_Pinap, gBerryPalette_Pinap}, + {gBerryPic_Pomeg, gBerryPalette_Pomeg}, + {gBerryPic_Kelpsy, gBerryPalette_Kelpsy}, + {gBerryPic_Qualot, gBerryPalette_Qualot}, + {gBerryPic_Hondew, gBerryPalette_Hondew}, + {gBerryPic_Grepa, gBerryPalette_Grepa}, + {gBerryPic_Tamato, gBerryPalette_Tamato}, + {gBerryPic_Cornn, gBerryPalette_Cornn}, + {gBerryPic_Magost, gBerryPalette_Magost}, + {gBerryPic_Rabuta, gBerryPalette_Rabuta}, + {gBerryPic_Nomel, gBerryPalette_Nomel}, + {gBerryPic_Spelon, gBerryPalette_Spelon}, + {gBerryPic_Pamtre, gBerryPalette_Pamtre}, + {gBerryPic_Watmel, gBerryPalette_Watmel}, + {gBerryPic_Durin, gBerryPalette_Durin}, + {gBerryPic_Belue, gBerryPalette_Belue}, + {gBerryPic_Liechi, gBerryPalette_Liechi}, + {gBerryPic_Ganlon, gBerryPalette_Ganlon}, + {gBerryPic_Salac, gBerryPalette_Salac}, + {gBerryPic_Petaya, gBerryPalette_Petaya}, + {gBerryPic_Apicot, gBerryPalette_Apicot}, + {gBerryPic_Lansat, gBerryPalette_Lansat}, + {gBerryPic_Starf, gBerryPalette_Starf}, + {gBerryPic_Enigma, gBerryPalette_Enigma}, +}; + +static void DrawBerryPic(const u8 *src, u8 *dst) +{ + u8 i; + u8 j; + + memset(dst, 0, 0x800); + dst += 0x100; + for (i = 0; i < 6; i++) + { + dst += 32; + for (j = 0; j < 6; j++) + { + memcpy(dst, src, 32); + dst += 32; + src += 32; + } + if (i != 5) + dst += 32; + } +} + +static void LoadBerryPic(u8 berryId) +{ + struct SpritePalette spritePal; + + if (berryId == 0x2A && IsEnigmaBerryValid() == TRUE) + { + DrawBerryPic(gSaveBlock1.enigmaBerry.pic, ewramBerryPic); + spritePal.data = gSaveBlock1.enigmaBerry.palette; + spritePal.tag = 0x7544; + LoadSpritePalette(&spritePal); + } + else + { + spritePal.data = (u16 *)sBerryGraphicsTable[berryId].lzPalette; + spritePal.tag = 0x7544; + LoadCompressedObjectPalette((struct CompressedSpritePalette *)&spritePal); + LZDecompressWram(sBerryGraphicsTable[berryId].lzPic, ewramBerryPicTemp); + DrawBerryPic(ewramBerryPicTemp, ewramBerryPic); + } +} + +u8 CreateBerrySprite(u8 berryId, s16 x, s16 y) +{ + LoadBerryPic(berryId); + return CreateSprite(&sBerrySpriteTemplate, x, y, 0); +} + +static void SpriteCB_BerrySprite(struct Sprite *sprite) +{ + sprite->pos2.y = -gUnknown_030041B4; +} + +void sub_80A7DD4(void) +{ + FreeSpritePaletteByTag(0x7544); + FreeSpritePaletteByTag(8); +} + +u8 sub_80A7DEC(u8 berryId, u8 x, u8 y, bool8 animate) +{ + u8 spriteId; + + FreeSpritePaletteByTag(0x7544); + LoadBerryPic(berryId); + spriteId = CreateSprite(&gSpriteTemplate_83C1E04, x, y, 0); + if (animate == TRUE) + StartSpriteAffineAnim(&gSprites[spriteId], 1); + return spriteId; +} + +const struct CompressedSpriteSheet gUnknown_083C1F74 = {gBerryCheckCircle_Gfx, 2048, 0x2710}; + +const struct CompressedSpritePalette gUnknown_083C1F7C = {gBerryCheck_Pal, 0x2710}; + +static const struct OamData gOamData_83C1F84 = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd gSpriteAnim_83C1F8C[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd *const gSpriteAnimTable_83C1F94[] = +{ + gSpriteAnim_83C1F8C, +}; + +static const struct SpriteTemplate gSpriteTemplate_83C1F98 = +{ + .tileTag = 10000, + .paletteTag = 10000, + .oam = &gOamData_83C1F84, + .anims = gSpriteAnimTable_83C1F94, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_BerrySprite, +}; + +u8 sub_80A7E5C(s16 x) +{ + return CreateSprite(&gSpriteTemplate_83C1F98, x, 99, 0); +} diff --git a/src/field/item_use.c b/src/field/item_use.c new file mode 100644 index 000000000..68da27fdb --- /dev/null +++ b/src/field/item_use.c @@ -0,0 +1,1200 @@ +#include "global.h" +#include "item_use.h" +#include "battle.h" +#include "berry.h" +#include "bike.h" +#include "coins.h" +#include "data2.h" +#include "event_data.h" +#include "field_effect.h" +#include "field_fadetransition.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "item.h" +#include "item_menu.h" +#include "items.h" +#include "mail.h" +#include "main.h" +#include "map_obj_lock.h" +#include "menu.h" +#include "menu_helpers.h" +#include "metatile_behavior.h" +#include "palette.h" +#include "party_menu.h" +#include "pokeblock.h" +#include "pokemon_item_effect.h" +#include "pokemon_menu.h" +#include "overworld.h" +#include "rom_8094928.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "vars.h" + +extern void (*gFieldItemUseCallback)(u8); +extern void (*gFieldCallback)(void); +extern void (*gUnknown_0300485C)(void); +extern void (*gUnknown_03004AE4)(u8, u16, TaskFunc); + +extern u8 gUnknown_02038561; +extern u8 gLastFieldPokeMenuOpened; +extern u8 gBankInMenu; + +extern u8 gUnknown_081A1654[]; +extern u8 gUnknown_081A168F[]; + +extern u16 gBattlePartyID[]; + +extern u16 gBattleTypeFlags; + +static const u8 gSSTidalBetaString[] = _("この チケットで ふねに のりほうだい\nはやく のってみたいな"); +static const u8 gSSTidalBetaString2[] = _("この チケットで ふねに のりほうだい\nはやく のってみたいな"); + +static const u8 *const gUnknown_083D61DC[2] = +{ + gSSTidalBetaString, + gSSTidalBetaString2, +}; + +static const MainCallback gExitToOverworldFuncList[] = +{ + sub_808B020, + c2_exit_to_overworld_2_switch, + sub_810B96C, +}; + +static const u8 gItemFinderDirections[] = { DIR_NORTH, DIR_EAST, DIR_SOUTH, DIR_WEST }; + +static const struct YesNoFuncTable gUnknown_083D61F4 = +{ + .yesFunc = sub_80C9FC0, + .noFunc = CleanUpItemMenuMessage, +}; + +void ExecuteSwitchToOverworldFromItemUse(u8 taskId) +{ + u8 taskData; + + if (gScriptItemId == 0xAF) + taskData = gTasks[taskId].data[15] - 1; + else + taskData = ItemId_GetType(gScriptItemId) - 1; + + gTasks[taskId].data[8] = (u32)gExitToOverworldFuncList[taskData] >> 16; + gTasks[taskId].data[9] = (u32)gExitToOverworldFuncList[taskData]; + gTasks[taskId].func = HandleItemMenuPaletteFade; +} + +void ItemMenu_ConfirmNormalFade(u8 var) +{ + ExecuteSwitchToOverworldFromItemUse(var); + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); +} + +void ItemMenu_ConfirmComplexFade(u8 var) +{ + ExecuteSwitchToOverworldFromItemUse(var); + fade_screen(1, 0); +} + +void SetUpItemUseOnFieldCallback(u8 taskId) +{ + if (gTasks[taskId].data[2] != 1) + { + gFieldCallback = ExecuteItemUseFromBlackPalette; + ItemMenu_ConfirmNormalFade(taskId); + } + else + { + gFieldItemUseCallback(taskId); + } +} + +void HandleDeniedItemUseMessage(u8 var1, u8 playerMenuStatus, const u8 *text) +{ + StringExpandPlaceholders(gStringVar4, text); + + switch (playerMenuStatus) + { + case 0: // Item Menu + MenuZeroFillWindowRect(0, 13, 13, 20); + DisplayItemMessageOnField(var1, gStringVar4, CleanUpItemMenuMessage, 1); + break; + default: // Field + DisplayItemMessageOnField(var1, gStringVar4, CleanUpOverworldMessage, 0); + break; + } +} + +void DisplayDadsAdviceCannotUseItemMessage(u8 var1, u8 playerMenuStatus) +{ + HandleDeniedItemUseMessage(var1, playerMenuStatus, gOtherText_DadsAdvice); +} + +void DisplayCantGetOffBikeItemMessage(u8 var1, u8 playerMenuStatus) +{ + HandleDeniedItemUseMessage(var1, playerMenuStatus, gOtherText_CantGetOffBike); +} + +u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId) +{ + if (ItemId_GetFieldFunc(itemId) == ItemUseOutOfBattle_TMHM) + return 1; + else if (ItemId_GetFieldFunc(itemId) == ItemUseOutOfBattle_EvolutionStone) + return 2; + else + return 0; +} + +void ItemMenu_ReadMail(u8 taskId) +{ + struct MailStruct mailStruct; + + if (!gPaletteFade.active) + { + mailStruct.itemId = gScriptItemId; + HandleReadMail(&mailStruct, sub_80A5D04, 0); + DestroyTask(taskId); + } +} + +void ItemUseOutOfBattle_Mail(u8 taskId) +{ + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = ItemMenu_ReadMail; +} + +void ItemUseOutOfBattle_Bike(u8 taskId) +{ + s16 x, y; + u8 tileBehavior; + + PlayerGetDestCoords(&x, &y); + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + + if (FlagGet(SYS_CYCLING_ROAD) == TRUE // on cycling road? + || MetatileBehavior_IsVerticalRail(tileBehavior) == TRUE + || MetatileBehavior_IsHorizontalRail(tileBehavior) == TRUE + || MetatileBehavior_IsIsolatedVerticalRail(tileBehavior) == TRUE + || MetatileBehavior_IsIsolatedHorizontalRail(tileBehavior) == TRUE) + { + DisplayCantGetOffBikeItemMessage(taskId, gTasks[taskId].data[2]); + } + else + { + if (Overworld_IsBikingAllowed() == TRUE && IsBikingDisallowedByPlayer() == FALSE) + { + gFieldItemUseCallback = (void *)ItemUseOnFieldCB_Bike; + SetUpItemUseOnFieldCallback(taskId); + } + else + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].data[2]); + } +} + +void ItemUseOnFieldCB_Bike(u8 taskId) +{ + if (ItemId_GetSecondaryId(gScriptItemId) == 0) + GetOnOffBike(2); + if (ItemId_GetSecondaryId(gScriptItemId) == 1) + GetOnOffBike(4); + + sub_8064E2C(); + ScriptContext2_Disable(); + DestroyTask(taskId); +} + +bool32 CanFish(void) +{ + s16 x, y; + u16 tileBehavior; + + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + tileBehavior = MapGridGetMetatileBehaviorAt(x, y); + + if (MetatileBehavior_IsWaterfall(tileBehavior)) + return FALSE; + + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_4)) + return FALSE; + + if (!TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + { + if (IsPlayerFacingSurfableFishableWater()) + return TRUE; + } + else + { + if (MetatileBehavior_IsSurfableWaterOrUnderwater(tileBehavior) && !MapGridIsImpassableAt(x, y)) + return TRUE; + if (MetatileBehavior_IsBridge(tileBehavior) == TRUE) + return TRUE; + } + + return FALSE; +} + +void ItemUseOutOfBattle_Rod(u8 taskId) +{ + if (CanFish() == TRUE) + { + gFieldItemUseCallback = (void *)ItemUseOnFieldCB_Rod; + SetUpItemUseOnFieldCallback(taskId); + } + else + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].data[2]); +} + +void ItemUseOnFieldCB_Rod(u8 taskId) +{ + StartFishing(ItemId_GetSecondaryId(gScriptItemId)); + DestroyTask(taskId); +} + +void ItemUseOutOfBattle_Itemfinder(u8 var) +{ + IncrementGameStat(0x27); + gFieldItemUseCallback = (void *)ItemUseOnFieldCB_Itemfinder; + SetUpItemUseOnFieldCallback(var); +} + +void ItemUseOnFieldCB_Itemfinder(u8 taskId) +{ + if (ItemfinderCheckForHiddenItems(gMapHeader.events, taskId) == TRUE) + gTasks[taskId].func = RunItemfinderResults; + else + DisplayItemMessageOnField(taskId, gOtherText_NoResponse, ExitItemfinder, 0); +} + +void RunItemfinderResults(u8 taskId) +{ + u8 playerDir; + u8 playerDirToItem; + u8 i; + s16 *data = gTasks[taskId].data; + + if (!data[3]) + { + if (data[4] == 4) + { + playerDirToItem = GetPlayerDirectionTowardsHiddenItem(data[0], data[1]); + if (playerDirToItem) + { + SetPlayerDirectionTowardsItem(gItemFinderDirections[playerDirToItem - 1]); + gTasks[taskId].func = DisplayItemRespondingMessageAndExitItemfinder; + } + else // player is above hidden item. + { + playerDir = player_get_direction_lower_nybble(); + + // rotate player clockwise depending on current direction. + for (i = 0; i < 4; i++) + if (playerDir == gItemFinderDirections[i]) + data[5] = (i + 1) & 3; + + gTasks[taskId].func = RotatePlayerAndExitItemfinder; + data[3] = 0; + data[2] = 0; + } + return; + } + PlaySE(SE_DAUGI); // play the itemfinder jingle 4 times before executing the itemfinder. + data[4]++; + } + data[3] = (data[3] + 1) & 0x1F; +} + +void ExitItemfinder(u8 taskId) +{ + MenuZeroFillWindowRect(0, 14, 29, 19); + sub_8064E2C(); + ScriptContext2_Disable(); + DestroyTask(taskId); +} + +bool8 ItemfinderCheckForHiddenItems(struct MapEvents *events, u8 taskId) +{ + int distanceX, distanceY; + u16 x, y; + s16 newDistanceX, newDistanceY, i; + + PlayerGetDestCoords(&x, &y); + gTasks[taskId].data[2] = FALSE; + + for (i = 0; i < events->bgEventCount; i++) + { + if ((events -> bgEvents[i].kind == 7) && !FlagGet(events -> bgEvents[i].bgUnion.hiddenItem.hiddenItemId + 600)) + { + // do a distance lookup of each item so long as the index remains less than the objects on the current map. + distanceX = (u16)events -> bgEvents[i].x + 7; + newDistanceX = distanceX - x; + distanceY = (u16)events -> bgEvents[i].y + 7; + newDistanceY = distanceY - y; + + // is item in range? + if ((u16)(newDistanceX + 7) < 15 && (newDistanceY >= -5) && (newDistanceY < 6)) + sub_80C9838(taskId, newDistanceX, newDistanceY); // send coordinates of the item relative to the player + } + } + sub_80C9720(taskId); + + // hidden item detected? + if (gTasks[taskId].data[2] == TRUE) + return TRUE; + else + return FALSE; +} + +bool8 HiddenItemAtPos(struct MapEvents *events, s16 x, s16 y) +{ + u8 bgEventCount = events->bgEventCount; + struct BgEvent *bgEvent = events->bgEvents; + int i; + + for (i = 0; i < bgEventCount; i++) + { + if (bgEvent[i].kind == 7 && x == (u16)bgEvent[i].x && y == (u16)bgEvent[i].y) // hidden item and coordinates matches x and y passed? + { + if (!FlagGet(bgEvent[i].bgUnion.hiddenItem.hiddenItemId + 600)) + return TRUE; + else + return FALSE; + } + } + return FALSE; +} + +bool8 sub_80C9688(struct MapConnection *connection, int x, int y) +{ + struct MapHeader *mapHeader; + u16 localX, localY; + u32 localOffset; + s32 localLength; + + mapHeader = mapconnection_get_mapheader(connection); + + switch (connection->direction) + { + // same weird temp variable behavior seen in HiddenItemAtPos + case 2: + localOffset = connection->offset + 7; + localX = x - localOffset; + localLength = mapHeader->mapData->height - 7; + localY = localLength + y; // additions are reversed for some reason + break; + case 1: + localOffset = connection->offset + 7; + localX = x - localOffset; + localLength = gMapHeader.mapData->height + 7; + localY = y - localLength; + break; + case 3: + localLength = mapHeader->mapData->width - 7; + localX = localLength + x; // additions are reversed for some reason + localOffset = connection->offset + 7; + localY = y - localOffset; + break; + case 4: + localLength = gMapHeader.mapData->width + 7; + localX = x - localLength; + localOffset = connection->offset + 7; + localY = y - localOffset; + break; + default: + return FALSE; + } + return HiddenItemAtPos(mapHeader->events, localX, localY); +} + +// weird math +#ifdef NONMATCHING +void sub_80C9720(u8 taskId) +{ + s16 x, y; + s16 curX, curY; + s16 width = gMapHeader.mapData->width + 7; + s16 height = gMapHeader.mapData->height + 7; + + PlayerGetDestCoords(&x, &y); + + for (curX = x - 7; curX <= x + 7; curX++) + { + for (curY = y - 5; curY <= y + 5; curY++) + { + if (7 > curX + || curX >= width + || 7 > curY + || curY >= height) + { + struct MapConnection *conn = sub_8056BA0(curX, curY); + if (conn && sub_80C9688(conn, curX, curY) == TRUE) + sub_80C9838(taskId, curX - x, curY - y); + } + } + } +} +#else +__attribute__((naked)) +void sub_80C9720(u8 taskId) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x14\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x4]\n\ + ldr r0, _080C9834 @ =gMapHeader\n\ + ldr r1, [r0]\n\ + ldr r0, [r1]\n\ + adds r0, 0x7\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [sp, 0x8]\n\ + ldr r0, [r1, 0x4]\n\ + adds r0, 0x7\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [sp, 0xC]\n\ + mov r4, sp\n\ + adds r4, 0x2\n\ + mov r0, sp\n\ + adds r1, r4, 0\n\ + bl PlayerGetDestCoords\n\ + mov r0, sp\n\ + ldrh r0, [r0]\n\ + subs r0, 0x7\n\ + lsls r0, 16\n\ + lsrs r3, r0, 16\n\ + asrs r0, 16\n\ + mov r1, sp\n\ + movs r2, 0\n\ + ldrsh r1, [r1, r2]\n\ + adds r1, 0x7\n\ + cmp r0, r1\n\ + bgt _080C9824\n\ +_080C976E:\n\ + mov r5, sp\n\ + ldrh r0, [r5, 0x2]\n\ + subs r0, 0x5\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + lsls r2, r4, 16\n\ + asrs r1, r2, 16\n\ + movs r6, 0x2\n\ + ldrsh r0, [r5, r6]\n\ + adds r0, 0x5\n\ + lsls r3, 16\n\ + mov r8, r3\n\ + cmp r1, r0\n\ + bgt _080C980E\n\ + movs r0, 0x7\n\ + str r0, [sp, 0x10]\n\ + mov r1, r8\n\ + asrs r1, 16\n\ + mov r9, r1\n\ + mov r10, r0\n\ +_080C9796:\n\ + ldr r3, [sp, 0x10]\n\ + cmp r3, r9\n\ + bgt _080C97B8\n\ + ldr r5, [sp, 0x8]\n\ + lsls r0, r5, 16\n\ + asrs r0, 16\n\ + cmp r9, r0\n\ + bge _080C97B8\n\ + asrs r1, r2, 16\n\ + cmp r10, r1\n\ + bgt _080C97B8\n\ + ldr r6, [sp, 0xC]\n\ + lsls r0, r6, 16\n\ + asrs r0, 16\n\ + lsls r7, r4, 16\n\ + cmp r1, r0\n\ + blt _080C97F6\n\ +_080C97B8:\n\ + mov r0, r8\n\ + asrs r5, r0, 16\n\ + lsls r4, 16\n\ + asrs r6, r4, 16\n\ + adds r0, r5, 0\n\ + adds r1, r6, 0\n\ + bl sub_8056BA0\n\ + adds r7, r4, 0\n\ + cmp r0, 0\n\ + beq _080C97F6\n\ + adds r1, r5, 0\n\ + adds r2, r6, 0\n\ + bl sub_80C9688\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _080C97F6\n\ + mov r0, sp\n\ + ldrh r1, [r0]\n\ + subs r1, r5, r1\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + ldrh r2, [r0, 0x2]\n\ + subs r2, r6, r2\n\ + lsls r2, 16\n\ + asrs r2, 16\n\ + ldr r0, [sp, 0x4]\n\ + bl sub_80C9838\n\ +_080C97F6:\n\ + movs r1, 0x80\n\ + lsls r1, 9\n\ + adds r0, r7, r1\n\ + lsrs r4, r0, 16\n\ + lsls r2, r4, 16\n\ + asrs r1, r2, 16\n\ + mov r3, sp\n\ + movs r5, 0x2\n\ + ldrsh r0, [r3, r5]\n\ + adds r0, 0x5\n\ + cmp r1, r0\n\ + ble _080C9796\n\ +_080C980E:\n\ + movs r1, 0x80\n\ + lsls r1, 9\n\ + add r1, r8\n\ + lsrs r3, r1, 16\n\ + asrs r1, 16\n\ + mov r0, sp\n\ + movs r6, 0\n\ + ldrsh r0, [r0, r6]\n\ + adds r0, 0x7\n\ + cmp r1, r0\n\ + ble _080C976E\n\ +_080C9824:\n\ + add sp, 0x14\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080C9834: .4byte gMapHeader\n\ + .syntax divided"); +} +#endif + +void sub_80C9838(u8 taskId, s16 x, s16 y) +{ + s16 *data = gTasks[taskId].data; + s16 var1, var2, var3, var4; + + if (data[2] == FALSE) + { + data[0] = x; + data[1] = y; + data[2] = TRUE; + } + else + { + // data[0] and data[1] contain the player's coordinates. + // x and y contain the item's coordinates. + if (data[0] < 0) + var1 = data[0] * -1; // item is to the left + else + var1 = data[0]; // item is to the right + + if (data[1] < 0) + var2 = data[1] * -1; // item is to the north + else + var2 = data[1]; // item is to the south + + if (x < 0) + var3 = x * -1; + else + var3 = x; + + if (y < 0) + var4 = y * -1; + else + var4 = y; + + if (var1 + var2 > var3 + var4) + { + data[0] = x; + data[1] = y; + } + else + { + if (var1 + var2 == var3 + var4 && (var2 > var4 || (var2 == var4 && data[1] < y))) + { + data[0] = x; + data[1] = y; + } + } + } +} + +u8 GetPlayerDirectionTowardsHiddenItem(s16 itemX, s16 itemY) +{ + s16 abX, abY; + + if (itemX == 0 && itemY == 0) + return DIR_NONE; // player is standing on the item. + + // get absolute X distance. + if (itemX < 0) + abX = itemX * -1; + else + abX = itemX; + + // get absolute Y distance. + if (itemY < 0) + abY = itemY * -1; + else + abY = itemY; + + if (abX > abY) + { + if (itemX < 0) + return DIR_EAST; + else + return DIR_NORTH; + } + else + { + if (abX < abY) + { + if (itemY < 0) + return DIR_SOUTH; + else + return DIR_WEST; + } + if (abX == abY) + { + if (itemY < 0) + return DIR_SOUTH; + else + return DIR_WEST; + } + return DIR_NONE; // should never get here. return something so it doesnt crash. + } +} + +void SetPlayerDirectionTowardsItem(u8 direction) +{ + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0)]); + FieldObjectClearAnim(&gMapObjects[GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0)]); + UnfreezeMapObject(&gMapObjects[GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0)]); + PlayerTurnInPlace(direction); +} + +void DisplayItemRespondingMessageAndExitItemfinder(u8 taskId) +{ + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(&gMapObjects[GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0)]) == TRUE) + DisplayItemMessageOnField(taskId, gOtherText_ItemfinderResponding, ExitItemfinder, 0); +} + +void RotatePlayerAndExitItemfinder(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(&gMapObjects[GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0)]) == TRUE + || data[2] == FALSE) + { + SetPlayerDirectionTowardsItem(gItemFinderDirections[data[5]]); + data[2] = 1; + data[5] = (data[5] + 1) & 3; + data[3]++; + + if (data[3] == 4) + DisplayItemMessageOnField(taskId, gOtherText_ItemfinderItemUnderfoot, ExitItemfinder, 0); + } +} + +void ItemUseOutOfBattle_PokeblockCase(u8 taskId) +{ + if (sub_80F9344() == TRUE) + { + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].data[2]); + } + else if (gTasks[taskId].data[2] != TRUE) + { + sub_810BA7C(0); + ItemMenu_ConfirmNormalFade(taskId); + } + else + { + gFieldCallback = (void *)sub_8080E28; + sub_810BA7C(1); + ItemMenu_ConfirmComplexFade(taskId); + } +} + +void ItemUseOutOfBattle_CoinCase(u8 taskId) +{ + ConvertIntToDecimalStringN(gStringVar1, GetCoins(), 0, 4); + StringExpandPlaceholders(gStringVar4, gOtherText_Coins3); + + if (!gTasks[taskId].data[2]) + { + MenuZeroFillWindowRect(0, 0xD, 0xD, 0x14); + DisplayItemMessageOnField(taskId, gStringVar4, CleanUpItemMenuMessage, 1); + } + else + { + DisplayItemMessageOnField(taskId, gStringVar4, CleanUpOverworldMessage, 0); + } +} + +void sub_80C9BB8(u8 var) +{ + if (gMain.newKeys & A_BUTTON) + CleanUpItemMenuMessage(var); +} + +void sub_80C9BD8(u8 var) +{ + if (gMain.newKeys & A_BUTTON) + CleanUpOverworldMessage(var); +} + +// unused +void ItemUseOutOfBattle_SSTicket(u8 taskId) +{ + if (gTasks[taskId].data[2] == 0) + { + MenuZeroFillWindowRect(0, 0xD, 0xD, 0x14); + DisplayItemMessageOnField(taskId, gUnknown_083D61DC[ItemId_GetSecondaryId(gScriptItemId)], sub_80C9BB8, 1); + } + else + { + DisplayItemMessageOnField(taskId, gUnknown_083D61DC[ItemId_GetSecondaryId(gScriptItemId)], sub_80C9BD8, 0); + } +} + +void sub_80C9C7C(u8 taskId) +{ + if (IsPlayerFacingPlantedBerryTree() == TRUE) + { + gFieldItemUseCallback = sub_80C9D00; + gFieldCallback = ExecuteItemUseFromBlackPalette; + gTasks[taskId].data[8] = (u32)c2_exit_to_overworld_2_switch >> 16; + gTasks[taskId].data[9] = (u32)c2_exit_to_overworld_2_switch; + gTasks[taskId].func = HandleItemMenuPaletteFade; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0); + } + else + { + ItemId_GetFieldFunc(gScriptItemId)(taskId); + } +} + +void sub_80C9D00(u8 taskId) +{ + RemoveBagItem(gScriptItemId, 1); + ScriptContext2_Enable(); + ScriptContext1_SetupScript(gUnknown_081A1654); + DestroyTask(taskId); +} + +void ItemUseOutOfBattle_WailmerPail(u8 taskId) +{ + if (TryToWaterBerryTree() == TRUE) + { + gFieldItemUseCallback = sub_80C9D74; + SetUpItemUseOnFieldCallback(taskId); + } + else + { + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].data[2]); + } +} + +void sub_80C9D74(u8 taskId) +{ + ScriptContext2_Enable(); + ScriptContext1_SetupScript(gUnknown_081A168F); + DestroyTask(taskId); +} + +void sub_80C9D98(u8 taskId) +{ + gUnknown_02038561 = 0; + ItemMenu_ConfirmNormalFade(taskId); +} + +void ItemUseOutOfBattle_Medicine(u8 taskId) +{ + gUnknown_03004AE4 = UseMedicine; + sub_80C9D98(taskId); +} + +void ItemUseOutOfBattle_SacredAsh(u8 taskId) +{ + u8 i; + + gLastFieldPokeMenuOpened = 0; + + for (i = 0; i < 6; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_SPECIES) != 0 && GetMonData(&gPlayerParty[i], MON_DATA_HP) == 0) + { + gLastFieldPokeMenuOpened = i; + break; + } + } + gUnknown_03004AE4 = sub_8070048; + gUnknown_02038561 = 4; + ItemMenu_ConfirmNormalFade(taskId); +} + +void ItemUseOutOfBattle_PPRecovery(u8 taskId) +{ + gUnknown_03004AE4 = DoPPRecoveryItemEffect; + sub_80C9D98(taskId); +} + +void ItemUseOutOfBattle_PPUp(u8 taskId) +{ + gUnknown_03004AE4 = DoPPUpItemEffect; + sub_80C9D98(taskId); +} + +void ItemUseOutOfBattle_RareCandy(u8 taskId) +{ + gUnknown_03004AE4 = DoRareCandyItemEffect; + sub_80C9D98(taskId); +} + +void ItemUseOutOfBattle_TMHM(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0xD, 0xD, 0x14); + + if (gScriptItemId >= ITEM_HM01) + DisplayItemMessageOnField(taskId, gOtherText_BootedHM, sub_80C9EE4, 1); // HM + else + DisplayItemMessageOnField(taskId, gOtherText_BootedTM, sub_80C9EE4, 1); // TM +} + +void sub_80C9EE4(u8 taskId) +{ + PlaySE(SE_PC_LOGON); + gTasks[taskId].func = sub_80C9F10; +} + +void sub_80C9F10(u8 taskId) +{ + if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) + { + StringCopy(gStringVar1, gMoveNames[ItemIdToBattleMoveId(gScriptItemId)]); + StringExpandPlaceholders(gStringVar4, gOtherText_ContainsMove); + DisplayItemMessageOnField(taskId, gStringVar4, sub_80C9F80, 1); + } +} + +void sub_80C9F80(u8 var) +{ + DisplayYesNoMenu(7, 7, 1); + sub_80A3FA0(gBGTilemapBuffers[1], 8, 8, 5, 4, 1); + DoYesNoFuncWithChoice(var, &gUnknown_083D61F4); +} + +void sub_80C9FC0(u8 var) +{ + gUnknown_03004AE4 = TeachMonTMMove; + sub_80C9D98(var); +} + +static void PrepareItemUseMessage(void) +{ + RemoveBagItem(gScriptItemId, 1); + sub_80A3E0C(); + CopyItemName(gScriptItemId, gStringVar2); + StringExpandPlaceholders(gStringVar4, gOtherText_UsedItem); +} + +void ItemUseOutOfBattle_Repel(u8 var) +{ + if (VarGet(VAR_REPEL_STEP_COUNT) == FALSE) + { + VarSet(VAR_REPEL_STEP_COUNT, ItemId_GetHoldEffectParam(gScriptItemId)); + PrepareItemUseMessage(); + DisplayItemMessageOnField(var, gStringVar4, CleanUpItemMenuMessage, 1); + } + else + { + DisplayItemMessageOnField(var, gOtherText_RepelLingers, CleanUpItemMenuMessage, 1); + } +} + +void sub_80CA07C(void) +{ + sub_80A3E0C(); + CopyItemName(gScriptItemId, gStringVar2); +} + +void sub_80CA098(u8 taskId) +{ + if(++gTasks[taskId].data[15] > 7) + { + PlaySE(SE_BIDORO); + DisplayItemMessageOnField(taskId, gStringVar4, CleanUpItemMenuMessage, 1); + } +} + +void ItemUseOutOfBattle_BlackWhiteFlute(u8 taskId) +{ + if (gScriptItemId == ITEM_WHITE_FLUTE) + { + FlagSet(SYS_ENC_UP_ITEM); + FlagClear(SYS_ENC_DOWN_ITEM); + sub_80CA07C(); + StringExpandPlaceholders(gStringVar4, gOtherText_UsedFlute); + gTasks[taskId].func = sub_80CA098; + gTasks[taskId].data[15] = 0; + } + else if (gScriptItemId == ITEM_BLACK_FLUTE) + { + FlagSet(SYS_ENC_DOWN_ITEM); + FlagClear(SYS_ENC_UP_ITEM); + sub_80CA07C(); + StringExpandPlaceholders(gStringVar4, gOtherText_UsedRepel); + gTasks[taskId].func = sub_80CA098; + gTasks[taskId].data[15] = 0; + } +} + +void task08_080A1C44(u8 taskId) +{ + player_avatar_init_params_reset(); + sub_80878A8(); + DestroyTask(taskId); +} + +void EscapeRopeCallback(u8 taskId) +{ + Overworld_ResetStateAfterDigEscRope(); + PrepareItemUseMessage(); + gTasks[taskId].data[0] = 0; + DisplayItemMessageOnField(taskId, gStringVar4, task08_080A1C44, 0); +} + +bool8 CanUseEscapeRopeOnCurrMap(void) +{ + if (gMapHeader.mapType == MAP_TYPE_UNDERGROUND) + return TRUE; + else + return FALSE; +} + +void ItemUseOutOfBattle_EscapeRope(u8 taskId) +{ + if (CanUseEscapeRopeOnCurrMap() == TRUE) + { + gFieldItemUseCallback = EscapeRopeCallback; + SetUpItemUseOnFieldCallback(taskId); + } + else + { + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].data[2]); + } +} + +void ItemUseOutOfBattle_EvolutionStone(u8 var) +{ + gUnknown_03004AE4 = DoEvolutionStoneItemEffect; + sub_80C9D98(var); +} + +void ItemUseInBattle_PokeBall(u8 var) +{ + if (PlayerPartyAndPokemonStorageFull() == FALSE) // have room for mon? + { + RemoveBagItem(gScriptItemId, 1); + sub_80A7094(var); + } + else + { + MenuZeroFillWindowRect(0, 0xD, 0xD, 0x14); + DisplayItemMessageOnField(var, gOtherText_BoxIsFull, CleanUpItemMenuMessage, 1); + } +} + +void sub_80CA294(u8 var) +{ + if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) + sub_80A7094(var); +} + +void sub_80CA2BC(u8 taskId) +{ + if(++gTasks[taskId].data[15] > 7) + { + PlaySE(SE_KAIFUKU); + RemoveBagItem(gScriptItemId, 1); + DisplayItemMessageOnField(taskId, sub_803F378(gScriptItemId), sub_80CA294, 1); + } +} + +void ItemUseInBattle_StatIncrease(u8 taskId) +{ + u16 partyId = gBattlePartyID[gBankInMenu]; + + MenuZeroFillWindowRect(0, 0xD, 0xD, 0x14); + + if (ExecuteTableBasedItemEffect_(&gPlayerParty[partyId], gScriptItemId, partyId, 0) != FALSE) + { + DisplayItemMessageOnField(taskId, gOtherText_WontHaveAnyEffect, CleanUpItemMenuMessage, 1); + } + else + { + gTasks[taskId].func = sub_80CA2BC; + gTasks[taskId].data[15] = 0; + } +} + +void sub_80CA394(u8 taskId) +{ + if (!gPaletteFade.active) + { + sub_8094E4C(); + gpu_pal_allocator_reset__manage_upper_four(); + DestroyTask(taskId); + } +} + +void sub_80CA3C0(u8 taskId) +{ + gTasks[taskId].func = sub_80CA394; + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); +} + +void ItemUseInBattle_Medicine(u8 var) +{ + gUnknown_03004AE4 = UseMedicine; + sub_80CA3C0(var); +} + +void unref_sub_80CA410(u8 var) +{ + gUnknown_03004AE4 = sub_8070048; + sub_80CA3C0(var); +} + +void ItemUseInBattle_PPRecovery(u8 var) +{ + gUnknown_03004AE4 = DoPPRecoveryItemEffect; + sub_80CA3C0(var); +} + +void unref_sub_80CA448(u8 var) +{ + MenuZeroFillWindowRect(0, 0xD, 0xD, 0x14); + + if (ExecuteTableBasedItemEffect__(0, gScriptItemId, 0) == FALSE) + { + RemoveBagItem(gScriptItemId, 1); + GetMonNickname(&gPlayerParty[0], gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_SnapConfusion); + DisplayItemMessageOnField(var, gStringVar4, sub_80A7094, 1); + } + else + { + DisplayItemMessageOnField(var, gOtherText_WontHaveAnyEffect, CleanUpItemMenuMessage, 1); + } +} + +void ItemUseInBattle_Escape(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0xD, 0xD, 0x14); + + if((gBattleTypeFlags & BATTLE_TYPE_TRAINER) == FALSE) + { + PrepareItemUseMessage(); + DisplayItemMessageOnField(taskId, gStringVar4, sub_80A7094, 1); + } + else + { + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].data[2]); + } +} + +void ItemUseOutOfBattle_EnigmaBerry(u8 taskId) +{ + switch (GetItemEffectType(gScriptItemId) - 1) + { + case 1: + case 2: + case 3: + case 4: + case 5: + case 6: + case 10: + case 11: + case 12: + case 13: + case 14: + case 15: + case 16: + gTasks[taskId].data[15] = 1; + ItemUseOutOfBattle_Medicine(taskId); + break; + case 9: + gTasks[taskId].data[15] = 1; + ItemUseOutOfBattle_SacredAsh(taskId); + break; + case 0: + gTasks[taskId].data[15] = 1; + ItemUseOutOfBattle_RareCandy(taskId); + break; + case 18: + case 19: + gTasks[taskId].data[15] = 1; + ItemUseOutOfBattle_PPUp(taskId); + break; + case 20: + gTasks[taskId].data[15] = 1; + ItemUseOutOfBattle_PPRecovery(taskId); + break; + default: + gTasks[taskId].data[15] = 4; + ItemUseOutOfBattle_CannotUse(taskId); + } +} + +void ItemUseInBattle_EnigmaBerry(u8 taskId) +{ + switch (GetItemEffectType(gScriptItemId)) + { + case 0: + ItemUseInBattle_StatIncrease(taskId); + break; + case 2: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + case 9: + case 11: + ItemUseInBattle_Medicine(taskId); + break; + case 21: + ItemUseInBattle_PPRecovery(taskId); + break; + default: + ItemUseOutOfBattle_CannotUse(taskId); + } +} + +void ItemUseOutOfBattle_CannotUse(u8 taskId) +{ + DisplayDadsAdviceCannotUseItemMessage(taskId, gTasks[taskId].data[2]); +} diff --git a/src/field/landmark.c b/src/field/landmark.c new file mode 100644 index 000000000..6a53716bb --- /dev/null +++ b/src/field/landmark.c @@ -0,0 +1,73 @@ +#include "global.h" +#include "landmark.h" +#include "event_data.h" + +#define MAPSEC_NONE 0x58 + +struct Landmark +{ + u8 *name; + u16 flag; +}; + +struct LandmarkList +{ + u8 mapSection; + u8 id; + const struct Landmark **landmarks; +}; + +extern const struct LandmarkList gLandmarkLists[]; + +static const struct Landmark **GetLandmarks(u8 mapSection, u8 id); + +u8 *GetLandmarkName(u8 mapSection, u8 id, u8 count) +{ + const struct Landmark **landmarks = GetLandmarks(mapSection, id); + + if (!landmarks) + return NULL; + + while (1) + { + const struct Landmark *landmark = *landmarks; + + if (landmark->flag == 0xFFFF || FlagGet(landmark->flag) == TRUE) + { + if (count == 0) + break; + else + count--; + } + + landmarks++; + if (!*landmarks) + return NULL; + } + + return (*landmarks)->name; +} + +static const struct Landmark **GetLandmarks(u8 mapSection, u8 id) +{ + u16 i = 0; + + for (; gLandmarkLists[i].mapSection != MAPSEC_NONE; i++) + { + if (gLandmarkLists[i].mapSection > mapSection) + return NULL; + if (gLandmarkLists[i].mapSection == mapSection) + break; + } + + if (gLandmarkLists[i].mapSection == MAPSEC_NONE) + return NULL; + + for (; gLandmarkLists[i].mapSection == mapSection; i++) + { + if (gLandmarkLists[i].id == id) + return gLandmarkLists[i].landmarks; + } + + return NULL; +} diff --git a/src/field/lottery_corner.c b/src/field/lottery_corner.c new file mode 100644 index 000000000..c2c25b9ac --- /dev/null +++ b/src/field/lottery_corner.c @@ -0,0 +1,174 @@ +#include "global.h" +#include "lottery_corner.h" +#include "event_data.h" +#include "items.h" +#include "rng.h" +#include "species.h" +#include "string_util.h" +#include "text.h" + +extern u16 gScriptResult; +extern u16 gSpecialVar_0x8004; +extern struct PokemonStorage gPokemonStorage; +extern u16 gSpecialVar_0x8005; +extern u16 gSpecialVar_0x8006; +static EWRAM_DATA u16 sWinNumberDigit = 0; +static EWRAM_DATA u16 sOtIdDigit = 0; + +static const u16 sLotteryPrizes[] = +{ + ITEM_PP_UP, + ITEM_EXP_SHARE, + ITEM_MAX_REVIVE, + ITEM_MASTER_BALL, +}; + +static u8 GetMatchingDigits(u16, u16); + +void ResetLotteryCorner(void) +{ + u16 rand = Random(); + + SetLotteryNumber((Random() << 16) | rand); + VarSet(VAR_POKELOT_PRIZE, 0); +} + +void SetRandomLotteryNumber(u16 i) +{ + u32 var = Random(); + + while (--i != 0xFFFF) + var = var * 1103515245 + 12345; + + SetLotteryNumber(var); +} + +void RetrieveLotteryNumber(void) +{ + u16 lottoNumber = GetLotteryNumber(); + gScriptResult = lottoNumber; +} + +void PickLotteryCornerTicket(void) +{ + u16 i; + u16 j; + u32 box; + u32 slot; + + gSpecialVar_0x8004 = 0; + slot = 0; + box = 0; + for (i = 0; i < 6; i++) + { + struct Pokemon *pkmn = &gPlayerParty[i]; + + // UB: Too few arguments for function GetMonData + if (GetMonData(pkmn, MON_DATA_SPECIES) != SPECIES_NONE) + { + // do not calculate ticket values for eggs. + if (!GetMonData(pkmn, MON_DATA_IS_EGG)) + { + u32 otId = GetMonData(pkmn, MON_DATA_OT_ID); + u8 numMatchingDigits = GetMatchingDigits(gScriptResult, otId); + + if (numMatchingDigits > gSpecialVar_0x8004 && numMatchingDigits > 1) + { + gSpecialVar_0x8004 = numMatchingDigits - 1; + box = 14; + slot = i; + } + } + } + else // pokemon are always arranged from populated spots first to unpopulated, so the moment a NONE species is found, that's the end of the list. + break; + } + + // player has 14 boxes. + for (i = 0; i < 14; i++) + { + // player has 30 slots per box. + for (j = 0; j < 30; j++) + { + struct BoxPokemon *pkmn = &gPokemonStorage.boxes[i][j]; + + // UB: Too few arguments for function GetMonData + if (GetBoxMonData(pkmn, MON_DATA_SPECIES) != SPECIES_NONE && + !GetBoxMonData(pkmn, MON_DATA_IS_EGG)) + { + u32 otId = GetBoxMonData(pkmn, MON_DATA_OT_ID); + u8 numMatchingDigits = GetMatchingDigits(gScriptResult, otId); + + if (numMatchingDigits > gSpecialVar_0x8004 && numMatchingDigits > 1) + { + gSpecialVar_0x8004 = numMatchingDigits - 1; + box = i; + slot = j; + } + } + } + } + + if (gSpecialVar_0x8004 != 0) + { + gSpecialVar_0x8005 = sLotteryPrizes[gSpecialVar_0x8004 - 1]; + + if (box == 14) + { + gSpecialVar_0x8006 = 0; + GetMonData(&gPlayerParty[slot], MON_DATA_NICKNAME, gStringVar1); + } + else + { + gSpecialVar_0x8006 = 1; + GetBoxMonData(&gPokemonStorage.boxes[box][slot], MON_DATA_NICKNAME, gStringVar1); + } + StringGetEnd10(gStringVar1); + } +} + +static u8 GetMatchingDigits(u16 winNumber, u16 otId) +{ + u8 i; + u8 matchingDigits = 0; + + for (i = 0; i < 5; i++) + { + sWinNumberDigit = winNumber % 10; + sOtIdDigit = otId % 10; + + if (sWinNumberDigit == sOtIdDigit) + { + winNumber = winNumber / 10; + otId = otId / 10; + matchingDigits++; + } + else + break; + } + return matchingDigits; +} + +// lottery numbers go from 0 to 99999, not 65535 (0xFFFF). interestingly enough, the function that calls GetLotteryNumber shifts to u16, so it cant be anything above 65535 anyway. +void SetLotteryNumber(u32 lotteryNum) +{ + u16 lowNum = lotteryNum >> 16; + u16 highNum = lotteryNum; + + VarSet(VAR_POKELOT_RND1, highNum); + VarSet(VAR_POKELOT_RND2, lowNum); +} + +u32 GetLotteryNumber(void) +{ + u16 highNum = VarGet(VAR_POKELOT_RND1); + u16 lowNum = VarGet(VAR_POKELOT_RND2); + + return (lowNum << 16) | highNum; +} + +// interestingly, this may have been the original lottery number set function, but GF tried to change it to 32-bit later but didnt finish changing all calls as one GetLotteryNumber still shifts to u16. +void SetLotteryNumber16_Unused(u16 lotteryNum) +{ + SetLotteryNumber(lotteryNum); +} diff --git a/src/field/map_name_popup.c b/src/field/map_name_popup.c new file mode 100644 index 000000000..01105d0db --- /dev/null +++ b/src/field/map_name_popup.c @@ -0,0 +1,107 @@ +#include "global.h" +#include "map_name_popup.h" +#include "event_data.h" +#include "menu.h" +#include "region_map.h" +#include "task.h" + +EWRAM_DATA static u8 sTaskId = 0; + +static void Task_MapNamePopup(u8); +static void DrawMapNamePopup(void); + +bool8 unref_sub_80A2F44(void) +{ + CloseMenu(); + ShowMapNamePopup(); + return 1; +} + +void ShowMapNamePopup(void) +{ + if (FlagGet(0x4000) != TRUE) + { + if (!FuncIsActiveTask(Task_MapNamePopup)) + { + sTaskId = CreateTask(Task_MapNamePopup, 90); + REG_BG0VOFS = 32; + DrawMapNamePopup(); + gTasks[sTaskId].data[0] = 0; + gTasks[sTaskId].data[2] = 32; + } + else + { + if (gTasks[sTaskId].data[0] != 2) + gTasks[sTaskId].data[0] = 2; + gTasks[sTaskId].data[3] = 1; + } + } +} + +void Task_MapNamePopup(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + task->data[2] -= 2; + if (task->data[2] <= 0 ) + { + task->data[0] = 1; + gTasks[sTaskId].data[1] = 0; + } + break; + case 1: + task->data[1]++; + if (task->data[1] > 120 ) + { + task->data[1] = 0; + task->data[0] = 2; + } + break; + case 2: + task->data[2] += 2; + if (task->data[2] > 31) + { + if (task->data[3]) + { + DrawMapNamePopup(); + task->data[0] = 0; + task->data[3] = 0; + } + else + { + task->data[0] = 4; + return; + } + } + break; + case 4: + HideMapNamePopup(); + return; + } + + REG_BG0VOFS = task->data[2]; +} + +void HideMapNamePopup(void) +{ + if (FuncIsActiveTask(Task_MapNamePopup)) + { + MenuLoadTextWindowGraphics(); + MenuZeroFillWindowRect(0, 0, 13, 3); + REG_BG0VOFS = 0; + DestroyTask(sTaskId); + } +} + +void DrawMapNamePopup(void) +{ + u8 name[20]; + + MenuLoadTextWindowGraphics_OverrideFrameType(0); + GetMapSectionName(name, gMapHeader.regionMapSectionId, 0); + MenuDrawTextWindow(0, 0, 13, 3); + sub_8072BD8(name, 1, 1, 0x60); +} diff --git a/src/field/map_obj_lock.c b/src/field/map_obj_lock.c new file mode 100644 index 000000000..2856320b8 --- /dev/null +++ b/src/field/map_obj_lock.c @@ -0,0 +1,118 @@ +#include "global.h" +#include "map_obj_lock.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "script_movement.h" +#include "task.h" + +extern u16 gScriptFacing; + +bool8 walkrun_is_standing_still(void) +{ + if (gPlayerAvatar.running1 == 1) + return FALSE; + else + return TRUE; +} + +void sub_8064CDC(u8 taskId) +{ + if (walkrun_is_standing_still()) + { + sub_80594C0(); + DestroyTask(taskId); + } +} + +bool8 sub_8064CFC(void) +{ + if (FuncIsActiveTask(sub_8064CDC)) + { + return FALSE; + } + else + { + sub_80597F4(); + return TRUE; + } +} + +void ScriptFreezeMapObjects(void) +{ + FreezeMapObjects(); + CreateTask(sub_8064CDC, 80); +} + +void sub_8064D38(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + if (!task->data[0] && walkrun_is_standing_still() == TRUE) + { + sub_80594C0(); + task->data[0] = 1; + } + if (!task->data[1] && !gMapObjects[gSelectedMapObject].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[gSelectedMapObject]); + task->data[1] = 1; + } + if (task->data[0] && task->data[1]) + DestroyTask(taskId); +} + +bool8 sub_8064DB4(void) +{ + if (FuncIsActiveTask(sub_8064D38)) + { + return FALSE; + } + else + { + sub_80597F4(); + return TRUE; + } +} + +void LockSelectedMapObject(void) +{ + u8 taskId; + FreezeMapObjectsExceptOne(gSelectedMapObject); + taskId = CreateTask(sub_8064D38, 80); + if (!gMapObjects[gSelectedMapObject].mapobj_bit_1) + { + FreezeMapObject(&gMapObjects[gSelectedMapObject]); + gTasks[taskId].data[1] = 1; + } +} + +void sub_8064E2C(void) +{ + u8 objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]); + sub_80A2178(); + UnfreezeMapObjects(); +} + +void unref_sub_8064E5C(void) +{ + u8 objectId; + + if (gMapObjects[gSelectedMapObject].active) + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gSelectedMapObject]); + objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]); + sub_80A2178(); + UnfreezeMapObjects(); +} + +void sub_8064EAC(void) +{ + FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedMapObject], gScriptFacing); +} + +void sub_8064ED4(void) +{ + FieldObjectClearAnimIfSpecialAnimActive(&gMapObjects[gSelectedMapObject]); +} diff --git a/src/field/mauville_man.c b/src/field/mauville_man.c new file mode 100644 index 000000000..33bc39648 --- /dev/null +++ b/src/field/mauville_man.c @@ -0,0 +1,1311 @@ +#include "global.h" +#include "bard_music.h" +#include "mauville_man.h" +#include "easy_chat.h" +#include "event_data.h" +#include "field_message_box.h" +#include "m4a.h" +#include "menu.h" +#include "overworld.h" +#include "rng.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "trader.h" + +#define MACRO1(a) (((a) % 4) + (((a) / 8) & 1)) + +extern struct MusicPlayerInfo gMPlay_SE2; + +extern u16 gScriptResult; +extern u16 gSpecialVar_0x8004; + +extern const u8 gTextStoryteller_Story1Title[]; +extern const u8 gTextStoryteller_Story1Action[]; +extern const u8 gTextStoryteller_Story1Text[]; +extern const u8 gTextStoryteller_Story2Title[]; +extern const u8 gTextStoryteller_Story2Action[]; +extern const u8 gTextStoryteller_Story2Text[]; +extern const u8 gTextStoryteller_Story3Title[]; +extern const u8 gTextStoryteller_Story3Action[]; +extern const u8 gTextStoryteller_Story3Text[]; +extern const u8 gTextStoryteller_Story4Title[]; +extern const u8 gTextStoryteller_Story4Action[]; +extern const u8 gTextStoryteller_Story4Text[]; +extern const u8 gTextStoryteller_Story5Title[]; +extern const u8 gTextStoryteller_Story5Action[]; +extern const u8 gTextStoryteller_Story5Text[]; +extern const u8 gTextStoryteller_Story6Title[]; +extern const u8 gTextStoryteller_Story6Action[]; +extern const u8 gTextStoryteller_Story6Text[]; +extern const u8 gTextStoryteller_Story7Title[]; +extern const u8 gTextStoryteller_Story7Action[]; +extern const u8 gTextStoryteller_Story7Text[]; +extern const u8 gTextStoryteller_Story8Title[]; +extern const u8 gTextStoryteller_Story8Action[]; +extern const u8 gTextStoryteller_Story8Text[]; +extern const u8 gTextStoryteller_Story9Title[]; +extern const u8 gTextStoryteller_Story9Action[]; +extern const u8 gTextStoryteller_Story9Text[]; +extern const u8 gTextStoryteller_Story10Title[]; +extern const u8 gTextStoryteller_Story10Action[]; +extern const u8 gTextStoryteller_Story10Text[]; +extern const u8 gTextStoryteller_Story11Title[]; +extern const u8 gTextStoryteller_Story11Action[]; +extern const u8 gTextStoryteller_Story11Text[]; +extern const u8 gTextStoryteller_Story12Title[]; +extern const u8 gTextStoryteller_Story12Action[]; +extern const u8 gTextStoryteller_Story12Text[]; +extern const u8 gTextStoryteller_Story13Title[]; +extern const u8 gTextStoryteller_Story13Action[]; +extern const u8 gTextStoryteller_Story13Text[]; +extern const u8 gTextStoryteller_Story14Title[]; +extern const u8 gTextStoryteller_Story14Action[]; +extern const u8 gTextStoryteller_Story14Text[]; +extern const u8 gTextStoryteller_Story15Title[]; +extern const u8 gTextStoryteller_Story15Action[]; +extern const u8 gTextStoryteller_Story15Text[]; +extern const u8 gTextStoryteller_Story16Title[]; +extern const u8 gTextStoryteller_Story16Action[]; +extern const u8 gTextStoryteller_Story16Text[]; +extern const u8 gTextStoryteller_Story17Title[]; +extern const u8 gTextStoryteller_Story17Action[]; +extern const u8 gTextStoryteller_Story17Text[]; +extern const u8 gTextStoryteller_Story18Title[]; +extern const u8 gTextStoryteller_Story18Action[]; +extern const u8 gTextStoryteller_Story18Text[]; +extern const u8 gTextStoryteller_Story19Title[]; +extern const u8 gTextStoryteller_Story19Action[]; +extern const u8 gTextStoryteller_Story19Text[]; +extern const u8 gTextStoryteller_Story20Title[]; +extern const u8 gTextStoryteller_Story20Action[]; +extern const u8 gTextStoryteller_Story20Text[]; +extern const u8 gTextStoryteller_Story21Title[]; +extern const u8 gTextStoryteller_Story21Action[]; +extern const u8 gTextStoryteller_Story21Text[]; +extern const u8 gTextStoryteller_Story22Title[]; +extern const u8 gTextStoryteller_Story22Action[]; +extern const u8 gTextStoryteller_Story22Text[]; +extern const u8 gTextStoryteller_Story23Title[]; +extern const u8 gTextStoryteller_Story23Action[]; +extern const u8 gTextStoryteller_Story23Text[]; +extern const u8 gTextStoryteller_Story24Title[]; +extern const u8 gTextStoryteller_Story24Action[]; +extern const u8 gTextStoryteller_Story24Text[]; +extern const u8 gTextStoryteller_Story25Title[]; +extern const u8 gTextStoryteller_Story25Action[]; +extern const u8 gTextStoryteller_Story25Text[]; +extern const u8 gTextStoryteller_Story26Title[]; +extern const u8 gTextStoryteller_Story26Action[]; +extern const u8 gTextStoryteller_Story26Text[]; +extern const u8 gTextStoryteller_Story27Title[]; +extern const u8 gTextStoryteller_Story27Action[]; +extern const u8 gTextStoryteller_Story27Text[]; +extern const u8 gTextStoryteller_Story28Title[]; +extern const u8 gTextStoryteller_Story28Action[]; +extern const u8 gTextStoryteller_Story28Text[]; +extern const u8 gTextStoryteller_Story29Title[]; +extern const u8 gTextStoryteller_Story29Action[]; +extern const u8 gTextStoryteller_Story29Text[]; +extern const u8 gTextStoryteller_Story30Title[]; +extern const u8 gTextStoryteller_Story30Action[]; +extern const u8 gTextStoryteller_Story30Text[]; +extern const u8 gTextStoryteller_Story31Title[]; +extern const u8 gTextStoryteller_Story31Action[]; +extern const u8 gTextStoryteller_Story31Text[]; +extern const u8 gTextStoryteller_Story32Title[]; +extern const u8 gTextStoryteller_Story32Action[]; +extern const u8 gTextStoryteller_Story32Text[]; +extern const u8 gTextStoryteller_Story33Title[]; +extern const u8 gTextStoryteller_Story33Action[]; +extern const u8 gTextStoryteller_Story33Text[]; +extern const u8 gTextStoryteller_Story34Title[]; +extern const u8 gTextStoryteller_Story34Action[]; +extern const u8 gTextStoryteller_Story34Text[]; +extern const u8 gTextStoryteller_Story35Title[]; +extern const u8 gTextStoryteller_Story35Action[]; +extern const u8 gTextStoryteller_Story35Text[]; +extern const u8 gTextStoryteller_Story36Title[]; +extern const u8 gTextStoryteller_Story36Action[]; +extern const u8 gTextStoryteller_Story36Text[]; + +extern struct BardSong gUnknown_03005DA0; + +EWRAM_DATA static u16 gUnknown_020388BC = 0; // set but not used? + +static const u16 sDefaultBardSongLyrics[] = +{ +#ifdef ENGLISH + EC_WORD_SISTER, + EC_WORD_EATS, + EC_WORD_SWEETS, + EC_WORD_VORACIOUS, + EC_WORD_AND, + EC_WORD_DROOLING, +#else + EC_WORD_SISTER, + EC_WORD_MUST_BE, + EC_WORD_SWEETS, + EC_WORD_VORACIOUS, + EC_WORD_DROOLING, + EC_WORD_THICK, +#endif +}; + +static const u8 *const sGiddyAdjectives[] = +{ + OtherText_SoPretty, + OtherText_SoDarling, + OtherText_SoRelaxed, + OtherText_SoSunny, + OtherText_SoDesirable, + OtherText_SoExciting, + OtherText_SoAmusing, + OtherText_SoMagical, +}; + +static const u8 *const sGiddyQuestions[] = +{ + OtherText_WantVacationNicePlace, + OtherText_BoughtCrayonsIsNice, + OtherText_IfWeCouldFloat, + OtherText_SandWashesAwayMakeSad, + OtherText_WhatsBottomSeaLike, + OtherText_SeeSettingSun, + OtherText_LyingInGreenGrass, + OtherText_SecretBasesWonderful, +}; + +static void sub_80F7DC0(void); +static void Task_BardSong(u8); +static void StartBardSong(u8); +static void StorytellerSetup(void); +static void sub_80F8428(void); + +static void SetupBard(void) +{ + u16 i; + struct MauvilleManBard *bard = &gSaveBlock1.mauvilleMan.bard; + + bard->id = MAUVILLE_MAN_BARD; + bard->hasChangedSong = FALSE; + for (i = 0; i < 6; i++) + bard->songLyrics[i] = sDefaultBardSongLyrics[i]; +} + +static void SetupHipster(void) +{ + struct MauvilleManHipster *hipster = &gSaveBlock1.mauvilleMan.hipster; + + hipster->id = MAUVILLE_MAN_HIPSTER; + hipster->alreadySpoken = FALSE; +} + +static void SetupStoryteller(void) +{ + StorytellerSetup(); +} + +static void SetupGiddy(void) +{ + struct MauvilleManGiddy *giddy = &gSaveBlock1.mauvilleMan.giddy; + + giddy->id = MAUVILLE_MAN_GIDDY; + giddy->taleCounter = 0; +} + +static void SetupTrader(void) +{ + TraderSetup(); +} + +void SetupMauvilleOldMan(void) +{ + u16 trainerId = (gSaveBlock2.playerTrainerId[1] << 8) | gSaveBlock2.playerTrainerId[0]; + + // Determine man based on the last digit of the player's trainer ID. + switch ((trainerId % 10) / 2) + { + case MAUVILLE_MAN_BARD: + SetupBard(); + break; + case MAUVILLE_MAN_HIPSTER: + SetupHipster(); + break; + case MAUVILLE_MAN_TRADER: + SetupTrader(); + break; + case MAUVILLE_MAN_STORYTELLER: + SetupStoryteller(); + break; + case MAUVILLE_MAN_GIDDY: + SetupGiddy(); + break; + } + sub_80F83D0(); +} + +static u8 GetCurrentMauvilleOldMan(void) +{ + struct MauvilleManCommon *common = &gSaveBlock1.mauvilleMan.common; + + return common->id; +} + +void ScrSpecial_GetCurrentMauvilleMan(void) +{ + gScriptResult = GetCurrentMauvilleOldMan(); +} + +void ScrSpecial_HasBardSongBeenChanged(void) +{ + u16 *scriptResult = &gScriptResult; // why?? + struct MauvilleManBard *bard = &gSaveBlock1.mauvilleMan.bard; + + *scriptResult = bard->hasChangedSong; +} + +void ScrSpecial_SaveBardSongLyrics(void) +{ + u16 i; + struct MauvilleManBard *bard = &gSaveBlock1.mauvilleMan.bard; + + StringCopy(bard->playerName, gSaveBlock2.playerName); + + for (i = 0; i < 4; i++) + bard->playerTrainerId[i] = gSaveBlock2.playerTrainerId[i]; + + for (i = 0; i < 6; i++) + bard->songLyrics[i] = bard->temporaryLyrics[i]; + + bard->hasChangedSong = TRUE; +} + +// Copies lyrics into gStringVar4 +void PrepareSongText(void) +{ + struct MauvilleManBard *bard = &gSaveBlock1.mauvilleMan.bard; + u16 specialVar = gSpecialVar_0x8004; // It's a bit odd to use this temp variable, but it seems needed to match. + u16 *lyrics; + u16 lineNum; + u8 *wordEnd; + u8 *str; + + lyrics = bard->temporaryLyrics; + if (specialVar == 0) + lyrics = bard->songLyrics; + wordEnd = gStringVar4; + str = wordEnd; + // Put three words on each line + for (lineNum = 0; lineNum < 2; lineNum++) + { + wordEnd = EasyChat_GetWordText(wordEnd, *(lyrics++)); + while (wordEnd != str) + { + if (*str == CHAR_SPACE) + *str = CHAR_SONG_WORD_SEPARATOR; + str++; + } + + str++; + *(wordEnd++) = CHAR_SPACE; + + wordEnd = EasyChat_GetWordText(wordEnd, *(lyrics++)); + while (wordEnd != str) + { + if (*str == CHAR_SPACE) + *str = CHAR_SONG_WORD_SEPARATOR; + str++; + } + + str++; + *(wordEnd++) = CHAR_NEWLINE; + + wordEnd = EasyChat_GetWordText(wordEnd, *(lyrics++)); + while (wordEnd != str) + { + if (*str == CHAR_SPACE) + *str = CHAR_SONG_WORD_SEPARATOR; + str++; + } + + if (lineNum == 0) + { + *(wordEnd++) = EXT_CTRL_CODE_BEGIN; + *(wordEnd++) = 15; + } + } +} + +void ScrSpecial_PlayBardSong(void) +{ + StartBardSong(gSpecialVar_0x8004); + MenuDisplayMessageBox(); + ScriptContext1_Stop(); +} + +void ScrSpecial_GetHipsterSpokenFlag(void) +{ + u16 *scriptResult = &gScriptResult; // again?? + struct MauvilleManHipster *hipster = &gSaveBlock1.mauvilleMan.hipster; + + *scriptResult = hipster->alreadySpoken; +} + +void ScrSpecial_SetHipsterSpokenFlag(void) +{ + struct MauvilleManHipster *hipster = &gSaveBlock1.mauvilleMan.hipster; + + hipster->alreadySpoken = TRUE; +} + +void ScrSpecial_HipsterTeachWord(void) +{ + u16 var = sub_80EB8EC(); + + if (var == 0xFFFF) + { + gScriptResult = FALSE; + } + else + { + EasyChat_GetWordText(gStringVar1, var); + gScriptResult = TRUE; + } +} + +void ScrSpecial_GiddyShouldTellAnotherTale(void) +{ + struct MauvilleManGiddy *giddy = &gSaveBlock1.mauvilleMan.giddy; + + if (giddy->taleCounter == 10) + { + gScriptResult = FALSE; + giddy->taleCounter = 0; + } + else + { + gScriptResult = TRUE; + } +} + +void ScrSpecial_GenerateGiddyLine(void) +{ + struct MauvilleManGiddy *giddy = &gSaveBlock1.mauvilleMan.giddy; + + if (giddy->taleCounter == 0) + sub_80F7DC0(); + + if (giddy->randomWords[giddy->taleCounter] != 0xFFFF) // is not the last element of the array? + { + u8 *stringPtr; + u32 adjective = Random(); + + adjective %= 8; + stringPtr = EasyChat_GetWordText(gStringVar4, giddy->randomWords[giddy->taleCounter]); + stringPtr = StringCopy(stringPtr, gOtherText_Is); + stringPtr = StringCopy(stringPtr, sGiddyAdjectives[adjective]); + StringCopy(stringPtr, gOtherText_DontYouAgree); + } + else + { + StringCopy(gStringVar4, sGiddyQuestions[giddy->questionList[giddy->questionNum++]]); + } + + if (!(Random() % 10)) + giddy->taleCounter = 10; + else + giddy->taleCounter++; + + gScriptResult = TRUE; +} + +#ifdef NONMATCHING +static void sub_80F7DC0(void) +{ + u16 arr[][2] = + { + { 0x0, 0}, + { 0xC, 0}, + { 0xD, 0}, + {0x12, 0}, + {0x13, 0}, + {0x15, 0}, + }; + u16 i; + u16 r10; + u16 r7; + + for (i = 0; i < 8; i++) + { + struct MauvilleManGiddy *giddy = &gSaveBlock1.mauvilleMan.giddy; + + //gSaveBlock1.mauvilleMan.giddy.questionList[i] = i; + giddy->questionList[i] = i; + } + + // Scramble questions + for (i = 0; i < 8; i++) + { + struct MauvilleManGiddy *giddy = &gSaveBlock1.mauvilleMan.giddy; + + /* + u16 r1 = Random() % (i + 1); + u8 r7 = gSaveBlock1.mauvilleMan.giddy.questionList[i]; + gSaveBlock1.mauvilleMan.giddy.questionList[i] = gSaveBlock1.mauvilleMan.giddy.questionList[r1]; + gSaveBlock1.mauvilleMan.giddy.questionList[r1] = r7; + */ + u16 r1 = Random() % (i + 1); + u8 r7 = giddy->questionList[i]; + giddy->questionList[i] = giddy->questionList[r1]; + giddy->questionList[r1] = r7; + } + + r10 = 0; + for (i = 0; i < 6; i++) + { + arr[i][1] = sub_80EAE88(arr[i][0]); + r10 += arr[i][1]; + } + + { + struct MauvilleManGiddy *giddy = &gSaveBlock1.mauvilleMan.giddy; + giddy->questionNum = 0; + } + //gSaveBlock1.mauvilleMan.giddy.questionNum = 0; + + r7 = 0; + for (i = 0; i < 10; i++) + { + struct MauvilleManGiddy *giddy = &gSaveBlock1.mauvilleMan.giddy; + + u16 var = Random() % 10; + if (var < 3 && r7 < 8) + { + //gSaveBlock1.mauvilleMan.giddy.randomWords[i] = 0xFFFF; + giddy->randomWords[i] = 0xFFFF; + r7++; + } + //_080F7E90 + else + { + s16 r2 = Random() % r10; + + u16 r1 = 0; + + while (i < 6) // comparing the wrong variable + { + r2 = arr[r1][1] - r2; + if (r2 <= 0) + break; + r1++; + } + + if (r1 == 6) + r1 = 0; + //gSaveBlock1.mauvilleMan.giddy.randomWords[i] = sub_80EB784(arr[r1][0]); + giddy->randomWords[i] = sub_80EB784(arr[r1][0]); + } + } +} +#else + +static const u16 gUnknown_083E53C8[][2] = +{ + { 0x0, 0}, + { 0xC, 0}, + { 0xD, 0}, + {0x12, 0}, + {0x13, 0}, + {0x15, 0}, +}; + +__attribute__((naked)) +static void sub_80F7DC0(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x18\n\ + ldr r1, _080F7E84 @ =gUnknown_083E53C8\n\ + mov r0, sp\n\ + movs r2, 0x18\n\ + bl memcpy\n\ + movs r5, 0\n\ + movs r0, 0x2\n\ + add r0, sp\n\ + mov r8, r0\n\ + ldr r1, _080F7E88 @ =gSaveBlock1 + 0x2D94\n\ + adds r1, 0x18\n\ + adds r3, r1, 0\n\ +_080F7DE4:\n\ + adds r0, r3, r5\n\ + strb r5, [r0]\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, 0x7\n\ + bls _080F7DE4\n\ + movs r5, 0\n\ + ldr r2, _080F7E88 @ =gSaveBlock1 + 0x2D94\n\ + adds r2, 0x4\n\ + mov r9, r2\n\ + adds r6, r1, 0\n\ +_080F7DFC:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + adds r4, r5, 0x1\n\ + adds r1, r4, 0\n\ + bl __modsi3\n\ + lsls r0, 16\n\ + lsrs r1, r0, 16\n\ + adds r2, r6, r5\n\ + ldrb r7, [r2]\n\ + adds r1, r6, r1\n\ + ldrb r0, [r1]\n\ + strb r0, [r2]\n\ + strb r7, [r1]\n\ + lsls r4, 16\n\ + lsrs r5, r4, 16\n\ + cmp r5, 0x7\n\ + bls _080F7DFC\n\ + movs r3, 0\n\ + mov r10, r3\n\ + movs r5, 0\n\ +_080F7E2A:\n\ + lsls r4, r5, 2\n\ + mov r1, sp\n\ + adds r0, r1, r4\n\ + ldrb r0, [r0]\n\ + bl sub_80EAE88\n\ + add r4, r8\n\ + strh r0, [r4]\n\ + add r0, r10\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + mov r10, r0\n\ + adds r0, r5, 0x1\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, 0x5\n\ + bls _080F7E2A\n\ + movs r0, 0\n\ + ldr r2, _080F7E88 @ =gSaveBlock1 + 0x2D94\n\ + strb r0, [r2, 0x2]\n\ + movs r7, 0\n\ + movs r5, 0\n\ +_080F7E56:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + movs r1, 0xA\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + lsrs r1, r0, 16\n\ + cmp r1, 0x2\n\ + bhi _080F7E90\n\ + cmp r7, 0x7\n\ + bhi _080F7E90\n\ + lsls r0, r5, 1\n\ + add r0, r9\n\ + ldr r1, _080F7E8C @ =0x0000ffff\n\ + strh r1, [r0]\n\ + adds r0, r7, 0x1\n\ + lsls r0, 16\n\ + lsrs r7, r0, 16\n\ + adds r4, r5, 0x1\n\ + b _080F7EE2\n\ + .align 2, 0\n\ +_080F7E84: .4byte gUnknown_083E53C8\n\ +_080F7E88: .4byte gSaveBlock1 + 0x2D94\n\ +_080F7E8C: .4byte 0x0000ffff\n\ +_080F7E90:\n\ + bl Random\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + mov r1, r10\n\ + bl __umodsi3\n\ + lsls r0, 16\n\ + lsrs r2, r0, 16\n\ + movs r1, 0\n\ + adds r4, r5, 0x1\n\ + lsls r6, r5, 1\n\ + cmp r5, 0x5\n\ + bhi _080F7ECC\n\ + mov r3, r8\n\ + ldrh r0, [r3]\n\ + b _080F7EC2\n\ +_080F7EB2:\n\ + adds r0, r1, 0x1\n\ + lsls r0, 16\n\ + lsrs r1, r0, 16\n\ + cmp r5, 0x5\n\ + bhi _080F7ECC\n\ + lsls r0, r1, 2\n\ + adds r0, r3, r0\n\ + ldrh r0, [r0]\n\ +_080F7EC2:\n\ + subs r0, r2, r0\n\ + lsls r0, 16\n\ + lsrs r2, r0, 16\n\ + cmp r0, 0\n\ + bgt _080F7EB2\n\ +_080F7ECC:\n\ + cmp r1, 0x6\n\ + bne _080F7ED2\n\ + movs r1, 0\n\ +_080F7ED2:\n\ + lsls r0, r1, 2\n\ + add r0, sp\n\ + ldrh r0, [r0]\n\ + bl sub_80EB784\n\ + mov r2, r9\n\ + adds r1, r2, r6\n\ + strh r0, [r1]\n\ +_080F7EE2:\n\ + lsls r0, r4, 16\n\ + lsrs r5, r0, 16\n\ + cmp r5, 0x9\n\ + bls _080F7E56\n\ + add sp, 0x18\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .syntax divided\n"); +} +#endif + +static void sub_80F7EFC(void) +{ + struct MauvilleManBard *bard = &gSaveBlock1.mauvilleMan.bard; + + bard->hasChangedSong = FALSE; +} + +static void sub_80F7F0C(void) +{ + struct MauvilleManHipster *hipster = &gSaveBlock1.mauvilleMan.hipster; + + hipster->alreadySpoken = FALSE; +} + +static void sub_80F7F18(void) +{ + sub_8109A20(); +} + +static void sub_80F7F24(void) +{ + sub_80F8428(); +} + +void sub_80F7F30(void) +{ + switch (GetCurrentMauvilleOldMan()) + { + case MAUVILLE_MAN_BARD: + sub_80F7EFC(); + break; + case MAUVILLE_MAN_HIPSTER: + sub_80F7F0C(); + break; + case MAUVILLE_MAN_STORYTELLER: + sub_80F7F24(); + break; + case MAUVILLE_MAN_TRADER: + sub_80F7F18(); + break; + case MAUVILLE_MAN_GIDDY: + break; + } + sub_80F83D0(); +} + +#define tState data[0] +#define tCharIndex data[3] +#define tCurrWord data[4] +#define tUseTemporaryLyrics data[5] + +static void StartBardSong(bool8 useTemporaryLyrics) +{ + u8 taskId = CreateTask(Task_BardSong, 0x50); + + gTasks[taskId].tUseTemporaryLyrics = useTemporaryLyrics; +} + +static void BardSing(struct Task *task, struct BardSong *song) +{ + switch (task->tState) + { + case 0: // Initialize song + { + struct MauvilleManBard *bard = &gSaveBlock1.mauvilleMan.bard; + u16 *lyrics; + s32 i; + + // Copy lyrics + if (gSpecialVar_0x8004 == 0) + lyrics = bard->songLyrics; + else + lyrics = bard->temporaryLyrics; + for (i = 0; i < 6; i++) + song->lyrics[i] = lyrics[i]; + + // Clear phonemes + for (i = 0; i < 6; i++) + { + song->phonemes[i].sound = 0xFFFF; + song->phonemes[i].length = 0; + song->phonemes[i].pitch = 0; + song->phonemes[i].volume = 0; + } + song->currWord = 0; + song->currPhoneme = 0; + song->var04 = 0; + } + break; + case 1: // Wait for BGM to end + break; + case 2: // Initialize word + { + u16 word = song->lyrics[song->currWord]; + const struct BardSound *sounds = GetWordSounds(EC_GROUP(word), EC_INDEX(word)); + + song->var04 = 0; + GetWordPhonemes(song, sounds, MACRO1(word)); + } + break; + case 3: + case 4: + { + struct BardPhoneme *phoneme = &song->phonemes[song->currPhoneme]; + + switch (song->state) + { + case 0: + if (song->phonemeTimer == 0) // Timer has expired. Move to next phoneme + { + if (song->currPhoneme == 6 || phoneme->sound == 0xFF) + { + song->state = 0xFE; + break; + } + song->phonemeTimer = phoneme->length; + if (phoneme->sound <= 50) + { + u16 num = phoneme->sound / 3; + + m4aSongNumStart(249 + num * 3); + } + song->state = 1; + } + else + { + if (song->voiceInflection > 10) + song->volume -= 2; + if (song->voiceInflection & 1) + song->pitch += 64; + else + song->pitch -= 64; + m4aMPlayVolumeControl(&gMPlay_SE2, 0xFFFF, song->volume); + m4aMPlayPitchControl(&gMPlay_SE2, 0xFFFF, song->pitch); + song->voiceInflection++; + } + song->phonemeTimer--; + break; + case 1: + song->currPhoneme++; + song->state = 0; + if (phoneme->sound <= 50) + { + song->volume = 0x100 + phoneme->volume * 16; + m4aMPlayVolumeControl(&gMPlay_SE2, 0xFFFF, song->volume); + song->pitch = 0x200 + phoneme->pitch; + m4aMPlayPitchControl(&gMPlay_SE2, 0xFFFF, song->pitch); + } + break; + case 0xFE: + m4aMPlayStop(&gMPlay_SE2); + song->state = 0xFF; + break; + } + } + break; + case 5: + break; + } +} + +static void Task_BardSong(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; // r5 + + BardSing(task, &gUnknown_03005DA0); + switch (task->tState) + { + case 0: // Initialize song + PrepareSongText(); + InitWindowFromConfig(gMenuWindowPtr, &gWindowConfig_81E6CE4); + sub_8002EB0(gMenuWindowPtr, gStringVar4, 2, 4, 15); + task->data[1] = 0; + task->data[2] = 0; + task->tCharIndex = 0; + task->tCurrWord = 0; + FadeOutBGMTemporarily(4); + task->tState = 1; + break; + case 1: // Wait for BGM to end + if (IsBGMPausedOrStopped()) + task->tState = 2; + break; + case 2: // Initialize word + { + struct MauvilleManBard *bard = &gSaveBlock1.mauvilleMan.bard; + u8 *str = gStringVar4 + task->tCharIndex; + u16 wordLen = 0; + // Can't get it to match without hacking + u32 temp; + register s16 zero asm("r1"); + + while (*str != CHAR_SPACE + && *str != CHAR_NEWLINE + && *str != EXT_CTRL_CODE_BEGIN + && *str != EOS) + { + str++; + wordLen++; + } + if (!task->tUseTemporaryLyrics) + gUnknown_020388BC = MACRO1(bard->songLyrics[task->tCurrWord]); + else + gUnknown_020388BC = MACRO1(bard->temporaryLyrics[task->tCurrWord]); + temp = gUnknown_03005DA0.var04 / wordLen; + zero = 0; + gUnknown_03005DA0.var04 = temp; + if (gUnknown_03005DA0.var04 <= 0) + gUnknown_03005DA0.var04 = 1; + task->tCurrWord++; + if (task->data[2] == 0) + task->tState = 3; + else + task->tState = 5; + task->data[1] = zero; + } + break; + case 5: + if (task->data[2] == 0) + task->tState = 3; + else + task->data[2]--; + break; + case 3: + if (gStringVar4[task->tCharIndex] == EOS) + { + FadeInNewBGM(BGM_POKECEN, 6); + m4aMPlayFadeOutTemporarily(&gMPlay_SE2, 2); + EnableBothScriptContexts(); + DestroyTask(taskId); + } + else if (gStringVar4[task->tCharIndex] == CHAR_SPACE) + { + sub_8003418(gMenuWindowPtr); + task->tCharIndex++; + task->tState = 2; + task->data[2] = 0; + } + else if (gStringVar4[task->tCharIndex] == CHAR_NEWLINE) + { + task->tCharIndex++; + task->tState = 2; + task->data[2] = 0; + } + else if (gStringVar4[task->tCharIndex] == EXT_CTRL_CODE_BEGIN) + { + task->tCharIndex += 2; // skip over control codes + task->tState = 2; + task->data[2] = 8; + } + else if (gStringVar4[task->tCharIndex] == CHAR_SONG_WORD_SEPARATOR) + { + gStringVar4[task->tCharIndex] = CHAR_SPACE; // restore it back to a space + sub_8003418(gMenuWindowPtr); + task->tCharIndex++; + task->data[2] = 0; + } + else + { + switch (task->data[1]) + { + case 0: + sub_8003418(gMenuWindowPtr); + task->data[1]++; + break; + case 1: + task->data[1]++; + break; + case 2: + task->tCharIndex++; + task->data[1] = 0; + task->data[2] = gUnknown_03005DA0.var04; + task->tState = 4; + break; + } + } + break; + case 4: + task->data[2]--; + if (task->data[2] == 0) + task->tState = 3; + break; + } +} + +void sub_80F83D0(void) +{ + VarSet(0x4010, 0x45 + GetCurrentMauvilleOldMan()); +} + +struct Story +{ + u8 stat; + u8 minVal; + const u8 *title; + const u8 *action; + const u8 *fullText; +}; + +static const struct Story sStorytellerStories[] = +{ + {0x32, 1, gTextStoryteller_Story1Title, gTextStoryteller_Story1Action, gTextStoryteller_Story1Text}, + {0x02, 1, gTextStoryteller_Story2Title, gTextStoryteller_Story2Action, gTextStoryteller_Story2Text}, + {0x03, 1, gTextStoryteller_Story3Title, gTextStoryteller_Story3Action, gTextStoryteller_Story3Text}, + {0x04, 1, gTextStoryteller_Story4Title, gTextStoryteller_Story4Action, gTextStoryteller_Story4Text}, + {0x06, 1, gTextStoryteller_Story5Title, gTextStoryteller_Story5Action, gTextStoryteller_Story5Text}, + {0x09, 1, gTextStoryteller_Story6Title, gTextStoryteller_Story6Action, gTextStoryteller_Story6Text}, + {0x0B, 1, gTextStoryteller_Story7Title, gTextStoryteller_Story7Action, gTextStoryteller_Story7Text}, + {0x0C, 1, gTextStoryteller_Story8Title, gTextStoryteller_Story8Action, gTextStoryteller_Story8Text}, + {0x0D, 1, gTextStoryteller_Story9Title, gTextStoryteller_Story9Action, gTextStoryteller_Story9Text}, + {0x0E, 1, gTextStoryteller_Story10Title, gTextStoryteller_Story10Action, gTextStoryteller_Story10Text}, + {0x0F, 1, gTextStoryteller_Story11Title, gTextStoryteller_Story11Action, gTextStoryteller_Story11Text}, + {0x10, 1, gTextStoryteller_Story12Title, gTextStoryteller_Story12Action, gTextStoryteller_Story12Text}, + {0x11, 1, gTextStoryteller_Story13Title, gTextStoryteller_Story13Action, gTextStoryteller_Story13Text}, + {0x12, 1, gTextStoryteller_Story14Title, gTextStoryteller_Story14Action, gTextStoryteller_Story14Text}, + {0x13, 1, gTextStoryteller_Story15Title, gTextStoryteller_Story15Action, gTextStoryteller_Story15Text}, + {0x14, 1, gTextStoryteller_Story16Title, gTextStoryteller_Story16Action, gTextStoryteller_Story16Text}, + {0x1A, 1, gTextStoryteller_Story17Title, gTextStoryteller_Story17Action, gTextStoryteller_Story17Text}, + {0x1B, 1, gTextStoryteller_Story18Title, gTextStoryteller_Story18Action, gTextStoryteller_Story18Text}, + {0x1C, 1, gTextStoryteller_Story19Title, gTextStoryteller_Story19Action, gTextStoryteller_Story19Text}, + {0x1D, 2, gTextStoryteller_Story20Title, gTextStoryteller_Story20Action, gTextStoryteller_Story20Text}, + {0x1E, 1, gTextStoryteller_Story21Title, gTextStoryteller_Story21Action, gTextStoryteller_Story21Text}, + {0x21, 1, gTextStoryteller_Story22Title, gTextStoryteller_Story22Action, gTextStoryteller_Story22Text}, + {0x24, 1, gTextStoryteller_Story23Title, gTextStoryteller_Story23Action, gTextStoryteller_Story23Text}, + {0x25, 1, gTextStoryteller_Story24Title, gTextStoryteller_Story24Action, gTextStoryteller_Story24Text}, + {0x26, 1, gTextStoryteller_Story25Title, gTextStoryteller_Story25Action, gTextStoryteller_Story25Text}, + {0x27, 1, gTextStoryteller_Story26Title, gTextStoryteller_Story26Action, gTextStoryteller_Story26Text}, + {0x28, 1, gTextStoryteller_Story27Title, gTextStoryteller_Story27Action, gTextStoryteller_Story27Text}, + {0x29, 1, gTextStoryteller_Story28Title, gTextStoryteller_Story28Action, gTextStoryteller_Story28Text}, + {0x2A, 1, gTextStoryteller_Story29Title, gTextStoryteller_Story29Action, gTextStoryteller_Story29Text}, + {0x2B, 1, gTextStoryteller_Story30Title, gTextStoryteller_Story30Action, gTextStoryteller_Story30Text}, + {0x2C, 1, gTextStoryteller_Story31Title, gTextStoryteller_Story31Action, gTextStoryteller_Story31Text}, + {0x2D, 1, gTextStoryteller_Story32Title, gTextStoryteller_Story32Action, gTextStoryteller_Story32Text}, + {0x2E, 1, gTextStoryteller_Story33Title, gTextStoryteller_Story33Action, gTextStoryteller_Story33Text}, + {0x2F, 1, gTextStoryteller_Story34Title, gTextStoryteller_Story34Action, gTextStoryteller_Story34Text}, + {0x30, 1, gTextStoryteller_Story35Title, gTextStoryteller_Story35Action, gTextStoryteller_Story35Text}, + {0x31, 1, gTextStoryteller_Story36Title, gTextStoryteller_Story36Action, gTextStoryteller_Story36Text}, +}; + +static void StorytellerSetup(void) +{ + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + s32 i; + + storyteller->id = MAUVILLE_MAN_STORYTELLER; + storyteller->alreadyRecorded = FALSE; + for (i = 0; i < 4; i++) + { + storyteller->gameStatIDs[i] = 0; + storyteller->trainerNames[0][i] = EOS; // Maybe they meant storyteller->trainerNames[i][0] instead? + } +} + +static void sub_80F8428(void) +{ + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + + storyteller->id = MAUVILLE_MAN_STORYTELLER; + storyteller->alreadyRecorded = FALSE; +} + +static u32 StorytellerGetGameStat(u8 stat) +{ + if (stat == NUM_GAME_STATS) + stat = 0; + return GetGameStat(stat); +} + +static const struct Story *GetStoryByStat(u32 stat) +{ + s32 i; + + for (i = 0; i < 36; i++) + { + if (sStorytellerStories[i].stat == stat) + return &sStorytellerStories[i]; + } + return &sStorytellerStories[35]; +} + +static const u8 *GetStoryTitleByStat(u32 stat) +{ + return GetStoryByStat(stat)->title; +} + +static const u8 *GetStoryTextByStat(u32 stat) +{ + return GetStoryByStat(stat)->fullText; +} + +static const u8 *GetStoryActionByStat(u32 stat) +{ + return GetStoryByStat(stat)->action; +} + +static u8 GetFreeStorySlot(void) +{ + u8 i; + + for (i = 0; i < 4; i++) + { + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + + if (storyteller->gameStatIDs[i] == 0) + break; + } + return i; +} + +static u32 StorytellerGetRecordedTrainerStat(u32 trainer) +{ + u8 *ptr = gSaveBlock1.mauvilleMan.storyteller.statValues[trainer]; + + return ptr[0] | (ptr[1] << 8) | (ptr[2] << 16) | (ptr[3] << 24); +} + +static void StorytellerSetRecordedTrainerStat(u32 trainer, u32 val) +{ + u8 *ptr = gSaveBlock1.mauvilleMan.storyteller.statValues[trainer]; + + ptr[0] = val; + ptr[1] = val >> 8; + ptr[2] = val >> 16; + ptr[3] = val >> 24; +} + +static bool32 HasTrainerStatIncreased(u32 trainer) +{ + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + + if (StorytellerGetGameStat(storyteller->gameStatIDs[trainer]) > StorytellerGetRecordedTrainerStat(trainer)) + return TRUE; + else + return FALSE; +} + +static void GetStoryByStattellerPlayerName(u32 player, void *dst) +{ + u8 *name = gSaveBlock1.mauvilleMan.storyteller.trainerNames[player]; + + memset(dst, EOS, 8); + memcpy(dst, name, 7); +} + +static void StorytellerSetPlayerName(u32 player, const u8 *src) +{ + u8 *name = gSaveBlock1.mauvilleMan.storyteller.trainerNames[player]; + u8 len = StringLength(src); + + memset(name, EOS, 7); + StringCopyN(name, src, len); +} + +static void StorytellerRecordNewStat(u32 player, u32 stat) +{ + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + + storyteller->gameStatIDs[player] = stat; + StorytellerSetPlayerName(player, gSaveBlock2.playerName); + StorytellerSetRecordedTrainerStat(player, StorytellerGetGameStat(stat)); + ConvertIntToDecimalStringN(gStringVar1, StorytellerGetGameStat(stat), 0, 10); + StringCopy(gStringVar2, GetStoryActionByStat(stat)); +} + +static void ScrambleStatList(u8 *arr, s32 count) +{ + s32 i; + + for (i = 0; i < count; i++) + arr[i] = i; + for (i = 0; i < count; i++) + { + u32 a = Random() % count; + u32 b = Random() % count; + u8 temp = arr[a]; + arr[a] = arr[b]; + arr[b] = temp; + } +} + +// What purpose does this struct even serve? Only the length field is used. +static const struct {u32 length; struct MauvilleManStoryteller *unused1; u32 unused2;} sStorytellerStuff = +{ + 36, + &gSaveBlock1.mauvilleMan.storyteller, // unused + 12, // unused +}; + +static bool8 StorytellerInitializeRandomStat(void) +{ + u8 arr[sStorytellerStuff.length]; + s32 i; + s32 j; + + ScrambleStatList(arr, 36); + for (i = 0; i < 36; i++) + { + u8 stat = sStorytellerStories[arr[i]].stat; + u8 minVal = sStorytellerStories[arr[i]].minVal; + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + + for (j = 0; j < 4; j++) + { + if (gSaveBlock1.mauvilleMan.storyteller.gameStatIDs[j] == stat) + break; + } + if (j == 4 && StorytellerGetGameStat(stat) >= minVal) + { + storyteller->alreadyRecorded = TRUE; + StorytellerRecordNewStat(GetFreeStorySlot(), stat); + return TRUE; + } + } + return FALSE; +} + +static void StorytellerDisplayStory(u32 player) +{ + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + u8 stat = storyteller->gameStatIDs[player]; + + ConvertIntToDecimalStringN(gStringVar1, StorytellerGetRecordedTrainerStat(player), 0, 10); + StringCopy(gStringVar2, GetStoryActionByStat(stat)); + GetStoryByStattellerPlayerName(player, gStringVar3); + ShowFieldMessage(GetStoryTextByStat(stat)); +} + +static void PrintStoryList(void) +{ + s32 i; + + MenuDrawTextWindow(0, 0, 25, 4 + GetFreeStorySlot() * 2); + for (i = 0; i < 4; i++) + { + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + u8 stat = storyteller->gameStatIDs[i]; + + if (stat == 0) + break; + MenuPrint(GetStoryTitleByStat(stat), 1, 2 + i * 2); + } + MenuPrint(gPCText_Cancel, 1, 2 + i * 2); +} + +static u8 gUnknown_03000748; + +static void Task_StoryListMenu(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + s32 selection; + + switch (task->data[0]) + { + case 0: + PrintStoryList(); + InitMenu(0, 1, 2, GetFreeStorySlot() + 1, 0, 24); + task->data[0]++; + break; + case 1: + selection = ProcessMenuInput(); + if (selection == -2) + break; + if (selection == -1 || selection == GetFreeStorySlot()) + { + gScriptResult = 0; + } + else + { + gScriptResult = 1; + gUnknown_03000748 = selection; + } + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 25, 12); + DestroyTask(taskId); + EnableBothScriptContexts(); + break; + } +} + +// Sets gScriptResult to TRUE if player selected a story +void ScrSpecial_StorytellerStoryListMenu(void) +{ + CreateTask(Task_StoryListMenu, 0x50); +} + +void ScrSpecial_StorytellerDisplayStory(void) +{ + StorytellerDisplayStory(gUnknown_03000748); +} + +u8 ScrSpecial_StorytellerGetFreeStorySlot(void) +{ + return GetFreeStorySlot(); +} + +// Returns TRUE if stat has increased +bool8 ScrSpecial_StorytellerUpdateStat(void) +{ + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + u8 r4 = storyteller->gameStatIDs[gUnknown_03000748]; + + if (HasTrainerStatIncreased(gUnknown_03000748) == TRUE) + { + StorytellerRecordNewStat(gUnknown_03000748, r4); + return TRUE; + } + return FALSE; +} + +bool8 ScrSpecial_HasStorytellerAlreadyRecorded(void) +{ + struct MauvilleManStoryteller *storyteller = &gSaveBlock1.mauvilleMan.storyteller; + + if (storyteller->alreadyRecorded == FALSE) + return FALSE; + else + return TRUE; +} + +bool8 ScrSpecial_StorytellerInitializeRandomStat(void) +{ + return StorytellerInitializeRandomStat(); +} diff --git a/src/field/menu_helpers.c b/src/field/menu_helpers.c new file mode 100644 index 000000000..14e823355 --- /dev/null +++ b/src/field/menu_helpers.c @@ -0,0 +1,572 @@ +#include "global.h" +#include "item_menu.h" +#include "items.h" +#include "link.h" +#include "mail_data.h" +#include "main.h" +#include "map_constants.h" +#include "menu.h" +#include "menu_helpers.h" +#include "overworld.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "task.h" +#include "text.h" + +#define SCROLL_INDICATOR_PAL_TAG 6 + +static void sub_80F9834(struct Sprite *sprite); + +static EWRAM_DATA u8 gUnknown_020388C0[4] = {0}; +static EWRAM_DATA struct YesNoFuncTable gUnknown_020388C4 = {0}; + +static TaskFunc gUnknown_0300074C; + +static const u8 gSpriteImage_83E5808[] = INCBIN_U8("graphics/unknown_sprites/83E59A0/0.4bpp"); + +static const u8 gSpriteImage_83E5848[] = INCBIN_U8("graphics/unknown_sprites/83E59A0/1.4bpp"); + +static const u8 gSpriteImage_83E5888[] = INCBIN_U8("graphics/unknown_sprites/83E59B0/0.4bpp"); + +static const u8 gSpriteImage_83E58C8[] = INCBIN_U8("graphics/unknown_sprites/83E59B0/1.4bpp"); + +static const u8 gSpriteImage_83E5908[] = INCBIN_U8("graphics/unknown_sprites/83E59C0/0.4bpp"); + +static const u8 gSpriteImage_83E5928[] = INCBIN_U8("graphics/unknown_sprites/83E59C0/1.4bpp"); + +static const u16 Palette_3E5948[] = INCBIN_U16("graphics/interface/83E5948.gbapal"); + +static const struct SpritePalette gUnknown_083E5968 = { Palette_3E5948, SCROLL_INDICATOR_PAL_TAG }; + +static const struct OamData gOamData_83E5970 = +{ + .tileNum = 1 +}; + +static const struct OamData gOamData_83E5978 = +{ + .shape = ST_OAM_H_RECTANGLE, + .tileNum = 1 +}; + +static const struct OamData gOamData_83E5980 = +{ + .shape = ST_OAM_V_RECTANGLE, + .tileNum = 1 +}; + +static const union AnimCmd gSpriteAnim_83E5988[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd gSpriteAnim_83E5990[] = +{ + ANIMCMD_FRAME(1, 0), + ANIMCMD_END, +}; + +static const union AnimCmd *const gSpriteAnimTable_83E5998[] = +{ + gSpriteAnim_83E5988, + gSpriteAnim_83E5990, +}; + +static const struct SpriteFrameImage gSpriteImageTable_83E59A0[] = +{ + { gSpriteImage_83E5808, 0x40 }, + { gSpriteImage_83E5848, 0x40 }, +}; + +static const struct SpriteFrameImage gSpriteImageTable_83E59B0[] = +{ + { gSpriteImage_83E5888, 0x40 }, + { gSpriteImage_83E58C8, 0x40 }, +}; + +static const struct SpriteFrameImage gSpriteImageTable_83E59C0[] = +{ + { gSpriteImage_83E5908, 0x20 }, + { gSpriteImage_83E5928, 0x20 }, +}; + +static const struct SpriteTemplate gSpriteTemplate_83E59D0 = +{ + .tileTag = 0xFFFF, + .paletteTag = SCROLL_INDICATOR_PAL_TAG, + .oam = &gOamData_83E5978, + .anims = gSpriteAnimTable_83E5998, + .images = gSpriteImageTable_83E59A0, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80F9834, +}; + +static const struct SpriteTemplate gSpriteTemplate_83E59E8 = +{ + .tileTag = 0xFFFF, + .paletteTag = SCROLL_INDICATOR_PAL_TAG, + .oam = &gOamData_83E5980, + .anims = gSpriteAnimTable_83E5998, + .images = gSpriteImageTable_83E59B0, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_80F9834, +}; + +static const struct SpriteTemplate gSpriteTemplate_83E5A00 = +{ + .tileTag = 0xFFFF, + .paletteTag = SCROLL_INDICATOR_PAL_TAG, + .oam = &gOamData_83E5970, + .anims = gSpriteAnimTable_83E5998, + .images = gSpriteImageTable_83E59C0, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +void sub_80F9020(void) +{ + memset(&gBGTilemapBuffers[1], 0, 0x800); + memset(&gBGTilemapBuffers[2], 0, 0x800); + memset(&gBGTilemapBuffers[3], 0, 0x800); +} + +// display message box, fill box with tile if tile is not zero, print string +static void PrintMessage(const u8 *str, u16 tile) +{ + MenuDisplayMessageBox(); + if (tile) + { + sub_80A3FA0(&gBGTilemapBuffers[1][0], 2, 15, 26, 4, tile); + } + MenuPrintMessageDefaultCoords(str); +} + +static void sub_80F9090(u8 taskId) +{ + if (MenuUpdateWindowText() == TRUE) + { + gUnknown_0300074C(taskId); + } +} + +void DisplayItemMessageOnField(u8 taskId, const u8 *str, TaskFunc callback, u16 tile) +{ + PrintMessage(str, tile); + gUnknown_0300074C = callback; + gTasks[taskId].func = sub_80F9090; +} + +static void Task_CallYesOrNoCallback(u8 taskId) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: + PlaySE(SE_SELECT); + gUnknown_020388C4.yesFunc(taskId); + break; + case 1: + case -1: + PlaySE(SE_SELECT); + gUnknown_020388C4.noFunc(taskId); + } +} + +void DoYesNoFuncWithChoice(u8 taskId, const struct YesNoFuncTable *funcTable) +{ + gUnknown_020388C4 = *funcTable; + gTasks[taskId].func = Task_CallYesOrNoCallback; +} + +static void PrintStringWithPalette(const u8 *str, u8 paletteNum, u8 left, u8 top) +{ + u8 paletteStr[] = _("{PALETTE 0}"); + + if (paletteNum != 0xFF) + { + paletteStr[2] = paletteNum; + StringCopy(gStringVar4, paletteStr); + StringAppend(gStringVar4, str); + paletteStr[2] = gMenuWindowPtr->paletteNum; + StringAppend(gStringVar4, paletteStr); + } + else + { + StringCopy(gStringVar4, str); + } + + MenuPrint(gStringVar4, left, top); +} + +// unused +void PrintNumberWithPalette(s32 value, u8 paletteNum, u8 n, u8 mode, u8 left, u8 top) +{ + ConvertIntToDecimalStringN(gStringVar1, value, mode, n); + if (paletteNum != 0xFF) + { + PrintStringWithPalette(gStringVar1, paletteNum, left, top); + } + else + { + MenuPrint(gStringVar1, left, top); + } +} + +// unused +void PrintTriangleCursorWithPalette(u8 left, u8 top, u8 paletteNum) +{ + u8 cursorStr[] = _("▶"); + PrintStringWithPalette(cursorStr, paletteNum, left, top); +} + +u8 sub_80F9284(void) +{ + if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR) + { + if (gMain.newKeys & L_BUTTON) + { + return 1; + } + if (gMain.newKeys & R_BUTTON) + { + return 2; + } + } + + return 0; +} + +u8 sub_80F92BC(void) +{ + if (gSaveBlock2.optionsButtonMode == OPTIONS_BUTTON_MODE_LR) + { + if (gMain.newAndRepeatedKeys & L_BUTTON) + { + return 1; + } + if (gMain.newAndRepeatedKeys & R_BUTTON) + { + return 2; + } + } + + return 0; +} + +bool8 sub_80F92F4(u16 itemId) +{ + if (itemId != ITEM_ENIGMA_BERRY) + { + return TRUE; + } + + if (!(gSaveBlock1.location.mapGroup == MAP_GROUP_TRADE_CENTER && gSaveBlock1.location.mapNum == MAP_ID_TRADE_CENTER)) + { + return TRUE; + } + + return FALSE; +} + +bool8 sub_80F931C(u16 itemId) +{ + if (is_c1_link_related_active() != TRUE) + { + return TRUE; + } + + if (ItemIsMail(itemId) != TRUE) + { + return TRUE; + } + + return FALSE; +} + +bool8 sub_80F9344(void) +{ + if (is_c1_link_related_active() == TRUE || gReceivedRemoteLinkPlayers == 1) + { + return TRUE; + } + + return FALSE; +} + +void sub_80F9368(void) +{ + u8 *addr; + u32 size; + + REG_DISPCNT = 0; + REG_BG3CNT = 0; + REG_BG2CNT = 0; + REG_BG1CNT = 0; + REG_BG0CNT = 0; + REG_BG3HOFS = 0; + REG_BG3VOFS = 0; + REG_BG2HOFS = 0; + REG_BG2VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + + addr = (u8 *)VRAM; + size = 0x18000; + while (1) + { + DmaFill16(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill16(3, 0, addr, size); + break; + } + } + + DmaClear32(3, OAM, OAM_SIZE); + DmaClear16(3, PLTT, PLTT_SIZE); +} + +void sub_80F9438(void) +{ + SetVBlankCallback(NULL); + SetHBlankCallback(NULL); +} + +void sub_80F944C(void) +{ + u8 i; + + for (i = 0; i < 4; i++) + { + gUnknown_020388C0[i] = 0xFF; + } + + FreeSpritePaletteByTag(SCROLL_INDICATOR_PAL_TAG); + LoadSpritePalette(&gUnknown_083E5968); +} + +void sub_80F9480(u8 *data, u8 n) +{ + u8 i; + + for (i = 0; i < n; i++) + { + data[i] = 0xFF; + } +} + +void sub_80F94A4(u8 animNum, u8 *spriteId, s16 x, s16 y) +{ + if (animNum <= 5) + { + if (*spriteId == 0xFF) + { + *spriteId = CreateSprite(&gSpriteTemplate_83E5A00, x, y, 0); + } + animNum -= 4; + StartSpriteAnim(&gSprites[*spriteId], animNum); + } +} + +void sub_80F94F8(u8 *spriteId) +{ + if (*spriteId != 0xFF) + { + DestroySprite(&gSprites[*spriteId]); + *spriteId = 0xFF; + } +} + +void sub_80F9520(u8 *data, u8 n) +{ + u8 i; + + for (i = 0; i < 8; i++) + { + sub_80F94F8(&data[i]); + } +} + +void CreateVerticalScrollIndicators(u8 id, u16 x, u16 y) +{ + if (id >= 4) + { + return; + } + + switch (id) + { + case 0: + if (gUnknown_020388C0[0] == 0xFF) + { + gUnknown_020388C0[0] = CreateSprite(&gSpriteTemplate_83E59D0, x, y, 0); + gSprites[gUnknown_020388C0[0]].data2 = -1; + if (gUnknown_020388C0[1] != 0xFF) + { + gSprites[gUnknown_020388C0[0]].pos2.y = gSprites[gUnknown_020388C0[1]].pos2.y * -1; + gSprites[gUnknown_020388C0[0]].data3 = gSprites[gUnknown_020388C0[1]].data3; + } + else + { + gSprites[gUnknown_020388C0[0]].data3 = 0; + } + } + break; + + case 1: + if (gUnknown_020388C0[1] == 0xFF) + { + gUnknown_020388C0[1] = CreateSprite(&gSpriteTemplate_83E59D0, x, y, 0); + gSprites[gUnknown_020388C0[1]].data2 = 1; + if (gUnknown_020388C0[0] != 0xFF) + { + gSprites[gUnknown_020388C0[1]].pos2.y = gSprites[gUnknown_020388C0[0]].pos2.y * -1; + gSprites[gUnknown_020388C0[1]].data3 = gSprites[gUnknown_020388C0[0]].data3; + } + else + { + gSprites[gUnknown_020388C0[1]].data3 = 0; + } + } + break; + + case 2: + if (gUnknown_020388C0[2] == 0xFF) + { + gUnknown_020388C0[2] = CreateSprite(&gSpriteTemplate_83E59E8, x, y, 0); + gSprites[gUnknown_020388C0[2]].data0 = -1; + if (gUnknown_020388C0[3] != 0xFF) + { + gSprites[gUnknown_020388C0[2]].pos2.x = gSprites[gUnknown_020388C0[3]].pos2.x * -1; + gSprites[gUnknown_020388C0[2]].data1 = gSprites[gUnknown_020388C0[3]].data1; + } + else + { + gSprites[gUnknown_020388C0[2]].data1 = 0; + } + } + break; + + case 3: + if (gUnknown_020388C0[3] == 0xFF) + { + gUnknown_020388C0[3] = CreateSprite(&gSpriteTemplate_83E59E8, x, y, 0); + gSprites[gUnknown_020388C0[3]].data0 = 1; + if (gUnknown_020388C0[2] != 0xFF) + { + gSprites[gUnknown_020388C0[3]].pos2.x = gSprites[gUnknown_020388C0[2]].pos2.x * -1; + gSprites[gUnknown_020388C0[3]].data1 = gSprites[gUnknown_020388C0[2]].data1; + } + else + { + gSprites[gUnknown_020388C0[3]].data1 = 0; + } + } + break; + } + + StartSpriteAnim(&gSprites[gUnknown_020388C0[id]], id & 1); +} + +void sub_80F979C(u8 id, bool8 invisible) +{ + if (id < 4 && gUnknown_020388C0[id] != 0xFF) + { + gSprites[gUnknown_020388C0[id]].invisible = invisible; + } +} + +void DestroyVerticalScrollIndicator(u8 id) +{ + if (id < 4 && gUnknown_020388C0[id] != 0xFF) + { + DestroySprite(&gSprites[gUnknown_020388C0[id]]); + gUnknown_020388C0[id] = 0xFF; + } +} + +void LoadScrollIndicatorPalette(void) +{ + LoadSpritePalette(&gUnknown_083E5968); +} + +void BuyMenuFreeMemory(void) +{ + FreeSpritePaletteByTag(SCROLL_INDICATOR_PAL_TAG); +} + +static void sub_80F9834(struct Sprite *sprite) +{ + if (sprite->data1 == 0) + { + sprite->pos2.x += sprite->data0; + } + if (sprite->data3 == 0) + { + sprite->pos2.y += sprite->data2; + } + sprite->data1++; + sprite->data3++; + if (sprite->data1 > 2) + { + sprite->data1 = 0; + } + if (sprite->data3 > 2) + { + sprite->data3 = 0; + } + if (sprite->pos2.x == 8 || sprite->pos2.x == -8) + { + sprite->pos2.x = 0; + } + if (sprite->pos2.y == 8 || sprite->pos2.y == -8) + { + sprite->pos2.y = 0; + } +} + +void sub_80F98A4(u8 id) +{ + if (gUnknown_020388C0[id] != 0xFF && id < 4) + { + gSprites[gUnknown_020388C0[id]].callback = SpriteCallbackDummy; + } +} + +void StartVerticalScrollIndicators(u8 id) +{ + if (gUnknown_020388C0[id] != 0xFF && id < 4) + { + gSprites[gUnknown_020388C0[id]].callback = sub_80F9834; + } +} + +static void sub_80F9914(u8 id) +{ + if (gUnknown_020388C0[id] != 0xFF && id < 4) + { + gSprites[gUnknown_020388C0[id]].pos2.x = 0; + gSprites[gUnknown_020388C0[id]].pos2.y = 0; + gSprites[gUnknown_020388C0[id]].data1 = 0; + gSprites[gUnknown_020388C0[id]].data3 = 0; + } +} + +void PauseVerticalScrollIndicator(u8 id) +{ + sub_80F98A4(id); + sub_80F9914(id); +} + +void sub_80F9988(u8 id, u8 priority) +{ + if (gUnknown_020388C0[id] != 0xFF && id < 4) + { + gSprites[gUnknown_020388C0[id]].oam.priority = priority; + } +} diff --git a/src/field/metatile_behavior.c b/src/field/metatile_behavior.c new file mode 100644 index 000000000..d05ba0b89 --- /dev/null +++ b/src/field/metatile_behavior.c @@ -0,0 +1,1308 @@ +#include "global.h" +#include "metatile_behavior.h" +#include "metatile_behaviors.h" + +#define TILE_ATTRIBUTES(three, two, one) (((one) ? 1 : 0) | ((two) ? 2 : 0) | ((three) ? 4 : 0)) + +static const u8 sTileBitAttributes[] = +{ + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, TRUE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, TRUE), + TILE_ATTRIBUTES(TRUE, TRUE, TRUE), + TILE_ATTRIBUTES(TRUE, TRUE, TRUE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, TRUE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, TRUE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(TRUE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE), + TILE_ATTRIBUTES(FALSE, FALSE, FALSE) +}; + +// only used as default case for checking jump landing in field_ground_effect. +bool8 MetatileBehavior_IsATile(u8 var) +{ + return TRUE; +} + +bool8 MetatileBehavior_IsEncounterTile(u8 var) +{ + if ((sTileBitAttributes[var] & 1) != 0) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsJumpEast(u8 var) +{ + if (var == MB_JUMP_EAST) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsJumpWest(u8 var) +{ + if (var == MB_JUMP_WEST) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsJumpNorth(u8 var) +{ + if (var == MB_JUMP_NORTH) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsJumpSouth(u8 var) +{ + if (var == MB_JUMP_SOUTH) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsPokeGrass(u8 var) +{ + if (var == MB_TALL_GRASS || var == MB_LONG_GRASS) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSandOrDeepSand(u8 var) +{ + if (var == MB_SAND || var == MB_DEEP_SAND) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsDeepSand(u8 var) +{ + if (var == MB_DEEP_SAND) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsReflective(u8 var) +{ + if (var == MB_POND_WATER || var == MB_PUDDLE || var == MB_1A || var == MB_ICE || var == MB_SOOTOPOLIS_DEEP_WATER || var == MB_REFLECTION_UNDER_BRIDGE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsIce(u8 var) +{ + if (var == MB_ICE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWarpDoor(u8 var) +{ + if (var == MB_ANIMATED_DOOR) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsDoor(u8 var) +{ + if (var == MB_8D || var == MB_ANIMATED_DOOR) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsEscalator(u8 var) +{ + if (var == MB_UP_ESCALATOR || var == MB_DOWN_ESCALATOR) + return TRUE; + else + return FALSE; +} + +bool8 unref_sub_8056EE0(u8 var) +{ + if (var == MB_04) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsLadder(u8 var) +{ + if (var == MB_LADDER) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsNonAnimDoor(u8 var) +{ + if (var == MB_NON_ANIMATED_DOOR || var == MB_WATER_DOOR || var == MB_DEEP_SOUTH_WARP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsDeepSouthWarp(u8 var) +{ + if (var == MB_DEEP_SOUTH_WARP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSurfableWaterOrUnderwater(u8 var) +{ + if ((sTileBitAttributes[var] & 2) != 0) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsEastArrowWarp(u8 var) +{ + if (var == MB_EAST_ARROW_WARP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWestArrowWarp(u8 var) +{ + if (var == MB_WEST_ARROW_WARP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsNorthArrowWarp(u8 var) +{ + if (var == MB_NORTH_ARROW_WARP || var == MB_STAIRS_OUTSIDE_ABANDONED_SHIP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSouthArrowWarp(u8 var) +{ + if (var == MB_SOUTH_ARROW_WARP || var == MB_WATER_SOUTH_ARROW_WARP || var == MB_SHOAL_CAVE_ENTRANCE) + return TRUE; + else + return FALSE; +} + +// unused +bool8 MetatileBehavior_IsArrowWarp(u8 var) +{ + u8 var2 = 0; + + if (MetatileBehavior_IsEastArrowWarp(var) + || MetatileBehavior_IsWestArrowWarp(var) + || MetatileBehavior_IsNorthArrowWarp(var) + || MetatileBehavior_IsSouthArrowWarp(var)) + { + var2 = 1; + } + return var2; +} + +bool8 MetatileBehavior_IsMoveTile(u8 var) +{ + if ((var >= MB_WALK_EAST && var <= MB_TRICK_HOUSE_PUZZLE_8_FLOOR) || (var >= MB_EASTWARD_CURRENT && var <= MB_SOUTHWARD_CURRENT) + || var == MB_MUDDY_SLOPE || var == MB_CRACKED_FLOOR || var == MB_WATERFALL || var == MB_ICE || var == MB_BB || var == MB_BC) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsIce_2(u8 var) +{ + if (var == MB_ICE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsTrickHouseSlipperyFloor(u8 var) +{ + if (var == MB_TRICK_HOUSE_PUZZLE_8_FLOOR) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_0x05(u8 var) +{ + if (var == MB_05) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWalkNorth(u8 var) +{ + if (var == MB_WALK_NORTH) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWalkSouth(u8 var) +{ + if (var == MB_WALK_SOUTH) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWalkWest(u8 var) +{ + if (var == MB_WALK_WEST) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWalkEast(u8 var) +{ + if (var == MB_WALK_EAST) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsNorthwardCurrent(u8 var) +{ + if (var == MB_NORTHWARD_CURRENT) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSouthwardCurrent(u8 var) +{ + if (var == MB_SOUTHWARD_CURRENT) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWestwardCurrent(u8 var) +{ + if (var == MB_WESTWARD_CURRENT) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsEastwardCurrent(u8 var) +{ + if (var == MB_EASTWARD_CURRENT) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSlideNorth(u8 var) +{ + if (var == MB_SLIDE_NORTH) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSlideSouth(u8 var) +{ + if (var == MB_SLIDE_SOUTH) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSlideWest(u8 var) +{ + if (var == MB_SLIDE_WEST) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSlideEast(u8 var) +{ + if (var == MB_SLIDE_EAST) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsCounter(u8 var) +{ + if (var == MB_COUNTER) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsPlayerFacingTVScreen(u8 tile, u8 playerDir) +{ + if (playerDir != CONNECTION_NORTH) // if the player isn't facing north, forget about it. + return FALSE; + else if (tile == MB_TELEVISION) // is the player's north tile a TV? + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsPC(u8 var) +{ + if (var == MB_PC) + return TRUE; + else + return FALSE; +} + +bool8 is_tile_x84(u8 var) +{ + if (var == MB_84) + return TRUE; + else + return FALSE; +} + +bool8 sub_80571C0(u8 var) +{ + if (var == MB_91 || var == MB_93 || var == MB_95 || var == MB_97 + || var == MB_99 || var == MB_9B || var == MB_9D) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSecretBaseCave(u8 var) +{ + if (var == MB_SECRET_BASE_SPOT_RED_CAVE || var == MB_SECRET_BASE_SPOT_BROWN_CAVE || var == MB_SECRET_BASE_SPOT_YELLOW_CAVE || var == MB_SECRET_BASE_SPOT_BLUE_CAVE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSecretBaseTree(u8 var) +{ + if (var == MB_SECRET_BASE_SPOT_TREE_1 || var == MB_SECRET_BASE_SPOT_TREE_2) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSecretBaseShrub(u8 var) +{ + if (var == MB_SECRET_BASE_SPOT_SHRUB) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSecretBasePC(u8 var) +{ + if (var == MB_SECRET_BASE_PC) + return TRUE; + else + return FALSE; +} + +bool8 sub_805724C(u8 var) +{ + if (var == MB_B1) + return TRUE; + else + return FALSE; +} + +bool8 unref_sub_8057260(u8 var) +{ + if (var == MB_B2) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057274(u8 var) +{ + if (var == MB_B3) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057288(u8 var) +{ + if (var == MB_B9) + return TRUE; + else + return FALSE; +} + +bool8 sub_805729C(u8 var) +{ + if (var == MB_NORMAL) + return TRUE; + else + return FALSE; +} + +bool8 sub_80572B0(u8 var) +{ + if (var == MB_B7) + return TRUE; + else + return FALSE; +} + +bool8 unref_sub_80572C4(u8 var) +{ + if (var == MB_B2) + return TRUE; + else + return FALSE; +} + +bool8 sub_80572D8(u8 var) +{ + if (var == MB_B5) + return TRUE; + else + return FALSE; +} + +bool8 sub_80572EC(u8 var) +{ + if (var == MB_C3) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057300(u8 var) +{ + if (var == MB_C2) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057314(u8 var) +{ + if (var == MB_B8) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057328(u8 var) +{ + if (var == MB_BE) + return TRUE; + else + return FALSE; +} + +bool8 sub_805733C(u8 var) +{ + if (var == MB_BD) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057350(u8 var) +{ + if (var == MB_BA) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057364(u8 var) +{ + if (var == MB_BF) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057378(u8 var) +{ + if (var == MB_C4) + return TRUE; + else + return FALSE; +} + +bool8 sub_805738C(u8 var) +{ + if (var == MB_C5) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_HasRipples(u8 var) +{ + if (var == MB_POND_WATER || var == MB_PUDDLE || var == MB_SOOTOPOLIS_DEEP_WATER) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsPuddle(u8 var) +{ + if (var == MB_PUDDLE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsTallGrass(u8 var) +{ + if (var == MB_TALL_GRASS) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsLongGrass(u8 var) +{ + if (var == MB_LONG_GRASS) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsBerryTreeSoil(u8 var) +{ + if (var == MB_BERRY_TREE_SOIL) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsAshGrass(u8 var) +{ + if (var == MB_ASHGRASS) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsUnusedFootprintMetatile(u8 var) +{ + if (var == MB_25) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsBridge(u8 var) +{ + if (var >= MB_WARP_OR_BRIDGE && var <= MB_ROUTE120_NORTH_BRIDGE_2) + return TRUE; + else + return FALSE; +} + +u8 sub_8057450(u8 var) +{ + u8 result = var - MB_WARP_OR_BRIDGE; + + if (result > 3) + result = 0; + + return result; +} + +bool8 MetatileBehavior_IsLandWildEncounter(u8 var) +{ + if (MetatileBehavior_IsSurfableWaterOrUnderwater(var) == FALSE && MetatileBehavior_IsEncounterTile(var) == TRUE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWaterWildEncounter(u8 var) +{ + if (MetatileBehavior_IsSurfableWaterOrUnderwater(var) == TRUE && MetatileBehavior_IsEncounterTile(var) == TRUE) + return TRUE; + else + return FALSE; +} + +bool8 sub_80574C4(u8 var) +{ + if (var == MB_0B) + return TRUE; + else + return FALSE; +} + +bool8 sub_80574D8(u8 var) +{ + if (var == MB_MOUNTAIN_TOP) + return TRUE; + else + return FALSE; +} + +bool8 sub_80574EC(u8 var) +{ + if (var == MB_SEMI_DEEP_WATER || var == MB_DEEP_WATER || var == MB_SOOTOPOLIS_DEEP_WATER) + return TRUE; + else + return FALSE; +} + +bool8 sub_805750C(u8 var) +{ + if (var == MB_NO_SURFACING || var == MB_SEAWEED_NO_SURFACING) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsShallowFlowingWater(u8 var) +{ + if (var == MB_SHALLOW_WATER || var == MB_STAIRS_OUTSIDE_ABANDONED_SHIP || var == MB_SHOAL_CAVE_ENTRANCE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsThinIce(u8 var) +{ + if (var == MB_THIN_ICE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsCrackedIce(u8 var) +{ + if (var == MB_CRACKED_ICE) + return TRUE; + else + return FALSE; +} + +bool8 sub_8057568(u8 var) +{ + if (var == MB_OCEAN_WATER || var == MB_SEMI_DEEP_WATER || var == MB_DEEP_WATER) + return TRUE; + else + return FALSE; +} + +bool8 unref_sub_8057584(u8 var) +{ + if (var == MB_18 || var == MB_1A) + return TRUE; + else + return FALSE; +} + +bool8 sub_805759C(u8 var) +{ + if (MetatileBehavior_IsSurfableWaterOrUnderwater(var) && MetatileBehavior_IsWaterfall(var) == FALSE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsEastBlocked(u8 var) +{ + if (var == MB_IMPASSABLE_EAST || var == MB_IMPASSABLE_NORTHEAST || var == MB_IMPASSABLE_SOUTHEAST || var == MB_C1 || var == MB_BE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWestBlocked(u8 var) +{ + if (var == MB_IMPASSABLE_WEST || var == MB_IMPASSABLE_NORTHWEST || var == MB_IMPASSABLE_SOUTHWEST || var == MB_C1 || var == MB_BE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsNorthBlocked(u8 var) +{ + if (var == MB_IMPASSABLE_NORTH || var == MB_IMPASSABLE_NORTHEAST || var == MB_IMPASSABLE_NORTHWEST || var == MB_BED) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSouthBlocked(u8 var) +{ + if (var == MB_IMPASSABLE_SOUTH || var == MB_IMPASSABLE_SOUTHEAST || var == MB_IMPASSABLE_SOUTHWEST || var == MB_BED) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsShortGrass(u8 var) +{ + if (var == MB_SHORT_GRASS) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsHotSprings(u8 var) +{ + if (var == MB_HOT_SPRINGS) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsWaterfall(u8 var) +{ + if (var == MB_WATERFALL) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsFortreeBridge(u8 var) +{ + if (var == MB_FORTREE_BRIDGE) + return TRUE; + else + return FALSE; +} + +bool8 sub_80576A0(u8 var) +{ + if (var == MB_PACIFIDLOG_VERTICAL_LOG_1) + return TRUE; + else + return FALSE; +} + +bool8 sub_80576B4(u8 var) +{ + if (var == MB_PACIFIDLOG_VERTICAL_LOG_2) + return TRUE; + else + return FALSE; +} + +bool8 sub_80576C8(u8 var) +{ + if (var == MB_PACIFIDLOG_HORIZONTAL_LOG_1) + return TRUE; + else + return FALSE; +} + +bool8 sub_80576DC(u8 var) +{ + if (var == MB_PACIFIDLOG_HORIZONTAL_LOG_2) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsPacifidlogLog(u8 var) +{ + if (var >= MB_PACIFIDLOG_VERTICAL_LOG_1 && var <= MB_PACIFIDLOG_HORIZONTAL_LOG_2) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsTrickHousePuzzleDoor(u8 var) +{ + if (var == MB_TRICK_HOUSE_PUZZLE_DOOR) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsRegionMap(u8 var) +{ + if (var == MB_REGION_MAP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsClosedSootopolisGymDoor(u8 var) +{ + if (var == MB_CLOSED_SOOTOPOLIS_GYM_DOOR) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsRoulette(u8 var) +{ + if (var == MB_ROULETTE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsPokeblockFeeder(u8 var) +{ + if (var == MB_POKEBLOCK_FEEDER) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_0xBB(u8 var) +{ + if (var == MB_BB) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_0xBC(u8 var) +{ + if (var == MB_BC) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsLavaridgeB1FWarp(u8 var) +{ + if (var == MB_LAVARIDGE_GYM_B1F_WARP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsLavaridge1FWarp(u8 var) +{ + if (var == MB_LAVARIDGE_GYM_1F_WARP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsAquaHideoutWarp(u8 var) +{ + if (var == MB_AQUA_HIDEOUT_WARP) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSurfableFishableWater(u8 var) +{ + if (var == MB_POND_WATER || var == MB_OCEAN_WATER || var == MB_SEMI_DEEP_WATER || var == MB_DEEP_WATER || var == MB_SOOTOPOLIS_DEEP_WATER || (var >= MB_EASTWARD_CURRENT && var <= MB_SOUTHWARD_CURRENT)) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsMtPyreHole(u8 var) +{ + if (var == MB_MT_PYRE_HOLE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsCrackedFloorHole(u8 var) +{ + if (var == MB_CRACKED_FLOOR_HOLE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsCrackedFloor(u8 var) +{ + if (var == MB_CRACKED_FLOOR) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsMuddySlope(u8 var) +{ + if (var == MB_MUDDY_SLOPE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsBumpySlope(u8 var) +{ + if (var == MB_BUMPY_SLOPE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsIsolatedVerticalRail(u8 var) +{ + if (var == MB_ISOLATED_VERTICAL_RAIL) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsIsolatedHorizontalRail(u8 var) +{ + if (var == MB_ISOLATED_HORIZONTAL_RAIL) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsVerticalRail(u8 var) +{ + if (var == MB_VERTICAL_RAIL) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsHorizontalRail(u8 var) +{ + if (var == MB_HORIZONTAL_RAIL) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsSeaweed(u8 var) +{ + if (var == MB_SEAWEED || var == MB_SEAWEED_NO_SURFACING) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsRunningDisallowed(u8 var) +{ + if (var == MB_NO_RUNNING || var == MB_LONG_GRASS || var == MB_HOT_SPRINGS || MetatileBehavior_IsPacifidlogLog(var) != FALSE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsCuttableGrass(u8 var) +{ + if (var == MB_TALL_GRASS || var == MB_LONG_GRASS || var == MB_ASHGRASS || var == MB_LONG_GRASS_SOUTH_EDGE) + return TRUE; + else + return FALSE; +} + +bool8 sub_805791C(u8 var) +{ + if (var == MB_8E) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsPictureBookShelf(u8 var) +{ + if (var == MB_PICTURE_BOOK_SHELF) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsBookShelf(u8 var) +{ + if (var == MB_BOOKSHELF) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsPokeCenterBookShelf(u8 var) +{ + if (var == MB_POKEMON_CENTER_BOOKSHELF) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsVase(u8 var) +{ + if (var == MB_VASE) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsTrashCan(u8 var) +{ + if (var == MB_TRASH_CAN) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsShopShelf(u8 var) +{ + if (var == MB_SHOP_SHELF) + return TRUE; + else + return FALSE; +} + +bool8 MetatileBehavior_IsBlueprint(u8 var) +{ + if (var == MB_BLUEPRINT) + return TRUE; + else + return FALSE; +} diff --git a/src/field/money.c b/src/field/money.c new file mode 100644 index 000000000..5d0f0ae8d --- /dev/null +++ b/src/field/money.c @@ -0,0 +1,263 @@ +#include "global.h" +#include "money.h" +#include "decompress.h" +#include "menu.h" +#include "sprite.h" +#include "string_util.h" + +#define SPRITE_TAG_MONEY (0x2722) + +extern u16 gSpecialVar_0x8005; + +static EWRAM_DATA u8 gUnknown_02038734 = 0; + +extern const struct CompressedSpriteSheet gUnknown_083CF584; +extern const struct CompressedSpritePalette gUnknown_083CF58C; +extern const struct SpriteTemplate gSpriteTemplate_83CF56C; + +bool8 IsEnoughMoney(u32 budget, u32 cost) +{ + if (budget >= cost) + { + return TRUE; + } + + return FALSE; +} + +void AddMoney(u32 *arg0, u32 arg1) +{ + if (*arg0 > *arg0 + arg1) + { + *arg0 = 999999; + return; + } + + *arg0 = *arg0 + arg1; + if (*arg0 > 999999) + { + *arg0 = 999999; + } +} + +void RemoveMoney(u32 *arg0, u32 arg1) +{ + if (*arg0 < arg1) + { + *arg0 = 0; + } + else + { + *arg0 = *arg0 - arg1; + } +} + +void GetMoneyAmountText(u8 *buffer, u32 amount, u8 arg2) +{ + u8 width; + u8 i; + + if (amount > 999999) + width = 7; + else if (amount > 99999) + width = 6; + else if (amount > 10000) + width = 5; + else if (amount > 999) + width = 4; + else if (amount > 99) + width = 3; + else if (amount > 9) + width = 2; + else + width = 1; + + buffer[0] = EXT_CTRL_CODE_BEGIN; + buffer[1] = 0x14; + buffer[2] = 0x06; + buffer += 3; + + for (i = 0; i < arg2 - width; i++) + { + buffer[0] = CHAR_SPACE; + buffer += 1; + } + + buffer[0] = CHAR_CURRENCY; + buffer += 1; + + buffer = ConvertIntToDecimalString(buffer, amount); + + buffer[0] = EXT_CTRL_CODE_BEGIN; + buffer[1] = 0x14; + buffer[2] = 0x00; + buffer[3] = EOS; +} + +void PrintMoneyAmount(u32 amount, u8 size, u8 x, u8 y) +{ + u8 buffer[16]; + u8 stringWidth; + + GetMoneyAmountText(buffer, amount, size); + stringWidth = sub_8072CA4(buffer); + + if (stringWidth >= (size + 1) * 8) + { + MenuPrint(buffer, x, y); + } + else + { + int xPlusOne = x + 1; + MenuPrint_PixelCoords(buffer, (xPlusOne + size) * 8 - stringWidth, y * 8, 1); + } +} + +void sub_80B7AEC(u32 arg0, u8 left, u8 top) +{ + u8 buffer[32]; + u8 *ptr; + + ptr = &buffer[0]; + + ptr[0] = CHAR_CURRENCY; + ptr++; + + ptr = ConvertIntToDecimalString(ptr, arg0); + + MenuPrint_RightAligned(buffer, left, top); + +#ifdef ENGLISH + ptr[0] = 0xFC; + ptr[1] = 0x14; + ptr[2] = 0x00; + ptr[3] = 0xFF; +#endif +} + +__attribute__((naked)) +void sub_80B7B34(u8 var1, u8 var2, int var3) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r9\n\ + mov r6, r8\n\ + push {r6,r7}\n\ + sub sp, 0x4\n\ + mov r8, r0\n\ + adds r5, r1, 0\n\ + mov r9, r2\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + lsls r5, 24\n\ + lsrs r5, 24\n\ + mov r1, r9\n\ + lsls r1, 8\n\ + mov r9, r1\n\ + ldr r4, _080B7BD8 @ =gDecoration10000_Gfx\n\ + adds r0, r1, r4\n\ + lsls r6, r5, 4\n\ + subs r6, r5\n\ + lsls r1, r6, 6\n\ + mov r3, r8\n\ + adds r3, 0x1\n\ + lsls r3, 5\n\ + ldr r2, _080B7BDC @ =0x06008000\n\ + adds r3, r2\n\ + adds r1, r3\n\ + movs r2, 0x20\n\ + str r3, [sp]\n\ + bl CpuFastSet\n\ + adds r4, 0x80\n\ + add r9, r4\n\ + adds r0, r5, 0x1\n\ + lsls r4, r0, 4\n\ + subs r4, r0\n\ + lsls r1, r4, 6\n\ + ldr r3, [sp]\n\ + adds r1, r3\n\ + mov r0, r9\n\ + movs r2, 0x20\n\ + bl CpuFastSet\n\ + movs r3, 0\n\ + lsls r5, 5\n\ + mov r0, r8\n\ + adds r7, r5, r0\n\ + lsls r6, 1\n\ + adds r6, 0x1\n\ + add r6, r8\n\ + ldr r1, _080B7BE0 @ =0xfffff000\n\ + adds r5, r1, 0\n\ + ldr r0, _080B7BE4 @ =0x0600f800\n\ + mov r12, r0\n\ + ldr r1, _080B7BE8 @ =0x0600f840\n\ + mov r9, r1\n\ + lsls r4, 1\n\ + adds r4, 0x1\n\ + add r4, r8\n\ +_080B7BAA:\n\ + adds r1, r7, r3\n\ + lsls r1, 1\n\ + mov r0, r12\n\ + adds r2, r1, r0\n\ + adds r0, r3, r6\n\ + adds r0, r5\n\ + strh r0, [r2]\n\ + add r1, r9\n\ + adds r0, r3, r4\n\ + adds r0, r5\n\ + strh r0, [r1]\n\ + adds r0, r3, 0x1\n\ + lsls r0, 16\n\ + lsrs r3, r0, 16\n\ + cmp r3, 0x3\n\ + bls _080B7BAA\n\ + add sp, 0x4\n\ + pop {r3,r4}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080B7BD8: .4byte gDecoration10000_Gfx\n\ +_080B7BDC: .4byte 0x06008000\n\ +_080B7BE0: .4byte 0xfffff000\n\ +_080B7BE4: .4byte 0x0600f800\n\ +_080B7BE8: .4byte 0x0600f840\n\ + .syntax divided\n"); +} + +void UpdateMoneyWindow(u32 amount, u8 x, u8 y) +{ + PrintMoneyAmount(amount, 6, x + 6, y + 1); +} + +void OpenMoneyWindow(u32 amount, u8 x, u8 y) +{ + MenuDrawTextWindow(x, y, x + 13, y + 3); + UpdateMoneyWindow(amount, x, y); + + LoadCompressedObjectPic(&gUnknown_083CF584); + LoadCompressedObjectPalette(&gUnknown_083CF58C); + + gUnknown_02038734 = CreateSprite(&gSpriteTemplate_83CF56C, x * 8 + 19, y * 8 + 11, 0); +} + +void CloseMoneyWindow(u8 x, u8 y) +{ + DestroySpriteAndFreeResources(&gSprites[gUnknown_02038734]); + FreeSpritePaletteByTag(SPRITE_TAG_MONEY); + MenuZeroFillWindowRect(x, y, x + 13, y + 3); +} + +bool8 sub_80B7CE8(void) +{ + return IsEnoughMoney(gSaveBlock1.money, gSpecialVar_0x8005); +} + +void sub_80B7D0C(void) +{ + RemoveMoney(&gSaveBlock1.money, gSpecialVar_0x8005); +} diff --git a/src/field/overworld.c b/src/field/overworld.c new file mode 100644 index 000000000..d6f255409 --- /dev/null +++ b/src/field/overworld.c @@ -0,0 +1,2674 @@ +#include "global.h" +#include "overworld.h" +#include "battle_setup.h" +#include "berry.h" +#include "cable_club.h" +#include "clock.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_control_avatar.h" +#include "field_effect.h" +#include "field_fadetransition.h" +#include "field_ground_effect.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_message_box.h" +#include "field_player_avatar.h" +#include "field_screen_effect.h" +#include "field_special_scene.h" +#include "field_specials.h" +#include "field_tasks.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "fldeff_flash.h" +#include "heal_location.h" +#include "link.h" +#include "load_save.h" +#include "main.h" +#include "map_constants.h" +#include "map_name_popup.h" +#include "menu.h" +#include "metatile_behavior.h" +#include "new_game.h" +#include "palette.h" +#include "play_time.h" +#include "rng.h" +#include "roamer.h" +#include "rotating_gate.h" +#include "safari_zone.h" +#include "script.h" +#include "script_pokemon_80C4.h" +#include "secret_base.h" +#include "songs.h" +#include "sound.h" +#include "species.h" +#include "start_menu.h" +#include "task.h" +#include "tileset_anim.h" +#include "time_events.h" +#include "tv.h" +#include "unknown_task.h" +#include "wild_encounter.h" + +#ifdef SAPPHIRE +#define LEGENDARY_MUSIC BGM_OOAME // Heavy Rain +#else +#define LEGENDARY_MUSIC BGM_HIDERI // Drought +#endif + +struct UnkTVStruct +{ + u32 tv_field_0; + u32 tv_field_4; +}; + +extern u16 gUnknown_03004898; +extern u16 gUnknown_0300489C; + +extern u8 S_WhiteOut[]; +extern u8 gUnknown_0819FC9F[]; +extern u8 SingleBattleColosseum_EventScript_1A436F[]; +extern u8 SingleBattleColosseum_EventScript_1A4379[]; +extern u8 DoubleBattleColosseum_EventScript_1A4383[]; +extern u8 DoubleBattleColosseum_EventScript_1A439E[]; +extern u8 DoubleBattleColosseum_EventScript_1A43B9[]; +extern u8 DoubleBattleColosseum_EventScript_1A43D4[]; +extern u8 TradeCenter_EventScript_1A43F0[]; +extern u8 TradeCenter_EventScript_1A43FA[]; +extern u8 RecordCorner_EventScript_1A4418[]; +extern u8 RecordCorner_EventScript_1A442D[]; +extern u8 RecordCorner_EventScript_1A4442[]; +extern u8 RecordCorner_EventScript_1A4457[]; +extern u8 TradeRoom_ReadTrainerCard1[]; +extern u8 TradeRoom_ReadTrainerCard2[]; +extern u8 TradeRoom_TooBusyToNotice[]; +extern u8 TradeRoom_PromptToCancelLink[]; +extern u8 TradeRoom_TerminateLink[]; +extern u8 gUnknown_081A4508[]; + +extern struct MapData * const gMapAttributes[]; +extern struct MapHeader * const * const gMapGroups[]; +extern s32 gMaxFlashLevel; + +EWRAM_DATA struct WarpData gUnknown_020297F0 = {0}; +EWRAM_DATA struct WarpData gWarpDestination = {0}; // new warp position +EWRAM_DATA struct WarpData gUnknown_02029800 = {0}; +EWRAM_DATA struct WarpData gUnknown_02029808 = {0}; +EWRAM_DATA struct UnkPlayerStruct gUnknown_02029810 = {0}; +EWRAM_DATA static u16 sAmbientCrySpecies = 0; +EWRAM_DATA static bool8 sIsAmbientCryWaterMon = FALSE; +EWRAM_DATA struct LinkPlayerMapObject gLinkPlayerMapObjects[4] = {0}; + +static u8 gUnknown_03000580[4]; +static u16 (*gUnknown_03000584)(u32); +static u8 gUnknown_03000588; + +u16 word_3004858; +void (*gFieldCallback)(void); +u8 gUnknown_03004860; +u8 gFieldLinkPlayerCount; + +static const struct WarpData sDummyWarpData = +{ + .mapGroup = -1, + .mapNum = -1, + .warpId = -1, + .x = -1, + .y = -1, +}; + +static const u8 sUnusedData[] = +{ + 0xB0, 0x04, 0x00, 0x00, + 0x10, 0x0E, 0x00, 0x00, + 0xB0, 0x04, 0x00, 0x00, + 0x60, 0x09, 0x00, 0x00, + 0x32, 0x00, 0x00, 0x00, + 0x50, 0x00, 0x00, 0x00, + 0xD4, 0xFF, 0xFF, 0xFF, + 0x2C, 0x00, 0x00, 0x00, +}; + +const struct UCoords32 gUnknown_0821664C[] = +{ + { 0, 0}, + { 0, 1}, + { 0, -1}, + {-1, 0}, + { 1, 0}, + {-1, 1}, + { 1, 1}, + {-1, -1}, + { 1, -1}, +}; + +const struct UnknownTaskStruct gUnknown_08216694 = +{ + (void *)REG_ADDR_WIN0H, + ((DMA_ENABLE | DMA_START_HBLANK | DMA_REPEAT | DMA_DEST_RELOAD) << 16) | 1, + 1, + 0, +}; + +static u8 sub_8055C68(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_8055C88(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_8055C8C(struct LinkPlayerMapObject *, struct MapObject *, u8); + +static u8 (*const gUnknown_082166A0[])(struct LinkPlayerMapObject *, struct MapObject *, u8) = +{ + sub_8055C68, + sub_8055C88, + sub_8055C8C, +}; + +static u8 sub_8055CAC(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_8055CB0(struct LinkPlayerMapObject *, struct MapObject *, u8); +static u8 sub_8055D18(struct LinkPlayerMapObject *, struct MapObject *, u8); + +static u8 (*const gUnknown_082166AC[])(struct LinkPlayerMapObject *, struct MapObject *, u8) = +{ + sub_8055CAC, + sub_8055CB0, + sub_8055CB0, + sub_8055CB0, + sub_8055CB0, + sub_8055CAC, + sub_8055CAC, + sub_8055D18, + sub_8055D18, + sub_8055D18, + sub_8055D18, +}; + +static void sub_8055D30(struct LinkPlayerMapObject *, struct MapObject *); +static void sub_8055D38(struct LinkPlayerMapObject *, struct MapObject *); + +static void (*const gUnknown_082166D8[])(struct LinkPlayerMapObject *, struct MapObject *) = +{ + sub_8055D30, + sub_8055D38, +}; + + +static void DoWhiteOut(void) +{ + ScriptContext2_RunNewScript(S_WhiteOut); + gSaveBlock1.money /= 2; + ScrSpecial_HealPlayerParty(); + Overworld_ResetStateAfterWhiteOut(); + Overworld_SetWarpDestToLastHealLoc(); + warp_in(); +} + +void Overworld_ResetStateAfterFly(void) +{ + player_avatar_init_params_reset(); + FlagClear(SYS_CYCLING_ROAD); + FlagClear(SYS_CRUISE_MODE); + FlagClear(SYS_SAFARI_MODE); + FlagClear(SYS_USE_STRENGTH); + FlagClear(SYS_USE_FLASH); +} + +void Overworld_ResetStateAfterTeleport(void) +{ + player_avatar_init_params_reset(); + FlagClear(SYS_CYCLING_ROAD); + FlagClear(SYS_CRUISE_MODE); + FlagClear(SYS_SAFARI_MODE); + FlagClear(SYS_USE_STRENGTH); + FlagClear(SYS_USE_FLASH); + ScriptContext2_RunNewScript(gUnknown_0819FC9F); +} + +void Overworld_ResetStateAfterDigEscRope(void) +{ + player_avatar_init_params_reset(); + FlagClear(SYS_CYCLING_ROAD); + FlagClear(SYS_CRUISE_MODE); + FlagClear(SYS_SAFARI_MODE); + FlagClear(SYS_USE_STRENGTH); + FlagClear(SYS_USE_FLASH); +} + +void Overworld_ResetStateAfterWhiteOut(void) +{ + player_avatar_init_params_reset(); + FlagClear(SYS_CYCLING_ROAD); + FlagClear(SYS_CRUISE_MODE); + FlagClear(SYS_SAFARI_MODE); + FlagClear(SYS_USE_STRENGTH); + FlagClear(SYS_USE_FLASH); +} + +void sub_805308C(void) +{ + FlagClear(SYS_SAFARI_MODE); + ChooseAmbientCrySpecies(); + ResetCyclingRoadChallengeData(); + UpdateLocationHistoryForRoamer(); + RoamerMoveToOtherLocationSet(); +} + +void ResetGameStats(void) +{ + s32 i; + + for (i = 0; i < NUM_GAME_STATS; i++) + gSaveBlock1.gameStats[i] = 0; +} + +void IncrementGameStat(u8 index) +{ + if (index < NUM_GAME_STATS) + { + if (gSaveBlock1.gameStats[index] < 0xFFFFFF) + gSaveBlock1.gameStats[index]++; + else + gSaveBlock1.gameStats[index] = 0xFFFFFF; + } +} + +u32 GetGameStat(u8 index) +{ + if (index >= NUM_GAME_STATS) + return 0; + + return gSaveBlock1.gameStats[index]; +} + +void SetGameStat(u8 index, u32 value) +{ + if (index < NUM_GAME_STATS) + gSaveBlock1.gameStats[index] = value; +} + +void LoadMapObjTemplatesFromHeader(void) +{ + // Clear map object templates + CpuFill32(0, gSaveBlock1.mapObjectTemplates, sizeof(gSaveBlock1.mapObjectTemplates)); + + // Copy map header events to save block + CpuCopy32(gMapHeader.events->mapObjects, + gSaveBlock1.mapObjectTemplates, + gMapHeader.events->mapObjectCount * sizeof(struct MapObjectTemplate)); +} + +static void LoadSaveblockMapObjScripts(void) +{ + struct MapObjectTemplate *mapObjectTemplates = gSaveBlock1.mapObjectTemplates; + s32 i; + + for (i = 0; i < 64; i++) + mapObjectTemplates[i].script = gMapHeader.events->mapObjects[i].script; +} + +void Overworld_SetMapObjTemplateCoords(u8 localId, s16 x, s16 y) +{ + s32 i; + for (i = 0; i < 64; i++) + { + struct MapObjectTemplate *mapObjectTemplate = &gSaveBlock1.mapObjectTemplates[i]; + if (mapObjectTemplate->localId == localId) + { + mapObjectTemplate->x = x; + mapObjectTemplate->y = y; + return; + } + } +} + +void Overworld_SetMapObjTemplateMovementType(u8 localId, u8 movementType) +{ + s32 i; + + for (i = 0; i < 64; i++) + { + struct MapObjectTemplate *mapObjectTemplate = &gSaveBlock1.mapObjectTemplates[i]; + if (mapObjectTemplate->localId == localId) + { + mapObjectTemplate->movementType = movementType; + return; + } + } +} + +static void mapdata_load_assets_to_gpu_and_full_redraw(void) +{ + move_tilemap_camera_to_upper_left_corner(); + copy_map_tileset1_tileset2_to_vram(gMapHeader.mapData); + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + DrawWholeMapView(); + cur_mapheader_run_tileset_funcs_after_some_cpuset(); +} + +static struct MapData *get_mapdata_header(void) +{ + u16 mapDataId = gSaveBlock1.mapDataId; + if (mapDataId) + return gMapAttributes[mapDataId - 1]; + return NULL; +} + +static void ApplyCurrentWarp(void) +{ + gUnknown_020297F0 = gSaveBlock1.location; + gSaveBlock1.location = gWarpDestination; + gUnknown_02029800 = sDummyWarpData; + gUnknown_02029808 = sDummyWarpData; +} + +static void SetWarpData(struct WarpData *warp, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + warp->mapGroup = mapGroup; + warp->mapNum = mapNum; + warp->warpId = warpId; + warp->x = x; + warp->y = y; +} + +static bool32 warp_data_is_not_neg_1(struct WarpData *warp) +{ + if (warp->mapGroup != -1) + return FALSE; + if (warp->mapNum != -1) + return FALSE; + if (warp->warpId != -1) + return FALSE; + if (warp->x != -1) + return FALSE; + if (warp->y != -1) + return FALSE; + return TRUE; +} + +struct MapHeader *const Overworld_GetMapHeaderByGroupAndId(u16 mapGroup, u16 mapNum) +{ + return gMapGroups[mapGroup][mapNum]; +} + +struct MapHeader *const warp1_get_mapheader(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gWarpDestination.mapGroup, gWarpDestination.mapNum); +} + +static void set_current_map_header_from_sav1_save_old_name(void) +{ + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum); + gSaveBlock1.mapDataId = gMapHeader.mapDataId; + gMapHeader.mapData = get_mapdata_header(); +} + +static void LoadSaveblockMapHeader(void) +{ + gMapHeader = *Overworld_GetMapHeaderByGroupAndId(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum); + gMapHeader.mapData = get_mapdata_header(); +} + +void sub_80533CC(void) +{ + if (gSaveBlock1.location.warpId >= 0 && gSaveBlock1.location.warpId < gMapHeader.events->warpCount) + { + gSaveBlock1.pos.x = gMapHeader.events->warps[gSaveBlock1.location.warpId].x; + gSaveBlock1.pos.y = gMapHeader.events->warps[gSaveBlock1.location.warpId].y; + } + else if (gSaveBlock1.location.x >= 0 && gSaveBlock1.location.y >= 0) + { + gSaveBlock1.pos.x = gSaveBlock1.location.x; + gSaveBlock1.pos.y = gSaveBlock1.location.y; + } + else + { + gSaveBlock1.pos.x = gMapHeader.mapData->width / 2; + gSaveBlock1.pos.y = gMapHeader.mapData->height / 2; + } +} + +void warp_in(void) +{ + ApplyCurrentWarp(); + set_current_map_header_from_sav1_save_old_name(); + sub_80533CC(); +} + +void Overworld_SetWarpDestination(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gWarpDestination, mapGroup, mapNum, warpId, x, y); +} + +void warp1_set_2(s8 mapGroup, s8 mapNum, s8 warpId) +{ + Overworld_SetWarpDestination(mapGroup, mapNum, warpId, -1, -1); +} + +void saved_warp2_set(int unused, s8 mapGroup, s8 mapNum, s8 warpId) +{ + SetWarpData(&gSaveBlock1.warp2, mapGroup, mapNum, warpId, gSaveBlock1.pos.x, gSaveBlock1.pos.y); +} + +void saved_warp2_set_2(int unused, s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1.warp2, mapGroup, mapNum, warpId, x, y); +} + +void copy_saved_warp2_bank_and_enter_x_to_warp1(u8 unused) +{ + gWarpDestination = gSaveBlock1.warp2; +} + +void sub_8053538(u8 a1) +{ + const struct HealLocation *warp = GetHealLocation(a1); + + if (warp) + Overworld_SetWarpDestination(warp->group, warp->map, -1, warp->x, warp->y); +} + +void Overworld_SetWarpDestToLastHealLoc(void) +{ + gWarpDestination = gSaveBlock1.lastHealLocation; +} + +void Overworld_SetHealLocationWarp(u8 healLocationId) +{ + const struct HealLocation *healLocation = GetHealLocation(healLocationId); + + if (healLocation != NULL) + SetWarpData(&gSaveBlock1.lastHealLocation, healLocation->group, healLocation->map, -1, healLocation->x, healLocation->y); +} + +void sub_80535C4(s16 a1, s16 a2) +{ + u8 currMapType = Overworld_GetMapTypeOfSaveblockLocation(); + u8 destMapType = GetMapTypeByGroupAndId(gWarpDestination.mapGroup, gWarpDestination.mapNum); + if (is_map_type_1_2_3_5_or_6(currMapType) && is_map_type_1_2_3_5_or_6(destMapType) != TRUE) + sub_805363C(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum, -1, a1 - 7, a2 - 6); +} + +void sub_805363C(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1.warp4, mapGroup, mapNum, warpId, x, y); +} + +void sub_8053678(void) +{ + gWarpDestination = gSaveBlock1.warp4; +} + +void sub_8053690(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gUnknown_02029800, mapGroup, mapNum, warpId, x, y); +} + +static void warp1_set_to_warp2(void) +{ + gWarpDestination = gUnknown_02029800; +} + +void sub_80536E4(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gUnknown_02029808, mapGroup, mapNum, warpId, x, y); +} + +void sub_8053720(s16 x, s16 y) +{ + if (warp_data_is_not_neg_1(&gUnknown_02029808) == TRUE) + { + gWarpDestination = gUnknown_020297F0; + } + else + { + Overworld_SetWarpDestination(gUnknown_02029808.mapGroup, gUnknown_02029808.mapNum, -1, x, y); + } +} + +void sub_8053778(void) +{ + gWarpDestination = gSaveBlock1.warp1; +} + +void unref_sub_8053790(s8 mapGroup, s8 mapNum, s8 warpId, s8 x, s8 y) +{ + SetWarpData(&gSaveBlock1.warp1, mapGroup, mapNum, warpId, x, y); +} + +void sub_80537CC(u8 a1) +{ + const struct HealLocation *warp = GetHealLocation(a1); + if (warp) + SetWarpData(&gSaveBlock1.warp1, warp->group, warp->map, -1, warp->x, warp->y); +} + +void gpu_sync_bg_hide() +{ + gSaveBlock1.warp1 = gSaveBlock1.warp2; +} + +struct MapConnection *GetMapConnection(u8 dir) +{ + s32 i; + s32 count = gMapHeader.connections->count; + struct MapConnection *connection = gMapHeader.connections->connections; + + if (connection == NULL) + return NULL; + + for(i = 0; i < count; i++, connection++) + if (connection->direction == dir) + return connection; + + return NULL; +} + +bool8 sub_8053850(u8 dir, u16 x, u16 y) +{ + struct MapConnection *connection = GetMapConnection(dir); + + if (connection != NULL) + { + Overworld_SetWarpDestination(connection->mapGroup, connection->mapNum, -1, x, y); + } + else + { + mapheader_run_script_with_tag_x6(); + if (warp_data_is_not_neg_1(&gUnknown_02029800)) + return FALSE; + warp1_set_to_warp2(); + } + return TRUE; +} + +bool8 sub_80538B0(u16 x, u16 y) +{ + return sub_8053850(CONNECTION_EMERGE, x, y); +} + +bool8 sub_80538D0(u16 x, u16 y) +{ + return sub_8053850(CONNECTION_DIVE, x, y); +} + +void sub_80538F0(u8 mapGroup, u8 mapNum) +{ + s32 i; + + Overworld_SetWarpDestination(mapGroup, mapNum, -1, -1, -1); + sub_8053F0C(); + ApplyCurrentWarp(); + set_current_map_header_from_sav1_save_old_name(); + LoadMapObjTemplatesFromHeader(); + ClearTempFieldEventData(); + ResetCyclingRoadChallengeData(); + prev_quest_postbuffer_cursor_backup_reset(); + sub_8082BD0(mapGroup, mapNum); + DoTimeBasedEvents(); + sub_80806E4(); + ChooseAmbientCrySpecies(); + SetDefaultFlashLevel(); + Overworld_ClearSavedMusic(); + mapheader_run_script_with_tag_x3(); + not_trainer_hill_battle_pyramid(); + sub_8056D38(gMapHeader.mapData); + apply_map_tileset2_palette(gMapHeader.mapData); + + for (i = 6; i < 12; i++) + sub_807D874(i); + + sub_8072ED0(); + UpdateLocationHistoryForRoamer(); + RoamerMove(); + DoCurrentWeather(); + ResetFieldTasksArgs(); + mapheader_run_script_with_tag_x5(); + ShowMapNamePopup(); +} + +void sub_8053994(u32 a1) +{ + bool8 v2; + bool8 v3; + + set_current_map_header_from_sav1_save_old_name(); + LoadMapObjTemplatesFromHeader(); + v2 = is_map_type_1_2_3_5_or_6(gMapHeader.mapType); + v3 = Overworld_MapTypeIsIndoors(gMapHeader.mapType); + ClearTempFieldEventData(); + ResetCyclingRoadChallengeData(); + prev_quest_postbuffer_cursor_backup_reset(); + sub_8082BD0(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum); + if (a1 != 1) + DoTimeBasedEvents(); + sub_80806E4(); + ChooseAmbientCrySpecies(); + if (v2) + FlagClear(SYS_USE_FLASH); + SetDefaultFlashLevel(); + Overworld_ClearSavedMusic(); + mapheader_run_script_with_tag_x3(); + UpdateLocationHistoryForRoamer(); + RoamerMoveToOtherLocationSet(); + not_trainer_hill_battle_pyramid(); + if (a1 != 1 && v3) + { + UpdateTVScreensOnMap(gUnknown_03004870.width, gUnknown_03004870.height); + sub_80BBCCC(1); + } +} + +void player_avatar_init_params_reset(void) +{ + gUnknown_02029810.player_field_1 = 1; + gUnknown_02029810.player_field_0 = 1; +} + +void walkrun_find_lowest_active_bit_in_bitfield(void) +{ + gUnknown_02029810.player_field_1 = player_get_direction_lower_nybble(); + + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE)) + gUnknown_02029810.player_field_0 = 2; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_ACRO_BIKE)) + gUnknown_02029810.player_field_0 = 4; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + gUnknown_02029810.player_field_0 = 8; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_4)) + gUnknown_02029810.player_field_0 = 16; + else + gUnknown_02029810.player_field_0 = 1; +} + +struct UnkPlayerStruct *sub_8053AA8(void) +{ + struct UnkPlayerStruct playerStruct; + u8 mapType = Overworld_GetMapTypeOfSaveblockLocation(); + u16 v2 = cur_mapdata_block_role_at_screen_center_acc_to_sav1(); + u8 v4 = sub_8053B00(&gUnknown_02029810, v2, mapType); + playerStruct.player_field_0 = v4; + playerStruct.player_field_1 = sub_8053B60(&gUnknown_02029810, v4, v2, mapType); + gUnknown_02029810 = playerStruct; + return &gUnknown_02029810; +} + +u8 sub_8053B00(struct UnkPlayerStruct *playerStruct, u16 a2, u8 a3) +{ + if (a3 != 8 && FlagGet(SYS_CRUISE_MODE)) + return 1; + if (a3 == 5) + return 16; + if (MetatileBehavior_IsSurfableWaterOrUnderwater(a2) == 1) + return 8; + if (Overworld_IsBikingAllowed() != TRUE) + return 1; + if (playerStruct->player_field_0 == 2) + return 2; + if (playerStruct->player_field_0 != 4) + return 1; + return 4; +} + +u8 sub_8053B60(struct UnkPlayerStruct *playerStruct, u8 a2, u16 a3, u8 a4) +{ + if (FlagGet(SYS_CRUISE_MODE) && a4 == 6) + return 4; + if (MetatileBehavior_IsDeepSouthWarp(a3) == TRUE) + return 2; + if (MetatileBehavior_IsNonAnimDoor(a3) == TRUE || MetatileBehavior_IsDoor(a3) == TRUE) + return 1; + if (MetatileBehavior_IsSouthArrowWarp(a3) == TRUE) + return 2; + if (MetatileBehavior_IsNorthArrowWarp(a3) == TRUE) + return 1; + if (MetatileBehavior_IsWestArrowWarp(a3) == TRUE) + return 4; + if (MetatileBehavior_IsEastArrowWarp(a3) == TRUE) + return 3; + if ((playerStruct->player_field_0 == 16 && a2 == 8) + || (playerStruct->player_field_0 == 8 && a2 == 16)) + return playerStruct->player_field_1; + if (MetatileBehavior_IsLadder(a3) == TRUE) + return playerStruct->player_field_1; + return 1; +} + +u16 cur_mapdata_block_role_at_screen_center_acc_to_sav1(void) +{ + return MapGridGetMetatileBehaviorAt(gSaveBlock1.pos.x + 7, gSaveBlock1.pos.y + 7); +} + +bool32 Overworld_IsBikingAllowed(void) +{ + // is player in cycling road entrance? + if (gSaveBlock1.location.mapGroup == MAP_GROUP_ROUTE110_SEASIDE_CYCLING_ROAD_SOUTH_ENTRANCE + && (gSaveBlock1.location.mapNum == MAP_ID_ROUTE110_SEASIDE_CYCLING_ROAD_SOUTH_ENTRANCE + || gSaveBlock1.location.mapNum == MAP_ID_ROUTE110_SEASIDE_CYCLING_ROAD_NORTH_ENTRANCE)) + return TRUE; + + // is player indoor, in a secret base, or underwater? + if (gMapHeader.mapType == MAP_TYPE_INDOOR) + return FALSE; + if (gMapHeader.mapType == MAP_TYPE_SECRET_BASE) + return FALSE; + if (gMapHeader.mapType == MAP_TYPE_UNDERWATER) + return FALSE; + + // Thou shalt not bike on the sacred resting grounds of Kyogre/Groudon. + if (gSaveBlock1.location.mapGroup == MAP_GROUP_SEAFLOOR_CAVERN_ROOM9 + && gSaveBlock1.location.mapNum == MAP_ID_SEAFLOOR_CAVERN_ROOM9) + return FALSE; + if (gSaveBlock1.location.mapGroup == MAP_GROUP_CAVE_OF_ORIGIN_B4F + && gSaveBlock1.location.mapNum == MAP_ID_CAVE_OF_ORIGIN_B4F) + return FALSE; + + return TRUE; +} + +void SetDefaultFlashLevel(void) +{ + if (!gMapHeader.cave) + gSaveBlock1.flashLevel = 0; + else if (FlagGet(SYS_USE_FLASH)) + gSaveBlock1.flashLevel = 1; + else + gSaveBlock1.flashLevel = gMaxFlashLevel; +} + +void Overworld_SetFlashLevel(s32 flashLevel) +{ + if (flashLevel < 0 || flashLevel > gMaxFlashLevel) + flashLevel = 0; + gSaveBlock1.flashLevel = flashLevel; +} + +u8 Overworld_GetFlashLevel(void) +{ + return gSaveBlock1.flashLevel; +} + +void sub_8053D14(u16 mapDataId) +{ + gSaveBlock1.mapDataId = mapDataId; + gMapHeader.mapData = get_mapdata_header(); +} + +static bool16 ShouldLegendaryMusicPlayAtLocation(struct WarpData *warp) +{ + if (!FlagGet(SYS_WEATHER_CTRL)) + return FALSE; + if (warp->mapGroup == 0) + { + switch (warp->mapNum) + { + case MAP_ID_LILYCOVE_CITY: + case MAP_ID_MOSSDEEP_CITY: + case MAP_ID_SOOTOPOLIS_CITY: + case MAP_ID_EVER_GRANDE_CITY: + return TRUE; + case MAP_ID_ROUTE124: + case MAP_ID_ROUTE125: + case MAP_ID_ROUTE126: + case MAP_ID_ROUTE127: + case MAP_ID_ROUTE128: + return TRUE; + } + } + return FALSE; +} + +static bool16 IsInfiltratedWeatherInstitute(struct WarpData *warp) +{ + if (VarGet(VAR_WEATHER_INSTITUTE_CLEARED)) + return FALSE; + if (warp->mapGroup != MAP_GROUP_ROUTE119_WEATHER_INSTITUTE_1F) + return FALSE; + if (warp->mapNum == MAP_ID_ROUTE119_WEATHER_INSTITUTE_1F + || warp->mapNum == MAP_ID_ROUTE119_WEATHER_INSTITUTE_2F) + return TRUE; + return FALSE; +} + +static u16 GetLocationMusic(struct WarpData *warp) +{ + if (ShouldLegendaryMusicPlayAtLocation(warp) == TRUE) + return LEGENDARY_MUSIC; + else if (IsInfiltratedWeatherInstitute(warp) == TRUE) + return BGM_TOZAN; + else + return Overworld_GetMapHeaderByGroupAndId(warp->mapGroup, warp->mapNum)->music; +} + +u16 GetCurrLocationDefaultMusic(void) +{ + u16 music; + + // Play the desert music only when the sandstorm is active on Route 111. + if (gSaveBlock1.location.mapGroup == MAP_GROUP_ROUTE111 + && gSaveBlock1.location.mapNum == MAP_ID_ROUTE111 + && GetSav1Weather() == 8) + return BGM_ASHROAD; + + music = GetLocationMusic(&gSaveBlock1.location); + if (music != 0x7FFF) + { + return music; + } + else + { + if (gSaveBlock1.pos.x < 24) + return BGM_DOORO_X1; + else + return BGM_GRANROAD; + } +} + +u16 GetWarpDestinationMusic(void) +{ + u16 music = GetLocationMusic(&gWarpDestination); + if (music != 0x7FFF) + { + return music; + } + else + { + if (gSaveBlock1.location.mapGroup == MAP_GROUP_MAUVILLE_CITY + && gSaveBlock1.location.mapNum == MAP_ID_MAUVILLE_CITY) + return BGM_DOORO_X1; + else + return BGM_GRANROAD; + } +} + +void Overworld_ResetMapMusic(void) +{ + ResetMapMusic(); +} + +void Overworld_PlaySpecialMapMusic(void) +{ + u16 music = GetCurrLocationDefaultMusic(); + + if (music != LEGENDARY_MUSIC) + { + if (gSaveBlock1.savedMusic) + music = gSaveBlock1.savedMusic; + else if (Overworld_GetMapTypeOfSaveblockLocation() == MAP_TYPE_UNDERWATER) + music = BGM_DEEPDEEP; + else if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + music = BGM_NAMINORI; + } + + if (music != GetCurrentMapMusic()) + PlayNewMapMusic(music); +} + +void Overworld_SetSavedMusic(u16 songNum) +{ + gSaveBlock1.savedMusic = songNum; +} + +void Overworld_ClearSavedMusic(void) +{ + gSaveBlock1.savedMusic = 0; +} + +void sub_8053F0C(void) +{ + if (FlagGet(SPECIAL_FLAG_1) != TRUE) + { + u16 newMusic = GetWarpDestinationMusic(); + u16 currentMusic = GetCurrentMapMusic(); + if (newMusic != LEGENDARY_MUSIC) + { + if (currentMusic == BGM_DEEPDEEP || currentMusic == BGM_NAMINORI) + return; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING)) + newMusic = BGM_NAMINORI; + } + if (newMusic != currentMusic) + { + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) + FadeOutAndFadeInNewMapMusic(newMusic, 4, 4); + else + FadeOutAndPlayNewMapMusic(newMusic, 8); + } + } +} + +void Overworld_ChangeMusicToDefault(void) +{ + u16 currentMusic = GetCurrentMapMusic(); + if (currentMusic != GetCurrLocationDefaultMusic()) + FadeOutAndPlayNewMapMusic(GetCurrLocationDefaultMusic(), 8); +} + +void Overworld_ChangeMusicTo(u16 newMusic) +{ + u16 currentMusic = GetCurrentMapMusic(); + if (currentMusic != newMusic && currentMusic != LEGENDARY_MUSIC) + FadeOutAndPlayNewMapMusic(newMusic, 8); +} + +u8 GetMapMusicFadeoutSpeed(void) +{ + struct MapHeader *mapHeader = warp1_get_mapheader(); + if (Overworld_MapTypeIsIndoors(mapHeader->mapType) == TRUE) + return 2; + else + return 4; +} + +void sub_8053FF8(void) +{ + u16 music = GetWarpDestinationMusic(); + if (FlagGet(SPECIAL_FLAG_1) != TRUE && music != GetCurrentMapMusic()) + { + u8 speed = GetMapMusicFadeoutSpeed(); + FadeOutMapMusic(speed); + } +} + +bool8 sub_8054034(void) +{ + return IsNotWaitingForBGMStop(); +} + +void Overworld_FadeOutMapMusic(void) +{ + FadeOutMapMusic(4); +} + +static void PlayAmbientCry(void) +{ + s16 x, y; + s8 pan; + s8 volume; + + PlayerGetDestCoords(&x, &y); + if (sIsAmbientCryWaterMon == TRUE + && !MetatileBehavior_IsSurfableWaterOrUnderwater(MapGridGetMetatileBehaviorAt(x, y))) + return; + pan = (Random() % 88) + 212; + volume = (Random() % 30) + 50; + PlayCry2(sAmbientCrySpecies, pan, volume, 1); +} + +void UpdateAmbientCry(s16 *state, u16 *delayCounter) +{ + switch (*state) + { + case 0: + if (sAmbientCrySpecies == SPECIES_NONE) + *state = 4; + else + *state = 1; + break; + case 1: + *delayCounter = (Random() % 2400) + 1200; + *state = 3; + break; + case 2: + *delayCounter = (Random() % 1200) + 1200; + *state = 3; + break; + case 3: + (*delayCounter)--; + if (*delayCounter == 0) + { + PlayAmbientCry(); + *state = 2; + } + break; + case 4: + break; + } +} + +void ChooseAmbientCrySpecies(void) +{ + if ((gSaveBlock1.location.mapGroup == MAP_GROUP_ROUTE130 + && gSaveBlock1.location.mapNum == MAP_ID_ROUTE130) + && !IsMirageIslandPresent()) + { + // Only play water pokemon cries on this route + // when Mirage Island is not present + sIsAmbientCryWaterMon = TRUE; + sAmbientCrySpecies = GetLocalWaterMon(); + } + else + { + sAmbientCrySpecies = GetLocalWildMon(&sIsAmbientCryWaterMon); + } +} + +u8 GetMapTypeByGroupAndId(s8 mapGroup, s8 mapNum) +{ + return Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum)->mapType; +} + +u8 GetMapTypeByWarpData(struct WarpData *warp) +{ + return GetMapTypeByGroupAndId(warp->mapGroup, warp->mapNum); +} + +u8 Overworld_GetMapTypeOfSaveblockLocation(void) +{ + return GetMapTypeByWarpData(&gSaveBlock1.location); +} + +u8 get_map_type_from_warp0(void) +{ + return GetMapTypeByWarpData(&gUnknown_020297F0); +} + +bool8 is_map_type_1_2_3_5_or_6(u8 mapType) +{ + if (mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_UNDERWATER + || mapType == MAP_TYPE_CITY + || mapType == MAP_TYPE_6) + return TRUE; + else + return FALSE; +} + +bool8 Overworld_MapTypeAllowsTeleportAndFly(u8 mapType) +{ + if (mapType == MAP_TYPE_ROUTE + || mapType == MAP_TYPE_TOWN + || mapType == MAP_TYPE_6 + || mapType == MAP_TYPE_CITY) + return TRUE; + else + return FALSE; +} + +bool8 Overworld_MapTypeIsIndoors(u8 mapType) +{ + if (mapType == MAP_TYPE_INDOOR + || mapType == MAP_TYPE_SECRET_BASE) + return TRUE; + else + return FALSE; +} + +u8 unref_sub_8054260(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1.warp2.mapGroup, gSaveBlock1.warp2.mapNum)->regionMapSectionId; +} + +u8 sav1_map_get_name(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum)->regionMapSectionId; +} + +u8 sav1_map_get_battletype(void) +{ + return Overworld_GetMapHeaderByGroupAndId(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum)->battleType; +} + +void ResetSafariZoneFlag_(void) +{ + ResetSafariZoneFlag(); +} + +bool32 is_c1_link_related_active(void) +{ + if (gMain.callback1 == sub_8055354) + return TRUE; + else + return FALSE; +} + +void c1_overworld_normal(u16 newKeys, u16 heldKeys) +{ + struct FieldInput inputStruct; + + sub_8059204(); + FieldClearPlayerInput(&inputStruct); + FieldGetPlayerInput(&inputStruct, newKeys, heldKeys); + if (!ScriptContext2_IsEnabled()) + { + if (sub_8068024(&inputStruct) == 1) + { + ScriptContext2_Enable(); + HideMapNamePopup(); + } + else + { + player_step(inputStruct.dpadDirection, newKeys, heldKeys); + } + } +} + +void c1_overworld(void) +{ + if (gMain.callback2 == c2_overworld) + c1_overworld_normal(gMain.newKeys, gMain.heldKeys); +} + +void OverworldBasic(void) +{ + ScriptContext2_RunScript(); + RunTasks(); + AnimateSprites(); + CameraUpdate(); + UpdateCameraPanning(); + BuildOamBuffer(); + UpdatePaletteFade(); + sub_8072EDC(); +} + +// This CB2 is used when starting +void CB2_OverworldBasic(void) +{ + OverworldBasic(); +} + +void c2_overworld(void) +{ + int fading = (gPaletteFade.active != 0); + if (fading) + SetVBlankCallback(NULL); + OverworldBasic(); + if (fading) + SetFieldVBlankCallback(); +} + +void set_callback1(MainCallback cb) +{ + gMain.callback1 = cb; +} + +void sub_80543DC(u16 (*a1)(u32)) +{ + gUnknown_03000584 = a1; +} + +void sub_80543E8(void) +{ + if (gFieldCallback != NULL) + gFieldCallback(); + else + mapldr_default(); + gFieldCallback = NULL; +} + +void CB2_NewGame(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + NewGameInitData(); + player_avatar_init_params_reset(); + PlayTimeCounter_Start(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback = ExecuteTruckSequence; + do_load_map_stuff_loop(&gMain.state); + SetFieldVBlankCallback(); + set_callback1(c1_overworld); + SetMainCallback2(c2_overworld); +} + +void CB2_WhiteOut(void) +{ + u8 val; + gMain.state++; + if (gMain.state >= 120) + { + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + DoWhiteOut(); + player_avatar_init_params_reset(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + gFieldCallback = sub_8080B60; + val = 0; + do_load_map_stuff_loop(&val); + SetFieldVBlankCallback(); + set_callback1(c1_overworld); + SetMainCallback2(c2_overworld); + } +} + +void CB2_LoadMap(void) +{ + FieldClearVBlankHBlankCallbacks(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + set_callback1(NULL); + SetMainCallback2(sub_810CC80); + gMain.savedCallback = CB2_LoadMap2; +} + +void CB2_LoadMap2(void) +{ + do_load_map_stuff_loop(&gMain.state); + SetFieldVBlankCallback(); + set_callback1(c1_overworld); + SetMainCallback2(c2_overworld); +} + +void sub_8054534(void) +{ + if (!gMain.state) + { + FieldClearVBlankHBlankCallbacks(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + set_callback1(NULL); + } + if (sub_805493C(&gMain.state, 1)) + { + SetFieldVBlankCallback(); + set_callback1(c1_overworld); + SetMainCallback2(c2_overworld); + } +} + +void sub_8054588(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_8080AC4; + SetMainCallback2(c2_80567AC); +} + +void c2_80567AC(void) +{ + if (sub_805483C(&gMain.state)) + { + SetFieldVBlankCallback(); + set_callback1(sub_8055354); + sub_80543DC(sub_8055390); + SetMainCallback2(c2_overworld); + } +} + +void c2_exit_to_overworld_2_switch(void) +{ + if (is_c1_link_related_active() == TRUE) + { + SetMainCallback2(c2_exit_to_overworld_2_link); + } + else + { + FieldClearVBlankHBlankCallbacks(); + SetMainCallback2(c2_exit_to_overworld_2_local); + } +} + +void c2_exit_to_overworld_2_local(void) +{ + if (sub_8054A4C(&gMain.state)) + { + SetFieldVBlankCallback(); + SetMainCallback2(c2_overworld); + } +} + +void c2_exit_to_overworld_2_link(void) +{ + if (!sub_8055870() && sub_8054A9C(&gMain.state)) + SetMainCallback2(c2_overworld); +} + +void sub_805465C(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + sub_8054F70(); + set_callback1(sub_8055354); + sub_80543DC(sub_8055390); + gFieldCallback = sub_8080A3C; + ScriptContext1_Init(); + ScriptContext2_Disable(); + c2_exit_to_overworld_2_switch(); +} + +void sub_805469C(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = atk17_seteffectuser; + c2_exit_to_overworld_2_switch(); +} + +void sub_80546B8(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_80809B0; + c2_exit_to_overworld_2_switch(); +} + +void c2_exit_to_overworld_1_continue_scripts_restart_music(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_8080990; + c2_exit_to_overworld_2_switch(); +} + +void sub_80546F0(void) +{ + FieldClearVBlankHBlankCallbacks(); + gFieldCallback = sub_8080B60; + c2_exit_to_overworld_2_switch(); +} + +void sub_805470C(void) +{ + if (gMapHeader.flags == 1 && sub_80BBB24() == 1) + ShowMapNamePopup(); + sub_8080B60(); +} + +void CB2_ContinueSavedGame(void) +{ + FieldClearVBlankHBlankCallbacks(); + StopMapMusic(); + ResetSafariZoneFlag_(); + LoadSaveblockMapHeader(); + LoadSaveblockMapObjScripts(); + UnfreezeMapObjects(); + DoTimeBasedEvents(); + sub_805308C(); + sub_8055FC0(); + PlayTimeCounter_Start(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + if (GetSecretBase2Field_9() == 1) + { + ClearSecretBase2Field_9(); + sub_8053778(); + warp_in(); + SetMainCallback2(CB2_LoadMap); + } + else + { + gFieldCallback = sub_805470C; + set_callback1(c1_overworld); + c2_exit_to_overworld_2_switch(); + } +} + +void FieldClearVBlankHBlankCallbacks(void) +{ + u16 savedIme = REG_IME; + REG_IME = 0; + REG_IE &= ~INTR_FLAG_HBLANK; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = savedIme; + SetVBlankCallback(NULL); + SetHBlankCallback(NULL); +} + +void SetFieldVBlankCallback(void) +{ + SetVBlankCallback(VBlankCB_Field); +} + +void VBlankCB_Field(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + sub_8089668(); + sub_8057A58(); + TransferPlttBuffer(); + sub_8072E74(); +} + +void sub_8054814(void) +{ + u8 val = Overworld_GetFlashLevel(); + if (val) + { + sub_80815E0(val); + sub_80895F8(gUnknown_08216694); + } +} + +bool32 sub_805483C(u8 *a1) +{ + switch (*a1) + { + case 0: + FieldClearVBlankHBlankCallbacks(); + ScriptContext1_Init(); + ScriptContext2_Disable(); + sub_8054F70(); + sub_8054BA8(); + (*a1)++; + break; + case 1: + sub_8053994(1); + (*a1)++; + break; + case 2: + sub_8054D4C(1); + (*a1)++; + break; + case 3: + sub_8054E98(); + sub_8054D90(); + sub_8054EC8(); + sub_8054E60(); + (*a1)++; + break; + case 4: + sub_8054814(); + sub_8054C54(); + SetUpWindowConfig(&gWindowConfig_81E6C3C); + InitMenuWindow(&gWindowConfig_81E6CE4); + (*a1)++; + break; + case 5: + move_tilemap_camera_to_upper_left_corner(); + (*a1)++; + break; + case 6: + sub_8056D28(gMapHeader.mapData); + (*a1)++; + break; + case 7: + sub_8056D38(gMapHeader.mapData); + (*a1)++; + break; + case 8: + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*a1)++; + break; + case 9: + DrawWholeMapView(); + (*a1)++; + break; + case 10: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*a1)++; + break; + case 12: + sub_80543E8(); + (*a1)++; + break; + case 11: + (*a1)++; + break; + case 13: + return 1; + } + return 0; +} + +bool32 sub_805493C(u8 *a1, u32 a2) +{ + switch (*a1) + { + case 0: + FieldClearVBlankHBlankCallbacks(); + sub_8053994(a2); + (*a1)++; + break; + case 1: + sub_8054BA8(); + (*a1)++; + break; + case 2: + sub_8054D4C(a2); + (*a1)++; + break; + case 3: + mli4_mapscripts_and_other(); + sub_8054E34(); + (*a1)++; + break; + case 4: + sub_8054814(); + sub_8054C54(); + SetUpWindowConfig(&gWindowConfig_81E6C3C); + InitMenuWindow(&gWindowConfig_81E6CE4); + (*a1)++; + break; + case 5: + move_tilemap_camera_to_upper_left_corner(); + (*a1)++; + break; + case 6: + sub_8056D28(gMapHeader.mapData); + (*a1)++; + break; + case 7: + sub_8056D38(gMapHeader.mapData); + (*a1)++; + break; + case 8: + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*a1)++; + break; + case 9: + DrawWholeMapView(); + (*a1)++; + break; + case 10: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*a1)++; + break; + case 11: + if (gMapHeader.flags == 1 && sub_80BBB24() == 1) + ShowMapNamePopup(); + (*a1)++; + break; + case 12: + sub_80543E8(); + (*a1)++; + break; + case 13: + return 1; + } + return 0; +} + +bool32 sub_8054A4C(u8 *a1) +{ + switch (*a1) + { + case 0: + sub_8054BA8(); + sub_8054D4C(0); + sub_8054E20(); + sub_8054E34(); + (*a1)++; + break; + case 1: + sub_8054C2C(); + (*a1)++; + break; + case 2: + sub_80543E8(); + (*a1)++; + break; + case 3: + return 1; + } + return 0; +} + +bool32 sub_8054A9C(u8 *a1) +{ + switch (*a1) + { + case 0: + FieldClearVBlankHBlankCallbacks(); + sub_8054BA8(); + (*a1)++; + break; + case 1: + sub_8054D4C(1); + (*a1)++; + break; + case 2: + sub_8054F48(); + sub_8054E20(); + sub_8054E7C(); + (*a1)++; + break; + case 3: + sub_8054814(); + sub_8054C54(); + SetUpWindowConfig(&gWindowConfig_81E6C3C); + InitMenuWindow(&gWindowConfig_81E6CE4); + (*a1)++; + break; + case 4: + move_tilemap_camera_to_upper_left_corner(); + (*a1)++; + break; + case 5: + sub_8056D28(gMapHeader.mapData); + (*a1)++; + break; + case 6: + sub_8056D38(gMapHeader.mapData); + (*a1)++; + break; + case 7: + apply_map_tileset1_tileset2_palette(gMapHeader.mapData); + (*a1)++; + break; + case 8: + DrawWholeMapView(); + (*a1)++; + break; + case 9: + cur_mapheader_run_tileset_funcs_after_some_cpuset(); + (*a1)++; + break; + case 12: + sub_80543E8(); + (*a1)++; + break; + case 10: + case 11: + (*a1)++; + break; + case 13: + SetFieldVBlankCallback(); + (*a1)++; + return 1; + } + return 0; +} + +void do_load_map_stuff_loop(u8 *a1) +{ + while (!sub_805493C(a1, 0)) + ; +} + +void sub_8054BA8(void) +{ + u8 *addr; + u32 size; + + REG_DISPCNT = 0; + + remove_some_task(); + + DmaClear16(3, PLTT + 2, PLTT_SIZE - 2); + + addr = (void *)VRAM; + size = 0x18000; + while (1) + { + DmaFill16(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill16(3, 0, addr, size); + break; + } + } + + ResetOamRange(0, 128); + LoadOam(); +} + +void sub_8054C2C(void) +{ + sub_8054814(); + sub_8054C54(); + SetUpWindowConfig(&gWindowConfig_81E6C3C); + InitMenuWindow(&gWindowConfig_81E6CE4); + mapdata_load_assets_to_gpu_and_full_redraw(); +} + +void sub_8054C54(void) +{ + REG_MOSAIC = 0; + REG_WININ = 7967; + REG_WINOUT = 257; + REG_WIN0H = 255; + REG_WIN0V = 255; + REG_WIN1H = -1; + REG_WIN1V = -1; + REG_BLDCNT = gUnknown_081E29E0[1] | gUnknown_081E29E0[2] | gUnknown_081E29E0[3] | 0x1040; + REG_BLDALPHA = 1805; + *gBGHOffsetRegs[0] = 0; + *gBGVOffsetRegs[0] = 0; + *gBGControlRegs[0] = 0; + *gBGHOffsetRegs[1] = 0; + *gBGVOffsetRegs[1] = 0; + *gBGControlRegs[1] = 7489; + *gBGHOffsetRegs[2] = 0; + *gBGVOffsetRegs[2] = 0; + *gBGControlRegs[2] = 7234; + *gBGHOffsetRegs[3] = 0; + *gBGVOffsetRegs[3] = 0; + *gBGControlRegs[3] = 7747; + REG_DISPCNT = gUnknown_081E29D8[1] | 0x7060 | gUnknown_081E29D8[2] | gUnknown_081E29D8[0] | gUnknown_081E29D8[3]; +} + +void sub_8054D4C(u32 a1) +{ + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + dp12_8087EA4(); + ResetCameraUpdateInfo(); + InstallCameraPanAheadCallback(); + sub_805C7C4(0); + FieldEffectActiveListClear(); + InitFieldMessageBox(); + sub_807C828(); + sub_8080750(); + if (!a1) + SetUpFieldTasks(); + mapheader_run_script_with_tag_x5(); +} + +void sub_8054D90(void) +{ + gUnknown_0300489C = 0; + gUnknown_03004898 = 0; + sub_805AA98(); + sub_805B55C(0, 0); + mapheader_run_first_tag4_script_list_match(); +} + +void mli4_mapscripts_and_other(void) +{ + s16 x, y; + struct UnkPlayerStruct *player; + gUnknown_0300489C = 0; + gUnknown_03004898 = 0; + sub_805AA98(); + sav1_camera_get_focus_coords(&x, &y); + player = sub_8053AA8(); + InitPlayerAvatar(x, y, player->player_field_1, gSaveBlock2.playerGender); + SetPlayerAvatarTransitionFlags(player->player_field_0); + player_avatar_init_params_reset(); + sub_805B55C(0, 0); + ResetBerryTreeSparkleFlags(); + mapheader_run_first_tag4_script_list_match(); +} + +void sub_8054E20(void) +{ + sub_805B710(0, 0); + RotatingGate_InitPuzzleAndGraphics(); +} + +void sub_8054E34(void) +{ + gMapObjects[gPlayerAvatar.mapObjectId].mapobj_bit_15 = 1; + InitCameraUpdateCallback(gPlayerAvatar.spriteId); +} + +void sub_8054E60(void) +{ + InitCameraUpdateCallback(sub_8055AE8(gUnknown_03004860)); +} + +void sub_8054E7C(void) +{ + InitCameraUpdateCallback(sub_8055AE8(gUnknown_03004860)); +} + +void sub_8054E98(void) +{ + u16 x, y; + sav1_camera_get_focus_coords(&x, &y); + sub_8056C50(x + gUnknown_03004860, y); +} + +void sub_8054EC8(void) +{ + u16 i; + u16 x, y; + + sav1_camera_get_focus_coords(&x, &y); + x -= gUnknown_03004860; + + for (i = 0; i < gFieldLinkPlayerCount; i++) + { + SpawnLinkPlayerMapObject(i, i + x, y, gLinkPlayers[i].gender); + CreateLinkPlayerSprite(i); + } + + sub_8055340(word_3002910); +} + +void sub_8054F48(void) +{ + u16 i; + for (i = 0; i < gFieldLinkPlayerCount; i++) + CreateLinkPlayerSprite(i); +} + +void sub_8054F70(void) +{ + int i; + for (i = 0; i < 4; i++) + gUnknown_03000580[i] = 0x80; +} + +bool32 sub_8054F88(u16 a1) +{ + int i; + int count = gFieldLinkPlayerCount; + + for (i = 0; i < count; i++) + if (gUnknown_03000580[i] != a1) + return FALSE; + return TRUE; +} + +bool32 sub_8054FC0(u16 a1) +{ + int i; + int count = gFieldLinkPlayerCount; + + for (i = 0; i < count; i++) + if (gUnknown_03000580[i] == a1) + return TRUE; + return FALSE; +} + +void sub_8054FF8(u32 a1, u16 a2, struct UnkStruct_8054FF8 *a3, u16 *a4) +{ + u8 *script; + + if (gUnknown_03000580[a1] == 0x80) + { + script = sub_8055648(a3); + if (script) + { + *a4 = sub_8055758(script); + gUnknown_03000580[a1] = 0x81; + if (a3->b) + { + sub_80543DC(sub_80553E4); + sub_8055808(script); + } + return; + } + if (sub_8054FC0(0x83) == 1) + { + gUnknown_03000580[a1] = 0x81; + if (a3->b) + { + sub_80543DC(sub_80553E4); + sub_805585C(); + } + return; + } + switch (a2) + { + case 24: + if (sub_8055630(a3)) + { + gUnknown_03000580[a1] = 0x81; + if (a3->b) + { + sub_80543DC(sub_80553E4); + sub_80557F4(); + } + } + break; + case 18: + if (sub_8055660(a3) == 1) + { + gUnknown_03000580[a1] = 0x81; + if (a3->b) + { + sub_80543DC(sub_80553E4); + sub_8055824(); + } + } + break; + case 25: + script = sub_805568C(a3); + if (script) + { + gUnknown_03000580[a1] = 0x81; + if (a3->b) + { + sub_80543DC(sub_80553E4); + sub_8055840(script); + } + } + break; + case 27: + if (sub_8055618(a3)) + { + gUnknown_03000580[a1] = 0x81; + if (a3->b) + { + sub_80543DC(sub_8055408); + sub_80557E8(); + } + } + break; + case 28: + if (sub_8055618(a3)) + { + gUnknown_03000580[a1] = 0x81; + if (a3->b) + { + sub_80543DC(sub_8055438); + sub_80557E8(); + } + } + break; + } + } + + switch (a2) + { + case 23: + gUnknown_03000580[a1] = 0x83; + break; + case 22: + gUnknown_03000580[a1] = 0x82; + break; + case 26: + gUnknown_03000580[a1] = 0x80; + if (a3->b) + sub_80543DC(sub_8055390); + break; + case 29: + if (gUnknown_03000580[a1] == 0x82) + gUnknown_03000580[a1] = 0x81; + break; + } +} + +void sub_8055218(u16 *a1, int a2) +{ + struct UnkStruct_8054FF8 st; + int i; + for (i = 0; i < 4; i++) + { + u16 v5 = a1[i]; + u16 v8 = 0; + sub_80555B0(i, a2, &st); + sub_8054FF8(i, v5, &st, &v8); + if (gUnknown_03000580[i] == 0x80) + v8 = sub_805530C(v5); + sub_8055BFC(i, v8); + } +} + +void sub_8055280(u16 a1) +{ + if (a1 >= 17 && a1 < 30) + word_3004858 = a1; + else + word_3004858 = 17; +} + +u16 sub_80552B0(u32 a1) +{ + if (gMain.heldKeys & DPAD_UP) + { + return 19; + } + else if (gMain.heldKeys & DPAD_DOWN) + { + return 18; + } + else if (gMain.heldKeys & DPAD_LEFT) + { + return 20; + } + else if (gMain.heldKeys & DPAD_RIGHT) + { + return 21; + } + else if (gMain.newKeys & START_BUTTON) + { + return 24; + } + else if (gMain.newKeys & A_BUTTON) + { + return 25; + } + else + { + return 17; + } +} + +u16 sub_805530C(u16 a1) +{ + switch (a1) + { + case 21: + return 4; + case 20: + return 3; + case 19: + return 1; + case 18: + return 2; + default: + return 0; + } +} + +void sub_8055340(u16 *a1) +{ + int i; + for (i = 0; i < 4; i++) + a1[i] = 17; +} + +void sub_8055354(void) +{ + u8 val = gUnknown_03004860; + sub_8055218(word_3002910, val); + sub_8055280(gUnknown_03000584(val)); + sub_8055340(word_3002910); +} + +u16 sub_8055390(u32 a1) +{ + if (ScriptContext2_IsEnabled() == 1) + return 17; + if (gLink.recvQueue.count > 4) + return 27; + if (gLink.sendQueue.count <= 4) + return sub_80552B0(a1); + return 28; +} + +u16 sub_80553E0(u32 a1) +{ + return 17; +} + +u16 sub_80553E4(u32 a1) +{ + u16 retVal; + if (ScriptContext2_IsEnabled() == 1) + { + retVal = 17; + } + else + { + retVal = 26; + sub_80543DC(sub_80553E0); + } + return retVal; +} + +u16 sub_8055408(u32 a1) +{ + u16 retVal; + if (gLink.recvQueue.count > 2) + { + retVal = 17; + } + else + { + retVal = 26; + ScriptContext2_Disable(); + sub_80543DC(sub_80553E0); + } + return retVal; +} + +u16 sub_8055438(u32 a1) +{ + u16 retVal; + if (gLink.sendQueue.count > 2) + { + retVal = 17; + } + else + { + retVal = 26; + ScriptContext2_Disable(); + sub_80543DC(sub_80553E0); + } + return retVal; +} + +u16 sub_8055468(u32 a1) +{ + return 17; +} + +u16 sub_805546C(u32 linkPlayerId) +{ + if (gUnknown_03000580[linkPlayerId] == 0x82 && (gMain.newKeys & B_BUTTON)) + { + sub_80543DC(sub_8055468); + return 29; + } + else + { + return 17; + } +} + +u16 sub_80554A4(u32 a1) +{ + sub_80543DC(sub_805546C); + return 22; +} + +u16 sub_80554B8(u32 a1) +{ + return 17; +} + +u16 sub_80554BC(u32 a1) +{ + if (sub_8054F88(0x83) == TRUE) + { + ScriptContext1_SetupScript(gUnknown_081A4508); + sub_80543DC(sub_80554B8); + } + return 17; +} + +u16 sub_80554E4(u32 a1) +{ + sub_80543DC(sub_80554BC); + return 23; +} + +u32 sub_80554F8(void) +{ + if (sub_8054FC0(0x83) == TRUE) + return 2; + if (gUnknown_03000584 == sub_805546C && gUnknown_03000580[gUnknown_03004860] != 0x82) + return 0; + if (gUnknown_03000584 == sub_8055468 && gUnknown_03000580[gUnknown_03004860] == 0x81) + return 2; + return sub_8054F88(0x82); +} + +bool32 unref_sub_8055568(void) +{ + return sub_8054FC0(0x83); +} + +u16 sub_8055574(void) +{ + sub_80543DC(sub_80554A4); + return 0; +} + +u16 sub_8055588(void) +{ + sub_80543DC(sub_80553E4); + return 0; +} + +u16 sub_805559C(void) +{ + sub_80543DC(sub_80554E4); + return 0; +} + +void sub_80555B0(int linkPlayerId, int a2, struct UnkStruct_8054FF8 *a3) +{ + s16 x, y; + + a3->a = linkPlayerId; + a3->b = (linkPlayerId == a2) ? 1 : 0; + a3->c = gLinkPlayerMapObjects[linkPlayerId].mode; + a3->d = sub_8055B30(linkPlayerId); + sub_8055B08(linkPlayerId, &x, &y); + a3->sub.x = x; + a3->sub.y = y; + a3->sub.height = sub_8055B50(linkPlayerId); + a3->field_C = MapGridGetMetatileBehaviorAt(x, y); +} + +bool32 sub_8055618(struct UnkStruct_8054FF8 *a1) +{ + u8 v1 = a1->c; + if (v1 == 2 || v1 == 0) + return TRUE; + else + return FALSE; +} + +bool32 sub_8055630(struct UnkStruct_8054FF8 *a1) +{ + u8 v1 = a1->c; + if (v1 == 2 || v1 == 0) + return TRUE; + else + return FALSE; +} + +u8 *sub_8055648(struct UnkStruct_8054FF8 *a1) +{ + if (a1->c != 2) + return 0; + return sub_8068E24(&a1->sub); +} + +bool32 sub_8055660(struct UnkStruct_8054FF8 *a1) +{ + if (a1->c != 2 && a1->c != 0) + return FALSE; + if (!MetatileBehavior_IsSouthArrowWarp(a1->field_C)) + return FALSE; + if (a1->d != 1) + return FALSE; + return TRUE; +} + +u8 *sub_805568C(struct UnkStruct_8054FF8 *a1) +{ + struct MapPosition unkStruct; + u8 linkPlayerId; + + if (a1->c && a1->c != 2) + return 0; + + unkStruct = a1->sub; + unkStruct.x += gUnknown_0821664C[a1->d].x; + unkStruct.y += gUnknown_0821664C[a1->d].y; + unkStruct.height = 0; + linkPlayerId = GetLinkPlayerIdAt(unkStruct.x, unkStruct.y); + + if (linkPlayerId != 4) + { + if (!a1->b) + return TradeRoom_TooBusyToNotice; + if (gUnknown_03000580[linkPlayerId] != 0x80) + return TradeRoom_TooBusyToNotice; + if (!sub_8083BF4(linkPlayerId)) + return TradeRoom_ReadTrainerCard1; + else + return TradeRoom_ReadTrainerCard2; + } + + return sub_80682A8(&unkStruct, a1->field_C, a1->d); +} + +u16 sub_8055758(u8 *script) +{ + if (script == DoubleBattleColosseum_EventScript_1A4383) + return 10; + if (script == DoubleBattleColosseum_EventScript_1A439E) + return 9; + if (script == DoubleBattleColosseum_EventScript_1A43B9) + return 10; + if (script == DoubleBattleColosseum_EventScript_1A43D4) + return 9; + if (script == RecordCorner_EventScript_1A4418) + return 10; + if (script == RecordCorner_EventScript_1A442D) + return 9; + if (script == RecordCorner_EventScript_1A4442) + return 10; + if (script == RecordCorner_EventScript_1A4457) + return 9; + if (script == SingleBattleColosseum_EventScript_1A436F) + return 10; + if (script == SingleBattleColosseum_EventScript_1A4379) + return 9; + if (script == TradeCenter_EventScript_1A43F0) + return 10; + if (script == TradeCenter_EventScript_1A43FA) + return 9; + return 0; +} + +void sub_80557E8(void) +{ + ScriptContext2_Enable(); +} + +void sub_80557F4(void) +{ + PlaySE(SE_WIN_OPEN); + sub_8071310(); + ScriptContext2_Enable(); +} + +void sub_8055808(u8 *script) +{ + PlaySE(SE_SELECT); + ScriptContext1_SetupScript(script); + ScriptContext2_Enable(); +} + +void sub_8055824(void) +{ + PlaySE(SE_WIN_OPEN); + ScriptContext1_SetupScript(TradeRoom_PromptToCancelLink); + ScriptContext2_Enable(); +} + +void sub_8055840(u8 *script) +{ + PlaySE(SE_SELECT); + ScriptContext1_SetupScript(script); + ScriptContext2_Enable(); +} + +void sub_805585C(void) +{ + ScriptContext1_SetupScript(TradeRoom_TerminateLink); + ScriptContext2_Enable(); +} + +bool32 sub_8055870(void) +{ + if (!is_c1_link_related_active()) + return 0; + if (gLink.recvQueue.count >= 3) + gUnknown_03000588 = 1; + else + gUnknown_03000588 = 0; + return gUnknown_03000588; +} + +bool32 sub_80558AC(void) +{ + u8 temp; + + if (is_c1_link_related_active() != TRUE) + return FALSE; + + if (sub_8007B24() != TRUE) + return FALSE; + + if (gUnknown_03000584 == sub_8055408) + return TRUE; + + if (gUnknown_03000584 != sub_80553E4) + return FALSE; + + temp = gUnknown_03000588; + gUnknown_03000588 = 0; + + if (temp == TRUE) + return TRUE; + + if (gPaletteFade.active && gPaletteFade.softwareFadeFinishing) + return TRUE; + + return FALSE; +} + +bool32 sub_8055910(void) +{ + if (is_c1_link_related_active() != TRUE) + return FALSE; + + if (sub_8007B24() != TRUE) + return FALSE; + + if (gUnknown_03000584 == sub_8055438) + return TRUE; + + return FALSE; +} + +bool32 sub_8055940(void) +{ + if (!sub_8007B24()) + return FALSE; + return TRUE; +} + +void ZeroLinkPlayerMapObject(struct LinkPlayerMapObject *linkPlayerMapObj) +{ + memset(linkPlayerMapObj, 0, sizeof(struct LinkPlayerMapObject)); +} + +void strange_npc_table_clear(void) +{ + memset(gLinkPlayerMapObjects, 0, sizeof(gLinkPlayerMapObjects)); +} + +void ZeroMapObject(struct MapObject *mapObj) +{ + memset(mapObj, 0, sizeof(struct MapObject)); +} + +void SpawnLinkPlayerMapObject(u8 linkPlayerId, s16 x, s16 y, u8 a4) +{ + u8 mapObjId = sub_805AB54(); + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + + ZeroLinkPlayerMapObject(linkPlayerMapObj); + ZeroMapObject(mapObj); + + linkPlayerMapObj->active = 1; + linkPlayerMapObj->linkPlayerId = linkPlayerId; + linkPlayerMapObj->mapObjId = mapObjId; + linkPlayerMapObj->mode = 0; + + mapObj->active = 1; + mapObj->mapobj_bit_1 = a4; + mapObj->mapobj_unk_19 = 2; + mapObj->spriteId = 64; + + InitLinkPlayerMapObjectPos(mapObj, x, y); +} + +void InitLinkPlayerMapObjectPos(struct MapObject *mapObj, s16 x, s16 y) +{ + mapObj->coords2.x = x; + mapObj->coords2.y = y; + mapObj->coords3.x = x; + mapObj->coords3.y = y; + sub_80603CC(x, y, &mapObj->coords1.x, &mapObj->coords1.y); + mapObj->coords1.x += 8; + FieldObjectUpdateZCoord(mapObj); +} + +void unref_sub_8055A6C(u8 linkPlayerId, u8 a2) +{ + if (gLinkPlayerMapObjects[linkPlayerId].active) + { + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + mapObj->mapobj_unk_19 = a2; + } +} + +void unref_sub_8055A9C(u8 linkPlayerId) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + if (mapObj->spriteId != 64 ) + DestroySprite(&gSprites[mapObj->spriteId]); + linkPlayerMapObj->active = 0; + mapObj->active = 0; +} + +u8 sub_8055AE8(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->spriteId; +} + +void sub_8055B08(u8 linkPlayerId, u16 *x, u16 *y) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + *x = mapObj->coords2.x; + *y = mapObj->coords2.y; +} + +u8 sub_8055B30(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->mapobj_unk_19; +} + +u8 sub_8055B50(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return mapObj->mapobj_unk_0B_0; +} + +s32 unref_sub_8055B74(u8 linkPlayerId) +{ + u8 mapObjId = gLinkPlayerMapObjects[linkPlayerId].mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + return 16 - (s8)mapObj->mapobj_unk_21; +} + +u8 GetLinkPlayerIdAt(s16 x, s16 y) +{ + u8 i; + for (i = 0; i < 4; i++) + { + if (gLinkPlayerMapObjects[i].active + && (gLinkPlayerMapObjects[i].mode == 0 || gLinkPlayerMapObjects[i].mode == 2)) + { + struct MapObject *mapObj = &gMapObjects[gLinkPlayerMapObjects[i].mapObjId]; + if (mapObj->coords2.x == x && mapObj->coords2.y == y) + return i; + } + } + return 4; +} + +void sub_8055BFC(u8 linkPlayerId, u8 a2) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + + if (linkPlayerMapObj->active) + { + if (a2 > 10) + mapObj->mapobj_bit_2 = 1; + else + gUnknown_082166D8[gUnknown_082166A0[linkPlayerMapObj->mode](linkPlayerMapObj, mapObj, a2)](linkPlayerMapObj, mapObj); + } +} + +static u8 sub_8055C68(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return gUnknown_082166AC[a3](linkPlayerMapObj, mapObj, a3); +} + +static u8 sub_8055C88(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return 1; +} + +static u8 sub_8055C8C(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return gUnknown_082166AC[a3](linkPlayerMapObj, mapObj, a3); +} + +static u8 sub_8055CAC(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + return 0; +} + +static u8 sub_8055CB0(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + s16 x, y; + + mapObj->mapobj_unk_19 = npc_something3(a3, mapObj->mapobj_unk_19); + FieldObjectMoveDestCoords(mapObj, mapObj->mapobj_unk_19, &x, &y); + + if (LinkPlayerDetectCollision(linkPlayerMapObj->mapObjId, mapObj->mapobj_unk_19, x, y)) + { + return 0; + } + else + { + mapObj->mapobj_unk_21 = 16; + npc_coords_shift(mapObj, x, y); + FieldObjectUpdateZCoord(mapObj); + return 1; + } +} + +static u8 sub_8055D18(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj, u8 a3) +{ + mapObj->mapobj_unk_19 = npc_something3(a3, mapObj->mapobj_unk_19); + return 0; +} + +static void sub_8055D30(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj) +{ + linkPlayerMapObj->mode = 0; +} + +static void sub_8055D38(struct LinkPlayerMapObject *linkPlayerMapObj, struct MapObject *mapObj) +{ + mapObj->mapobj_unk_21--; + linkPlayerMapObj->mode = 1; + MoveCoords(mapObj->mapobj_unk_19, &mapObj->coords1.x, &mapObj->coords1.y); + if (!mapObj->mapobj_unk_21) + { + npc_coords_shift_still(mapObj); + linkPlayerMapObj->mode = 2; + } +} + +u8 npc_something3(u8 a1, u8 a2) +{ + switch (a1 - 1) + { + case 0: + case 6: + return 2; + case 1: + case 7: + return 1; + case 2: + case 8: + return 3; + case 3: + case 9: + return 4; + } + return a2; +} + +u8 LinkPlayerDetectCollision(u8 selfMapObjId, u8 a2, s16 x, s16 y) +{ + u8 i; + for (i = 0; i < 16; i++) + { + if (i != selfMapObjId) + { + if ((gMapObjects[i].coords2.x == x && gMapObjects[i].coords2.y == y) + || (gMapObjects[i].coords3.x == x && gMapObjects[i].coords3.y == y)) + { + return 1; + } + } + } + return MapGridIsImpassableAt(x, y); +} + +void CreateLinkPlayerSprite(u8 linkPlayerId) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[linkPlayerId]; + u8 mapObjId = linkPlayerMapObj->mapObjId; + struct MapObject *mapObj = &gMapObjects[mapObjId]; + struct Sprite *sprite; + + if (linkPlayerMapObj->active) + { + u8 val = GetRivalAvatarGraphicsIdByStateIdAndGender(0, mapObj->mapobj_bit_1); + mapObj->spriteId = AddPseudoFieldObject(val, SpriteCB_LinkPlayer, 0, 0, 0); + sprite = &gSprites[mapObj->spriteId]; + sprite->coordOffsetEnabled = TRUE; + sprite->data0 = linkPlayerId; + mapObj->mapobj_bit_2 = 0; + } +} + +void SpriteCB_LinkPlayer(struct Sprite *sprite) +{ + struct LinkPlayerMapObject *linkPlayerMapObj = &gLinkPlayerMapObjects[sprite->data0]; + struct MapObject *mapObj = &gMapObjects[linkPlayerMapObj->mapObjId]; + sprite->pos1.x = mapObj->coords1.x; + sprite->pos1.y = mapObj->coords1.y; + SetObjectSubpriorityByZCoord(mapObj->elevation, sprite, 1); + sprite->oam.priority = ZCoordToPriority(mapObj->elevation); + if (!linkPlayerMapObj->mode) + StartSpriteAnim(sprite, FieldObjectDirectionToImageAnimId(mapObj->mapobj_unk_19)); + else + StartSpriteAnimIfDifferent(sprite, get_go_image_anim_num(mapObj->mapobj_unk_19)); + sub_806487C(sprite, 0); + if (mapObj->mapobj_bit_2) + { + sprite->invisible = ((sprite->data7 & 4) >> 2); + sprite->data7++; + } +} diff --git a/src/field/party_menu.c b/src/field/party_menu.c new file mode 100644 index 000000000..39477e293 --- /dev/null +++ b/src/field/party_menu.c @@ -0,0 +1,1494 @@ +#include "global.h" +#include "party_menu.h" +#include "battle.h" +#include "battle_interface.h" +#include "battle_party_menu.h" +#include "data2.h" +#include "event_data.h" +#include "item.h" +#include "item_use.h" +#include "mail_data.h" +#include "main.h" +#include "menu.h" +#include "palette.h" +#include "pokemon.h" +#include "pokemon_item_effect.h" +#include "pokemon_menu.h" +#include "pokemon_summary_screen.h" +#include "rom_8077ABC.h" +#include "rom_8094928.h" +#include "songs.h" +#include "sound.h" +#include "species.h" +#include "sprite.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "sprite.h" +#include "palette.h" +#include "event_data.h" +#include "main.h" +#include "item.h" +#include "battle_interface.h" +#include "species.h" +#include "party_menu.h" + +struct Unk201C000 +{ + /*0x00*/ struct Pokemon *pokemon; + /*0x04*/ u8 unk4; + /*0x05*/ u8 unk5; + /*0x06*/ u16 unk6; + /*0x08*/ u16 unk8; + /*0x0A*/ u8 pad_0A[2]; + /*0x0C*/ s32 unkC; + /*0x10*/ TaskFunc unk10; + /*0x14*/ TaskFunc unk14; +}; + +struct Unk201F000 +{ + u8 filler0[0xE00]; + u8 unkE00[3]; // not sure if this is an array or struct, or how big it is +}; + +struct UnknownStruct5 +{ + u8 unk0; + u8 unk1; + u16 *unk4; +}; + +#define ewram1C000 (*(struct Unk201C000 *)(ewram + 0x1C000)) +#define ewram1F000 (*(struct Unk201F000 *)(ewram + 0x1F000)) + +extern u8 gUnknown_0202E8F4; +extern u8 gUnknown_0202E8F6; +extern u16 gUnknown_0202E8F8; +extern u8 gUnknown_0202E8FA; +extern u8 gLastFieldPokeMenuOpened; +extern u8 gPlayerPartyCount; +extern s32 gBattleMoveDamage; + +//extern const u16 gUnknown_083769A8[][6]; +//extern const u8 gUnknown_083769A8[][12]; +extern void *const gUnknown_08376858[][6]; +extern const u8 gUnknown_083769A8[]; +extern const u8 gUnknown_08376D1C[DATA_COUNT]; +extern const u16 gUnknown_08376504[]; +extern void (*const gUnknown_08376B54[])(u8); +extern const u8 *const gUnknown_08376D04[DATA_COUNT]; +extern const struct UnknownStruct5 gUnknown_08376BB4[][6]; + +static void sub_806E884(u8 taskId); + +/* +void sub_806AEDC(void) +{ + const struct UnknownStruct5 *r5; + s32 i; + + AnimateSprites(); + BuildOamBuffer(); + r5 = gUnknown_08376BB4[gUnknown_0202E8FA]; + for (i = 0; i < 6; i++) + sub_800142C(r5[i].unk0 * 8, r5[i].unk1 * 8, r5[i].unk4, 0, (i << 5) | 0x200); + RunTasks(); + UpdatePaletteFade(); +} +*/ + +#if ENGLISH +#define WINDOW_LEFT (3) +#define WINDOW_RIGHT (26) +#elif GERMAN +#define WINDOW_LEFT (0) +#define WINDOW_RIGHT (29) +#endif + +u8 sub_806E834(const u8 *message, u8 arg1) +{ + u8 taskId; + + gUnknown_0202E8F6 = 1; + + MenuDrawTextWindow(WINDOW_LEFT, 14, WINDOW_RIGHT, 19); + MenuPrintMessage(message, WINDOW_LEFT + 1, 15); + + taskId = CreateTask(sub_806E884, 1); + gTasks[taskId].data[0] = arg1; + + return taskId; +} + +static void sub_806E884(u8 taskId) +{ + if (MenuUpdateWindowText()) + { + gUnknown_0202E8F6 = 0; + if (gTasks[taskId].data[0] == 0) + MenuZeroFillWindowRect(WINDOW_LEFT, 14, WINDOW_RIGHT, 19); + DestroyTask(taskId); + } +} + +void sub_806E8D0(u8 taskId, u16 b, TaskFunc c) +{ + ewram1C000.unk10 = c; + ewram1C000.unk4 = taskId; + ewram1C000.unk5 = sub_806CA38(taskId); + ewram1C000.unk6 = b; + ewram1C000.pokemon = &gPlayerParty[ewram1C000.unk5]; +} + +bool8 PartyMenuUpdateMonHeldItem(struct Pokemon *pkmn, u16 item) +{ + u8 itemData[2]; + + if (ItemIsMail(item) == TRUE) + { + if (GiveMailToMon(pkmn, item) == 0xFF) + return TRUE; + gUnknown_0202E8F4 = 2; + } + else + { + gUnknown_0202E8F4 = 1; + } + + itemData[0] = item; + itemData[1] = item >> 8; + SetMonData(pkmn, MON_DATA_HELD_ITEM, itemData); + return FALSE; +} + +void PartyMenuTryGiveMonHeldItem(u8 taskId, u16 newItem, TaskFunc c) +{ + u16 currentItem; + + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, newItem, c); + currentItem = GetMonData(ewram1C000.pokemon, MON_DATA_HELD_ITEM); + gUnknown_0202E8F4 = 0; + gUnknown_0202E8F8 = 0; + if (currentItem != 0) + { + if (ItemIsMail(currentItem) == TRUE) + { + sub_806E834(gOtherText_MailMustBeRemoved, 1); + CreateTask(party_menu_link_mon_held_item_object, 5); + } + else + { + GetMonNickname(ewram1C000.pokemon, gStringVar1); + CopyItemName(currentItem, gStringVar2); + StringExpandPlaceholders(gStringVar4, gOtherText_AlreadyHolding); + sub_806E834(gStringVar4, 1); + CreateTask(Task_ConfirmGiveHeldItem, 5); + if (ItemIsMail(newItem) == TRUE) + gUnknown_0202E8F8 = currentItem; + } + } + else + { + PartyMenuUpdateMonHeldItem(ewram1C000.pokemon, newItem); + RemoveBagItem(newItem, 1); + if (ItemIsMail(newItem)) + { + gTasks[taskId].func = c; + } + else + { + DisplayGiveHeldItemMessage(ewram1C000.unk5, newItem, 1); + CreateTask(party_menu_link_mon_held_item_object, 5); + } + } +} + +void party_menu_link_mon_held_item_object(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + SetHeldItemIconVisibility(ewram1C000.unk4, ewram1C000.unk5); + gTasks[ewram1C000.unk4].func = ewram1C000.unk10; + DestroyTask(taskId); + } +} + +void PartyMenuTryGiveMonHeldItem_806EACC(u8 taskId) +{ + s8 selection = ProcessMenuInputNoWrap_(); + + if (selection == 0) + { + u16 currentItem; + + MenuZeroFillWindowRect(23, 8, 29, 13); + currentItem = GetMonData(ewram1C000.pokemon, MON_DATA_HELD_ITEM); + RemoveBagItem(ewram1C000.unk6, 1); + if (AddBagItem(currentItem, 1) == TRUE) + { + PartyMenuUpdateMonHeldItem(ewram1C000.pokemon, ewram1C000.unk6); + if (ItemIsMail(ewram1C000.unk6)) + { + DisplayTakeHeldItemMessage(ewram1C000.unk5, currentItem, 1); + } + else + { + CopyItemName(ewram1C000.unk6, gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_TakenAndReplaced); + sub_806E834(gStringVar4, 1); + } + } + else + { + sub_806E834(gOtherText_BagFullCannotRemoveItem, 0); + AddBagItem(ewram1C000.unk6, 1); + } + } + else + { + if (selection != 1 && selection != -1) + return; + if (selection == -1) + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(23, 8, 29, 13); + } + gTasks[taskId].func = party_menu_link_mon_held_item_object; +} + +void Task_ConfirmGiveHeldItem(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + DisplayYesNoMenu(23, 8, 1); + gTasks[taskId].func = PartyMenuTryGiveMonHeldItem_806EACC; + } +} + +void DisplayGiveHeldItemMessage(u8 a, u16 b, u8 c) +{ + GetMonNickname(&gPlayerParty[a], gStringVar1); + CopyItemName(b, gStringVar2); + StringExpandPlaceholders(gStringVar4, gOtherText_WasGivenToHold); + sub_806E834(gStringVar4, c); +} + + +// Not sure about this one for now. +/* +void PartyMenuTryGiveMonMail(u8 taskId, TaskFunc func) +{ + u16 currentItem; + struct MailStruct *r4; + + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, 0, func); + currentItem = GetMonData(ewram1C000.pokemon, MON_DATA_HELD_ITEM); + gUnknown_0202E8F4 = 0; + r4 = &gSaveBlock1.mail[ewram1F000.unkE00[0] + ewram1F000.unkE00[2]]; + if (currentItem != 0) + { + sub_806E834(gOtherText_PokeHoldingItemCantMail, 1); + CreateTask(party_menu_link_mon_held_item_object, 5); + } + else + { + GiveMailToMon2(ewram1C000.pokemon, r4); + ClearMailStruct(r4); + sub_806E834(gOtherText_MailTransferredMailbox, 1); + CreateTask(party_menu_link_mon_held_item_object, 5); + } +} +*/ +__attribute__((naked)) +void PartyMenuTryGiveMonMail(u8 taskId, TaskFunc func) +{ + asm(".syntax unified\n\ + push {r4,r5,lr}\n\ + adds r2, r1, 0\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + ldr r3, _0806ECA0 @ =gTasks\n\ + lsls r1, r0, 2\n\ + adds r1, r0\n\ + lsls r1, 3\n\ + adds r1, r3\n\ + ldr r3, _0806ECA4 @ =TaskDummy\n\ + str r3, [r1]\n\ + movs r1, 0\n\ + bl sub_806E8D0\n\ + ldr r5, _0806ECA8 @ =0x0201c000\n\ + ldr r0, [r5]\n\ + movs r1, 0xC\n\ + bl GetMonData\n\ + lsls r0, 16\n\ + ldr r2, _0806ECAC @ =gUnknown_0202E8F4\n\ + movs r1, 0\n\ + strb r1, [r2]\n\ + movs r1, 0xF8\n\ + lsls r1, 6\n\ + adds r2, r5, r1\n\ + ldrb r1, [r2]\n\ + adds r1, 0x6\n\ + ldrb r2, [r2, 0x2]\n\ + adds r1, r2\n\ + lsls r2, r1, 3\n\ + adds r2, r1\n\ + lsls r2, 2\n\ + ldr r1, _0806ECB0 @ =gSaveBlock1 + 0x2B4C\n\ + adds r4, r2, r1\n\ + cmp r0, 0\n\ + beq _0806ECBC\n\ + ldr r0, _0806ECB4 @ =gOtherText_PokeHoldingItemCantMail\n\ + movs r1, 0x1\n\ + bl sub_806E834\n\ + ldr r0, _0806ECB8 @ =party_menu_link_mon_held_item_object\n\ + movs r1, 0x5\n\ + bl CreateTask\n\ + b _0806ECDA\n\ + .align 2, 0\n\ +_0806ECA0: .4byte gTasks\n\ +_0806ECA4: .4byte TaskDummy\n\ +_0806ECA8: .4byte 0x0201c000\n\ +_0806ECAC: .4byte gUnknown_0202E8F4\n\ +_0806ECB0: .4byte gSaveBlock1 + 0x2B4C\n\ +_0806ECB4: .4byte gOtherText_PokeHoldingItemCantMail\n\ +_0806ECB8: .4byte party_menu_link_mon_held_item_object\n\ +_0806ECBC:\n\ + ldr r0, [r5]\n\ + adds r1, r4, 0\n\ + bl GiveMailToMon2\n\ + adds r0, r4, 0\n\ + bl ClearMailStruct\n\ + ldr r0, _0806ECE0 @ =gOtherText_MailTransferredMailbox\n\ + movs r1, 0x1\n\ + bl sub_806E834\n\ + ldr r0, _0806ECE4 @ =party_menu_link_mon_held_item_object\n\ + movs r1, 0x5\n\ + bl CreateTask\n\ +_0806ECDA:\n\ + pop {r4,r5}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0806ECE0: .4byte gOtherText_MailTransferredMailbox\n\ +_0806ECE4: .4byte party_menu_link_mon_held_item_object\n\ + .syntax divided\n"); +} + +void PartyMenuTryGiveMonHeldItem_806ECE8(u8 taskId, TaskFunc func) +{ + u16 currentItem; + + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, 0, func); + currentItem = GetMonData(ewram1C000.pokemon, MON_DATA_HELD_ITEM); + if (currentItem == 0) + { + StringExpandPlaceholders(gStringVar4, gOtherText_NotHoldingAnything); + sub_806E834(gStringVar4, 0); + CreateTask(party_menu_link_mon_held_item_object, 5); + } + else + { + u8 itemData[2]; + + itemData[0] = 0; + itemData[1] = 0; + if (AddBagItem(currentItem, 1) == TRUE) + { + if (ItemIsMail(currentItem) == TRUE) + TakeMailFromMon(ewram1C000.pokemon); + DisplayTakeHeldItemMessage(ewram1C000.unk5, currentItem, 0); + SetMonData(ewram1C000.pokemon, MON_DATA_HELD_ITEM, itemData); + } + else + { + sub_806E834(gOtherText_BagFullCannotRemoveItem, 0); + } + CreateTask(party_menu_link_mon_held_item_object, 5); + } +} + +void DisplayTakeHeldItemMessage(u8 a, u16 b, u8 c) +{ + GetMonNickname(&gPlayerParty[a], gStringVar1); + CopyItemName(b, gStringVar2); + StringExpandPlaceholders(gStringVar4, gOtherText_ReceivedTheThingFrom); + sub_806E834(gStringVar4, c); +} + +void DoTakeMail(u8 taskId, TaskFunc func) +{ + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, 0, func); + ewram1C000.unk6 = GetMonData(ewram1C000.pokemon, MON_DATA_HELD_ITEM); + sub_806E834(gOtherText_SendRemovedMailPrompt, 1); + CreateTask(Task_ConfirmTakeHeldMail, 5); +} + +void Task_LoseMailMessage(u8 taskId) +{ + s8 selection = ProcessMenuInputNoWrap_(); + + if (selection == 0) + { + if (AddBagItem(ewram1C000.unk6, 1) == TRUE) + { + TakeMailFromMon(ewram1C000.pokemon); + sub_806E834(gOtherText_MailTaken, 0); + } + else + { + sub_806E834(gOtherText_BagFullCannotRemoveItem, 0); + } + MenuZeroFillWindowRect(23, 8, 29, 13); + gTasks[taskId].func = party_menu_link_mon_held_item_object; + } + else + { + if (selection != 1 && selection != -1) + return; + if (selection == -1) + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(23, 8, 29, 13); + MenuZeroFillWindowRect(0, 14, 29, 19); + gTasks[taskId].func = party_menu_link_mon_held_item_object; + } +} + +void Task_ConfirmLoseMailMessage(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + DisplayYesNoMenu(23, 8, 1); + gTasks[taskId].func = Task_LoseMailMessage; + } +} + +void Task_TakeHeldMail(u8 taskId) +{ + s8 selection = ProcessMenuInputNoWrap_(); + + if (selection == 0) + { + MenuZeroFillWindowRect(23, 8, 29, 13); + if (TakeMailFromMon2(ewram1C000.pokemon) != 0xFF) + sub_806E834(gOtherText_MailWasSent, 0); + else + sub_806E834(gOtherText_MailboxIsFull, 0); + gTasks[taskId].func = party_menu_link_mon_held_item_object; + } + else + { + if (selection != 1 && selection != -1) + return; + if (selection == -1) + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(23, 8, 29, 13); + sub_806E834(gOtherText_MailRemovedMessageLost, 1); + gTasks[taskId].func = Task_ConfirmLoseMailMessage; + } +} + +void Task_ConfirmTakeHeldMail(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + DisplayYesNoMenu(23, 8, 1); + gTasks[taskId].func = Task_TakeHeldMail; + } +} + +u16 ItemIdToBattleMoveId(u16 item) +{ + u16 moveId = item - 289; + + return gUnknown_08376504[moveId]; +} + +bool8 pokemon_has_move(struct Pokemon *pkmn, u16 move) +{ + u8 i; + + for (i = 0; i < 4; i++) + { + if (GetMonData(pkmn, MON_DATA_MOVE1 + i) == move) + return TRUE; + } + return FALSE; +} + +void TeachMonTMMove(u8 taskId, u16 move, TaskFunc func) +{ + PlaySE(SE_SELECT); + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, move, func); + CreateTask(Task_TeamMonTMMove, 5); +} + +void Task_TeamMonTMMove(u8 taskId) +{ + GetMonNickname(ewram1C000.pokemon, gStringVar1); + ewram1C000.unk8 = ItemIdToBattleMoveId(ewram1C000.unk6); + StringCopy(gStringVar2, gMoveNames[ewram1C000.unk8]); + ewram1B000.unk282 = 0; + if (pokemon_has_move(ewram1C000.pokemon, ewram1C000.unk8)) + { + StringExpandPlaceholders(gStringVar4, gOtherText_AlreadyKnows); + sub_806E834(gStringVar4, 1); + gTasks[taskId].func = party_menu_link_mon_held_item_object; + } + else + { + if (!CanMonLearnTMHM(ewram1C000.pokemon, ewram1C000.unk6 - 33)) + { + StringExpandPlaceholders(gStringVar4, gOtherText_NotCompatible); + sub_806E834(gStringVar4, 1); + gTasks[taskId].func = party_menu_link_mon_held_item_object; + } + else + { + if (GiveMoveToMon(ewram1C000.pokemon, ewram1C000.unk8) != 0xFFFF) + { + Task_TeamMonTMMove2(taskId); + } + else + { + StringExpandPlaceholders(gStringVar4, gOtherText_WantsToLearn); + sub_806E834(gStringVar4, 1); + gTasks[taskId].func = sub_806F358; + } + } + } +} + +void Task_TeamMonTMMove2(u8 taskId) +{ + StringCopy(gStringVar2, gMoveNames[ewram1C000.unk8]); + StringExpandPlaceholders(gStringVar4, gOtherText_LearnedMove); + sub_806E834(gStringVar4, 1); + AdjustFriendship(ewram1C000.pokemon, 4); + if (ewram1B000.unk282 == 0 && ewram1C000.unk6 <= 0x152) + RemoveBagItem(ewram1C000.unk6, 1); + gTasks[taskId].func = Task_TeamMonTMMove3; +} + +void Task_TeamMonTMMove3(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + PlayFanfare(BGM_FANFA1); + gTasks[taskId].func = Task_TeamMonTMMove4; + } +} + +void Task_TeamMonTMMove4(u8 taskId) +{ + if (IsFanfareTaskInactive()) + { + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + SetHeldItemIconVisibility(ewram1C000.unk4, ewram1C000.unk5); + if (ewram1B000.unk282 == 1) + { + sub_8070C54(taskId); + } + else + { + gTasks[ewram1C000.unk4].func = ewram1C000.unk10; + DestroyTask(taskId); + } + } + } +} + +void sub_806F2FC(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + SetHeldItemIconVisibility(ewram1C000.unk4, ewram1C000.unk5); + if (ewram1B000.unk282 == 1) + { + sub_8070C54(taskId); + } + else + { + gTasks[ewram1C000.unk4].func = ewram1C000.unk10; + DestroyTask(taskId); + } + } +} + +void sub_806F358(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + DisplayYesNoMenu(23, 8, 1); + gTasks[taskId].func = sub_806F390; + } +} + +void sub_806F390(u8 taskId) +{ + s8 selection = ProcessMenuInputNoWrap_(); + + if (selection == 0) + { + MenuZeroFillWindowRect(23, 8, 29, 13); + sub_806E834(gOtherText_WhichMoveToForget2, 1); + gTasks[taskId].func = sub_806F44C; + } + else + { + if (selection != 1 && selection != -1) + return; + if (selection == -1) + PlaySE(SE_SELECT); + StopTryingToTeachMove_806F614(taskId); + } +} + +void sub_806F3FC(u8 taskId) +{ + if (!gPaletteFade.active) + { + sub_809D9F0(gPlayerParty, ewram1C000.unk5, gPlayerPartyCount - 1, sub_808B564, ewram1C000.unk8); + DestroyTask(taskId); + } +} + +void sub_806F44C(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + gTasks[taskId].func = sub_806F3FC; + } +} + +void TaughtMove(u8 taskId) +{ + if (!gPaletteFade.active) + { + u8 moveIndex; + u16 r4; + + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, gScriptItemId, sub_808B508); + moveIndex = sub_809FA30(); + r4 = GetMonData(ewram1C000.pokemon, MON_DATA_MOVE1 + moveIndex); + GetMonNickname(ewram1C000.pokemon, gStringVar1); + StringCopy(gStringVar2, gMoveNames[r4]); + StringExpandPlaceholders(gStringVar4, gOtherText_ForgetMove123_2); + sub_806E834(gStringVar4, 1); + CreateTask(TMMoveUpdateMoveSlot, 5); + } +} + +void TMMoveUpdateMoveSlot(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + RemoveMonPPBonus(ewram1C000.pokemon, sub_809FA30()); + SetMonMoveSlot(ewram1C000.pokemon, ewram1C000.unk8, sub_809FA30()); + Task_TeamMonTMMove2(taskId); + } +} + +void StopTryingToTeachMove_806F588(u8 taskId) +{ + if (!gPaletteFade.active) + { + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, gScriptItemId, sub_808B508); + StringCopy(gStringVar2, gMoveNames[ewram1C000.unk8]); + StringExpandPlaceholders(gStringVar4, gOtherText_StopTryingTo); + sub_806E834(gStringVar4, 1); + CreateTask(StopTryingToTeachMove_806F67C, 5); + } +} + +void StopTryingToTeachMove_806F614(u8 taskId) +{ + MenuZeroFillWindowRect(23, 8, 29, 13); + StringCopy(gStringVar2, gMoveNames[ewram1C000.unk8]); + StringExpandPlaceholders(gStringVar4, gOtherText_StopTryingTo); + sub_806E834(gStringVar4, 1); + gTasks[taskId].func = StopTryingToTeachMove_806F67C; +} + +void StopTryingToTeachMove_806F67C(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + DisplayYesNoMenu(23, 8, 1); + gTasks[taskId].func = StopTryingToTeachMove_806F6B4; + } +} + +void StopTryingToTeachMove_806F6B4(u8 taskId) +{ + s8 selection = ProcessMenuInputNoWrap_(); + + if (selection == 0) + { + MenuZeroFillWindowRect(23, 8, 29, 13); + GetMonNickname(ewram1C000.pokemon, gStringVar1); + StringCopy(gStringVar2, gMoveNames[ewram1C000.unk8]); + StringExpandPlaceholders(gStringVar4, gOtherText_DidNotLearnMove2); + sub_806E834(gStringVar4, 1); + gTasks[taskId].func = sub_806F2FC; + } + else + { + if (selection != 1 && selection != -1) + return; + if (selection == -1) + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(23, 8, 29, 13); + GetMonNickname(ewram1C000.pokemon, gStringVar1); + StringCopy(gStringVar2, gMoveNames[ewram1C000.unk8]); + StringExpandPlaceholders(gStringVar4, gOtherText_WantsToLearn); + sub_806E834(gStringVar4, 1); + gTasks[taskId].func = sub_806F358; + } +} + +bool8 IsHMMove(u16 move) +{ + u8 i; + + for (i = 0; i < 8; i++) + { + if (gUnknown_08376504[50 + i] == move) + return TRUE; + } + return FALSE; +} + +s16 sub_806F7E8(u8 taskId, struct BattleInterfaceStruct1 *b, s8 c) +{ + s16 *taskData; + u8 hpBarLevel; + void *vramPtr; + + taskData = gTasks[taskId].data; + + b->unk0 = taskData[10]; + b->unk4 = taskData[11]; + b->unk8 = taskData[12] * c; + b->unk10 = 0x100; + hpBarLevel = GetHPBarLevel(ewram1B000.unk282, b->unk0); + if (hpBarLevel > 2) + b->unkC_0 = 4; + if (hpBarLevel == 2) + b->unkC_0 = 5; + if (hpBarLevel < 2) + b->unkC_0 = 6; + vramPtr = gUnknown_08376858[IsDoubleBattle()][ewram1C000.unk5]; + return sub_80460C8(b, &ewram1C000.unkC, vramPtr, 0); +} + +void sub_806F8AC(u8 taskId) +{ + struct BattleInterfaceStruct1 sp0; + u16 sp14; + + ewram1B000.unk282 = sub_806F7E8(taskId, &sp0, -1); + if (ewram1B000.unk282 == -1) + { + ewram1C000.unkC = 0; + if (-sp0.unk8 + sp0.unk4 > sp0.unk0) + sp14 = sp0.unk0 - sp0.unk4; + else + sp14 = -sp0.unk8; + gBattleMoveDamage = -sp14; + GetMonNickname(ewram1C000.pokemon, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, sp14, 0, 3); + if (gTasks[taskId].data[14] == 0) + StringExpandPlaceholders(gStringVar4, gOtherText_HPRestoredBy); + else + StringExpandPlaceholders(gStringVar4, gOtherText_RegainedHealth); + SetMonIconAnim(GetMonIconSpriteId_maybe(ewram1C000.unk4, ewram1C000.unk5), ewram1C000.pokemon); + task_pc_turn_off(&gUnknown_083769A8[IsDoubleBattle() * 12 + ewram1C000.unk5 * 2], 7); + ewram1B000.unk261 = 2; + sub_806E834(gStringVar4, 1); + sp14 += sp0.unk4; + SetMonData(ewram1C000.pokemon, MON_DATA_HP, (u8 *)&sp14); + RemoveBagItem(ewram1C000.unk6, 1); + sub_8032638(); + gTasks[taskId].func = sub_806FB44; + } + else + { + PartyMenuDoPrintHP(ewram1C000.unk5, IsDoubleBattle(), ewram1B000.unk282, sp0.unk0); + } +} + +void sub_806FA18(u8 taskId) +{ + struct BattleInterfaceStruct1 sp0; + + ewram1B000.unk282 = sub_806F7E8(taskId, &sp0, 1); + if (ewram1B000.unk282 == -1) + { + PlaySE(SE_KAIFUKU); + ewram1C000.unkC = 0; + gTasks[taskId].data[11] -= gTasks[taskId].data[12]; + SetMonData(ewram1C000.pokemon, MON_DATA_HP, (u8 *)&gTasks[taskId].data[11]); + SetMonIconAnim(GetMonIconSpriteId_maybe(ewram1C000.unk4, ewram01000.unk1), ewram1C000.pokemon); + ewram1C000.unk5 = gSprites[ewram01000.unk2].data0; + ewram1C000.pokemon = &gPlayerParty[ewram1C000.unk5]; + gTasks[taskId].data[10] = GetMonData(ewram1C000.pokemon, MON_DATA_MAX_HP); + gTasks[taskId].data[11] = GetMonData(ewram1C000.pokemon, MON_DATA_HP); + ewram1C000.unkC = -32768; + ewram1C000.unk14 = ewram1C000.unk10; + gTasks[taskId].func = sub_806F8AC; + ewram1B000.unk282 = gTasks[taskId].data[11]; + } + else + { + PartyMenuDoPrintHP(ewram1C000.unk5, IsDoubleBattle(), ewram1B000.unk282, sp0.unk0); + } +} + +void sub_806FB0C(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + gTasks[ewram1C000.unk4].func = ewram1C000.unk10; + DestroyTask(taskId); + } +} + +void sub_806FB44(u8 taskId) +{ + if (gUnknown_0202E8F6 == 0) + { + gTasks[ewram1C000.unk4].func = ewram1C000.unk14; + DestroyTask(taskId); + } +} + +bool8 IsHPRecoveryItem(u16 item) +{ + const u8 *itemEffect; + + if (item == 0xAF) + itemEffect = gSaveBlock1.enigmaBerry.itemEffect; + else + itemEffect = gItemEffectTable[item - 13]; + + if (itemEffect[4] & 4) + return TRUE; + else + return FALSE; +} + +void PartyMenuUpdateLevelOrStatus(struct Pokemon *pkmn, u8 b) +{ + PartyMenuClearLevelStatusTilemap(b); + PartyMenuPrintMonLevelOrStatus(b, pkmn); +} + +void GetMedicineItemEffectMessage(u16 item) +{ + switch (GetItemEffectType(item)) + { + case 3: + StringExpandPlaceholders(gStringVar4, gOtherText_CuredPoisoning); + break; + case 4: + StringExpandPlaceholders(gStringVar4, gOtherText_WokeUp); + break; + case 5: + StringExpandPlaceholders(gStringVar4, gOtherText_BurnHealed); + break; + case 6: + StringExpandPlaceholders(gStringVar4, gOtherText_ThawedOut); + break; + case 7: + StringExpandPlaceholders(gStringVar4, gOtherText_CuredParalysis); + break; + case 8: + StringExpandPlaceholders(gStringVar4, gOtherText_SnapConfusion); + break; + case 9: + StringExpandPlaceholders(gStringVar4, gOtherText_GotOverLove); + break; + case 11: + StringExpandPlaceholders(gStringVar4, gOtherText_BecameHealthy); + break; + case 13: + StringCopy(gStringVar2, gOtherText_Hp2); + StringExpandPlaceholders(gStringVar4, gOtherText_WasRaised); + break; + case 12: + StringCopy(gStringVar2, gOtherText_Attack); + StringExpandPlaceholders(gStringVar4, gOtherText_WasRaised); + break; + case 17: + StringCopy(gStringVar2, gOtherText_Defense); + StringExpandPlaceholders(gStringVar4, gOtherText_WasRaised); + break; + case 16: + StringCopy(gStringVar2, gOtherText_Speed); + StringExpandPlaceholders(gStringVar4, gOtherText_WasRaised); + break; + case 14: + StringCopy(gStringVar2, gOtherText_SpAtk2); + StringExpandPlaceholders(gStringVar4, gOtherText_WasRaised); + break; + case 15: + StringCopy(gStringVar2, gOtherText_SpDef2); + StringExpandPlaceholders(gStringVar4, gOtherText_WasRaised); + break; + case 19: + case 20: + StringExpandPlaceholders(gStringVar4, gOtherText_PPIncreased); + break; + case 21: + StringExpandPlaceholders(gStringVar4, gOtherText_PPRestored); + break; + default: + StringExpandPlaceholders(gStringVar4, gOtherText_WontHaveAnyEffect); + break; + } +} + +bool8 IsMedicineIneffective(struct Pokemon *pkmn, u16 item) +{ + if (GetItemEffectType(item) == 13 + && GetMonData(pkmn, MON_DATA_SPECIES) == SPECIES_SHEDINJA) + return TRUE; + else + return FALSE; +} + +bool8 ExecuteTableBasedItemEffect__(u8 a, u16 b, u8 c) +{ + if (gMain.inBattle) + return ExecuteTableBasedItemEffect_(&gPlayerParty[a], b, sub_8094C20(a), c); + else + return ExecuteTableBasedItemEffect_(&gPlayerParty[a], b, a, c); +} + +void UseMedicine(u8 taskId, u16 item, TaskFunc func) +{ + u8 r7; + bool8 r9 = FALSE; + bool8 r0; + + gTasks[taskId].func = TaskDummy; + r7 = CreateTask(TaskDummy, 5); + sub_806E8D0(taskId, item, func); + if (!IsMedicineIneffective(ewram1C000.pokemon, item)) + { + r9 = IsHPRecoveryItem(item); + if (r9 == TRUE) + { + gTasks[r7].data[10] = GetMonData(ewram1C000.pokemon, MON_DATA_MAX_HP); + gTasks[r7].data[11] = GetMonData(ewram1C000.pokemon, MON_DATA_HP); + if (gTasks[r7].data[10] == gTasks[r7].data[11]) + { + r9 = FALSE; + gTasks[r7].data[10] = 0; + gTasks[r7].data[11] = 0; + } + } + r0 = ExecuteTableBasedItemEffect__(ewram1C000.unk5, item, 0); + } + else + { + r0 = TRUE; + } + + if (r0) + { + gUnknown_0202E8F4 = 0; + PlaySE(SE_SELECT); + sub_806E834(gOtherText_WontHaveAnyEffect, 1); + gTasks[r7].func = sub_806FB0C; + } + else + { + u8 statusAndPkrs; + + gUnknown_0202E8F4 = 1; + if (!IsBlueYellowRedFlute(item)) + PlaySE(SE_KAIFUKU); + else + PlaySE(SE_BIDORO); + statusAndPkrs = GetMonStatusAndPokerus(ewram1C000.pokemon); + if (statusAndPkrs == 6 || statusAndPkrs == 0) + PartyMenuUpdateLevelOrStatus(ewram1C000.pokemon, ewram1C000.unk5); + if (r9 == TRUE) + { + gTasks[r7].data[12] = GetMonData(ewram1C000.pokemon, MON_DATA_HP) - gTasks[r7].data[11]; + ewram1C000.unkC = -32768; + if (gTasks[r7].data[11] == 0) + gTasks[r7].data[14] = 1; + else + gTasks[r7].data[14] = 0; + ewram1C000.unk14 = ewram1C000.unk10; + gTasks[r7].func = sub_806F8AC; + ewram1B000.unk282 = gTasks[r7].data[11]; + } + else + { + GetMonNickname(ewram1C000.pokemon, gStringVar1); + if (!IsBlueYellowRedFlute(item)) + RemoveBagItem(item, 1); + GetMedicineItemEffectMessage(item); + TryPrintPartyMenuMonNickname(ewram1C000.unk5, ewram1C000.pokemon); + sub_806E834(gStringVar4, 1); + gTasks[r7].func = sub_806FB0C; + } + } +} + +bool8 IsBlueYellowRedFlute(u16 item) +{ + if (item == 0x27 + || item == 0x29 + || item == 0x28) + return TRUE; + else + return FALSE; +} + +void sub_8070048(u8 taskId, u16 item, TaskFunc func) +{ + ewram1C000.unk10 = func; + ewram1C000.unk4 = taskId; + ewram1C000.unk6 = item; + ewram1C000.unk5 = 0; + ewram1C000.unk14 = sub_80701DC; + ewram1B000.unk27E = 0; + ewram1B000.unk280 = 0; + sub_8070088(taskId); +} + +void sub_8070088(u8 taskId) +{ + u8 taskId2; + + gTasks[taskId].func = TaskDummy; + if (GetMonData(&gPlayerParty[ewram1C000.unk5], MON_DATA_SPECIES) == 0) + { + gTasks[taskId].func = sub_80701DC; + } + else + { + s16 *taskData; + + taskId2 = CreateTask(TaskDummy, 5); + taskData = gTasks[taskId2].data; + ewram1C000.pokemon = &gPlayerParty[ewram1C000.unk5]; + taskData[10] = GetMonData(ewram1C000.pokemon, MON_DATA_MAX_HP); + taskData[11] = GetMonData(ewram1C000.pokemon, MON_DATA_HP); + if (ExecuteTableBasedItemEffect__(ewram1C000.unk5, ewram1C000.unk6, 0)) + { + DestroyTask(taskId2); + gTasks[taskId].func = sub_80701DC; + } + else + { + gUnknown_0202E8F4 = 1; + MenuZeroFillWindowRect(WINDOW_LEFT, 14, WINDOW_RIGHT, 19); + PlaySE(SE_KAIFUKU); + PartyMenuUpdateLevelOrStatus(ewram1C000.pokemon, ewram1C000.unk5); + task_pc_turn_off(&gUnknown_083769A8[IsDoubleBattle() * 12 + ewram1C000.unk5 * 2], 9); + ewram1B000.unk261 = 2; + taskData[12] = GetMonData(ewram1C000.pokemon, MON_DATA_HP) - taskData[11]; + taskData[14] = 1; + ewram1B000.unk27E = 1; + ewram1B000.unk280 = 1; + ewram1B000.unk282 = taskData[11]; + ewram1C000.unkC = -32768; + gTasks[taskId2].func = sub_806F8AC; + } + } +} + +void sub_80701DC(u8 taskId) +{ + if (ewram1B000.unk27E == 1) + { + AddBagItem(ewram1C000.unk6, 1); + if (GetMonData(&gPlayerParty[ewram1C000.unk5], MON_DATA_SPECIES) != 0) + { + task_pc_turn_off(&gUnknown_083769A8[IsDoubleBattle() * 12 + ewram1C000.unk5 * 2], 3); + ewram1B000.unk261 = 2; + } + ewram1B000.unk27E = 0; + } + ewram1C000.unk5++; + if (ewram1C000.unk5 == 6) + { + gUnknown_0202E8F4 = 0; + if (ewram1B000.unk280 == 0) + { + gTasks[taskId].func = TaskDummy; + sub_806E834(gOtherText_WontHaveAnyEffect, 1); + CreateTask(sub_806FB0C, 8); + } + else + { + RemoveBagItem(ewram1C000.unk6, 1); + gTasks[taskId].func = ewram1C000.unk10; + } + gLastFieldPokeMenuOpened = 0; + } + else + { + sub_8070088(taskId); + } +} + +void CreateItemUseMoveMenu(u8 partyMonIndex) +{ + u8 r6; + u8 i; + + r6 = 0; + MenuDrawTextWindow(19, 10, 29, 19); + for (i = 0; i < 4; i++) + { + u16 move = GetMonData(&gPlayerParty[partyMonIndex], MON_DATA_MOVE1 + i); + + MenuPrint(gMoveNames[move], 20, i * 2 + 11); + if (move != 0) + r6++; + } + InitMenu(0, 20, 11, r6, 0, 9); +} + +void Task_HandleItemUseMoveMenuInput(u8 taskId) +{ + if (gMain.newKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + } + else if (gMain.newKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + } + else if (gMain.newKeys & A_BUTTON) + { + gUnknown_08376B54[0](taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gUnknown_08376B54[1](taskId); + } +} + +void DoPPRecoveryItemEffect(u8 taskId, u16 b, TaskFunc c) +{ + const u8 *itemEffect; + u8 taskId2; + + if (b == 0xAF) + itemEffect = gSaveBlock1.enigmaBerry.itemEffect; + else + itemEffect = gItemEffectTable[b - 13]; + gTasks[taskId].func = TaskDummy; + taskId2 = CreateTask(TaskDummy, 5); + sub_806E8D0(taskId, b, c); + if (!(itemEffect[4] & 0x10)) + { + gTasks[taskId2].data[11] = 0; + DoRecoverPP(taskId2); + } + else + { + PlaySE(SE_SELECT); + sub_806D538(10, 3); + CreateItemUseMoveMenu(ewram1C000.unk5); + gTasks[taskId2].func = Task_HandleItemUseMoveMenuInput; + gMain.newKeys = 0; + } +} + +void ItemUseMoveMenu_HandleMoveSelection(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(19, 10, 29, 19); + sub_806D5A4(); + gTasks[taskId].data[11] = GetMenuCursorPos(); + DoRecoverPP(taskId); +} + +void ItemUseMoveMenu_HandleCancel(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(19, 10, 29, 19); + if (gMain.inBattle) + gTasks[ewram1C000.unk4].func = SetUpBattlePokemonMenu; + else + gTasks[ewram1C000.unk4].func = sub_808B0C0; + sub_806D538(3, 0); + DestroyTask(taskId); +} + +void DoRecoverPP(u8 taskId) +{ + u16 r5 = 0; + + if (ExecuteTableBasedItemEffect__(ewram1C000.unk5, ewram1C000.unk6, gTasks[taskId].data[11])) + { + gUnknown_0202E8F4 = r5; + PlaySE(SE_SELECT); + sub_806E834(gOtherText_WontHaveAnyEffect, 1); + } + else + { + gUnknown_0202E8F4 = 1; + PlaySE(SE_KAIFUKU); + RemoveBagItem(ewram1C000.unk6, 1); + r5 = GetMonData(ewram1C000.pokemon, MON_DATA_MOVE1 + gTasks[taskId].data[11]); + StringCopy(gStringVar1, gMoveNames[r5]); + GetMedicineItemEffectMessage(ewram1C000.unk6); + sub_806E834(gStringVar4, 1); + } + gTasks[taskId].func = sub_806FB0C; +} + +void DoPPUpItemEffect(u8 taskId, u16 b, TaskFunc c) +{ + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, b, c); + PlaySE(SE_SELECT); + sub_806D538(11, 3); + CreateItemUseMoveMenu(ewram1C000.unk5); + CreateTask(Task_HandleItemUseMoveMenuInput, 5); + gMain.newKeys = 0; +} + +void DoRareCandyItemEffect(u8 taskId, u16 b, TaskFunc c) +{ + u8 i; + bool8 r0; + + gTasks[taskId].func = TaskDummy; + sub_806E8D0(taskId, b, c); + + if (GetMonData(ewram1C000.pokemon, MON_DATA_LEVEL) != 100) + { + for (i = 0; i < 6; i++) + ewram1B000.unk264[i] = GetMonData(ewram1C000.pokemon, gUnknown_08376D1C[i]); + r0 = ExecuteTableBasedItemEffect__(ewram1C000.unk5, b, 0); + } + else + r0 = TRUE; + + if (r0) + { + gUnknown_0202E8F4 = 0; + PlaySE(SE_SELECT); + sub_806E834(gOtherText_WontHaveAnyEffect, 1); + CreateTask(sub_806FB0C, 5); + } + else + { + u8 level; + + gUnknown_0202E8F4 = 1; + PlayFanfareByFanfareNum(0); + sub_8070A20(ewram1C000.unk5, ewram1C000.pokemon); + RemoveBagItem(b, 1); + GetMonNickname(ewram1C000.pokemon, gStringVar1); + level = GetMonData(ewram1C000.pokemon, MON_DATA_LEVEL); + ConvertIntToDecimalStringN(gStringVar2, level, 0, 3); + StringExpandPlaceholders(gStringVar4, gOtherText_ElevatedTo); + sub_806E834(gStringVar4, 1); + CreateTask(Task_RareCandy1, 5); + } +} + +void Task_RareCandy1(u8 taskId) +{ + if (WaitFanfare(0) && gUnknown_0202E8F6 == 0) + { + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + PlaySE(SE_SELECT); + sub_8070848(taskId); + gTasks[taskId].func = Task_RareCandy2; + } + } +} + +void Task_RareCandy2(u8 taskId) +{ + if ((gMain.newKeys & A_BUTTON) || (gMain.newKeys & B_BUTTON)) + { + PlaySE(SE_SELECT); + sub_8070968(taskId); + gTasks[taskId].func = Task_RareCandy3; + } +} + +#if ENGLISH +void sub_8070848(u8 taskId) +{ + u8 i; + + MenuDrawTextWindow(11, 0, 29, 7); + + for (i = 0; i < DATA_COUNT; i++) + { + u8 x; + u8 y; + u32 stat; + + stat = GetMonData(ewram1C000.pokemon, gUnknown_08376D1C[i]); + + ewram1B000.unk264[i + DATA_COUNT] = stat; + ewram1B000.unk264[i] = stat - ewram1B000.unk264[i]; + + x = (i / 3) * 9 + 11; + y = ((i % 3) << 1) + 1; + + MenuPrint_PixelCoords(gUnknown_08376D04[i], (x + 1) * 8, y * 8, 1); + + if (i == 2) + MenuPrint_PixelCoords(gOtherText_TallPlusAndRightArrow, (x + 6) * 8 + 6, y * 8, 0); + else + MenuPrint_PixelCoords(gOtherText_TallPlusAndRightArrow, (x + 6) * 8 + 6, y * 8, 1); + + gStringVar1[0] = EXT_CTRL_CODE_BEGIN; + gStringVar1[1] = 0x14; + gStringVar1[2] = 0x06; + + ConvertIntToDecimalStringN(gStringVar1 + 3, ewram1B000.unk264[i], 1, 2); + + MenuPrint_PixelCoords(gStringVar1, (x + 6) * 8 + 12, y * 8, 0); + } +} +#elif GERMAN +__attribute__((naked)) +void sub_8070848(u8 taskId) { + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + movs r0, 0xB\n\ + movs r1, 0\n\ + movs r2, 0x1D\n\ + movs r3, 0x7\n\ + bl MenuDrawTextWindow\n\ + movs r7, 0\n\ + ldr r0, _0807092C @ =gStringVar1\n\ + mov r10, r0\n\ + movs r1, 0xFC\n\ + mov r9, r1\n\ + movs r2, 0x13\n\ + mov r8, r2\n\ +_0807086C:\n\ + ldr r1, _08070930 @ =0x0201c000\n\ + ldr r0, [r1]\n\ + ldr r1, _08070934 @ =gUnknown_08376D1C\n\ + adds r1, r7, r1\n\ + ldrb r1, [r1]\n\ + bl GetMonData\n\ + adds r1, r7, 0x6\n\ + lsls r1, 1\n\ + ldr r2, _08070938 @ =0x0201b264\n\ + adds r1, r2, r1\n\ + strh r0, [r1]\n\ + lsls r6, r7, 1\n\ + adds r6, r2, r6\n\ + ldrh r1, [r6]\n\ + subs r0, r1\n\ + strh r0, [r6]\n\ + adds r0, r7, 0\n\ + movs r1, 0x3\n\ + bl __udivsi3\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r4, r0, 3\n\ + adds r4, r0\n\ + adds r4, 0xB\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + adds r0, r7, 0\n\ + movs r1, 0x3\n\ + bl __umodsi3\n\ + adds r5, r0, 0\n\ + lsls r5, 1\n\ + adds r5, 0x1\n\ + lsls r5, 24\n\ + lsrs r5, 24\n\ + ldr r1, _0807093C @ =gUnknown_08376D04\n\ + lsls r0, r7, 2\n\ + adds r0, r1\n\ + ldr r1, [r0]\n\ + mov r0, r10\n\ + bl StringCopy\n\ + adds r2, r0, 0\n\ + mov r0, r9\n\ + strb r0, [r2]\n\ + adds r2, 0x1\n\ + mov r1, r8\n\ + strb r1, [r2]\n\ + adds r2, 0x1\n\ + movs r0, 0x2E\n\ + strb r0, [r2]\n\ + adds r2, 0x1\n\ + adds r0, r2, 0\n\ + ldr r1, _08070940 @ =gOtherText_TallPlusAndRightArrow\n\ + bl StringCopy\n\ + adds r2, r0, 0\n\ + mov r0, r9\n\ + strb r0, [r2]\n\ + adds r2, 0x1\n\ + mov r1, r8\n\ + strb r1, [r2]\n\ + adds r2, 0x1\n\ + movs r0, 0x34\n\ + strb r0, [r2]\n\ + adds r2, 0x1\n\ + movs r0, 0\n\ + ldrsh r1, [r6, r0]\n\ + adds r0, r2, 0\n\ + movs r2, 0x1\n\ + movs r3, 0x2\n\ + bl ConvertIntToDecimalStringN\n\ + adds r4, 0x1\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + mov r0, r10\n\ + adds r1, r4, 0\n\ + adds r2, r5, 0\n\ + bl MenuPrint\n\ + adds r0, r7, 0x1\n\ + lsls r0, 24\n\ + lsrs r7, r0, 24\n\ + cmp r7, 0x5\n\ + bls _0807086C\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0807092C: .4byte gStringVar1\n\ +_08070930: .4byte 0x0201c000\n\ +_08070934: .4byte gUnknown_08376D1C\n\ +_08070938: .4byte 0x0201b264\n\ +_0807093C: .4byte gUnknown_08376D04\n\ +_08070940: .4byte gOtherText_TallPlusAndRightArrow\n\ + .syntax divided\n"); +} +#endif diff --git a/src/field/player_pc.c b/src/field/player_pc.c new file mode 100644 index 000000000..83e6dd221 --- /dev/null +++ b/src/field/player_pc.c @@ -0,0 +1,1368 @@ +#include "global.h" +#include "player_pc.h" +#include "decoration.h" +#include "field_fadetransition.h" +#include "field_weather.h" +#include "item.h" +#include "item_menu.h" +#include "items.h" +#include "main.h" +#include "menu.h" +#include "menu_helpers.h" +#include "palette.h" +#include "script.h" +#include "sound.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "songs.h" +#include "name_string_util.h" +#include "mail.h" +#include "overworld.h" +#include "player_pc.h" + +extern void DisplayItemMessageOnField(u8, const u8*, TaskFunc, u16); +extern void DoPlayerPCDecoration(u8); +extern void BuyMenuFreeMemory(void); +extern void DestroyVerticalScrollIndicator(u8); +extern void PauseVerticalScrollIndicator(u8); +extern void LoadScrollIndicatorPalette(void); +extern void ClearMailStruct(struct MailStruct *); +extern u8 sub_807D770(void); +extern void sub_808B020(void); +extern void sub_80F944C(void); + +static EWRAM_DATA u8 *gPcItemMenuOptionOrder = NULL; + +static u8 gPcItemMenuOptionsNum; + +extern u8 gUnknown_02038561; + +// event scripts +extern u8 gBrendanHouse_TurnPCOff[]; +extern u8 gMayHouse_TurnPCOff[]; + +extern void (*gFieldCallback)(void); + +static void InitPlayerPCMenu(u8 taskId); +static void PlayerPCProcessMenuInput(u8 taskId); +static void InitItemStorageMenu(u8); +static void ItemStorageMenuPrint(const u8 *); +static void ItemStorageMenuProcessInput(u8); +static void ItemStorage_ProcessInput(u8); +static void ItemStorage_SetItemAndMailCount(u8); +static void ItemStorage_DoItemAction(u8); +static void ItemStorage_GoBackToPlayerPCMenu(u8); +static void ItemStorage_HandleQuantityRolling(u8); +static void ItemStorage_DoItemWithdraw(u8); +static void ItemStorage_DoItemToss(u8); +static void ItemStorage_HandleRemoveItem(u8); +static void ItemStorage_WaitPressHandleResumeProcessInput(u8); +static void ItemStorage_HandleResumeProcessInput(u8); +static void ItemStorage_DoItemSwap(u8, bool8); +static void ItemStorage_DrawItemList(u8); +static void ItemStorage_PrintItemPcResponse(u16); +static void ItemStorage_DrawBothListAndDescription(u8); +static void ItemStorage_GoBackToItemPCMenu(u8, u8); +static void ItemStorage_LoadPalette(void); +static u8 GetMailboxMailCount(void); +static void Mailbox_UpdateMailList(void); +static void Mailbox_DrawMailboxMenu(u8); +static void Mailbox_ProcessInput(u8); +static void Mailbox_CloseScrollIndicators(void); +static void Mailbox_PrintWhatToDoWithPlayerMailText(u8); +static void Mailbox_TurnOff(u8); +static void Mailbox_PrintMailOptions(u8); +static void Mailbox_MailOptionsProcessInput(u8); +static void Mailbox_FadeAndReadMail(u8); +static void Mailbox_ReturnToFieldFromReadMail(void); +static void Mailbox_DrawYesNoBeforeMove(u8); +static void Mailbox_DoGiveMailPokeMenu(u8); +static void Mailbox_NoPokemonForMail(u8); +static void Mailbox_Cancel(u8); +static void Mailbox_DrawMailMenuAndDoProcessInput(u8); +static void PlayerPC_ItemStorage(u8 taskId); +static void PlayerPC_Mailbox(u8 taskId); +static void PlayerPC_Decoration(u8 var); +static void PlayerPC_TurnOff(u8 taskId); +static void ItemStorage_Withdraw(u8); +static void ItemStorage_Deposit(u8); +static void ItemStorage_Toss(u8); +static void ItemStorage_Exit(u8); +static void ItemStorage_ResumeInputFromYesToss(u8); +static void ItemStorage_ResumeInputFromNoToss(u8); +static void Mailbox_DoMailMoveToBag(u8); +static void Mailbox_ReturnToInputAfterNo(u8); +static void Mailbox_DoMailRead(u8); +static void Mailbox_MoveToBag(u8); +static void Mailbox_Give(u8); +static void Mailbox_Cancel(u8); + +static const u8 *const gPCText_OptionDescList[] = +{ + PCText_TakeOutItems, + PCText_StoreItems, + PCText_ThrowAwayItems, + gMenuText_GoBackToPrev +}; + +static const struct MenuAction2 sPlayerPCMenuActions[] = +{ + { SecretBaseText_ItemStorage, PlayerPC_ItemStorage }, + { gPCText_Mailbox, PlayerPC_Mailbox }, + { SecretBaseText_Decoration, PlayerPC_Decoration }, + { SecretBaseText_TurnOff, PlayerPC_TurnOff } +}; + +static const u8 gBedroomPC_OptionOrder[] = +{ + PLAYERPC_MENU_ITEMSTORAGE, + PLAYERPC_MENU_MAILBOX, + PLAYERPC_MENU_DECORATION, + PLAYERPC_MENU_TURNOFF +}; + +static const u8 gPlayerPC_OptionOrder[] = +{ + PLAYERPC_MENU_ITEMSTORAGE, + PLAYERPC_MENU_MAILBOX, + PLAYERPC_MENU_TURNOFF +}; + +static const struct MenuAction2 gPCText_ItemPCOptionsText[] = +{ + { PCText_WithdrawItem, ItemStorage_Withdraw }, + { PCText_DepositItem, ItemStorage_Deposit }, + { PCText_TossItem, ItemStorage_Toss }, + { gUnknownText_Exit, ItemStorage_Exit } +}; + +static const struct YesNoFuncTable ResumeFromTossYesNoFuncList[] = // ResumeFromTossYesNoFuncList +{ + ItemStorage_ResumeInputFromYesToss, + ItemStorage_ResumeInputFromNoToss +}; + +static const struct YesNoFuncTable ResumeFromWithdrawYesNoFuncList[] = // ResumeFromWithdrawYesNoFuncList +{ + Mailbox_DoMailMoveToBag, + Mailbox_ReturnToInputAfterNo +}; + +// the use of this struct is meant to be an ItemSlot struct, but NewGameInitPCItems refuses to match without a weird pointer access. +static const struct ItemSlot gNewGamePCItems[] = +{ + { ITEM_POTION, 1 }, + { ITEM_NONE, 0 } +}; + +static const struct MenuAction2 gMailboxMailOptions[] = +{ + { OtherText_Read, Mailbox_DoMailRead }, + { gOtherText_MoveToBag, Mailbox_MoveToBag }, + { OtherText_Give, Mailbox_Give }, + { gOtherText_CancelNoTerminator, Mailbox_Cancel } +}; + +static const u8 gNonSelectedItemFormattedText[] = _("{STR_VAR_1}{CLEAR_TO 80}"); +static const u8 gSelectedItemFormattedText[] = _("{COLOR RED}{STR_VAR_1}{CLEAR_TO 80}"); +static const u8 gNonSelectedItemQuantityFormatText[] = _("{STR_VAR_1}"); +static const u8 gSelectedItemQuantityFormatText[] = _("{COLOR RED}{STR_VAR_1}"); +static const u8 gUnknown_08406330[] = _("{CLEAR_TO 32}"); + +static const u16 gUnknown_08406334[3] = +{ + 0x5294, + 0x6B5A, + 0x7FFF +}; + +static const u8 gHighlightedMoveToBagFormatText[] = _("{COLOR RED}{STR_VAR_1}"); + +extern u8 *gUnknown_02039314; +extern struct MenuAction gUnknown_08406298[]; + +extern u8 gUnknown_084062B8[]; +extern u8 gUnknown_084062BC[]; +extern u8 gUnknown_0840632A[]; +extern u8 gUnknown_08406327[]; +extern u8 gUnknown_0840631E[]; +extern u8 gUnknown_08406318[]; + +extern u8 gUnknown_030007B4; +extern u8 unk_201FE00[]; + +extern u8 gUnknown_08152850; +extern u8 gUnknown_08152C75; + +extern u32 gUnknown_08406288[]; +extern const struct MenuAction gUnknown_084062C0[]; +extern const struct YesNoFuncTable gUnknown_084062E0; + +void NewGameInitPCItems(void) +{ + u8 i; + + // because Game Freak don't know how to use a struct or a 2d array + for(i = 0, ClearItemSlots(gSaveBlock1.pcItems, ARRAY_COUNT(gSaveBlock1.pcItems)); NEW_GAME_PC_ITEMS(i, ITEM_ID) && NEW_GAME_PC_ITEMS(i, QUANTITY) && + AddPCItem(NEW_GAME_PC_ITEMS(i, ITEM_ID), NEW_GAME_PC_ITEMS(i, QUANTITY)) == TRUE; i++) + ; +} + +void BedroomPC(void) +{ + gPcItemMenuOptionOrder = (u8 *)gBedroomPC_OptionOrder; + gPcItemMenuOptionsNum = 4; + DisplayItemMessageOnField(CreateTask(TaskDummy, 0), gOtherText_WhatWillYouDo, InitPlayerPCMenu, 0); +} + +void PlayerPC(void) +{ + gPcItemMenuOptionOrder = (u8 *)gPlayerPC_OptionOrder; + gPcItemMenuOptionsNum = 3; + DisplayItemMessageOnField(CreateTask(TaskDummy, 0), gOtherText_WhatWillYouDo, InitPlayerPCMenu, 0); +} + +static void InitPlayerPCMenu(u8 taskId) +{ + MenuDrawTextWindow(0, 0, 10, gPcItemMenuOptionsNum * 2 + 1); + PrintMenuItemsReordered(1, 1, gPcItemMenuOptionsNum, sPlayerPCMenuActions, gPcItemMenuOptionOrder); + InitMenu(0, 1, 1, gPcItemMenuOptionsNum, 0, 9); + TASK.FUNC = PlayerPCProcessMenuInput; +} + +static void PlayerPCProcessMenuInput(u8 taskId) +{ + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + } + else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + } + else if (gMain.newKeys & A_BUTTON) + { + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + sPlayerPCMenuActions[gPcItemMenuOptionOrder[GetMenuCursorPos()]].func(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + sPlayerPCMenuActions[gPcItemMenuOptionsNum[gPcItemMenuOptionOrder - 1]].func(taskId); // run EXIT. + } +} + +void ReshowPlayerPC(u8 var) +{ + DisplayItemMessageOnField(var, gOtherText_WhatWillYouDo, InitPlayerPCMenu, 0); +} + +static void PlayerPC_ItemStorage(u8 taskId) +{ + InitItemStorageMenu(ITEMPC_MENU_WITHDRAW); + TASK.FUNC = ItemStorageMenuProcessInput; +} + +static void PlayerPC_Mailbox(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0, 10, 9); + gMailboxInfo.count = GetMailboxMailCount(); + + if (gMailboxInfo.count == 0) + DisplayItemMessageOnField(taskId, gOtherText_NoMailHere, ReshowPlayerPC, 0); + else + { + gMailboxInfo.cursorPos = 0; + gMailboxInfo.itemsAbove = 0; + Mailbox_UpdateMailList(); + ItemStorage_SetItemAndMailCount(taskId); + Mailbox_DrawMailboxMenu(taskId); + TASK.FUNC = Mailbox_ProcessInput; + } +} + +static void PlayerPC_Decoration(u8 var) +{ + MenuZeroFillWindowRect(0, 0, 10, 9); + DoPlayerPCDecoration(var); +} + +static void PlayerPC_TurnOff(u8 taskId) +{ + if (gPcItemMenuOptionsNum == 4) // if the option count is 4, we are at the bedroom PC and not player PC, so do gender specific handling. + { + MenuZeroFillWindowRect(0, 0, 0x1D, 0x13); + + if (gSaveBlock2.playerGender == MALE) + ScriptContext1_SetupScript(gBrendanHouse_TurnPCOff); + else + ScriptContext1_SetupScript(gMayHouse_TurnPCOff); + } + else + { + MenuZeroFillWindowRect(0, 0, 10, 9); + EnableBothScriptContexts(); + } + DestroyTask(taskId); +} + +static void InitItemStorageMenu(u8 var) +{ + MenuZeroFillWindowRect(0, 0, 10, 9); + MenuDrawTextWindow(0, 0, 11, 9); + PrintMenuItems(1, 1, 4, (struct MenuAction *)gPCText_ItemPCOptionsText); + InitMenu(0, 1, 1, 4, var, 10); + ItemStorageMenuPrint(gPCText_OptionDescList[var]); +} + +static void ItemStorageMenuPrint(const u8 *textPtr) +{ + MenuFillWindowRectWithBlankTile(2, 15, 27, 18); + MenuPrint(textPtr, 2, 15); +} + +static void ItemStorageMenuProcessInput(u8 var) +{ + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + ItemStorageMenuPrint(gPCText_OptionDescList[GetMenuCursorPos()]); + } + else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + ItemStorageMenuPrint(gPCText_OptionDescList[GetMenuCursorPos()]); + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + gPCText_ItemPCOptionsText[GetMenuCursorPos()].func(var); + } + else if (gMain.newKeys & B_BUTTON) + { + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + gPCText_ItemPCOptionsText[ITEMPC_MENU_EXIT].func(var); + } +} + +static void Task_ItemStorage_Deposit(u8 taskId) +{ + if (!gPaletteFade.active) + { + sub_80A6A30(); + DestroyTask(taskId); + } +} + +static void ItemStorage_Deposit(u8 taskId) +{ + TASK.FUNC = Task_ItemStorage_Deposit; + fade_screen(1, 0); +} + +static void ItemStorage_HandleReturnToProcessInput(u8 taskId) +{ + if (sub_807D770() == TRUE) + TASK.FUNC = ItemStorageMenuProcessInput; +} + +void ItemStorage_ReturnToMenuAfterDeposit(void) +{ + MenuDisplayMessageBox(); + InitItemStorageMenu(ITEMPC_MENU_DEPOSIT); + CreateTask(ItemStorage_HandleReturnToProcessInput, 0); + pal_fill_black(); +} + +static void ItemStorage_Withdraw(u8 taskId) +{ + s16 *data = TASK.data; + + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 11, 9); + NUM_ITEMS = CountUsedPCItemSlots(); + + if (NUM_ITEMS != 0) + { + MenuZeroFillWindowRect(0, 14, 29, 19); + CURRENT_ITEM_STORAGE_MENU = ITEMPC_MENU_WITHDRAW; + PAGE_INDEX = 0; + ITEMS_ABOVE_TOP = 0; + ItemStorage_SetItemAndMailCount(taskId); + ItemStorage_GoBackToItemPCMenu(taskId, 0); + TASK.FUNC = ItemStorage_ProcessInput; + } + else + DisplayItemMessageOnField(taskId, gOtherText_NoItems, PlayerPC_ItemStorage, 0); +} + +static void ItemStorage_Toss(u8 taskId) +{ + s16 *data = TASK.data; + + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 11, 9); + NUM_ITEMS = CountUsedPCItemSlots(); + + if (NUM_ITEMS) + { + MenuZeroFillWindowRect(0, 14, 29, 19); + CURRENT_ITEM_STORAGE_MENU = ITEMPC_MENU_TOSS; + PAGE_INDEX = 0; + ITEMS_ABOVE_TOP = 0; + ItemStorage_SetItemAndMailCount(taskId); + ItemStorage_GoBackToItemPCMenu(taskId, 2); + TASK.FUNC = ItemStorage_ProcessInput; + } + else + DisplayItemMessageOnField(taskId, gOtherText_NoItems, PlayerPC_ItemStorage, 0); +} + +static void ItemStorage_Exit(u8 var) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 11, 9); + ReshowPlayerPC(var); +} + +static void ItemStorage_SetItemAndMailCount(u8 taskId) +{ + s16 *data = TASK.data; + + if (NUM_ITEMS > 7) // we have a full page, so set the num of page items appropriately. + NUM_PAGE_ITEMS = 8; + else + NUM_PAGE_ITEMS = NUM_ITEMS + 1; // there are not enough items to fill a full page; take the # of items and add 1 for the cancel button. + + if (gMailboxInfo.count > 7) + gMailboxInfo.pageItems = 8; + else + gMailboxInfo.pageItems = gMailboxInfo.count + 1; +} + +static void ItemStorage_ProcessInput(u8 taskId) +{ + s16 *data = TASK.data; + s16 trueIndex; + + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + if(PAGE_INDEX != 0) // did the cursor move physically upwards? + { + PlaySE(SE_SELECT); + PAGE_INDEX = MoveMenuCursor(-1); + trueIndex = ITEMS_ABOVE_TOP + PAGE_INDEX; + if (SWITCH_MODE_ACTIVE == FALSE) // are we not currently switching items? + { + if (trueIndex == NUM_ITEMS) // if the cursor is on top of cancel, print the go back to prev description. + { + ItemStorage_PrintItemPcResponse(ITEMPC_GO_BACK_TO_PREV); + } + else + { + ItemStorage_PrintItemPcResponse(gSaveBlock1.pcItems[trueIndex].itemId); + } + } + } + else // the page cursor is at the top. but we may not be at the top of the true index list, so do another check. + { + if (ITEMS_ABOVE_TOP == 0) // did the cursor not move due to being at the top of the list? + return; + + PlaySE(SE_SELECT); + ITEMS_ABOVE_TOP--; + ItemStorage_DrawBothListAndDescription(taskId); + + if (SWITCH_MODE_ACTIVE != FALSE) + MoveMenuCursor(0); // don't move the cursor. it's at the top of the page index, but not the true index. + } + } + else if(gMain.newAndRepeatedKeys & DPAD_DOWN) // _0813A306 + { + if(PAGE_INDEX != NUM_PAGE_ITEMS - 1) + { + PlaySE(SE_SELECT); + PAGE_INDEX = MoveMenuCursor(1); + trueIndex = ITEMS_ABOVE_TOP + PAGE_INDEX; + + if(SWITCH_MODE_ACTIVE != FALSE) + return; + + if (trueIndex == NUM_ITEMS) + ItemStorage_PrintItemPcResponse(ITEMPC_GO_BACK_TO_PREV); // probably further down + else + ItemStorage_PrintItemPcResponse(gSaveBlock1.pcItems[trueIndex].itemId); + } + else if(ITEMS_ABOVE_TOP + PAGE_INDEX != NUM_ITEMS) + { + PlaySE(SE_SELECT); + ITEMS_ABOVE_TOP++; + ItemStorage_DrawBothListAndDescription(taskId); + + if (SWITCH_MODE_ACTIVE != FALSE) + MoveMenuCursor(0); + } + } + else if(gMain.newKeys & SELECT_BUTTON) // _0813A3A0 + { + if (SWITCH_MODE_ACTIVE == FALSE) + { + if (PAGE_INDEX + ITEMS_ABOVE_TOP != NUM_ITEMS) // you cannot swap the Cancel button. + { + PlaySE(SE_SELECT); + SWITCH_MODE_ACTIVE = TRUE; + SWAP_ITEM_INDEX = ITEMS_ABOVE_TOP + PAGE_INDEX; + ItemStorage_PrintItemPcResponse(ITEMPC_SWITCH_WHICH_ITEM); + } + // _0813A3DC + ItemStorage_DrawItemList(taskId); + } + else // _0813A3E8 + { + PlaySE(SE_SELECT); + ItemStorage_DoItemSwap(taskId, FALSE); + ItemStorage_DrawBothListAndDescription(taskId); + } + } + else if(gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if(SWITCH_MODE_ACTIVE == FALSE) + { + if(ITEMS_ABOVE_TOP + PAGE_INDEX != NUM_ITEMS) + { + ItemStorage_DoItemAction(taskId); + } + else + { + ItemStorage_GoBackToPlayerPCMenu(taskId); + } + } + else + { + ItemStorage_DoItemSwap(taskId, FALSE); + ItemStorage_DrawBothListAndDescription(taskId); + } + } + else if(gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + if(SWITCH_MODE_ACTIVE == FALSE) + { + HandleDestroyMenuCursors(); + ItemStorage_GoBackToPlayerPCMenu(taskId); + } + else + { + ItemStorage_DoItemSwap(taskId, TRUE); + ItemStorage_DrawBothListAndDescription(taskId); + } + } +} + +static void ItemStorage_GoBackToPlayerPCMenu(u8 taskId) +{ + BuyMenuFreeMemory(); + DestroyVerticalScrollIndicator(0); + DestroyVerticalScrollIndicator(1); + MenuZeroFillWindowRect(0, 0, 29, 19); + MenuDisplayMessageBox(); + InitItemStorageMenu(TASK.CURRENT_ITEM_STORAGE_MENU); + TASK.FUNC = ItemStorageMenuProcessInput; +} + +static void ItemStorage_DoItemAction(u8 taskId) +{ + s16 *data = TASK.data; + u8 trueIndex = PAGE_INDEX + ITEMS_ABOVE_TOP; + + PauseVerticalScrollIndicator(0); + PauseVerticalScrollIndicator(1); // PauseVerticalScrollIndicator + + if(CURRENT_ITEM_STORAGE_MENU == ITEMPC_MENU_WITHDRAW) + { + if(gSaveBlock1.pcItems[trueIndex].quantity == 1) + { + NUM_QUANTITY_ROLLER = 1; + ItemStorage_DoItemWithdraw(taskId); + return; + } + else // _0813A50C + { + ItemStorage_PrintItemPcResponse(ITEMPC_HOW_MANY_TO_WITHDRAW); + } + } + else if(gSaveBlock1.pcItems[trueIndex].quantity == 1) // _0813A518 + { + NUM_QUANTITY_ROLLER = 1; + ItemStorage_DoItemToss(taskId); + return; + } + else + { + ItemStorage_PrintItemPcResponse(ITEMPC_HOW_MANY_TO_TOSS); + } + NUM_QUANTITY_ROLLER = 1; + MenuDrawTextWindow(6, 8, 13, 11); + sub_80A418C(NUM_QUANTITY_ROLLER, STR_CONV_MODE_RIGHT_ALIGN, 8, 9, 3); + TASK.FUNC = ItemStorage_HandleQuantityRolling; +} + +static void ItemStorage_HandleQuantityRolling(u8 taskId) +{ + s16 *data = TASK.data; + u8 trueIndex = PAGE_INDEX + ITEMS_ABOVE_TOP; + + if(gMain.newAndRepeatedKeys & DPAD_UP) + { + if(NUM_QUANTITY_ROLLER != gSaveBlock1.pcItems[trueIndex].quantity) + NUM_QUANTITY_ROLLER++; + else + NUM_QUANTITY_ROLLER = 1; // you are at the max amount of items you have when you press Up, set your quantity back to 1. + + sub_80A418C(NUM_QUANTITY_ROLLER, STR_CONV_MODE_RIGHT_ALIGN, 8, 9, 3); // print quantity? + } + else if(gMain.newAndRepeatedKeys & DPAD_DOWN) + { + if(NUM_QUANTITY_ROLLER != 1) + NUM_QUANTITY_ROLLER--; + else + NUM_QUANTITY_ROLLER = gSaveBlock1.pcItems[trueIndex].quantity; // you are at 0 when you press down, set your quantity to the amount you have. + + sub_80A418C(NUM_QUANTITY_ROLLER, STR_CONV_MODE_RIGHT_ALIGN, 8, 9, 3); // print quantity? + } + else if(gMain.newAndRepeatedKeys & DPAD_LEFT) // reduce by 10. + { + NUM_QUANTITY_ROLLER -= 10; + + if(NUM_QUANTITY_ROLLER <= 0) + NUM_QUANTITY_ROLLER = 1; // dont underflow or allow 0! + + sub_80A418C(NUM_QUANTITY_ROLLER, STR_CONV_MODE_RIGHT_ALIGN, 8, 9, 3); // print quantity? + } + else if(gMain.newAndRepeatedKeys & DPAD_RIGHT) // add 10. + { + NUM_QUANTITY_ROLLER += 10; + + if(NUM_QUANTITY_ROLLER > gSaveBlock1.pcItems[trueIndex].quantity) + NUM_QUANTITY_ROLLER = gSaveBlock1.pcItems[trueIndex].quantity; // dont overflow! + + sub_80A418C(NUM_QUANTITY_ROLLER, STR_CONV_MODE_RIGHT_ALIGN, 8, 9, 3); // print quantity? + } + else if(gMain.newKeys & A_BUTTON) // confirm quantity. + { + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(6, 6, 0xD, 0xB); + + if(CURRENT_ITEM_STORAGE_MENU == ITEMPC_MENU_WITHDRAW) + ItemStorage_DoItemWithdraw(taskId); + else + ItemStorage_DoItemToss(taskId); + } + else if(gMain.newKeys & B_BUTTON) // cancel quantity. + { + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(6, 6, 0xD, 0xB); + StartVerticalScrollIndicators(0); + StartVerticalScrollIndicators(1); + ItemStorage_PrintItemPcResponse(gSaveBlock1.pcItems[ITEMS_ABOVE_TOP + PAGE_INDEX].itemId); // why not use trueIndex? + TASK.FUNC = ItemStorage_ProcessInput; + } +} + +static void ItemStorage_DoItemWithdraw(u8 taskId) +{ + s16 *data = TASK.data; + u8 trueIndex = PAGE_INDEX + ITEMS_ABOVE_TOP; + + if(AddBagItem(gSaveBlock1.pcItems[trueIndex].itemId, NUM_QUANTITY_ROLLER) == TRUE) // add item works. + { + CopyItemName(gSaveBlock1.pcItems[trueIndex].itemId, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, NUM_QUANTITY_ROLLER, 0, 3); + ItemStorage_PrintItemPcResponse(ITEMPC_WITHDREW_THING); + TASK.FUNC = ItemStorage_HandleRemoveItem; + } + else + { + NUM_QUANTITY_ROLLER = 0; + ItemStorage_PrintItemPcResponse(ITEMPC_NO_MORE_ROOM); + TASK.FUNC = ItemStorage_WaitPressHandleResumeProcessInput; + } +} + +static void ItemStorage_DoItemToss(u8 taskId) +{ + s16 *data = TASK.data; + u8 var = PAGE_INDEX + ITEMS_ABOVE_TOP; + + if(ItemId_GetImportance(gSaveBlock1.pcItems[var].itemId) == FALSE) + { + CopyItemName(gSaveBlock1.pcItems[var].itemId, gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, NUM_QUANTITY_ROLLER, 0, 3); + ItemStorage_PrintItemPcResponse(ITEMPC_OKAY_TO_THROW_AWAY); + DisplayYesNoMenu(7, 6, 1); + DoYesNoFuncWithChoice(taskId, (struct YesNoFuncTable *)&ResumeFromTossYesNoFuncList); + } + else + { + NUM_QUANTITY_ROLLER = 0; + ItemStorage_PrintItemPcResponse(ITEMPC_TOO_IMPORTANT); + TASK.FUNC = ItemStorage_HandleRemoveItem; + } +} + +static void ItemStorage_ResumeInputFromYesToss(u8 taskId) +{ + MenuZeroFillWindowRect(0x6, 0x6, 0xD, 0xB); + ItemStorage_PrintItemPcResponse(ITEMPC_THREW_AWAY_ITEM); + TASK.FUNC = ItemStorage_HandleRemoveItem; +} + +static void ItemStorage_ResumeInputFromNoToss(u8 taskId) +{ + s16 *data = TASK.data; + + MenuZeroFillWindowRect(0x6, 0x6, 0xD, 0xB); + InitMenu(0, 16, 2, NUM_PAGE_ITEMS, PAGE_INDEX, 0xD); + StartVerticalScrollIndicators(0); + StartVerticalScrollIndicators(1); + ItemStorage_PrintItemPcResponse(gSaveBlock1.pcItems[ITEMS_ABOVE_TOP + PAGE_INDEX].itemId); + TASK.FUNC = ItemStorage_ProcessInput; +} + +static void ItemStorage_HandleRemoveItem(u8 taskId) +{ + s16 *data = TASK.data; + s16 oldNumItems; + + if(gMain.newKeys & A_BUTTON || gMain.newKeys == B_BUTTON) + { + RemovePCItem(PAGE_INDEX + ITEMS_ABOVE_TOP, NUM_QUANTITY_ROLLER); + oldNumItems = NUM_ITEMS; + NUM_ITEMS = CountUsedPCItemSlots(); + + if(oldNumItems != NUM_ITEMS && oldNumItems < NUM_PAGE_ITEMS + ITEMS_ABOVE_TOP && ITEMS_ABOVE_TOP != 0) + ITEMS_ABOVE_TOP--; + + ItemStorage_SetItemAndMailCount(taskId); + ItemStorage_HandleResumeProcessInput(taskId); + InitMenu(0, 16, 2, NUM_PAGE_ITEMS, PAGE_INDEX, 0xD); + } +} + +static void ItemStorage_WaitPressHandleResumeProcessInput(u8 taskId) +{ + s16 *data = TASK.data; + + if(gMain.newKeys & A_BUTTON || gMain.newKeys == B_BUTTON) + { + ItemStorage_PrintItemPcResponse(gSaveBlock1.pcItems[ITEMS_ABOVE_TOP + PAGE_INDEX].itemId); + StartVerticalScrollIndicators(0); + StartVerticalScrollIndicators(1); + TASK.FUNC = ItemStorage_ProcessInput; + } +} + +static void ItemStorage_HandleResumeProcessInput(u8 taskId) +{ + MenuZeroFillWindowRect(0x6, 0x6, 0xD, 0xB); + StartVerticalScrollIndicators(0); + StartVerticalScrollIndicators(1); + ItemStorage_DrawBothListAndDescription(taskId); + TASK.FUNC = ItemStorage_ProcessInput; +} + +static void ItemStorage_DoItemSwap(u8 taskId, bool8 switchModeDisabled) +{ + s16 *data = TASK.data; + u8 trueIndex = ITEMS_ABOVE_TOP + PAGE_INDEX; + + SWITCH_MODE_ACTIVE = FALSE; + + if((u8)NUM_ITEMS > trueIndex && (u8)SWAP_ITEM_INDEX != trueIndex && switchModeDisabled == FALSE) + { + struct ItemSlot itemSlot = gSaveBlock1.pcItems[SWAP_ITEM_INDEX]; // backup the itemSlot before swapping the two. + + gSaveBlock1.pcItems[SWAP_ITEM_INDEX] = gSaveBlock1.pcItems[trueIndex]; + gSaveBlock1.pcItems[trueIndex] = itemSlot; + return; + } + else if(trueIndex == NUM_ITEMS) + { + ItemStorage_PrintItemPcResponse(ITEMPC_GO_BACK_TO_PREV); + } + else + { + ItemStorage_PrintItemPcResponse(gSaveBlock1.pcItems[trueIndex].itemId); + } + + /* + THEORY: This check produces essentially dead code, but it might have been working in an earlier build + in which case it allows a programmer to easily duplicate items without the use of a debug menu. + This gets the page index of the swap index for some reason. It is currently unknown what it would have been used + for, but perhaps it was used to increase the quantity of the item without a debug menu. + With the removal of a lot of the debug menus close to release, a programmer may have added this to + help test things with a low key (such as planting a lot of duplicated berries, which requires this lazy "cheat") + without bringing the relevent debug menus back. The commented out line is intentionally left in below to show + what it may have looked like. + */ + if(SWAP_ITEM_INDEX - ITEMS_ABOVE_TOP <= 0) { // this check is arbitrary and used to generate the correct assembly using the subtraction, which is what matters. the 0 check doesn't. + //gSaveBlock1.pcItems[SWAP_ITEM_INDEX].quantity += 100; + gSaveBlock1.pcItems[SWAP_ITEM_INDEX].quantity += 0; // do not enforce item cap. + } +} + +static void ItemStorage_DrawItemQuantity(u16 arg1, enum StringConvertMode arg2, u8 arg3, u8 arg4, int isSwapSelected) +{ + sub_80A4164(gStringVar1, arg1, arg2, arg4); + + if(isSwapSelected != FALSE) + MenuPrint(gSelectedItemQuantityFormatText, 0x1A, arg3); + else + MenuPrint(gNonSelectedItemQuantityFormatText, 0x1A, arg3); +} + +static void ItemStorage_DrawItemVoidQuantity(u8 var) +{ + MenuPrint(gUnknown_08406330, 0x19, var); +} + +static void ItemStorage_DrawItemName(struct ItemSlot *itemSlot, u8 var, int isSwapSelected) +{ + CopyItemName(itemSlot->itemId, gStringVar1); + + if(isSwapSelected != FALSE) + MenuPrint(gSelectedItemFormattedText, 16, var); + else + MenuPrint(gNonSelectedItemFormattedText, 16, var); +} + +static void ItemStorage_DrawNormalItemEntry(struct ItemSlot *itemSlot, u8 var, int var2) +{ + ItemStorage_DrawItemName(itemSlot, var, var2); + ItemStorage_DrawItemQuantity(itemSlot->quantity, STR_CONV_MODE_RIGHT_ALIGN, var, 3, var2); +} + +static void ItemStorage_DrawKeyItemEntry(struct ItemSlot *itemSlot, u8 var, int var2) +{ + ItemStorage_DrawItemName(itemSlot, var, var2); + ItemStorage_DrawItemVoidQuantity(var); +} + +static void ItemStorage_DrawTMHMEntry(struct ItemSlot *itemSlot, u8 var, int var2) +{ + ItemStorage_DrawItemName(itemSlot, var, var2); + + if(itemSlot->itemId < ITEM_HM01) + ItemStorage_DrawItemQuantity(itemSlot->quantity, STR_CONV_MODE_RIGHT_ALIGN, var, 3, var2); + else + ItemStorage_DrawItemVoidQuantity(var); // HMs do not have a quantity. +} + +static void ItemStorage_DrawItemList(u8 taskId) +{ + s16 *data = TASK.data; + int tempArg; + u16 i; + u16 yCoord = 0; + + // r5 is i and is unsigned 16-bit. + + for(i = ITEMS_ABOVE_TOP; i < ITEMS_ABOVE_TOP + NUM_PAGE_ITEMS; i++) + { + yCoord = (i - ITEMS_ABOVE_TOP) * 2; + + if(i != NUM_ITEMS) + { + tempArg = 0; + + if(SWITCH_MODE_ACTIVE != FALSE && i == SWAP_ITEM_INDEX) + tempArg = 1; + + switch(GetPocketByItemId(gSaveBlock1.pcItems[i].itemId) - 1) + { + case 0: + case 1: + case 3: + ItemStorage_DrawNormalItemEntry((struct ItemSlot *)&gSaveBlock1.pcItems[i], yCoord + 2, tempArg); + break; + case 4: + ItemStorage_DrawKeyItemEntry((struct ItemSlot *)&gSaveBlock1.pcItems[i], yCoord + 2, tempArg); + break; + case 2: + ItemStorage_DrawTMHMEntry((struct ItemSlot *)&gSaveBlock1.pcItems[i], yCoord + 2, tempArg); + break; + } + } + else + { + goto weirdCase; // what??? + } + } + +beforeLabel: + if(i - ITEMS_ABOVE_TOP < 8) + MenuFillWindowRectWithBlankTile(16, yCoord + 4, 0x1C, 0x12); + + switch(ITEMS_ABOVE_TOP) + { + default: + CreateVerticalScrollIndicators(0, 0xB8, 8); + break; +weirdCase: + sub_8072A18(gOtherText_CancelNoTerminator, 0x80, (yCoord + 2) * 8, 0x68, 1); + goto beforeLabel; + case 0: + DestroyVerticalScrollIndicator(0); + break; + } + + if(ITEMS_ABOVE_TOP + NUM_PAGE_ITEMS <= NUM_ITEMS) + CreateVerticalScrollIndicators(1, 0xB8, 0x98); + else + DestroyVerticalScrollIndicator(1); +} + +static void ItemStorage_PrintItemPcResponse(u16 itemId) +{ + const u8 *string; + + switch(itemId) + { + case ITEMPC_GO_BACK_TO_PREV: + string = gMenuText_GoBackToPrev; + break; + case ITEMPC_HOW_MANY_TO_WITHDRAW: + string = gOtherText_HowManyToWithdraw; + break; + case ITEMPC_WITHDREW_THING: + string = gOtherText_WithdrewThing; + break; + case ITEMPC_HOW_MANY_TO_TOSS: + string = gOtherText_HowManyToToss; + break; + case ITEMPC_THREW_AWAY_ITEM: + string = gOtherText_ThrewAwayItem; + break; + case ITEMPC_NO_MORE_ROOM: + string = gOtherText_NoMoreRoom; + break; + case ITEMPC_TOO_IMPORTANT: + string = gOtherText_TooImportant; + break; + case ITEMPC_OKAY_TO_THROW_AWAY: + string = gOtherText_OkayToThrowAwayPrompt; + break; + case ITEMPC_SWITCH_WHICH_ITEM: + string = gOtherText_SwitchWhichItem; + break; + default: + string = ItemId_GetDescription(itemId); + break; + } + + sub_8072AB0(string, 8, 0x68, 0x68, 0x30, 1); +} + +static void ItemStorage_DrawBothListAndDescription(u8 taskId) +{ + s16 *data = TASK.data; + s16 trueIndex = ITEMS_ABOVE_TOP + PAGE_INDEX; + + ItemStorage_DrawItemList(taskId); + + if(SWITCH_MODE_ACTIVE == FALSE) + { + if(trueIndex == NUM_ITEMS) + ItemStorage_PrintItemPcResponse(ITEMPC_GO_BACK_TO_PREV); + else + ItemStorage_PrintItemPcResponse(gSaveBlock1.pcItems[trueIndex].itemId); + } +} + +static void ItemStorage_GoBackToItemPCMenu(u8 taskId, u8 var) +{ + s16 *data = TASK.data; + + sub_80F944C(); + LoadScrollIndicatorPalette(); + ItemStorage_LoadPalette(); + MenuDrawTextWindow(0xF, 0, 0x1D, 0x13); + MenuDrawTextWindow(0, 0xC, 0xE, 0x13); + MenuDrawTextWindow(0, 0, 0xB, 3); + ItemStorage_PrintItemPcResponse(gSaveBlock1.pcItems[0].itemId); + MenuPrint(gPCText_ItemPCOptionsText[var].text, 1, 1); + ItemStorage_DrawItemList(taskId); + InitMenu(0, 0x10, 2, NUM_PAGE_ITEMS, PAGE_INDEX, 0xD); +} + +static void ItemStorage_LoadPalette(void) +{ + u16 arr[3]; + + memcpy(arr, gUnknown_08406334, sizeof(arr)); + LoadPalette(&arr[2], 0xDF, 2); + LoadPalette(&arr[1], 0xD1, 2); + LoadPalette(&arr[0], 0xD8, 2); +} + +static u8 GetMailboxMailCount(void) +{ + u8 i, j; + + for(i = 0, j = 6; j < 16; j++) + if(gSaveBlock1.mail[j].itemId != 0) + i++; + + return i; +} + +static void Mailbox_UpdateMailList(void) +{ + struct MailStruct mailBuffer; + u8 i, j; + + for (i=6; i<15; i++) + { + for (j=i+1; j<16; j++) + { + if (gSaveBlock1.mail[i].itemId == 0) + { + mailBuffer = gSaveBlock1.mail[i]; + gSaveBlock1.mail[i] = gSaveBlock1.mail[j]; + gSaveBlock1.mail[j] = mailBuffer; + } + } + } +} + +// WWHHHHHYYYYYYYY SOMEBODY PLEASE FIX THIS +static void Mailbox_DrawMailList(u8 taskId) // taskId is unused +{ + u16 yCoord = 0; + u16 i = gMailboxInfo.itemsAbove; + register struct MailboxStruct *tempMailbox asm("r1") = &gMailboxInfo; + register struct MailboxStruct *mailbox asm("r6"); + + if(i < i + tempMailbox->pageItems) + { + mailbox = tempMailbox; + goto forJump; + for(; i < mailbox->itemsAbove + mailbox->pageItems; i++) + { + forJump: + yCoord = (i - mailbox->itemsAbove) * 2; + MenuFillWindowRectWithBlankTile(0x15, yCoord + 2, 0x1C, yCoord + 3); + + if(i != mailbox->count) + { + StringCopy(gStringVar1, (u8 *)gSaveBlock1.mail[i + 6].playerName); + SanitizeNameString(gStringVar1); + MenuPrint(gStringVar1, 0x15, yCoord + 2); + } + else + { + goto weirdCase; // again, what??? + } + } + } + +beforeLabel: + if(i - gMailboxInfo.itemsAbove != 8) + MenuFillWindowRectWithBlankTile(0x15, yCoord + 4, 0x1C, 0x12); + + switch(gMailboxInfo.itemsAbove) + { + default: + CreateVerticalScrollIndicators(0, 0xC8, 8); + break; +weirdCase: + MenuPrint(gOtherText_CancelNoTerminator, 0x15, yCoord + 2); + goto beforeLabel; + case 0: + DestroyVerticalScrollIndicator(0); + break; + } + + if(gMailboxInfo.itemsAbove + gMailboxInfo.pageItems <= gMailboxInfo.count) + CreateVerticalScrollIndicators(1, 0xC8, 0x98); + else + DestroyVerticalScrollIndicator(1); +} + +static void Mailbox_DrawMailboxMenu(u8 taskId) +{ + sub_80F944C(); + LoadScrollIndicatorPalette(); + MenuZeroFillWindowRect(0, 0, 0x1D, 0x13); + MenuDrawTextWindow(0, 0, 0x8, 0x3); + MenuPrint(gPCText_Mailbox, 1, 1); + MenuDrawTextWindow(0x14, 0, 0x1D, 0x13); + Mailbox_DrawMailList(taskId); + InitMenu(0, 0x15, 2, gMailboxInfo.pageItems, gMailboxInfo.cursorPos, 8); +} + +// Mailbox_ProcessInput +static void Mailbox_ProcessInput(u8 taskId) +{ + if(!gPaletteFade.active) + { + if(gMain.newAndRepeatedKeys & DPAD_UP) + { + if(gMailboxInfo.cursorPos != 0) + { + PlaySE(SE_SELECT); + gMailboxInfo.cursorPos = MoveMenuCursor(-1); + } + else if(gMailboxInfo.itemsAbove != 0) + { + PlaySE(SE_SELECT); + gMailboxInfo.itemsAbove--; + Mailbox_DrawMailList(taskId); + } + } + else if(gMain.newAndRepeatedKeys & DPAD_DOWN) + { + if(gMailboxInfo.cursorPos != gMailboxInfo.pageItems - 1) + { + PlaySE(SE_SELECT); + gMailboxInfo.cursorPos = MoveMenuCursor(1); + } + else if(gMailboxInfo.itemsAbove + gMailboxInfo.cursorPos != gMailboxInfo.count) + { + PlaySE(SE_SELECT); + gMailboxInfo.itemsAbove++; + Mailbox_DrawMailList(taskId); + } + } + else if(gMain.newKeys & A_BUTTON) + { + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + + if(gMailboxInfo.itemsAbove + gMailboxInfo.cursorPos == gMailboxInfo.count) + { + Mailbox_TurnOff(taskId); + } + else + { + Mailbox_CloseScrollIndicators(); + TASK.FUNC = Mailbox_PrintWhatToDoWithPlayerMailText; + } + } + else if(gMain.newKeys & B_BUTTON) + { + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + Mailbox_TurnOff(taskId); + } + } +} + +static void Mailbox_CloseScrollIndicators(void) +{ + BuyMenuFreeMemory(); + DestroyVerticalScrollIndicator(0); + DestroyVerticalScrollIndicator(1); +} + +static void Mailbox_PrintWhatToDoWithPlayerMailText(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0, 0x1D, 0x13); + StringCopy(gStringVar1, gSaveBlock1.mail[gMailboxInfo.itemsAbove + 6 + gMailboxInfo.cursorPos].playerName); + SanitizeNameString(gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_WhatWillYouDoMail); + DisplayItemMessageOnField(taskId, gStringVar4, Mailbox_PrintMailOptions, 0); +} + +static void Mailbox_ReturnToPlayerPC(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0, 0x1D, 0x13); + ReshowPlayerPC(taskId); +} + +static void Mailbox_TurnOff(u8 taskId) +{ + Mailbox_CloseScrollIndicators(); + TASK.FUNC = Mailbox_ReturnToPlayerPC; +} + +static void Mailbox_PrintMailOptions(u8 taskId) // Mailbox_PrintMailOptions +{ + MenuDrawTextWindow(0, 0, 0xC, 0x9); + PrintMenuItems(1, 1, 4, (struct MenuAction *)gMailboxMailOptions); + InitMenu(0, 1, 1, 4, 0, 0xB); + TASK.FUNC = Mailbox_MailOptionsProcessInput; +} + +static void Mailbox_MailOptionsProcessInput(u8 taskId) +{ + if(gMain.newAndRepeatedKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + } + else if(gMain.newAndRepeatedKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + } + else if(gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + gMailboxMailOptions[GetMenuCursorPos()].func(taskId); + } + else if(gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + Mailbox_Cancel(taskId); + } +} + +static void Mailbox_DoMailRead(u8 taskId) +{ + fade_screen(1, 0); + TASK.FUNC = Mailbox_FadeAndReadMail; +} + +static void Mailbox_FadeAndReadMail(u8 taskId) +{ + if(!gPaletteFade.active) + { + HandleReadMail(&gSaveBlock1.mail[gMailboxInfo.itemsAbove + 6 + gMailboxInfo.cursorPos], Mailbox_ReturnToFieldFromReadMail, 1); + DestroyTask(taskId); + } +} + +static void Mailbox_HandleReturnToProcessInput(u8 taskId) // Mailbox_HandleReturnToProcessInput +{ + if(sub_807D770() == TRUE) // is black fade finished? why not gPaletteFade.active? + TASK.FUNC = Mailbox_ProcessInput; +} + +static void Mailbox_DoRedrawMailboxMenuAfterReturn(void) +{ + Mailbox_DrawMailboxMenu(CreateTask(Mailbox_HandleReturnToProcessInput, 0)); + pal_fill_black(); +} + +static void Mailbox_ReturnToFieldFromReadMail(void) +{ + gFieldCallback = Mailbox_DoRedrawMailboxMenuAfterReturn; + SetMainCallback2(c2_exit_to_overworld_2_switch); +} + +static void Mailbox_MoveToBag(u8 taskId) +{ + HandleDestroyMenuCursors(); + StringCopy(gStringVar1, gOtherText_MoveToBag); + MenuPrint(gHighlightedMoveToBagFormatText, 1, 3); // gHighlightedMoveToBagFormatText + DisplayItemMessageOnField(taskId, gOtherText_MessageWillBeLost, Mailbox_DrawYesNoBeforeMove, 0); +} + +static void Mailbox_DrawYesNoBeforeMove(u8 taskId) +{ + DisplayYesNoMenu(0x14, 0x8, 0x1); + DoYesNoFuncWithChoice(taskId, (struct YesNoFuncTable *)&ResumeFromWithdrawYesNoFuncList); +} + +static void Mailbox_DoMailMoveToBag(u8 taskId) +{ + struct MailStruct *mail = &gSaveBlock1.mail[gMailboxInfo.itemsAbove + 6 + gMailboxInfo.cursorPos]; + + MenuZeroFillWindowRect(0x14, 8, 0x1A, 0xD); + + if(AddBagItem(mail->itemId, 1) == FALSE) + { + DisplayItemMessageOnField(taskId, gOtherText_BagIsFull, Mailbox_DrawMailMenuAndDoProcessInput, 0); + } + else + { + DisplayItemMessageOnField(taskId, gOtherText_MailWasReturned, Mailbox_DrawMailMenuAndDoProcessInput, 0); + ClearMailStruct(mail); + Mailbox_UpdateMailList(); + + gMailboxInfo.count--; + + if(gMailboxInfo.count < gMailboxInfo.pageItems + gMailboxInfo.itemsAbove && gMailboxInfo.itemsAbove != 0) + gMailboxInfo.itemsAbove--; + + ItemStorage_SetItemAndMailCount(taskId); + } +} + +static void Mailbox_ReturnToInputAfterNo(u8 taskId) // Mailbox_ReturnToInputAfterNo +{ + MenuZeroFillWindowRect(0x14, 0x8, 0x1A, 0xD); + Mailbox_DrawMailMenuAndDoProcessInput(taskId); +} + +static void Mailbox_Give(u8 taskId) +{ + if(CalculatePlayerPartyCount() == 0) + Mailbox_NoPokemonForMail(taskId); // cannot be reached normally + else + { + fade_screen(1, 0); + TASK.FUNC = Mailbox_DoGiveMailPokeMenu; + } +} + +static void Mailbox_DoGiveMailPokeMenu(u8 taskId) // Mailbox_DoGiveMailPokeMenu +{ + if(!gPaletteFade.active) + { + SetMainCallback2(sub_808B020); + gUnknown_02038561 = 3; + DestroyTask(taskId); + } +} + +static void Mailbox_UpdateMailListAfterDeposit(void) +{ + u8 taskId = CreateTask(Mailbox_HandleReturnToProcessInput, 0); + u8 oldCount = gMailboxInfo.count; + + gMailboxInfo.count = GetMailboxMailCount(); + Mailbox_UpdateMailList(); + + if(oldCount != gMailboxInfo.count && gMailboxInfo.count < gMailboxInfo.pageItems + gMailboxInfo.itemsAbove && gMailboxInfo.itemsAbove != 0) // did the count update? + gMailboxInfo.itemsAbove--; + + ItemStorage_SetItemAndMailCount(taskId); + Mailbox_DrawMailboxMenu(taskId); + pal_fill_black(); +} + +void Mailbox_ReturnToMailListAfterDeposit(void) +{ + gFieldCallback = Mailbox_UpdateMailListAfterDeposit; + SetMainCallback2(c2_exit_to_overworld_2_switch); +} + +// you always have at least 1 POKeMON and you cannot receive mail before you leave Littleroot: therefore this function cannot be reached normally. +static void Mailbox_NoPokemonForMail(u8 taskId) +{ + DisplayItemMessageOnField(taskId, gOtherText_NoPokemon, Mailbox_DrawMailMenuAndDoProcessInput, 0); +} + +static void Mailbox_Cancel(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 0xC, 0x9); + Mailbox_DrawMailMenuAndDoProcessInput(taskId); +} + +static void Mailbox_DrawMailMenuAndDoProcessInput(u8 taskId) +{ + Mailbox_DrawMailboxMenu(taskId); + TASK.FUNC = Mailbox_ProcessInput; +} diff --git a/src/field/pokeblock.c b/src/field/pokeblock.c new file mode 100644 index 000000000..34f4ffa35 --- /dev/null +++ b/src/field/pokeblock.c @@ -0,0 +1,1133 @@ +// + +// + +#include "global.h" +#include "overworld.h" +#include "sprite.h" +#include "script.h" +#include "strings.h" +#include "task.h" +#include "unknown_task.h" +#include "text.h" +#include "main.h" +#include "menu.h" +#include "field_fadetransition.h" +#include "palette.h" +#include "graphics.h" +#include "decompress.h" +#include "menu_helpers.h" +#include "battle.h" +#include "item_menu.h" +#include "item_use.h" +#include "item.h" +#include "items.h" +#include "sound.h" +#include "songs.h" +#include "safari_zone.h" +#include "event_data.h" +#include "pokeblock.h" + +struct UnkPokeblockStruct +{ + u8 unk0; + u8 unk1; + u8 unk2; + u8 unk3; +}; + +extern u8 ewram[]; + + +static EWRAM_DATA u8 gUnknown_02039244 = 0; +static EWRAM_DATA struct UnkPokeblockStruct gUnknown_02039248 = {0}; +static EWRAM_DATA u8 gUnknown_0203924C = 0; + +// function declarations + +// gUnknown_083F7EF4 +static void sub_810C508(u8); +static void sub_810C5C0(u8); +static void sub_810C748(u8); +static void sub_810C788(u8); +static void sub_810C854(u8); + +// gUnknown_083F7F24 +static void sub_810C610(u8); +static void sub_810C668(u8); + +// sub_810B6C0 +static bool8 sub_810B998(void); +static void sub_810BC98(void); +static void sub_810BD08(void); +static void sub_810BB0C(void); +static void sub_810BB30(void); +static void sub_810BC84(u8); + +// sub_810B96C +static void sub_810BF7C(u8); + +// sub_810BC84 +static void sub_810BDAC(bool8); + +// sub_810BF38 +static void sub_810C8D4(struct Sprite *); + +// sub_810BF7C +static void sub_810C0C8(u8); +static void sub_810C31C(u8); +static void sub_810C368(u8); + +// sub_810C0C8 +static void sub_810C1C8(u8, u8); +static void sub_810C23C(u8); + +// sub_810C368 +static void sub_810C40C(u8); + +// sub_810C540 +static void sub_810C5EC(u8); + +// sub_810C610 +static void sub_810C704(u8); + +static const u8 *gUnknown_03000758; + +// rodata + +#define GFX_TAG_POKEBLOCK_CASE 14800 + +const s8 gPokeblockFlavorCompatibilityTable[] = { + // Cool, Beauty, Cute, Smart, Tough + 0, 0, 0, 0, 0, // Hardy + 1, 0, 0, 0, -1, // Lonely + 1, 0, -1, 0, 0, // Brave + 1, -1, 0, 0, 0, // Adamant + 1, 0, 0, -1, 0, // Naughty + -1, 0, 0, 0, 1, // Bold + 0, 0, 0, 0, 0, // Docile + 0, 0, -1, 0, 1, // Relaxed + 0, -1, 0, 0, 1, // Impish + 0, 0, 0, -1, 1, // Lax + -1, 0, 1, 0, 0, // Timid + 0, 0, 1, 0, -1, // Hasty + 0, 0, 0, 0, 0, // Serious + 0, -1, 1, 0, 0, // Jolly + 0, 0, 1, -1, 0, // Naive + -1, 1, 0, 0, 0, // Modest + 0, 1, 0, 0, -1, // Mild + 0, 1, -1, 0, 0, // Quiet + 0, 0, 0, 0, 0, // Bashful + 0, 1, 0, -1, 0, // Rash + -1, 0, 0, 1, 0, // Calm + 0, 0, 0, 1, -1, // Gentle + 0, 0, -1, 1, 0, // Sassy + 0, -1, 0, 1, 0, // Careful + 0, 0, 0, 0, 0 // Quirky +}; + +void (*const gUnknown_083F7EA8[])(void) = { + sub_80A5B40, + c2_exit_to_overworld_2_switch, + sub_802E424, + c2_exit_to_overworld_2_switch +}; + +const u8 *const gPokeblockNames[] = { + NULL, + ContestStatsText_RedPokeBlock, + ContestStatsText_BluePokeBlock, + ContestStatsText_PinkPokeBlock, + ContestStatsText_GreenPokeBlock, + ContestStatsText_YellowPokeBlock, + ContestStatsText_PurplePokeBlock, + ContestStatsText_IndigoPokeBlock, + ContestStatsText_BrownPokeBlock, + ContestStatsText_LiteBluePokeBlock, + ContestStatsText_OlivePokeBlock, + ContestStatsText_GrayPokeBlock, + ContestStatsText_BlackPokeBlock, + ContestStatsText_WhitePokeBlock, + ContestStatsText_GoldPokeBlock +}; + +const struct MenuAction2 gUnknown_083F7EF4[] = { + {OtherText_Use, sub_810C508}, + {OtherText_Toss, sub_810C5C0}, + {gOtherText_CancelNoTerminator, sub_810C748}, + {OtherText_Use, sub_810C788}, + {OtherText_Use, sub_810C854}, +}; + +const u8 gUnknown_083F7F1C[] = {0, 1, 2}; +const u8 gUnknown_083F7F1F[] = {3, 2}; +const u8 gUnknown_083F7F21[] = {4, 2}; + +const struct YesNoFuncTable gUnknown_083F7F24 = {sub_810C610, sub_810C668}; + +const u8 UnreferencedData_083F7F2C[] = {0x16, 0x17, 0x18, 0x21, 0x2f}; + +const struct OamData gOamData_83F7F34 = { + .size = 3, + .priority = 2 +}; + +const union AnimCmd gSpriteAnim_83F7F3C[] = { + ANIMCMD_FRAME(.imageValue = 0, .duration = 0), + ANIMCMD_END +}; + +const union AnimCmd *const gSpriteAnimTable_83F7F44[] = { + gSpriteAnim_83F7F3C +}; + +const union AffineAnimCmd gSpriteAffineAnim_83F7F48[] = { + AFFINEANIMCMD_FRAME(0, 0, -2, 2), + AFFINEANIMCMD_FRAME(0, 0, 2, 4), + AFFINEANIMCMD_FRAME(0, 0, -2, 4), + AFFINEANIMCMD_FRAME(0, 0, 2, 2), + AFFINEANIMCMD_END +}; + +const union AffineAnimCmd *const gSpriteAffineAnimTable_83F7F70[] = { + gSpriteAffineAnim_83F7F48 +}; + +const struct CompressedSpriteSheet gUnknown_083F7F74 = { + gMenuPokeblockDevice_Gfx, + 0x800, + GFX_TAG_POKEBLOCK_CASE +}; + +const struct CompressedSpritePalette gUnknown_083F7F7C = { + gMenuPokeblockDevice_Pal, + GFX_TAG_POKEBLOCK_CASE +}; + +const struct SpriteTemplate gSpriteTemplate_83F7F84 = { + GFX_TAG_POKEBLOCK_CASE, + GFX_TAG_POKEBLOCK_CASE, + &gOamData_83F7F34, + gSpriteAnimTable_83F7F44, + NULL, + gDummySpriteAffineAnimTable, + SpriteCallbackDummy +}; + +const struct Pokeblock gUnknown_083F7F9C[] = { + { PBLOCK_CLR_RED, 20, 0, 0, 0, 0, 20}, + { PBLOCK_CLR_BLUE, 0, 20, 0, 0, 0, 20}, + { PBLOCK_CLR_PINK, 0, 0, 20, 0, 0, 20}, + { PBLOCK_CLR_GREEN, 0, 0, 0, 20, 0, 20}, + { PBLOCK_CLR_YELLOW, 0, 0, 0, 0, 20, 20} +}; + +// text + +static void sub_810B674(void) +{ + AnimateSprites(); + BuildOamBuffer(); + RunTasks(); + UpdatePaletteFade(); +} + +static void sub_810B68C(void) +{ + u16 *src; + vu16 *dest; + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); + src = gBGTilemapBuffers[2]; + dest = (vu16 *)(VRAM + 0x7800); + DmaCopy16(3, src, dest, sizeof gBGTilemapBuffers[2]); +} + +static bool8 sub_810B6C0(void) +{ + u16 ime; + switch (gMain.state) + { + case 0: + sub_80F9438(); + sub_80F9368(); + REG_BG2CNT = BGCNT_SCREENBASE(15) | BGCNT_CHARBASE(2) | BGCNT_PRIORITY(2); + REG_BLDCNT = 0; + gMain.state++; + break; + case 1: + remove_some_task(); + gMain.state++; + break; + case 2: + ResetPaletteFade(); + gPaletteFade.bufferTransferDisabled = TRUE; + gMain.state++; + break; + case 3: + ResetSpriteData(); + gMain.state++; + break; + case 4: + if (gUnknown_02039244 != 2) + { + ResetTasks(); + } + gMain.state++; + break; + case 5: + SetUpWindowConfig(&gWindowConfig_81E6E34); + gMain.state++; + break; + case 6: + SetUpWindowConfig(&gWindowConfig_81E6E50); + gMain.state++; + break; + case 7: + MultistepInitMenuWindowBegin(&gWindowConfig_81E6E34); + gMain.state++; + break; + case 8: + if (MultistepInitMenuWindowContinue()) + { + gMain.state++; + } + break; + case 9: + MultistepInitMenuWindowBegin(&gWindowConfig_81E6E50); + gMain.state++; + break; + case 10: + if (MultistepInitMenuWindowContinue()) + { + ewram[0x1ffff] = 0; + gMain.state++; + } + break; + case 11: + if (sub_810B998()) + { + gMain.state++; + } + break; + case 12: + sub_80F944C(); + LoadScrollIndicatorPalette(); + CreateVerticalScrollIndicators(0, 0xb0, 0x08); + CreateVerticalScrollIndicators(1, 0xb0, 0x98); + gMain.state++; + break; + case 13: + ewram[0x1fffe] = sub_810BA50(0x38, 0x40, 0); + gMain.state++; + break; + case 14: + sub_810BC98(); + sub_810BD08(); + gMain.state++; + break; + case 15: + sub_810BB0C(); + sub_810BB30(); + sub_810BC84(gUnknown_02039248.unk1); + gMain.state++; + break; + case 16: + ime = REG_IME; + REG_IME = 0; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = ime; + REG_DISPSTAT |= DISPSTAT_VBLANK_INTR; + SetVBlankCallback(sub_810B68C); + REG_DISPCNT = DISPCNT_OBJ_ON | DISPCNT_BG2_ON | DISPCNT_BG1_ON | DISPCNT_BG0_ON | DISPCNT_OBJ_1D_MAP; + gMain.state++; + break; + case 17: + if (sub_8055870() != TRUE) + { + gMain.state++; + } + break; + case 18: + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + gPaletteFade.bufferTransferDisabled = FALSE; + SetMainCallback2(sub_810B674); + return TRUE; + } + return FALSE; +} + +void sub_810B96C(void) +{ + do { + if (sub_810B6C0() == TRUE) + { + CreateTask(sub_810BF7C, 0); + break; + } + } while (sub_80F9344() != TRUE); +} + +static bool8 sub_810B998(void) +{ + switch (ewram[0x1ffff]) + { + case 0: + LZDecompressVram(gMenuPokeblock_Gfx, (u8 *)BG_CHAR_ADDR(2)); + ewram[0x1ffff]++; + break; + case 1: + LZDecompressWram(gMenuPokeblock_Tilemap, gBGTilemapBuffers[2]); + ewram[0x1ffff]++; + break; + case 2: + LoadCompressedPalette(gMenuPokeblock_Pal, 0, 0xc0); + ewram[0x1ffff]++; + break; + case 3: + LoadCompressedObjectPic(&gUnknown_083F7F74); + ewram[0x1ffff]++; + break; + case 4: + LoadCompressedObjectPalette(&gUnknown_083F7F7C); + ewram[0x1ffff] = 0; + return TRUE; + } + return FALSE; +} + +u8 sub_810BA50(s16 x, s16 y, u8 subpriority) +{ + return CreateSprite(&gSpriteTemplate_83F7F84, x, y, subpriority); +} + +void sub_810BA7C(u8 a0) +{ + gUnknown_02039244 = a0; + switch (gUnknown_02039244) + { + default: + gUnknown_03000758 = gUnknown_083F7F1C; + gUnknown_0203924C = sizeof gUnknown_083F7F1C; + break; + case 2: + gUnknown_03000758 = gUnknown_083F7F1F; + gUnknown_0203924C = sizeof gUnknown_083F7F1F; + break; + case 3: + gUnknown_03000758 = gUnknown_083F7F21; + gUnknown_0203924C = sizeof gUnknown_083F7F21; + break; + } +} + +void sub_810BADC(void) +{ + sub_810BA7C(2); + SetMainCallback2(sub_810B96C); +} + +void sub_810BAF4(void) +{ + sub_810BA7C(3); + SetMainCallback2(sub_810B96C); +} + +#ifdef DEBUG +void debug_sub_8120F98(void) +{ + u8 i; + for (i=0; i<40 && gUnknown_083F7F9C[i].color != 0; i++) + { + gSaveBlock1.pokeblocks[i] = gUnknown_083F7F9C[i]; + } +} +#endif + +static void sub_810BB0C(void) +{ + BasicInitMenuWindow(&gWindowConfig_81E6E34); + sub_8072BD8(ItemId_GetItem(ITEM_POKEBLOCK_CASE)->name, 2, 1, 0x48); +} + +static void sub_810BB30(void) +{ + BasicInitMenuWindow(&gWindowConfig_81E6E34); + MenuPrint(gContestStatsText_Spicy, 2, 13); + MenuPrint(gContestStatsText_Dry, 2, 15); + MenuPrint(gContestStatsText_Sweet, 2, 17); + MenuPrint(gContestStatsText_Bitter, 8, 13); + MenuPrint(gContestStatsText_Sour, 8, 15); +} + +static void sub_810BB88(u8 a0) +{ + u8 i; + u8 y; + u8 *buf; + BasicInitMenuWindow(&gWindowConfig_81E6E34); + for (i=a0; i<=a0+8; i++) + { + y = (i - a0) << 1; + if (i == gUnknown_02039248.unk2) + { + buf = sub_8072C74(gStringVar1, gContestStatsText_StowCase, 0x78, 0); + MenuPrint(gStringVar1, 15, y + 1); + if (i != a0 + 8) + { + MenuZeroFillWindowRect(15, y + 3, 29, 18); + } + break; + } + buf = sub_8072C74(gStringVar1, gPokeblockNames[gSaveBlock1.pokeblocks[i].color], 0x5e, 0); + buf[0] = EXT_CTRL_CODE_BEGIN; + buf[1] = 0x14; + buf[2] = 0x06; + buf += 3; + ConvertIntToDecimalStringN(buf, sub_810C9B0(&gSaveBlock1.pokeblocks[i]), STR_CONV_MODE_RIGHT_ALIGN, 3); + MenuPrint(gStringVar1, 15, y + 1); + } +} + +static void sub_810BC84(u8 a0) +{ + sub_810BB88(a0); + sub_810BDAC(FALSE); +} + +static void sub_810BC98(void) +{ + u16 i, j; + struct Pokeblock buf; + for (i=0; i<39; i++) + { + for (j=i+1; j<40; j++) + { + if (gSaveBlock1.pokeblocks[i].color == 0) + { + buf = gSaveBlock1.pokeblocks[i]; + gSaveBlock1.pokeblocks[i] = gSaveBlock1.pokeblocks[j]; + gSaveBlock1.pokeblocks[j] = buf; + } + } + } +} + +static void sub_810BD08(void) +{ + u8 i; + gUnknown_02039248.unk2 = 0; + for (i=0; i<40; i++) + { + if (gSaveBlock1.pokeblocks[i].color != 0) + gUnknown_02039248.unk2++; + } + if (gUnknown_02039248.unk2 < 8) + { + gUnknown_02039248.unk3 = gUnknown_02039248.unk2; + } + else + { + gUnknown_02039248.unk3 = 8; + } + if (gUnknown_02039248.unk1 + 8 > gUnknown_02039248.unk2 && gUnknown_02039248.unk1 != 0) + { + gUnknown_02039248.unk1--; + } +} + +static void sub_810BD64(u16 a0, u16 a1) +{ + u8 i; + int y; + for (i=0; i<14; i++) + { + gBGTilemapBuffers[2][(2 * gUnknown_02039248.unk0 + 1) * 32 + (y = i + 15)] = a0; + gBGTilemapBuffers[2][(2 * gUnknown_02039248.unk0 + 2) * 32 + y] = a0; + } +} + +static void sub_810BDAC(bool8 flag) +{ + u8 i; + u16 v0; + if (!flag) + { + sub_810BD64(0x1005, 0x1014); + } + else + { + sub_810BD64(0x2005, 0x2014); + } + if (gUnknown_02039248.unk1) + { + sub_80F979C(0, 0); + } + else + { + sub_80F979C(0, 1); + } + if (gUnknown_02039248.unk2 > gUnknown_02039248.unk3 && gUnknown_02039248.unk1 + gUnknown_02039248.unk3 != gUnknown_02039248.unk2) + { + sub_80F979C(1, 0); + } + else + { + sub_80F979C(1, 1); + } + for (i=0; i<5; i++) + { + v0 = ((i % 3) << 6) + 0x1a1 + (i / 3) * 6; + if (gUnknown_02039248.unk0 + gUnknown_02039248.unk1 != gUnknown_02039248.unk2) + { + if (GetPokeblockData(&gSaveBlock1.pokeblocks[gUnknown_02039248.unk0 + gUnknown_02039248.unk1], i + 1) > 0) + { + gBGTilemapBuffers[2][v0] = (i << 12) + 23; + gBGTilemapBuffers[2][v0 + 32] = (i << 12) + 24; + } + else + { + gBGTilemapBuffers[2][v0] = 15; + gBGTilemapBuffers[2][v0 + 32] = 15; + } + } + else + { + gBGTilemapBuffers[2][v0] = 15; + gBGTilemapBuffers[2][v0 + 32] = 15; + } + } + BasicInitMenuWindow(&gWindowConfig_81E6E34); + if (gUnknown_02039248.unk0 + gUnknown_02039248.unk1 != gUnknown_02039248.unk2) + { + sub_8072C14(gStringVar1, sub_810C9E8(&gSaveBlock1.pokeblocks[gUnknown_02039248.unk0 + gUnknown_02039248.unk1]), 16, 1); + MenuPrint(gStringVar1, 11, 17); + } + else + { + MenuZeroFillWindowRect(11, 17, 12, 18); + } +} + +static void sub_810BF38(bool8 flag) +{ + PlaySE(SE_SELECT); + gSprites[ewram[0x1fffe]].callback = sub_810C8D4; + sub_810BDAC(flag); +} + +static void sub_810BF7C(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + if (gUnknown_02039248.unk0 != 0) + { + sub_810BD64(5, 20); + gUnknown_02039248.unk0--; + sub_810BF38(FALSE); + } + else if (gUnknown_02039248.unk1 != 0) + { + gUnknown_02039248.unk1--; + sub_810BB88(gUnknown_02039248.unk1); + sub_810BF38(FALSE); + } + } + else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + if (gUnknown_02039248.unk0 != gUnknown_02039248.unk3) + { + sub_810BD64(5, 20); + gUnknown_02039248.unk0++; + sub_810BF38(FALSE); + } + else if (gUnknown_02039248.unk1 + gUnknown_02039248.unk0 != gUnknown_02039248.unk2) + { + gUnknown_02039248.unk1++; + sub_810BB88(gUnknown_02039248.unk1); + sub_810BF38(FALSE); + } + } + else if (gMain.newKeys & SELECT_BUTTON) + { + if (gUnknown_02039248.unk1 + gUnknown_02039248.unk0 != gUnknown_02039248.unk2) + { + PlaySE(SE_SELECT); + sub_810BDAC(TRUE); + gTasks[taskId].data[0] = gUnknown_02039248.unk1 + gUnknown_02039248.unk0; + gTasks[taskId].func = sub_810C0C8; + } + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if (gUnknown_02039248.unk1 + gUnknown_02039248.unk0 == gUnknown_02039248.unk2) + { + gScriptResult = 0xffff; + sub_810C31C(taskId); + } + else + { + sub_810C368(taskId); + } + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gScriptResult = 0xffff; + sub_810C31C(taskId); + } + } +} + +static void sub_810C0C8(u8 taskId) +{ + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + if (gUnknown_02039248.unk0 != 0) + { + sub_810BD64(5, 20); + gUnknown_02039248.unk0--; + sub_810BF38(TRUE); + sub_810C1C8(taskId, 1); + } + else if (gUnknown_02039248.unk1 != 0) + { + sub_810C1C8(taskId, 0); + gUnknown_02039248.unk1--; + sub_810BB88(gUnknown_02039248.unk1); + sub_810BF38(TRUE); + sub_810C1C8(taskId, 1); + } + } + else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + if (gUnknown_02039248.unk0 != gUnknown_02039248.unk3) + { + sub_810BD64(5, 20); + gUnknown_02039248.unk0++; + sub_810BF38(TRUE); + sub_810C1C8(taskId, 1); + } + else if (gUnknown_02039248.unk1 + gUnknown_02039248.unk0 != gUnknown_02039248.unk2) + { + sub_810C1C8(taskId, 0); + gUnknown_02039248.unk1++; + sub_810BB88(gUnknown_02039248.unk1); + sub_810BF38(TRUE); + sub_810C1C8(taskId, 1); + } + } + else if (gMain.newKeys & A_BUTTON || gMain.newKeys & SELECT_BUTTON) + { + PlaySE(SE_SELECT); + sub_810C1C8(taskId, 0); + sub_810C23C(taskId); + gTasks[taskId].func = sub_810BF7C; + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + sub_810C1C8(taskId, 0); + sub_810BDAC(0); + gTasks[taskId].func = sub_810BF7C; + } +} + +static void sub_810C1C8(u8 taskId, u8 flag) +{ + u8 i; + u32 x; + s16 y; + u16 v0 = 0x1005; + if (!flag) + { + v0 = 0x0005; + } + y = gTasks[taskId].data[0] - gUnknown_02039248.unk1; + if ((u16)y <= 8 && y != gUnknown_02039248.unk0) + { + for (i=0; i<14; i++) + { + gBGTilemapBuffers[2][(2 * y + 1) * 32 + (x = i + 15)] = v0; + gBGTilemapBuffers[2][(2 * y + 2) * 32 + x] = v0; + } + } +} + +static void sub_810C23C(u8 taskId) +{ + struct Pokeblock buf; + u8 selidx = gUnknown_02039248.unk1 + gUnknown_02039248.unk0; + if (selidx == gUnknown_02039248.unk2) + { + sub_810BDAC(FALSE); + } + else + { + buf = gSaveBlock1.pokeblocks[selidx]; + gSaveBlock1.pokeblocks[selidx] = gSaveBlock1.pokeblocks[gTasks[taskId].data[0]]; + gSaveBlock1.pokeblocks[gTasks[taskId].data[0]] = buf; + sub_810BB88(gUnknown_02039248.unk1); + sub_810BDAC(FALSE); + } +} + +static void sub_810C2B0(void) +{ + DestroyVerticalScrollIndicator(0); + DestroyVerticalScrollIndicator(1); + BuyMenuFreeMemory(); +} + +static void sub_810C2C8(u8 taskId) +{ + if (!gPaletteFade.active) + { + if (gUnknown_02039244 == 3) + { + gFieldCallback = sub_8080990; + } + sub_810C2B0(); + SetMainCallback2(gUnknown_083F7EA8[gUnknown_02039244]); + DestroyTask(taskId); + } +} + +static void sub_810C31C(u8 taskId) +{ + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + if (gUnknown_02039244 > 1) + { + gScriptItemId = ITEM_NONE; + } + gTasks[taskId].func = sub_810C2C8; +} + +static void sub_810C368(u8 taskId) +{ + int v0 = 0; + if (gUnknown_02039244 > 1) + v0 = 2; + sub_80F98A4(0); + sub_80F98A4(1); + BasicInitMenuWindow(&gWindowConfig_81E6E50); + MenuDrawTextWindow(7, v0 + 4, 13, 11); + PrintMenuItemsReordered(8, v0 + 5, gUnknown_0203924C, gUnknown_083F7EF4, gUnknown_03000758); + InitMenu(0, 8, v0 + 5, gUnknown_0203924C, 0, 5); + gScriptItemId = gUnknown_02039248.unk0 + gUnknown_02039248.unk1; + gTasks[taskId].func = sub_810C40C; +} + +static void sub_810C40C(u8 taskId) +{ + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + if (GetMenuCursorPos()) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + } + } + else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + if (GetMenuCursorPos() != gUnknown_0203924C - 1) + { + PlaySE(SE_SELECT); + MoveMenuCursor(+1); + } + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + gUnknown_083F7EF4[gUnknown_03000758[GetMenuCursorPos()]].func(taskId); + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + sub_810C748(taskId); + } +} + +static void sub_810C4C4(u8 taskId) +{ + if (!gPaletteFade.active) + { + sub_810C2B0(); + sub_8136130(&gSaveBlock1.pokeblocks[gScriptItemId], sub_810B96C); + DestroyTask(taskId); + } +} + +static void sub_810C508(u8 taskId) +{ + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + gTasks[taskId].func = sub_810C4C4; +} + +static void sub_810C540(u8 taskId) +{ + BasicInitMenuWindow(&gWindowConfig_81E6E50); + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(7, 4, 13, 11); + StringCopy(gStringVar1, gPokeblockNames[gSaveBlock1.pokeblocks[gUnknown_02039248.unk0 + gUnknown_02039248.unk1].color]); + StringExpandPlaceholders(gStringVar4, gContestStatsText_ThrowAwayPrompt); + DisplayItemMessageOnField(taskId, gStringVar4, sub_810C5EC, 0); +} + +static void sub_810C5C0(u8 taskId) +{ + sub_80F979C(1, 1); + gTasks[taskId].func = sub_810C540; +} + +static void sub_810C5EC(u8 taskId) +{ + DisplayYesNoMenu(7, 6, 1); + DoYesNoFuncWithChoice(taskId, &gUnknown_083F7F24); +} + +static void sub_810C610(u8 taskId) +{ + MenuZeroFillWindowRect(7, 6, 13, 11); + PokeblockClearIfExists((gUnknown_02039248.unk0 + gUnknown_02039248.unk1)); + StringExpandPlaceholders(gStringVar4, gContestStatsText_WasThrownAway); + DisplayItemMessageOnField(taskId, gStringVar4, sub_810C704, 0); + sub_810BC98(); + sub_810BD08(); +} + +static void sub_810C668(u8 taskId) +{ + StartVerticalScrollIndicators(0); + StartVerticalScrollIndicators(1); + if (gUnknown_02039248.unk2 > gUnknown_02039248.unk3 && gUnknown_02039248.unk1 + gUnknown_02039248.unk3 != gUnknown_02039248.unk2) + { + sub_80F979C(1, 0); + } + BasicInitMenuWindow(&gWindowConfig_81E6E50); + MenuZeroFillWindowRect(7, 6, 13, 11); + MenuZeroFillWindowRect(0, 14, 29, 19); + gTasks[taskId].func = sub_810BF7C; +} + +static void sub_810C6DC(u8 taskId) +{ + if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) + { + sub_810C668(taskId); + } +} + +static void sub_810C704(u8 taskId) +{ + BasicInitMenuWindow(&gWindowConfig_81E6E34); + sub_810BC84(gUnknown_02039248.unk1); + sub_80F979C(1, 1); + gTasks[taskId].func = sub_810C6DC; +} + +static void sub_810C748(u8 taskId) +{ + StartVerticalScrollIndicators(0); + StartVerticalScrollIndicators(1); + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(7, 4, 13, 11); + gTasks[taskId].func = sub_810BF7C; +} + +static void sub_810C788(u8 taskId) +{ + s16 v0 = PokeblockGetGain(GetNature(&gEnemyParty[0]), &gSaveBlock1.pokeblocks[gScriptItemId]); + StringCopy(gBattleTextBuff1, gPokeblockNames[gSaveBlock1.pokeblocks[gScriptItemId].color]); + PokeblockClearIfExists(gScriptItemId); + gScriptItemId = gSaveBlock1.pokeblocks[gScriptItemId].color << 8; + if (v0 == 0) + { + gScriptItemId += 1; + } + if (v0 > 0) + { + gScriptItemId += 2; + } + if (v0 < 0) + { + gScriptItemId += 3; + } + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + gTasks[taskId].func = sub_810C2C8; +} + +static void sub_810C854(u8 taskId) +{ + SafariZoneActivatePokeblockFeeder(gScriptItemId); + StringCopy(gStringVar1, gPokeblockNames[gSaveBlock1.pokeblocks[gScriptItemId].color]); + gScriptResult = gScriptItemId; + PokeblockClearIfExists(gScriptItemId); + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + gTasks[taskId].func = sub_810C2C8; +} + +static void sub_810C8D4(struct Sprite *sprite) +{ + if (sprite->data0 > 1) + { + sprite->data0 = 0; + } + switch (sprite->data0) + { + case 0: + sprite->oam.affineMode = 1; + sprite->affineAnims = gSpriteAffineAnimTable_83F7F70; + InitSpriteAffineAnim(sprite); + sprite->data0 = 1; + sprite->data1 = 0; + break; + case 1: + if (++sprite->data1 > 11) + { + sprite->oam.affineMode = 0; + sprite->data0 = 0; + sprite->data1 = 0; + FreeOamMatrix(sprite->oam.matrixNum); + sprite->callback = SpriteCallbackDummy; + } + break; + } +} + +static void ClearPokeblock(u8 pokeblockIdx) +{ + gSaveBlock1.pokeblocks[pokeblockIdx].color = 0; + gSaveBlock1.pokeblocks[pokeblockIdx].spicy = 0; + gSaveBlock1.pokeblocks[pokeblockIdx].dry = 0; + gSaveBlock1.pokeblocks[pokeblockIdx].sweet = 0; + gSaveBlock1.pokeblocks[pokeblockIdx].bitter = 0; + gSaveBlock1.pokeblocks[pokeblockIdx].sour = 0; + gSaveBlock1.pokeblocks[pokeblockIdx].feel = 0; +} + +void ClearPokeblocks(void) +{ + u8 pokeblockIdx; + for (pokeblockIdx=0; pokeblockIdx<ARRAY_COUNT(gSaveBlock1.pokeblocks); pokeblockIdx++) + { + ClearPokeblock(pokeblockIdx); + } +} + +u8 sub_810C9B0(struct Pokeblock *pokeblock) +{ + u8 contestStat; + u8 maxRating; + u8 rating = GetPokeblockData(pokeblock, 1); + for (contestStat=1; contestStat<5; contestStat++) + { + maxRating = GetPokeblockData(pokeblock, contestStat + 1); + if (rating < maxRating) + { + rating = maxRating; + } + } + return rating; +} + +u8 sub_810C9E8(struct Pokeblock *pokeblock) +{ + u8 feel = GetPokeblockData(pokeblock, 6); + if (feel > 99) + feel = 99; + return feel; +} + +s8 sub_810CA00(void) +{ + u8 i; + for (i=0; i<ARRAY_COUNT(gSaveBlock1.pokeblocks); i++) + { + if (gSaveBlock1.pokeblocks[i].color == 0) + { + return i; + } + } + return -1; +} + +bool8 sub_810CA34(struct Pokeblock *pokeblock) +{ + s8 idx = sub_810CA00(); + if (idx == -1) + { + return FALSE; + } + gSaveBlock1.pokeblocks[idx] = *pokeblock; + return TRUE; +} + +bool8 PokeblockClearIfExists(u8 pokeblockIdx) +{ + if (gSaveBlock1.pokeblocks[pokeblockIdx].color == 0) + { + return FALSE; + } + ClearPokeblock(pokeblockIdx); + return TRUE; +} + +s16 GetPokeblockData(const struct Pokeblock *pokeblock, u8 field) +{ + if (field == PBLOCK_COLOR) + return pokeblock->color; + if (field == PBLOCK_SPICY) + return pokeblock->spicy; + if (field == PBLOCK_DRY) + return pokeblock->dry; + if (field == PBLOCK_SWEET) + return pokeblock->sweet; + if (field == PBLOCK_BITTER) + return pokeblock->bitter; + if (field == PBLOCK_SOUR) + return pokeblock->sour; + if (field == PBLOCK_FEEL) + return pokeblock->feel; + return 0; +} + +s16 PokeblockGetGain(u8 nature, const struct Pokeblock *pokeblock) +{ + u8 flavor; + s16 curGain; + s16 totalGain = 0; + for (flavor=0; flavor<5; flavor++) + { + curGain = GetPokeblockData(pokeblock, flavor + 1); + if (curGain > 0) + { + totalGain += curGain * gPokeblockFlavorCompatibilityTable[5 * nature + flavor]; + } + } + return totalGain; +} + +void PokeblockCopyName(struct Pokeblock *pokeblock, u8 *dest) +{ + u8 color = GetPokeblockData(pokeblock, PBLOCK_COLOR); + StringCopy(dest, gPokeblockNames[color]); +} + +bool8 sub_810CB68(u8 nature, u8 *dest) +{ + u8 flavor; + for (flavor=0; flavor<5; flavor++) + { + if (PokeblockGetGain(nature, &gUnknown_083F7F9C[flavor]) > 0) + { + StringCopy(dest, gPokeblockNames[flavor + 1]); + return TRUE; + } + } + return FALSE; +} diff --git a/src/field/pokenav.c b/src/field/pokenav.c new file mode 100644 index 000000000..21d7bb4e3 --- /dev/null +++ b/src/field/pokenav.c @@ -0,0 +1,42 @@ +#include "global.h" +#include "main.h" +#include "pokenav.h" +#include "battle.h" +#include "data2.h" +#include "de_rom_8040FE0.h" +#include "string_util.h" + +void sub_80F700C(u8 *arg0, u16 arg1) { + struct Trainer *trainer; + u8 *ptr; + +#if ENGLISH + trainer = (struct Trainer *) &gTrainers[gUnknown_083DFEC4->unkCEE8[arg1].unk0]; +#elif GERMAN + const u16 trainerIndex = gUnknown_083DFEC4->unkCEE8[arg1].unk0; + trainer = (struct Trainer *) &gTrainers[trainerIndex]; +#endif + + ptr = arg0; + if (arg1 < gUnknown_083DFEC4->unkD158) + { +#if ENGLISH + ptr = StringCopy(ptr, gTrainerClassNames[trainer->trainerClass]); +#elif GERMAN + ptr = StringCopy(ptr, de_sub_8041024(0, trainerIndex)); +#endif + + ptr[0] = 0xFC; + ptr[1] = 0x13; + ptr[2] = 0x4B; + ptr += 3; + ptr = StringCopy(ptr, trainer->trainerName); + } + + ptr[0] = 0xFC; + ptr[1] = 0x13; + ptr[2] = 0x80; + ptr[3] = 0xFF; +} + +IWRAM_DATA MainCallback gUnknown_03000744; diff --git a/src/field/region_map.c b/src/field/region_map.c new file mode 100644 index 000000000..bfd2729c2 --- /dev/null +++ b/src/field/region_map.c @@ -0,0 +1,1847 @@ +#include "global.h" +#include "event_data.h" +#include "field_effect.h" +#include "field_specials.h" +#include "m4a.h" +#include "main.h" +#include "map_constants.h" +#include "menu.h" +#include "palette.h" +#include "pokemon_menu.h" +#include "region_map.h" +#include "overworld.h" +#include "secret_base.h" +#include "songs.h" +#include "sprite.h" +#include "strings.h" +#include "string_util.h" +#include "text.h" +#include "trig.h" + +// Map Section IDs +#define MAPSEC_LITTLEROOT_TOWN 0 +#define MAPSEC_OLDALE_TOWN 1 +#define MAPSEC_DEWFORD_TOWN 2 +#define MAPSEC_LAVARIDGE_TOWN 3 +#define MAPSEC_FALLARBOR_TOWN 4 +#define MAPSEC_VERDANTURF_TOWN 5 +#define MAPSEC_PACIFIDLOG_TOWN 6 +#define MAPSEC_PETALBURG_CITY 7 +#define MAPSEC_SLATEPORT_CITY 8 +#define MAPSEC_MAUVILLE_CITY 9 +#define MAPSEC_RUSTBORO_CITY 10 +#define MAPSEC_FORTREE_CITY 11 +#define MAPSEC_LILYCOVE_CITY 12 +#define MAPSEC_MOSSDEEP_CITY 13 +#define MAPSEC_SOOTOPOLIS_CITY 14 +#define MAPSEC_EVER_GRANDE_CITY 15 +#define MAPSEC_ROUTE_101 0x10 +#define MAPSEC_ROUTE_102 0x11 +#define MAPSEC_ROUTE_103 0x12 +#define MAPSEC_ROUTE_104 0x13 +#define MAPSEC_ROUTE_105 0x14 +#define MAPSEC_ROUTE_106 0x15 +#define MAPSEC_ROUTE_107 0x16 +#define MAPSEC_ROUTE_108 0x17 +#define MAPSEC_ROUTE_109 0x18 +#define MAPSEC_ROUTE_110 0x19 +#define MAPSEC_ROUTE_111 0x1A +#define MAPSEC_ROUTE_112 0x1B +#define MAPSEC_ROUTE_113 0x1C +#define MAPSEC_ROUTE_114 0x1D +#define MAPSEC_ROUTE_115 0x1E +#define MAPSEC_ROUTE_116 0x1F +#define MAPSEC_ROUTE_117 0x20 +#define MAPSEC_ROUTE_118 0x21 +#define MAPSEC_ROUTE_119 0x22 +#define MAPSEC_ROUTE_120 0x23 +#define MAPSEC_ROUTE_121 0x24 +#define MAPSEC_ROUTE_122 0x25 +#define MAPSEC_ROUTE_123 0x26 +#define MAPSEC_ROUTE_124 0x27 +#define MAPSEC_ROUTE_125 0x28 +#define MAPSEC_ROUTE_126 0x29 +#define MAPSEC_ROUTE_127 0x2A +#define MAPSEC_ROUTE_128 0x2B +#define MAPSEC_ROUTE_129 0x2C +#define MAPSEC_ROUTE_130 0x2D +#define MAPSEC_ROUTE_131 0x2E +#define MAPSEC_ROUTE_132 0x2F +#define MAPSEC_ROUTE_133 0x30 +#define MAPSEC_ROUTE_134 0x31 +#define MAPSEC_UNDERWATER1 0x32 +#define MAPSEC_UNDERWATER2 0x33 +#define MAPSEC_UNDERWATER3 0x34 +#define MAPSEC_UNDERWATER4 0x35 +#define MAPSEC_UNDERWATER5 0x36 +#define MAPSEC_GRANITE_CAVE 0x37 +#define MAPSEC_MT_CHIMNEY 0x38 +#define MAPSEC_SAFARI_ZONE 0x39 +#define MAPSEC_BATTLE_TOWER 0x3A +#define MAPSEC_PETALBURG_WOODS 0x3B +#define MAPSEC_RUSTURF_TUNNEL 0x3C +#define MAPSEC_ABANDONED_SHIP 0x3D +#define MAPSEC_NEW_MAUVILLE 0x3E +#define MAPSEC_METEOR_FALLS_1 0x3F +#define MAPSEC_METEOR_FALLS_2 0x40 +#define MAPSEC_MT_PYRE 0x41 +#define MAPSEC_EVIL_TEAM_HIDEOUT 0x42 +#define MAPSEC_SHOAL_CAVE 0x43 +#define MAPSEC_SEAFLOOR_CAVERN 0x44 +#define MAPSEC_UNDERWATER6 0x45 +#define MAPSEC_VICTORY_ROAD 0x46 +#define MAPSEC_MIRAGE_ISLAND 0x47 +#define MAPSEC_CAVE_OF_ORIGIN 0x48 +#define MAPSEC_SOUTHERN_ISLAND 0x49 +#define MAPSEC_FIERY_PATH_1 0x4A +#define MAPSEC_FIERY_PATH_2 0x4B +#define MAPSEC_JAGGED_PASS_1 0x4C +#define MAPSEC_JAGGED_PASS_2 0x4D +#define MAPSEC_SEALED_CHAMBER 0x4E +#define MAPSEC_UNDERWATER7 0x4F +#define MAPSEC_SCORCHED_SLAB 0x50 +#define MAPSEC_ISLAND_CAVE 0x51 +#define MAPSEC_DESERT_RUINS 0x52 +#define MAPSEC_ANCIENT_TOMB 0x53 +#define MAPSEC_INSIDE_OF_TRUCK 0x54 +#define MAPSEC_SKY_PILLAR 0x55 +#define MAPSEC_SECRET_BASE 0x56 +#define MAPSEC_UNK_0x57 0x57 +#define MAPSEC_NONE 0x58 + +#define MAP_WIDTH 28 +#define MAP_HEIGHT 15 +#define MAPCURSOR_X_MIN 1 +#define MAPCURSOR_Y_MIN 2 +#define MAPCURSOR_X_MAX (MAPCURSOR_X_MIN + MAP_WIDTH - 1) +#define MAPCURSOR_Y_MAX (MAPCURSOR_Y_MIN + MAP_HEIGHT - 1) + +// Input events +enum +{ + INPUT_EVENT_NONE, + INPUT_EVENT_DPAD, + INPUT_EVENT_2, + INPUT_EVENT_3, + INPUT_EVENT_A_BUTTON, + INPUT_EVENT_B_BUTTON, +}; + +static EWRAM_DATA struct RegionMap *gRegionMap = NULL; + +static const u16 sRegionMapCursor_Pal[] = INCBIN_U16("graphics/pokenav/cursor.gbapal"); +static const u8 sRegionMapCursorSmall_ImageLZ[] = INCBIN_U8("graphics/pokenav/cursor_small.4bpp.lz"); +static const u8 sRegionMapCursorLarge_ImageLZ[] = INCBIN_U8("graphics/pokenav/cursor_large.4bpp.lz"); +static const u16 sRegionMapBrendanIcon_Pal[] = INCBIN_U16("graphics/pokenav/brendan_icon.gbapal"); +static const u8 sRegionMapBrendanIcon_Image[] = INCBIN_U8("graphics/pokenav/brendan_icon.4bpp"); +static const u16 sRegionMapMayIcon_Pal[] = INCBIN_U16("graphics/pokenav/may_icon.gbapal"); +static const u8 sRegionMapMayIcon_Image[] = INCBIN_U8("graphics/pokenav/may_icon.4bpp"); +static const u16 sRegionMapBkgnd_Pal[] = INCBIN_U16("graphics/pokenav/region_map.gbapal"); +static const u8 sRegionMapBkgnd_ImageLZ[] = INCBIN_U8("graphics/pokenav/region_map.8bpp.lz"); +static const u8 sRegionMapBkgnd_TilemapLZ[] = INCBIN_U8("graphics/pokenav/region_map_map.bin.lz"); + +#include "../data/region_map_layout.h" + +#if ENGLISH +#include "../data/region_map_names_en.h" +#elif GERMAN +#include "../data/region_map_names_de.h" +#endif + +struct RegionMapLocation +{ + u8 x, y; + u8 width, height; + const u8 *regionMapSectionId; +}; + +const struct RegionMapLocation gRegionMapLocations[] = +{ + { 4, 11, 1, 1, gMapName_LittlerootTown}, + { 4, 9, 1, 1, gMapName_OldaleTown}, + { 2, 14, 1, 1, gMapName_DewfordTown}, + { 5, 3, 1, 1, gMapName_LavaridgeTown}, + { 3, 0, 1, 1, gMapName_FallarborTown}, + { 4, 6, 1, 1, gMapName_VerdanturfTown}, + {17, 10, 1, 1, gMapName_PacifidlogTown}, + { 1, 9, 1, 1, gMapName_PetalburgCity}, + { 8, 10, 1, 2, gMapName_SlateportCity}, + { 8, 6, 2, 1, gMapName_MauvilleCity}, + { 0, 5, 1, 2, gMapName_RustboroCity}, + {12, 0, 1, 1, gMapName_FortreeCity}, + {18, 3, 2, 1, gMapName_LilycoveCity}, + {24, 5, 2, 1, gMapName_MossdeepCity}, + {21, 7, 1, 1, gMapName_SootopolisCity}, + {27, 8, 1, 2, gMapName_EverGrandeCity}, + { 4, 10, 1, 1, gMapName_Route101}, + { 2, 9, 2, 1, gMapName_Route102}, + { 4, 8, 4, 1, gMapName_Route103}, + { 0, 7, 1, 3, gMapName_Route104}, + { 0, 10, 1, 3, gMapName_Route105}, + { 0, 13, 2, 1, gMapName_Route106}, + { 3, 14, 3, 1, gMapName_Route107}, + { 6, 14, 2, 1, gMapName_Route108}, + { 8, 12, 1, 3, gMapName_Route109}, + { 8, 7, 1, 3, gMapName_Route110}, + { 8, 0, 1, 6, gMapName_Route111}, + { 6, 3, 2, 1, gMapName_Route112}, + { 4, 0, 4, 1, gMapName_Route113}, + { 1, 0, 2, 3, gMapName_Route114}, + { 0, 2, 1, 3, gMapName_Route115}, + { 1, 5, 4, 1, gMapName_Route116}, + { 5, 6, 3, 1, gMapName_Route117}, + {10, 6, 2, 1, gMapName_Route118}, + {11, 0, 1, 6, gMapName_Route119}, + {13, 0, 1, 4, gMapName_Route120}, + {14, 3, 4, 1, gMapName_Route121}, + {16, 4, 1, 2, gMapName_Route122}, + {12, 6, 5, 1, gMapName_Route123}, + {20, 3, 4, 3, gMapName_Route124}, + {24, 3, 2, 2, gMapName_Route125}, + {20, 6, 3, 3, gMapName_Route126}, + {23, 6, 3, 3, gMapName_Route127}, + {23, 9, 4, 1, gMapName_Route128}, + {24, 10, 2, 1, gMapName_Route129}, + {21, 10, 3, 1, gMapName_Route130}, + {18, 10, 3, 1, gMapName_Route131}, + {15, 10, 2, 1, gMapName_Route132}, + {12, 10, 3, 1, gMapName_Route133}, + { 9, 10, 3, 1, gMapName_Route134}, + {20, 3, 4, 3, gMapName_Underwater}, + {20, 6, 3, 3, gMapName_Underwater}, + {23, 6, 3, 3, gMapName_Underwater}, + {23, 9, 4, 1, gMapName_Underwater}, + {21, 7, 1, 1, gMapName_Underwater}, + { 1, 13, 1, 1, gMapName_GraniteCave}, + { 6, 2, 1, 1, gMapName_MtChimney}, + {16, 2, 1, 1, gMapName_SafariZone}, + {22, 12, 1, 1, gMapName_BattleTower}, + { 0, 8, 1, 1, gMapName_PetalburgWoods}, + { 2, 5, 1, 1, gMapName_RusturfTunnel}, + { 6, 14, 1, 1, gMapName_AbandonedShip}, + { 8, 7, 1, 1, gMapName_NewMauville}, + { 0, 3, 1, 1, gMapName_MeteorFalls}, + { 1, 2, 1, 1, gMapName_MeteorFalls}, + {16, 4, 1, 1, gMapName_MtPyre}, + {19, 3, 1, 1, gMapName_EvilTeamHideout}, + {24, 4, 1, 1, gMapName_ShoalCave}, + {24, 9, 1, 1, gMapName_SeafloorCavern}, + {24, 9, 1, 1, gMapName_Underwater}, + {27, 9, 1, 1, gMapName_VictoryRoad}, + {17, 10, 1, 1, gMapName_MirageIsland}, + {21, 7, 1, 1, gMapName_CaveOfOrigin}, + {12, 14, 1, 1, gMapName_SouthernIsland}, + { 6, 3, 1, 1, gMapName_FieryPath}, + { 7, 3, 1, 1, gMapName_FieryPath}, + { 6, 3, 1, 1, gMapName_JaggedPass}, + { 7, 2, 1, 1, gMapName_JaggedPass}, + {11, 10, 1, 1, gMapName_SealedChamber}, + {11, 10, 1, 1, gMapName_Underwater}, + {13, 0, 1, 1, gMapName_ScorchedSlab}, + {0, 10, 1, 1, gMapName_IslandCave}, + { 8, 3, 1, 1, gMapName_DesertRuins}, + {13, 2, 1, 1, gMapName_AncientTomb}, + { 0, 0, 1, 1, gMapName_InsideOfTruck}, + {19, 10, 1, 1, gMapName_SkyPillar}, + { 0, 0, 1, 1, gMapName_SecretBase}, + { 0, 0, 1, 1, gMapName_None}, +}; + +static const u16 gUnknown_083E7684[][2] = +{ + {MAPSEC_UNDERWATER1, MAPSEC_ROUTE_124}, + {MAPSEC_UNDERWATER2, MAPSEC_ROUTE_126}, + {MAPSEC_UNDERWATER3, MAPSEC_ROUTE_127}, + {MAPSEC_UNDERWATER4, MAPSEC_ROUTE_128}, + {MAPSEC_UNDERWATER5, MAPSEC_SOOTOPOLIS_CITY}, + {MAPSEC_UNDERWATER6, MAPSEC_ROUTE_128}, + {MAPSEC_EVIL_TEAM_HIDEOUT, MAPSEC_LILYCOVE_CITY}, + {MAPSEC_UNDERWATER7, MAPSEC_ROUTE_134}, + {MAPSEC_PETALBURG_WOODS, MAPSEC_ROUTE_104}, + {MAPSEC_JAGGED_PASS_1, MAPSEC_ROUTE_112}, + {MAPSEC_MT_PYRE, MAPSEC_ROUTE_122}, + {MAPSEC_SKY_PILLAR, MAPSEC_ROUTE_131}, + {MAPSEC_NONE, MAPSEC_NONE}, +}; + +static u8 sub_80FAB78(void); +static u8 _swiopen(void); +static u8 sub_80FAD04(void); +static u8 sub_80FADE4(void); +static void CalcZoomScrollParams(s16, s16, s16, s16, u16, u16, u8); +static void sub_80FB238(s16, s16); +void UpdateRegionMapVideoRegs(void); +static u16 GetRegionMapSectionAt(u16, u16); +static void InitializeCursorPosition(void); +static void sub_80FB600(void); +static u16 sub_80FB758(u16); +static u16 sub_80FB9C0(u16); +static void sub_80FBA18(void); +static bool8 sub_80FBAA0(u16); +void CreateRegionMapCursor(u16, u16); +static void sub_80FBCA0(void); +static void sub_80FBDF8(void); +static void sub_80FBE24(void); +static void SpriteCB_PlayerIconZoomedOut(struct Sprite *); +static void UpdateIconBlink(struct Sprite *); +static void SpriteCB_PlayerIconZoomedIn(struct Sprite *); +const u8 *GetMapSectionName(u8 *, u16, u16); +static void VBlankCB_FlyRegionMap(void); +static void CB2_FlyRegionMap(void); +static void sub_80FC244(void (*func)(void)); +static void PrintFlyTargetName(void); +static void CreateFlyTargetGraphics(void); +static void CreateCityTownFlyTargetIcons(void); +static void CreateSpecialAreaFlyTargetIcons(void); +static void SpriteCB_FlyTargetIcons(struct Sprite *); +static void sub_80FC5B4(void); +static void sub_80FC600(void); +static void sub_80FC69C(void); + +void InitRegionMap(struct RegionMap *regionMap, bool8 zoomed) +{ + sub_80FA904(regionMap, zoomed); + while (sub_80FA940()) + ; +} + +void sub_80FA904(struct RegionMap *regionMap, bool8 zoomed) +{ + gRegionMap = regionMap; + gRegionMap->initStep = 0; + gRegionMap->zoomed = zoomed; + gRegionMap->inputCallback = (zoomed == 0) ? sub_80FAB78 : sub_80FAD04; +} + +bool8 sub_80FA940(void) +{ + switch (gRegionMap->initStep) + { + case 0: + LZ77UnCompVram(sRegionMapBkgnd_ImageLZ, (void *)(VRAM + 0x8000)); + break; + case 1: + LZ77UnCompVram(sRegionMapBkgnd_TilemapLZ, (void *)(VRAM + 0xE000)); + break; + case 2: + LoadPalette(sRegionMapBkgnd_Pal, 0x70, 0x60); // Why isn't this the right size? + break; + case 3: + LZ77UnCompWram(sRegionMapCursorSmall_ImageLZ, gRegionMap->cursorSmallImage); + break; + case 4: + LZ77UnCompWram(sRegionMapCursorLarge_ImageLZ, gRegionMap->cursorLargeImage); + break; + case 5: + InitializeCursorPosition(); + gRegionMap->unk74 = gRegionMap->cursorPosX; + gRegionMap->unk76 = gRegionMap->cursorPosY; + gRegionMap->unk16 = sub_80FB758(gRegionMap->mapSecId); + gRegionMap->mapSecId = sub_80FB9C0(gRegionMap->mapSecId); + GetMapSectionName(gRegionMap->mapSecName, gRegionMap->mapSecId, 16); + break; + case 6: + if (gRegionMap->zoomed == FALSE) + { + CalcZoomScrollParams(0, 0, 0, 0, 0x100, 0x100, 0); + } + else + { + gRegionMap->scrollX = gRegionMap->cursorPosX * 8 - 52; + gRegionMap->scrollY = gRegionMap->cursorPosY * 8 - 68; + gRegionMap->unk64 = gRegionMap->cursorPosX; + gRegionMap->unk66 = gRegionMap->cursorPosY; + CalcZoomScrollParams(gRegionMap->scrollX, gRegionMap->scrollY, 0x38, 0x48, 0x80, 0x80, 0); + } + break; + case 7: + sub_80FBA18(); + UpdateRegionMapVideoRegs(); + gRegionMap->cursorSprite = NULL; + gRegionMap->playerIconSprite = NULL; + gRegionMap->unk7A = 0; + gRegionMap->blinkPlayerIcon = FALSE; + REG_BG2CNT = 0xBC8A; + gRegionMap->initStep++; + default: + return FALSE; + } + gRegionMap->initStep++; + return TRUE; +} + +void FreeRegionMapIconResources(void) +{ + if (gRegionMap->cursorSprite != NULL) + { + DestroySprite(gRegionMap->cursorSprite); + FreeSpriteTilesByTag(gRegionMap->cursorTileTag); + FreeSpritePaletteByTag(gRegionMap->cursorPaletteTag); + } + if (gRegionMap->playerIconSprite != NULL) + { + DestroySprite(gRegionMap->playerIconSprite); + FreeSpriteTilesByTag(gRegionMap->playerIconTileTag); + FreeSpritePaletteByTag(gRegionMap->playerIconPaletteTag); + } +} + +u8 sub_80FAB60(void) +{ + return gRegionMap->inputCallback(); +} + +static u8 sub_80FAB78(void) +{ + u8 event = INPUT_EVENT_NONE; + + gRegionMap->cursorDeltaX = 0; + gRegionMap->cursorDeltaY = 0; + if ((gMain.heldKeys & DPAD_UP) && gRegionMap->cursorPosY > MAPCURSOR_Y_MIN) + { + gRegionMap->cursorDeltaY = -1; + event = INPUT_EVENT_DPAD; + } + if ((gMain.heldKeys & DPAD_DOWN) && gRegionMap->cursorPosY < MAPCURSOR_Y_MAX) + { + gRegionMap->cursorDeltaY = 1; + event = INPUT_EVENT_DPAD; + } + if ((gMain.heldKeys & DPAD_LEFT) && gRegionMap->cursorPosX > MAPCURSOR_X_MIN) + { + gRegionMap->cursorDeltaX = -1; + event = INPUT_EVENT_DPAD; + } + if ((gMain.heldKeys & DPAD_RIGHT) && gRegionMap->cursorPosX < MAPCURSOR_X_MAX) + { + gRegionMap->cursorDeltaX = 1; + event = INPUT_EVENT_DPAD; + } + + if (gMain.newKeys & A_BUTTON) + event = INPUT_EVENT_A_BUTTON; + else if (gMain.newKeys & B_BUTTON) + event = INPUT_EVENT_B_BUTTON; + + if (event == INPUT_EVENT_DPAD) + { + gRegionMap->unk7A = 4; + gRegionMap->inputCallback = _swiopen; + } + return event; +} + +static u8 _swiopen(void) +{ + u16 mapSecId; + + if (gRegionMap->unk7A != 0) + return INPUT_EVENT_2; + + if (gRegionMap->cursorDeltaX > 0) + gRegionMap->cursorPosX++; + + if (gRegionMap->cursorDeltaX < 0) + gRegionMap->cursorPosX--; + + if (gRegionMap->cursorDeltaY > 0) + gRegionMap->cursorPosY++; + + if (gRegionMap->cursorDeltaY < 0) + gRegionMap->cursorPosY--; + + mapSecId = GetRegionMapSectionAt(gRegionMap->cursorPosX, gRegionMap->cursorPosY); + gRegionMap->unk16 = sub_80FB758(mapSecId); + if (mapSecId != gRegionMap->mapSecId) + { + gRegionMap->mapSecId = mapSecId; + GetMapSectionName(gRegionMap->mapSecName, gRegionMap->mapSecId, 16); + } + sub_80FBA18(); + gRegionMap->inputCallback = sub_80FAB78; + return INPUT_EVENT_3; +} + +static u8 sub_80FAD04(void) +{ + u8 event = INPUT_EVENT_NONE; + + gRegionMap->unk6A = 0; + gRegionMap->unk68 = 0; + if ((gMain.heldKeys & DPAD_UP) && gRegionMap->scrollY > -52) + { + gRegionMap->unk68 = -1; + event = INPUT_EVENT_DPAD; + } + if ((gMain.heldKeys & DPAD_DOWN) && gRegionMap->scrollY < 60) + { + gRegionMap->unk68 = 1; + event = INPUT_EVENT_DPAD; + } + if ((gMain.heldKeys & DPAD_LEFT) && gRegionMap->scrollX > -44) + { + gRegionMap->unk6A = -1; + event = INPUT_EVENT_DPAD; + } + if ((gMain.heldKeys & DPAD_RIGHT) && gRegionMap->scrollX < 172) + { + gRegionMap->unk6A = 1; + event = INPUT_EVENT_DPAD; + } + + if (gMain.newKeys & A_BUTTON) + event = INPUT_EVENT_A_BUTTON; + if (gMain.newKeys & B_BUTTON) + event = INPUT_EVENT_B_BUTTON; + + if (event == INPUT_EVENT_DPAD) + { + gRegionMap->inputCallback = sub_80FADE4; + gRegionMap->unk6C = 0; + } + return event; +} + +static u8 sub_80FADE4(void) +{ + gRegionMap->scrollY += gRegionMap->unk68; + gRegionMap->scrollX += gRegionMap->unk6A; + sub_80FB238(gRegionMap->scrollX, gRegionMap->scrollY); + gRegionMap->unk6C++; + if (gRegionMap->unk6C == 8) + { + u16 r3 = (gRegionMap->scrollX + 44) / 8 + 1; + u16 r1 = (gRegionMap->scrollY + 52) / 8 + 2; + + if (r3 != gRegionMap->unk64 || r1 != gRegionMap->unk66) + { + u16 mapSecId; + + gRegionMap->unk64 = r3; + gRegionMap->unk66 = r1; + mapSecId = GetRegionMapSectionAt(r3, r1); + gRegionMap->unk16 = sub_80FB758(mapSecId); + if (mapSecId != gRegionMap->mapSecId) + { + gRegionMap->mapSecId = mapSecId; + GetMapSectionName(gRegionMap->mapSecName, gRegionMap->mapSecId, 16); + } + sub_80FBA18(); + } + gRegionMap->unk6C = 0; + gRegionMap->inputCallback = sub_80FAD04; + return INPUT_EVENT_3; + } + return INPUT_EVENT_2; +} + +void sub_80FAEC4(void) +{ + if (gRegionMap->zoomed == FALSE) + { + gRegionMap->scrollY = 0; + gRegionMap->scrollX = 0; + gRegionMap->unk40 = 0; + gRegionMap->unk3C = 0; + gRegionMap->unk60 = gRegionMap->cursorPosX * 8 - 52; + gRegionMap->unk62 = gRegionMap->cursorPosY * 8 - 68; + gRegionMap->unk44 = (gRegionMap->unk60 << 8) / 16; + gRegionMap->unk48 = (gRegionMap->unk62 << 8) / 16; + gRegionMap->unk64 = gRegionMap->cursorPosX; + gRegionMap->unk66 = gRegionMap->cursorPosY; + gRegionMap->unk4C = (256 << 8); + gRegionMap->unk50 = -0x800; + } + else + { + gRegionMap->unk3C = gRegionMap->scrollX * 256; + gRegionMap->unk40 = gRegionMap->scrollY * 256; + gRegionMap->unk60 = 0; + gRegionMap->unk62 = 0; + gRegionMap->unk44 = -(gRegionMap->unk3C / 16); + gRegionMap->unk48 = -(gRegionMap->unk40 / 16); + gRegionMap->cursorPosX = gRegionMap->unk64; + gRegionMap->cursorPosY = gRegionMap->unk66; + gRegionMap->unk4C = (128 << 8); + gRegionMap->unk50 = 0x800; + } + gRegionMap->unk6E = 0; + sub_80FBCA0(); + sub_80FBDF8(); +} + +u8 sub_80FAFC0(void) +{ + u8 r4; + + if (gRegionMap->unk6E >= 16) + return 0; + gRegionMap->unk6E++; + if (gRegionMap->unk6E == 16) + { + gRegionMap->unk44 = 0; + gRegionMap->unk48 = 0; + gRegionMap->scrollX = gRegionMap->unk60; + gRegionMap->scrollY = gRegionMap->unk62; + gRegionMap->unk4C = (gRegionMap->zoomed == FALSE) ? (128 << 8) : (256 << 8); + gRegionMap->zoomed = !gRegionMap->zoomed; + gRegionMap->inputCallback = (gRegionMap->zoomed == FALSE) ? sub_80FAB78 : sub_80FAD04; + CreateRegionMapCursor(gRegionMap->cursorTileTag, gRegionMap->cursorPaletteTag); + sub_80FBE24(); + r4 = 0; + } + else + { + gRegionMap->unk3C += gRegionMap->unk44; + gRegionMap->unk40 += gRegionMap->unk48; + gRegionMap->scrollX = gRegionMap->unk3C >> 8; + gRegionMap->scrollY = gRegionMap->unk40 >> 8; + gRegionMap->unk4C += gRegionMap->unk50; + if ((gRegionMap->unk44 < 0 && gRegionMap->scrollX < gRegionMap->unk60) + || (gRegionMap->unk44 > 0 && gRegionMap->scrollX > gRegionMap->unk60)) + { + gRegionMap->scrollX = gRegionMap->unk60; + gRegionMap->unk44 = 0; + } + if ((gRegionMap->unk48 < 0 && gRegionMap->scrollY < gRegionMap->unk62) + || (gRegionMap->unk48 > 0 && gRegionMap->scrollY > gRegionMap->unk62)) + { + gRegionMap->scrollY = gRegionMap->unk62; + gRegionMap->unk48 = 0; + } + if (gRegionMap->zoomed == FALSE) + { + if (gRegionMap->unk4C < (128 << 8)) + { + gRegionMap->unk4C = (128 << 8); + gRegionMap->unk50 = 0; + } + } + else + { + if (gRegionMap->unk4C > (256 << 8)) + { + gRegionMap->unk4C = (256 << 8); + gRegionMap->unk50 = 0; + } + } + r4 = 1; + } + CalcZoomScrollParams(gRegionMap->scrollX, gRegionMap->scrollY, 0x38, 0x48, gRegionMap->unk4C >> 8, gRegionMap->unk4C >> 8, 0); + return r4; +} + +static void CalcZoomScrollParams(s16 a, s16 b, s16 c, s16 d, u16 e, u16 f, u8 rotation) +{ + s32 var1; + s32 var2; + s32 var3; + s32 var4; + + gRegionMap->unk2C = e * gSineTable[rotation + 64] >> 8; + gRegionMap->unk30 = e * -gSineTable[rotation] >> 8; + gRegionMap->unk34 = f * gSineTable[rotation] >> 8; + gRegionMap->unk38 = f * gSineTable[rotation + 64] >> 8; + + var1 = (a << 8) + (c << 8); + var2 = d * gRegionMap->unk34 + gRegionMap->unk2C * c; + gRegionMap->bg2x = var1 - var2; + + var3 = (b << 8) + (d << 8); + var4 = gRegionMap->unk38 * d + gRegionMap->unk30 * c; + gRegionMap->bg2y = var3 - var4; + + gRegionMap->needUpdateVideoRegs = TRUE; +} + +static void sub_80FB238(s16 x, s16 y) +{ + gRegionMap->bg2x = (0x1C << 8) + (x << 8); + gRegionMap->bg2y = (0x24 << 8) + (y << 8); + gRegionMap->needUpdateVideoRegs = TRUE; +} + +void UpdateRegionMapVideoRegs(void) +{ + if (gRegionMap->needUpdateVideoRegs) + { + REG_BG2PA = gRegionMap->unk2C; + REG_BG2PB = gRegionMap->unk34; + REG_BG2PC = gRegionMap->unk30; + REG_BG2PD = gRegionMap->unk38; + REG_BG2X = gRegionMap->bg2x; + REG_BG2Y = gRegionMap->bg2y; + gRegionMap->needUpdateVideoRegs = FALSE; + } +} + +void sub_80FB2A4(s16 a, s16 b) +{ + CalcZoomScrollParams(a, b, 0x38, 0x48, 0x100, 0x100, 0); + UpdateRegionMapVideoRegs(); + if (gRegionMap->playerIconSprite != NULL) + { + gRegionMap->playerIconSprite->pos2.x = -a; + gRegionMap->playerIconSprite->pos2.y = -b; + } +} + +static u16 GetRegionMapSectionAt(u16 x, u16 y) +{ + if (y < MAPCURSOR_Y_MIN || y > MAPCURSOR_Y_MAX || x < MAPCURSOR_X_MIN || x > MAPCURSOR_X_MAX) + return MAPSEC_NONE; + y -= MAPCURSOR_Y_MIN; + x -= MAPCURSOR_X_MIN; + return sRegionMapLayout[x + y * 28]; +} + +static void InitializeCursorPosition(void) +{ + struct MapHeader *mapHeader; + u16 mapWidth; + u16 mapHeight; + u16 x; + u16 y; + u16 r1; + u16 r9; + + if (gSaveBlock1.location.mapGroup == 25 + && (gSaveBlock1.location.mapNum == MAP_ID_SS_TIDAL_CORRIDOR + || gSaveBlock1.location.mapNum == MAP_ID_SS_TIDAL_LOWER_DECK + || gSaveBlock1.location.mapNum == MAP_ID_SS_TIDAL_ROOMS)) + { + sub_80FB600(); + return; + } + + switch (GetMapTypeByGroupAndId(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum) - 1) + { + default: + case 0: + case 1: + case 2: + case 4: + case 5: + gRegionMap->mapSecId = gMapHeader.regionMapSectionId; + gRegionMap->playerIsInCave = FALSE; + mapWidth = gMapHeader.mapData->width; + mapHeight = gMapHeader.mapData->height; + x = gSaveBlock1.pos.x; + y = gSaveBlock1.pos.y; + if (gRegionMap->mapSecId == MAPSEC_UNDERWATER6) + gRegionMap->playerIsInCave = TRUE; + break; + case 3: + case 6: + mapHeader = Overworld_GetMapHeaderByGroupAndId(gSaveBlock1.warp4.mapGroup, gSaveBlock1.warp4.mapNum); + gRegionMap->mapSecId = mapHeader->regionMapSectionId; + gRegionMap->playerIsInCave = TRUE; + mapWidth = mapHeader->mapData->width; + mapHeight = mapHeader->mapData->height; + x = gSaveBlock1.warp4.x; + y = gSaveBlock1.warp4.y; + break; + case 8: + mapHeader = Overworld_GetMapHeaderByGroupAndId(gSaveBlock1.warp2.mapGroup, gSaveBlock1.warp2.mapNum); + gRegionMap->mapSecId = mapHeader->regionMapSectionId; + gRegionMap->playerIsInCave = TRUE; + mapWidth = mapHeader->mapData->width; + mapHeight = mapHeader->mapData->height; + x = gSaveBlock1.warp2.x; + y = gSaveBlock1.warp2.y; + break; + case 7: + { + struct WarpData *r4; + + gRegionMap->mapSecId = gMapHeader.regionMapSectionId; + if (gRegionMap->mapSecId != MAPSEC_UNK_0x57) + { + r4 = &gSaveBlock1.warp4; + mapHeader = Overworld_GetMapHeaderByGroupAndId(r4->mapGroup, r4->mapNum); + } + else + { + r4 = &gSaveBlock1.warp2; + mapHeader = Overworld_GetMapHeaderByGroupAndId(r4->mapGroup, r4->mapNum); + gRegionMap->mapSecId = mapHeader->regionMapSectionId; + } + gRegionMap->playerIsInCave = FALSE; + mapWidth = mapHeader->mapData->width; + mapHeight = mapHeader->mapData->height; + x = r4->x; + y = r4->y; + } + break; + } + + r9 = x; + + r1 = mapWidth / gRegionMapLocations[gRegionMap->mapSecId].width; + if (r1 == 0) + r1 = 1; + x /= r1; + if (x >= gRegionMapLocations[gRegionMap->mapSecId].width) + x = gRegionMapLocations[gRegionMap->mapSecId].width - 1; + + r1 = mapHeight / gRegionMapLocations[gRegionMap->mapSecId].height; + if (r1 == 0) + r1 = 1; + y /= r1; + if (y >= gRegionMapLocations[gRegionMap->mapSecId].height) + y = gRegionMapLocations[gRegionMap->mapSecId].height - 1; + + switch (gRegionMap->mapSecId) + { + case MAPSEC_ROUTE_114: + if (y != 0) + x = 0; + break; + case MAPSEC_ROUTE_126: + case MAPSEC_UNDERWATER2: + x = 0; + if (gSaveBlock1.pos.x > 32) + x = 1; + if (gSaveBlock1.pos.x > 0x33) + x++; + y = 0; + if (gSaveBlock1.pos.y > 0x25) + y = 1; + if (gSaveBlock1.pos.y > 0x38) + y++; + break; + case MAPSEC_ROUTE_121: + x = 0; + if (r9 > 14) + x = 1; + if (r9 > 0x1C) + x++; + if (r9 > 0x36) + x++; + break; + } + gRegionMap->cursorPosX = gRegionMapLocations[gRegionMap->mapSecId].x + x + MAPCURSOR_X_MIN; + gRegionMap->cursorPosY = gRegionMapLocations[gRegionMap->mapSecId].y + y + MAPCURSOR_Y_MIN; +} + +static void sub_80FB600(void) +{ + u16 y = 0; + u16 x = 0; + u8 mapGroup; + u8 mapNum; + s16 sp2; + s16 sp4; + + switch (GetSSTidalLocation(&mapGroup, &mapNum, &sp2, &sp4)) + { + case 1: + gRegionMap->mapSecId = MAPSEC_SLATEPORT_CITY; + break; + case 2: + gRegionMap->mapSecId = MAPSEC_LILYCOVE_CITY; + break; + case 3: + gRegionMap->mapSecId = MAPSEC_ROUTE_124; + break; + case 4: + gRegionMap->mapSecId = MAPSEC_ROUTE_131; + break; + default: + case 0: + { + struct MapHeader *mapHeader = Overworld_GetMapHeaderByGroupAndId(mapGroup, mapNum); + u16 r1; + + gRegionMap->mapSecId = mapHeader->regionMapSectionId; + r1 = mapHeader->mapData->width / gRegionMapLocations[gRegionMap->mapSecId].width; + if (r1 == 0) + r1 = 1; + x = sp2 / r1; + if (x >= gRegionMapLocations[gRegionMap->mapSecId].width) + x = gRegionMapLocations[gRegionMap->mapSecId].width - 1; + + r1 = mapHeader->mapData->height / gRegionMapLocations[gRegionMap->mapSecId].height; + if (r1 == 0) + r1 = 1; + y = sp4 / r1; + if (y >= gRegionMapLocations[gRegionMap->mapSecId].height) + y = gRegionMapLocations[gRegionMap->mapSecId].height - 1; + } + break; + } + gRegionMap->playerIsInCave = FALSE; + gRegionMap->cursorPosX = gRegionMapLocations[gRegionMap->mapSecId].x + x + MAPCURSOR_X_MIN; + gRegionMap->cursorPosY = gRegionMapLocations[gRegionMap->mapSecId].y + y + MAPCURSOR_Y_MIN; +} + +static u16 sub_80FB758(u16 mapSecId) +{ + switch (mapSecId) + { + case MAPSEC_NONE: + return 0; + case MAPSEC_LITTLEROOT_TOWN: + return FlagGet(FLAG_VISITED_LITTLEROOT_TOWN) ? 2 : 3; + case MAPSEC_OLDALE_TOWN: + return FlagGet(FLAG_VISITED_OLDALE_TOWN) ? 2 : 3; + case MAPSEC_DEWFORD_TOWN: + return FlagGet(FLAG_VISITED_DEWFORD_TOWN) ? 2 : 3; + case MAPSEC_LAVARIDGE_TOWN: + return FlagGet(FLAG_VISITED_LAVARIDGE_TOWN) ? 2 : 3; + case MAPSEC_FALLARBOR_TOWN: + return FlagGet(FLAG_VISITED_FALLARBOR_TOWN) ? 2 : 3; + case MAPSEC_VERDANTURF_TOWN: + return FlagGet(FLAG_VISITED_VERDANTURF_TOWN) ? 2 : 3; + case MAPSEC_PACIFIDLOG_TOWN: + return FlagGet(FLAG_VISITED_PACIFIDLOG_TOWN) ? 2 : 3; + case MAPSEC_PETALBURG_CITY: + return FlagGet(FLAG_VISITED_PETALBURG_CITY) ? 2 : 3; + case MAPSEC_SLATEPORT_CITY: + return FlagGet(FLAG_VISITED_SLATEPORT_CITY) ? 2 : 3; + case MAPSEC_MAUVILLE_CITY: + return FlagGet(FLAG_VISITED_MAUVILLE_CITY) ? 2 : 3; + case MAPSEC_RUSTBORO_CITY: + return FlagGet(FLAG_VISITED_RUSTBORO_CITY) ? 2 : 3; + case MAPSEC_FORTREE_CITY: + return FlagGet(FLAG_VISITED_FORTREE_CITY) ? 2 : 3; + case MAPSEC_LILYCOVE_CITY: + return FlagGet(FLAG_VISITED_LILYCOVE_CITY) ? 2 : 3; + case MAPSEC_MOSSDEEP_CITY: + return FlagGet(FLAG_VISITED_MOSSDEEP_CITY) ? 2 : 3; + case MAPSEC_SOOTOPOLIS_CITY: + return FlagGet(FLAG_VISITED_SOOTOPOLIS_CITY) ? 2 : 3; + case MAPSEC_EVER_GRANDE_CITY: + return FlagGet(FLAG_VISITED_EVER_GRANDE_CITY) ? 2 : 3; + + case MAPSEC_BATTLE_TOWER: + return FlagGet(FLAG_UNLOCK_BATTLE_TOWER) ? 4 : 0; + case MAPSEC_SOUTHERN_ISLAND: + return FlagGet(FLAG_UNLOCK_SOUTHERN_ISLAND) ? 1 : 0; + default: + return 1; + } +} + +u16 GetRegionMapSectionAt_(u16 x, u16 y) +{ + return GetRegionMapSectionAt(x, y); +} + +static u16 sub_80FB9C0(u16 mapSecId) +{ + u16 i; + + for (i = 0; gUnknown_083E7684[i][0] != MAPSEC_NONE; i++) + { + if (gUnknown_083E7684[i][0] == mapSecId) + return gUnknown_083E7684[i][1]; + } + return mapSecId; +} + +u16 sub_80FBA04(u16 mapSecId) +{ + return sub_80FB9C0(mapSecId); +} + +static void sub_80FBA18(void) +{ + u16 x; + u16 y; + u16 i; + + if (gRegionMap->mapSecId == MAPSEC_NONE) + { + gRegionMap->everGrandeCityArea = 0; + return; + } + + if (gRegionMap->zoomed == FALSE) + { + x = gRegionMap->cursorPosX; + y = gRegionMap->cursorPosY; + } + else + { + x = gRegionMap->unk64; + y = gRegionMap->unk66; + } + + i = 0; + while (1) + { + if (x <= 1) + { + if (sub_80FBAA0(y)) + { + y--; + x = 0x1D; + } + else + { + break; + } + } + else + { + x--; + if (GetRegionMapSectionAt(x, y) == gRegionMap->mapSecId) + i++; + } + } + + gRegionMap->everGrandeCityArea = i; +} + +static bool8 sub_80FBAA0(u16 a) +{ + u16 x; + u16 y; + + y = a - 1; + if (y == 0xFFFF) + return FALSE; + + for (x = MAPCURSOR_X_MIN; x <= MAPCURSOR_X_MAX; x++) + { + if (GetRegionMapSectionAt(x, y) == gRegionMap->mapSecId) + return TRUE; + } + return FALSE; +} + +static const struct OamData sCursorOamData = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd sCursorAnimSeq0[] = +{ + ANIMCMD_FRAME(0, 20), + ANIMCMD_FRAME(4, 20), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd sCursorAnimSeq1[] = +{ + ANIMCMD_FRAME(0, 10), + ANIMCMD_FRAME(16, 10), + ANIMCMD_FRAME(32, 10), + ANIMCMD_FRAME(16, 10), + ANIMCMD_JUMP(0), +}; + +static const union AnimCmd *const sCursorAnimTable[] = +{ + sCursorAnimSeq0, + sCursorAnimSeq1, +}; + +static void SpriteCB_Cursor(struct Sprite *sprite) +{ + if (gRegionMap->unk7A != 0) + { + sprite->pos1.x += gRegionMap->cursorDeltaX * 2; + sprite->pos1.y += gRegionMap->cursorDeltaY * 2; + gRegionMap->unk7A--; + } +} + +static void nullsub_66(struct Sprite *sprite) +{ +} + +void CreateRegionMapCursor(u16 tileTag, u16 paletteTag) +{ + u8 spriteId; + struct SpriteSheet spriteSheet; + struct SpritePalette spritePalette = + { + .data = sRegionMapCursor_Pal, + }; + struct SpriteTemplate spriteTemplate = + { + .oam = &sCursorOamData, + .anims = sCursorAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCB_Cursor, + }; + + spriteSheet.tag = tileTag; + spriteTemplate.tileTag = tileTag; + gRegionMap->cursorTileTag = tileTag; + + spritePalette.tag = paletteTag; + spriteTemplate.paletteTag = paletteTag; + gRegionMap->cursorPaletteTag = paletteTag; + + if (gRegionMap->zoomed == FALSE) + { + spriteSheet.data = gRegionMap->cursorSmallImage; + spriteSheet.size = 0x100; + spriteTemplate.callback = SpriteCB_Cursor; + } + else + { + spriteSheet.data = gRegionMap->cursorLargeImage; + spriteSheet.size = 0x600; + spriteTemplate.callback = nullsub_66; + } + LoadSpriteSheet(&spriteSheet); + LoadSpritePalette(&spritePalette); + spriteId = CreateSprite(&spriteTemplate, 0x38, 0x48, 0); + if (spriteId != 64) + { + gRegionMap->cursorSprite = &gSprites[spriteId]; + if (gRegionMap->zoomed == TRUE) + { + gRegionMap->cursorSprite->oam.size = 2; + gRegionMap->cursorSprite->pos1.x -= 8; + gRegionMap->cursorSprite->pos1.y -= 8; + StartSpriteAnim(gRegionMap->cursorSprite, 1); + } + else + { + gRegionMap->cursorSprite->oam.size = 1; + gRegionMap->cursorSprite->pos1.x = gRegionMap->cursorPosX * 8 + 4; + gRegionMap->cursorSprite->pos1.y = gRegionMap->cursorPosY * 8 + 4; + } + gRegionMap->cursorSprite->data1 = 2; + gRegionMap->cursorSprite->data2 = IndexOfSpritePaletteTag(paletteTag) * 16 + 0x0101; + gRegionMap->cursorSprite->data3 = 1; + } +} + +static void sub_80FBCA0(void) +{ + if (gRegionMap->cursorSprite != NULL) + { + DestroySprite(gRegionMap->cursorSprite); + FreeSpriteTilesByTag(gRegionMap->cursorTileTag); + FreeSpritePaletteByTag(gRegionMap->cursorPaletteTag); + } +} + +void unref_sub_80FBCD0(void) +{ + gRegionMap->cursorSprite->data3 = 1; +} + +void unref_sub_80FBCE0(void) +{ + gRegionMap->cursorSprite->data3 = 0; +} + +static const struct OamData sPlayerIconOamData = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 2, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd sPlayerIconAnimSeq0[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sPlayerIconAnimTable[] = +{ + sPlayerIconAnimSeq0, +}; + +void CreateRegionMapPlayerIcon(u16 tileTag, u16 paletteTag) +{ + u8 spriteId; + struct SpriteSheet playerIconSpriteSheet = + { + .data = sRegionMapBrendanIcon_Image, + .size = 128, + .tag = tileTag, + }; + struct SpritePalette playerIconSpritePalette = + { + .data = sRegionMapBrendanIcon_Pal, + .tag = paletteTag, + }; + struct SpriteTemplate playerIconSpriteTemplate = + { + .tileTag = tileTag, + .paletteTag = paletteTag, + .oam = &sPlayerIconOamData, + .anims = sPlayerIconAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, + }; + + if (gSaveBlock2.playerGender == FEMALE) + { + playerIconSpriteSheet.data = sRegionMapMayIcon_Image; + playerIconSpritePalette.data = sRegionMapMayIcon_Pal; + } + LoadSpriteSheet(&playerIconSpriteSheet); + LoadSpritePalette(&playerIconSpritePalette); + spriteId = CreateSprite(&playerIconSpriteTemplate, 0, 0, 1); + gRegionMap->playerIconSprite = &gSprites[spriteId]; + if (gRegionMap->zoomed == FALSE) + { + gRegionMap->playerIconSprite->pos1.x = gRegionMap->unk74 * 8 + 4; + gRegionMap->playerIconSprite->pos1.y = gRegionMap->unk76 * 8 + 4; + gRegionMap->playerIconSprite->callback = SpriteCB_PlayerIconZoomedOut; + } + else + { + gRegionMap->playerIconSprite->pos1.x = gRegionMap->unk74 * 16 - 48; + gRegionMap->playerIconSprite->pos1.y = gRegionMap->unk76 * 16 - 66; + gRegionMap->playerIconSprite->callback = SpriteCB_PlayerIconZoomedIn; + } +} + +static void sub_80FBDF8(void) +{ + if (gRegionMap->playerIconSprite != NULL) + { + gRegionMap->playerIconSprite->invisible = TRUE; + gRegionMap->playerIconSprite->callback = SpriteCallbackDummy; + } +} + +static void sub_80FBE24(void) +{ + if (gRegionMap->playerIconSprite != NULL) + { + if (gRegionMap->zoomed == TRUE) + { + gRegionMap->playerIconSprite->pos1.x = gRegionMap->unk74 * 16 - 48; + gRegionMap->playerIconSprite->pos1.y = gRegionMap->unk76 * 16 - 66; + gRegionMap->playerIconSprite->callback = SpriteCB_PlayerIconZoomedIn; + gRegionMap->playerIconSprite->invisible = FALSE; + } + else + { + gRegionMap->playerIconSprite->pos1.x = gRegionMap->unk74 * 8 + 4; + gRegionMap->playerIconSprite->pos1.y = gRegionMap->unk76 * 8 + 4; + gRegionMap->playerIconSprite->pos2.x = 0; + gRegionMap->playerIconSprite->pos2.y = 0; + gRegionMap->playerIconSprite->callback = SpriteCB_PlayerIconZoomedOut; + gRegionMap->playerIconSprite->invisible = FALSE; + } + } +} + +static void SpriteCB_PlayerIconZoomedIn(struct Sprite *sprite) +{ + sprite->pos2.x = -(gRegionMap->scrollX * 2); + sprite->pos2.y = -(gRegionMap->scrollY * 2); + sprite->data0 = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY; + sprite->data1 = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX; + + // Determine if sprite is on screen + if (sprite->data0 < -8 || sprite->data0 > 0xA8 || sprite->data1 < -8 || sprite->data1 > 0xF8) + sprite->data2 = FALSE; + else + sprite->data2 = TRUE; + + if (sprite->data2 == TRUE) + UpdateIconBlink(sprite); + else + sprite->invisible = TRUE; +} + +static void SpriteCB_PlayerIconZoomedOut(struct Sprite *sprite) +{ + UpdateIconBlink(sprite); +} + +static void UpdateIconBlink(struct Sprite *sprite) +{ + if (gRegionMap->blinkPlayerIcon) + { + // Toggle visibility every 16 frames + sprite->data7++; + if (sprite->data7 > 16) + { + sprite->data7 = 0; + sprite->invisible = !sprite->invisible; + } + } + else + { + sprite->invisible = FALSE; + } +} + +void sub_80FBF94(void) +{ + if (gRegionMap->playerIsInCave) + gRegionMap->blinkPlayerIcon = TRUE; +} + +const u8 *GetMapSectionName(u8 *dest, u16 mapSecId, u16 length) +{ + if (mapSecId == MAPSEC_SECRET_BASE) + return GetSecretBaseMapName(dest); + if (mapSecId < MAPSEC_NONE) + return StringCopy(dest, gRegionMapLocations[mapSecId].regionMapSectionId); + if (length == 0) + length = 18; + return StringFill(dest, CHAR_SPACE, length); +} + +const u8 *CopyMapName(u8 *dest, u16 mapSecId) +{ + switch (mapSecId) + { + case MAPSEC_UNK_0x57: + return StringCopy(dest, gOtherText_Ferry); + case MAPSEC_SECRET_BASE: + return StringCopy(dest, gOtherText_SecretBase); + default: + return GetMapSectionName(dest, mapSecId, 0); + } +} + +const u8 *CopyLocationName(u8 *dest, u16 mapSecId) +{ + if (mapSecId == MAPSEC_EVIL_TEAM_HIDEOUT) + return StringCopy(dest, gOtherText_Hideout); + else + return CopyMapName(dest, mapSecId); +} + +static void GetRegionMapLocationPosition(u16 mapSecId, u16 *x, u16 *y, u16 *width, u16 *height) +{ + *x = gRegionMapLocations[mapSecId].x; + *y = gRegionMapLocations[mapSecId].y; + *width = gRegionMapLocations[mapSecId].width; + *height = gRegionMapLocations[mapSecId].height; +} + +struct UnknownStruct3 +{ + void (*unk0)(void); + u16 unk4; + u16 unk6; + struct RegionMap regionMap; +}; + +extern u8 ewram[]; +#define ewram0 (*(struct UnknownStruct3 *)(ewram + 0)) +#define ewram888 (ewram + 0x888) +#define ewramA6E (ewram[0xA6E]) +#define ewramBlankMapName (ewram + 0xA48) + +static const u16 sFlyRegionMapFrame_Pal[] = INCBIN_U16("graphics/pokenav/map_frame.gbapal"); +static const u8 sFlyRegionMapFrame_ImageLZ[] = INCBIN_U8("graphics/pokenav/map_frame.4bpp.lz"); +static const u8 sFlyRegionMapFrame_TilemapLZ[] = INCBIN_U8("graphics/pokenav/map_frame.bin.lz"); +static const u16 sFlyTargetIcons_Pal[] = INCBIN_U16("graphics/pokenav/fly_target_icons.gbapal"); +static const u8 sFlyTargetIcons_ImageLZ[] = INCBIN_U8("graphics/pokenav/fly_target_icons.4bpp.lz"); + +static const u8 sUnknown_083E7920[][3] = +{ + {0, 9, 1}, + {0, 10, 14}, + {0, 11, 15}, + {0, 12, 16}, + {0, 13, 17}, + {0, 14, 18}, + {0, 15, 19}, + {0, 0, 3}, + {0, 1, 4}, + {0, 2, 5}, + {0, 3, 6}, + {0, 4, 7}, + {0, 5, 8}, + {0, 6, 9}, + {0, 7, 10}, + {0, 8, 11}, + {0, 16, 0}, + {0, 17, 0}, + {0, 18, 0}, + {0, 19, 0}, + {0, 20, 0}, + {0, 21, 0}, + {0, 22, 0}, + {0, 23, 0}, + {0, 24, 0}, + {0, 25, 0}, + {0, 26, 0}, + {0, 27, 0}, + {0, 28, 0}, + {0, 29, 0}, + {0, 30, 0}, + {0, 31, 0}, + {0, 32, 0}, + {0, 33, 0}, + {0, 34, 0}, + {0, 35, 0}, + {0, 36, 0}, + {0, 37, 0}, + {0, 38, 0}, + {0, 39, 0}, + {0, 40, 0}, + {0, 41, 0}, + {0, 42, 0}, + {0, 43, 0}, + {0, 44, 0}, + {0, 45, 0}, + {0, 46, 0}, + {0, 47, 0}, + {0, 48, 0}, + {0, 49, 0}, +}; + +struct UnknownStruct4 +{ + const u8 *const *unk0; + u16 mapSecId; + u16 flag; +}; + +static const u8 *const sEverGrandeCityAreaNames[] = {OtherText_PokeLeague, OtherText_PokeCenter}; + +static const struct UnknownStruct4 sUnknown_083E79C0[1] = +{ + {sEverGrandeCityAreaNames, MAPSEC_EVER_GRANDE_CITY, SYS_POKEMON_LEAGUE_FLY}, +}; + +// XXX: what is this? +static u8 *const ewram_ = ewram; + +static const struct SpritePalette sFlyTargetIconSpritePalette = {sFlyTargetIcons_Pal, 2}; + +// Fly targets that are not cities or towns +static const u16 sSpecialFlyAreas[][2] = +{ + // flag, mapSecId + {0x848, MAPSEC_BATTLE_TOWER}, + {0xFFFF, MAPSEC_NONE}, +}; + +static const struct OamData sFlyTargetOamData = +{ + .y = 0, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 0, + .tileNum = 0, + .priority = 2, + .paletteNum = 0, + .affineParam = 0, +}; + +static const union AnimCmd sFlyTargetAnimSeq0[] = +{ + ANIMCMD_FRAME(0, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sFlyTargetAnimSeq1[] = +{ + ANIMCMD_FRAME(1, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sFlyTargetAnimSeq2[] = +{ + ANIMCMD_FRAME(3, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sFlyTargetAnimSeq3[] = +{ + ANIMCMD_FRAME(5, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sFlyTargetAnimSeq4[] = +{ + ANIMCMD_FRAME(6, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sFlyTargetAnimSeq5[] = +{ + ANIMCMD_FRAME(8, 5), + ANIMCMD_END, +}; + +static const union AnimCmd sFlyTargetAnimSeq6[] = +{ + ANIMCMD_FRAME(10, 5), + ANIMCMD_END, +}; + +static const union AnimCmd *const sFlyTargetAnimTable[] = +{ + sFlyTargetAnimSeq0, + sFlyTargetAnimSeq1, + sFlyTargetAnimSeq2, + sFlyTargetAnimSeq3, + sFlyTargetAnimSeq4, + sFlyTargetAnimSeq5, + sFlyTargetAnimSeq6, +}; + +static const struct SpriteTemplate gFlyTargetSpriteTemplate = +{ + .tileTag = 2, + .paletteTag = 2, + .oam = &sFlyTargetOamData, + .anims = sFlyTargetAnimTable, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = SpriteCallbackDummy, +}; + +void CB2_InitFlyRegionMap(void) +{ + switch (gMain.state) + { + case 0: + SetVBlankCallback(NULL); + REG_DISPCNT = 0; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG2VOFS = 0; + REG_BG2HOFS = 0; + REG_BG3HOFS = 0; + REG_BG3VOFS = 0; + ResetPaletteFade(); + ResetSpriteData(); + FreeSpriteTileRanges(); + FreeAllSpritePalettes(); + break; + case 1: + SetUpWindowConfig(&gWindowConfig_81E7224); + break; + case 2: + InitMenuWindow(&gWindowConfig_81E7224); + MenuZeroFillScreen(); + break; + case 3: + InitRegionMap(&ewram0.regionMap, 0); + CreateRegionMapCursor(0, 0); + CreateRegionMapPlayerIcon(1, 1); + ewram0.unk6 = ewram0.regionMap.mapSecId; + StringFill(ewramBlankMapName, CHAR_SPACE, 12); + PrintFlyTargetName(); + break; + case 4: + LZ77UnCompVram(sFlyRegionMapFrame_ImageLZ, (void *)(VRAM + 0xC000)); + break; + case 5: + LZ77UnCompVram(sFlyRegionMapFrame_TilemapLZ, (void *)(VRAM + 0xF000)); + break; + case 6: + LoadPalette(sFlyRegionMapFrame_Pal, 16, 32); + MenuPrint_PixelCoords(gOtherText_FlyToWhere, 1, 0x90, 1); + break; + case 7: + CreateFlyTargetGraphics(); + break; + case 8: + BlendPalettes(0xFFFFFFFF, 16, 0); + SetVBlankCallback(VBlankCB_FlyRegionMap); + break; + case 9: + REG_BLDCNT = 0; + REG_BG1CNT = 0x1E0D; + REG_DISPCNT = 0x1741; + sub_80FC244(sub_80FC5B4); + SetMainCallback2(CB2_FlyRegionMap); + break; + default: + return; + } + gMain.state++; +} + +static void VBlankCB_FlyRegionMap(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void CB2_FlyRegionMap(void) +{ + ewram0.unk0(); + AnimateSprites(); + BuildOamBuffer(); +} + +static void sub_80FC244(void (*func)(void)) +{ + ewram0.unk0 = func; + ewram0.unk4 = 0; +} + +static void PrintFlyTargetName(void) +{ + if (ewram0.regionMap.unk16 == 2 || ewram0.regionMap.unk16 == 4) + { + u16 i = 0; + int zero; + + for (i = 0; i < ARRAY_COUNT(sUnknown_083E79C0); i++) + { + const struct UnknownStruct4 *r4 = &sUnknown_083E79C0[i]; + + if (ewram0.regionMap.mapSecId == r4->mapSecId) + { + if (FlagGet(r4->flag)) + { + MenuDrawTextWindow(16, 14, 29, 19); + MenuPrint(ewram0.regionMap.mapSecName, 17, 15); + MenuPrint_RightAligned(r4->unk0[ewram0.regionMap.everGrandeCityArea], 29, 17); + return; + } + break; + } + } + // This check is always true, but somehow the compiler still performed it. + asm("mov %0, #0\n":"=r"(zero)); // zero = 0 + if (zero == 0) + { + MenuDrawTextWindow(16, 16, 29, 19); + MenuPrint(ewram0.regionMap.mapSecName, 17, 17); + MenuZeroFillWindowRect(16, 14, 29, 15); + } + } + else + { + MenuDrawTextWindow(16, 16, 29, 19); + MenuPrint(ewramBlankMapName, 17, 17); + MenuZeroFillWindowRect(16, 14, 29, 15); + } +} + +static void CreateFlyTargetGraphics(void) +{ + struct SpriteSheet spriteSheet; + + LZ77UnCompWram(sFlyTargetIcons_ImageLZ, ewram888); + spriteSheet.data = ewram888; + spriteSheet.size = 0x1C0; + spriteSheet.tag = 2; + LoadSpriteSheet(&spriteSheet); + LoadSpritePalette(&sFlyTargetIconSpritePalette); + CreateCityTownFlyTargetIcons(); + CreateSpecialAreaFlyTargetIcons(); +} + +// Draws a light overlay on cities and towns that the player can fly to +static void CreateCityTownFlyTargetIcons(void) +{ + u16 canFlyFlag = 0x80F; + u16 i; + + for (i = 0; i < 16; i++) + { + u16 x; + u16 y; + u16 width; + u16 height; + u16 r7; + u8 spriteId; + + GetRegionMapLocationPosition(i, &x, &y, &width, &height); + x = (x + 1) * 8 + 4; + y = (y + 2) * 8 + 4; + if (width == 2) + r7 = 1; + else if (height == 2) + r7 = 2; + else + r7 = 0; + spriteId = CreateSprite(&gFlyTargetSpriteTemplate, x, y, 10); + if (spriteId != 64) + { + gSprites[spriteId].oam.shape = r7; + if (FlagGet(canFlyFlag)) + gSprites[spriteId].callback = SpriteCB_FlyTargetIcons; + else + r7 += 3; + StartSpriteAnim(&gSprites[spriteId], r7); + gSprites[spriteId].data0 = i; + } + canFlyFlag++; + } +} + +// Draws a red box on other fly targets +// The Battle Tower is the only one of these +static void CreateSpecialAreaFlyTargetIcons(void) +{ + u16 i; + + for (i = 0; sSpecialFlyAreas[i][1] != MAPSEC_NONE; i++) + { + u16 x; + u16 y; + u16 width; + u16 height; + + if (FlagGet(sSpecialFlyAreas[i][0])) + { + u16 mapSecId = sSpecialFlyAreas[i][1]; + u8 spriteId; + + GetRegionMapLocationPosition(mapSecId, &x, &y, &width, &height); + x = (x + 1) * 8; + y = (y + 2) * 8; + spriteId = CreateSprite(&gFlyTargetSpriteTemplate, x, y, 10); + if (spriteId != 64) + { + gSprites[spriteId].oam.size = 1; + gSprites[spriteId].callback = SpriteCB_FlyTargetIcons; + StartSpriteAnim(&gSprites[spriteId], 6); + gSprites[spriteId].data0 = mapSecId; + } + } + } +} + +static void SpriteCB_FlyTargetIcons(struct Sprite *sprite) +{ + // Blink if our mapSecId is the one selected on the map + if (ewram0.regionMap.mapSecId == sprite->data0) + { + // Toggle visibility every 16 frames + sprite->data1++; + if (sprite->data1 > 16) + { + sprite->data1 = 0; + sprite->invisible = !sprite->invisible; + } + } + else + { + sprite->data1 = 16; + sprite->invisible = FALSE; + } +} + +static void sub_80FC5B4(void) +{ + switch (ewram0.unk4) + { + case 0: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 16, 0, 0); + ewram0.unk4++; + break; + case 1: + if (UpdatePaletteFade() != 0) + break; + sub_80FC244(sub_80FC600); + break; + } +} + +static void sub_80FC600(void) +{ + if (ewram0.unk4 == 0) + { + switch (sub_80FAB60()) + { + case INPUT_EVENT_NONE: + case INPUT_EVENT_DPAD: + case INPUT_EVENT_2: + break; + case INPUT_EVENT_3: + PrintFlyTargetName(); + break; + case INPUT_EVENT_A_BUTTON: + if (ewram0.regionMap.unk16 == 2 || ewram0.regionMap.unk16 == 4) + { + m4aSongNumStart(SE_SELECT); + ewramA6E = 1; + sub_80FC244(sub_80FC69C); + } + break; + case INPUT_EVENT_B_BUTTON: + m4aSongNumStart(SE_SELECT); + ewramA6E = 0; + sub_80FC244(sub_80FC69C); + break; + } + } +} + +static void sub_80FC69C(void) +{ + switch (ewram0.unk4) + { + case 0: + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 16, 0); + ewram0.unk4++; + break; + case 1: + if (UpdatePaletteFade() != 0) + break; + FreeRegionMapIconResources(); + if (ewramA6E != 0) + { + switch (ewram0.regionMap.mapSecId) + { + case MAPSEC_SOUTHERN_ISLAND: + sub_8053538(22); + break; + case MAPSEC_BATTLE_TOWER: + sub_8053538(21); + break; + case MAPSEC_LITTLEROOT_TOWN: + sub_8053538((gSaveBlock2.playerGender == MALE) ? 12 : 13); + break; + case MAPSEC_EVER_GRANDE_CITY: + sub_8053538((FlagGet(0x854) && ewram0.regionMap.everGrandeCityArea == 0) ? 20 : 11); + break; + default: + if (sUnknown_083E7920[ewram0.regionMap.mapSecId][2] != 0) + sub_8053538(sUnknown_083E7920[ewram0.regionMap.mapSecId][2]); + else + warp1_set_2(sUnknown_083E7920[ewram0.regionMap.mapSecId][0], sUnknown_083E7920[ewram0.regionMap.mapSecId][1], -1); + break; + } + sub_80865BC(); + } + else + { + SetMainCallback2(sub_808AD58); + } + break; + } +} diff --git a/src/field/roamer.c b/src/field/roamer.c new file mode 100644 index 000000000..948828d5e --- /dev/null +++ b/src/field/roamer.c @@ -0,0 +1,226 @@ +#include "global.h" +#include "roamer.h" +#include "pokemon.h" +#include "rng.h" +#include "species.h" + +#ifdef SAPPHIRE +#define ROAMER_SPECIES SPECIES_LATIAS +#else +#define ROAMER_SPECIES SPECIES_LATIOS +#endif + +enum +{ + MAP_GRP = 0, // map group + MAP_NUM = 1, // map number +}; + +EWRAM_DATA static u8 sLocationHistory[3][2] = {0}; +EWRAM_DATA static u8 sRoamerLocation[2] = {0}; + +static const u8 sRoamerLocations[][6] = +{ + { 0x19, 0x1A, 0x20, 0x21, 0x31, 0xFF }, + { 0x1A, 0x19, 0x20, 0x21, 0xFF, 0xFF }, + { 0x20, 0x1A, 0x19, 0x21, 0xFF, 0xFF }, + { 0x21, 0x20, 0x19, 0x1A, 0x22, 0x26 }, + { 0x22, 0x21, 0x23, 0xFF, 0xFF, 0xFF }, + { 0x23, 0x22, 0x24, 0xFF, 0xFF, 0xFF }, + { 0x24, 0x23, 0x25, 0x26, 0xFF, 0xFF }, + { 0x25, 0x24, 0x26, 0xFF, 0xFF, 0xFF }, + { 0x26, 0x25, 0x21, 0xFF, 0xFF, 0xFF }, + { 0x27, 0x24, 0x28, 0x29, 0xFF, 0xFF }, + { 0x28, 0x27, 0x2A, 0xFF, 0xFF, 0xFF }, + { 0x29, 0x27, 0x2A, 0xFF, 0xFF, 0xFF }, + { 0x2A, 0x28, 0x29, 0x2B, 0xFF, 0xFF }, + { 0x2B, 0x2A, 0x2C, 0xFF, 0xFF, 0xFF }, + { 0x2C, 0x2B, 0x2D, 0xFF, 0xFF, 0xFF }, + { 0x2D, 0x2C, 0x2E, 0xFF, 0xFF, 0xFF }, + { 0x2E, 0x2D, 0x2F, 0xFF, 0xFF, 0xFF }, + { 0x2F, 0x2E, 0x30, 0xFF, 0xFF, 0xFF }, + { 0x30, 0x2F, 0x31, 0xFF, 0xFF, 0xFF }, + { 0x31, 0x30, 0x19, 0xFF, 0xFF, 0xFF }, + { 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }, +}; + +void ClearRoamerData(void) +{ + memset(&gSaveBlock1.roamer, 0, sizeof(gSaveBlock1.roamer)); +} + +void ClearRoamerLocationData(void) +{ + u8 i; + + for (i = 0; i < 3; i++) + { + sLocationHistory[i][MAP_GRP] = 0; + sLocationHistory[i][MAP_NUM] = 0; + } + + sRoamerLocation[MAP_GRP] = 0; + sRoamerLocation[MAP_NUM] = 0; +} + +void CreateInitialRoamerMon(void) +{ + struct Roamer *roamer; + CreateMon(&gEnemyParty[0], ROAMER_SPECIES, 40, 0x20, 0, 0, 0, 0); + roamer = &gSaveBlock1.roamer; + roamer->species = ROAMER_SPECIES; + roamer->level = 40; + roamer->status = 0; + roamer->active = TRUE; + roamer->ivs = GetMonData(&gEnemyParty[0], MON_DATA_IVS); + roamer->personality = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY); + roamer->hp = GetMonData(&gEnemyParty[0], MON_DATA_MAX_HP); + roamer->cool = GetMonData(&gEnemyParty[0], MON_DATA_COOL); + roamer->beauty = GetMonData(&gEnemyParty[0], MON_DATA_BEAUTY); + roamer->cute = GetMonData(&gEnemyParty[0], MON_DATA_CUTE); + roamer->smart = GetMonData(&gEnemyParty[0], MON_DATA_SMART); + roamer->tough = GetMonData(&gEnemyParty[0], MON_DATA_TOUGH); + sRoamerLocation[MAP_GRP] = 0; + sRoamerLocation[MAP_NUM] = sRoamerLocations[Random() % 20][0]; +} + +void InitRoamer(void) +{ + ClearRoamerData(); + ClearRoamerLocationData(); + CreateInitialRoamerMon(); +} + +void UpdateLocationHistoryForRoamer(void) +{ + sLocationHistory[2][MAP_GRP] = sLocationHistory[1][MAP_GRP]; + sLocationHistory[2][MAP_NUM] = sLocationHistory[1][MAP_NUM]; + + sLocationHistory[1][MAP_GRP] = sLocationHistory[0][MAP_GRP]; + sLocationHistory[1][MAP_NUM] = sLocationHistory[0][MAP_NUM]; + + sLocationHistory[0][MAP_GRP] = gSaveBlock1.location.mapGroup; + sLocationHistory[0][MAP_NUM] = gSaveBlock1.location.mapNum; +} + +void RoamerMoveToOtherLocationSet(void) +{ + u8 val = 0; + struct Roamer *roamer = &gSaveBlock1.roamer; + + if (!roamer->active) + return; + + sRoamerLocation[MAP_GRP] = val; + + while (1) + { + val = sRoamerLocations[Random() % 20][0]; + if (sRoamerLocation[MAP_NUM] != val) + { + sRoamerLocation[MAP_NUM] = val; + return; + } + } +} + +void RoamerMove(void) +{ + u8 locSet = 0; + + if ((Random() % 16) == 0) + { + RoamerMoveToOtherLocationSet(); + } + else + { + struct Roamer *roamer = &gSaveBlock1.roamer; + + if (!roamer->active) + return; + + while (locSet < 20) + { + if (sRoamerLocation[MAP_NUM] == sRoamerLocations[locSet][0]) + { + u8 mapNum; + while (1) + { + mapNum = sRoamerLocations[locSet][(Random() % 5) + 1]; + if (!(sLocationHistory[2][MAP_GRP] == 0 && sLocationHistory[2][MAP_NUM] == mapNum) && mapNum != 0xFF) + break; + } + sRoamerLocation[MAP_NUM] = mapNum; + return; + } + locSet++; + } + } +} + +bool8 IsRoamerAt(u8 mapGroup, u8 mapNum) +{ + struct Roamer *roamer = &gSaveBlock1.roamer; + + if (roamer->active && mapGroup == sRoamerLocation[MAP_GRP] && mapNum == sRoamerLocation[MAP_NUM]) + return TRUE; + else + return FALSE; +} + +void CreateRoamerMonInstance(void) +{ + struct Pokemon *mon = &gEnemyParty[0]; + struct Roamer *roamer = &gSaveBlock1.roamer; + CreateMonWithIVsPersonality(mon, roamer->species, roamer->level, roamer->ivs, roamer->personality); + SetMonData(mon, MON_DATA_STATUS, (u8 *)&roamer->status); + SetMonData(mon, MON_DATA_HP, (u8 *)&roamer->hp); + SetMonData(mon, MON_DATA_COOL, (u8 *)&roamer->cool); + SetMonData(mon, MON_DATA_BEAUTY, (u8 *)&roamer->beauty); + SetMonData(mon, MON_DATA_CUTE, (u8 *)&roamer->cute); + SetMonData(mon, MON_DATA_SMART, (u8 *)&roamer->smart); + SetMonData(mon, MON_DATA_TOUGH, (u8 *)&roamer->tough); +} + +bool8 TryStartRoamerEncounter(void) +{ + if (IsRoamerAt(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum) == TRUE && (Random() % 4) == 0) + { + CreateRoamerMonInstance(); + return TRUE; + } + else + { + return FALSE; + } +} + +void UpdateRoamerHPStatus(struct Pokemon *mon) +{ + struct Roamer *roamer; + u16 hp; + u8 status; + + hp = GetMonData(mon, MON_DATA_HP); + + roamer = &gSaveBlock1.roamer; + roamer->hp = hp; + + status = GetMonData(mon, MON_DATA_STATUS); + + roamer->status = status; + + RoamerMoveToOtherLocationSet(); +} + +void SetRoamerInactive(void) +{ + struct Roamer *roamer = &gSaveBlock1.roamer; + roamer->active = FALSE; +} + +void GetRoamerLocation(u8 *mapGroup, u8 *mapNum) +{ + *mapGroup = sRoamerLocation[MAP_GRP]; + *mapNum = sRoamerLocation[MAP_NUM]; +} diff --git a/src/field/rotating_gate.c b/src/field/rotating_gate.c new file mode 100644 index 000000000..e8ab7e1bf --- /dev/null +++ b/src/field/rotating_gate.c @@ -0,0 +1,1155 @@ +#include "global.h" +#include "bike.h" +#include "event_data.h" +#include "field_map_obj.h" +#include "fieldmap.h" +#include "map_constants.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" + +#define ROTATING_GATE_TILE_TAG 0x1300 +#define ROTATING_GATE_PUZZLE_MAX 14 +#define GATE_ARM_MAX_LENGTH 2 + +#define GATE_ROT(rotationDirection, arm, longArm) \ + ((rotationDirection & 15) << 4) | ((arm & 7) << 1) | (longArm & 1) +#define GATE_ROT_CW(arm, longArm) GATE_ROT(ROTATE_CLOCKWISE, arm, longArm) +#define GATE_ROT_ACW(arm, longArm) GATE_ROT(ROTATE_ANTICLOCKWISE, arm, longArm) +#define GATE_ROT_NONE 255 + +static void SpriteCallback_RotatingGate(struct Sprite *sprite); +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY); +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite); + +enum +{ + /* + * | + * +-- + */ + GATE_SHAPE_L1, + + /* + * | + * | + * +-- + */ + GATE_SHAPE_L2, + + /* + * | + * +---- + */ + GATE_SHAPE_L3, + + /* + * | + * | + * +---- + */ + GATE_SHAPE_L4, + + /* + * | + * +-- + * | + */ + GATE_SHAPE_T1, + + /* + * | + * | + * +-- + * | + */ + GATE_SHAPE_T2, + + /* + * | + * +---- + * | + */ + GATE_SHAPE_T3, + + /* + * An unused T-shape gate + * | + * +-- + * | + * | + */ + GATE_SHAPE_T4, + + /* + * An unused T-shape gate + * | + * | + * +---- + * | + */ + GATE_SHAPE_UNUSED_T1, + + /* + * An unused T-shape gate + * | + * | + * +-- + * | + * | + */ + GATE_SHAPE_UNUSED_T2, + + /* + * An unused T-shape gate + * | + * +---- + * | + * | + */ + GATE_SHAPE_UNUSED_T3, + + /* + * An unused T-shape gate + * | + * | + * +---- + * | + * | + */ + GATE_SHAPE_UNUSED_T4, +}; + +enum +{ + /* + * 0 degrees (clockwise) + * | + * +-- + * | + */ + GATE_ORIENTATION_0, + + /* + * 90 degress (clockwise) + * --+-- + * | + */ + GATE_ORIENTATION_90, + + /* + * 180 degrees (clockwise) + * | + * --+ + * | + */ + GATE_ORIENTATION_180, + + /* + * 270 degrees (clockwise) + * | + * --+-- + */ + GATE_ORIENTATION_270, + + GATE_ORIENTATION_MAX, +}; + +// Describes the location of the gates "arms" when the gate has not +// been rotated (i.e. rotated 0 degrees) +enum +{ + GATE_ARM_NORTH, + GATE_ARM_EAST, + GATE_ARM_SOUTH, + GATE_ARM_WEST, +}; + +enum +{ + ROTATE_NONE, + ROTATE_ANTICLOCKWISE, + ROTATE_CLOCKWISE, +}; + +enum +{ + PUZZLE_NONE, + PUZZLE_FORTREE_CITY_GYM, + PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6, +}; + +struct RotatingGatePuzzle +{ + s16 x; + s16 y; + u8 shape; + u8 orientation; +}; + +struct Coords8 +{ + s8 deltaX; + s8 deltaY; +}; + +// Fortree +static const struct RotatingGatePuzzle sRotatingGate_FortreePuzzleConfig[] = +{ + {12, 5, GATE_SHAPE_L4, GATE_ORIENTATION_0}, + {14, 7, GATE_SHAPE_L4, GATE_ORIENTATION_270}, + {16, 4, GATE_SHAPE_T2, GATE_ORIENTATION_90}, + {15, 14, GATE_SHAPE_L2, GATE_ORIENTATION_0}, + {18, 13, GATE_SHAPE_T1, GATE_ORIENTATION_180}, + { 8, 20, GATE_SHAPE_T1, GATE_ORIENTATION_180}, + {16, 20, GATE_SHAPE_T4, GATE_ORIENTATION_90}, +}; + +// Trickhouse +static const struct RotatingGatePuzzle sRotatingGate_TrickHousePuzzleConfig[] = +{ + {13, 3, GATE_SHAPE_T1, GATE_ORIENTATION_270}, + {12, 6, GATE_SHAPE_T1, GATE_ORIENTATION_180}, + { 3, 6, GATE_SHAPE_T1, GATE_ORIENTATION_180}, + { 3, 9, GATE_SHAPE_T2, GATE_ORIENTATION_270}, + { 8, 8, GATE_SHAPE_L1, GATE_ORIENTATION_90}, + { 2, 12, GATE_SHAPE_T3, GATE_ORIENTATION_180}, + { 9, 13, GATE_SHAPE_L2, GATE_ORIENTATION_0}, + { 3, 14, GATE_SHAPE_L3, GATE_ORIENTATION_90}, + { 9, 15, GATE_SHAPE_L4, GATE_ORIENTATION_180}, + { 3, 18, GATE_SHAPE_T2, GATE_ORIENTATION_180}, + { 2, 19, GATE_SHAPE_T1, GATE_ORIENTATION_0}, + { 5, 21, GATE_SHAPE_L1, GATE_ORIENTATION_0}, + { 9, 19, GATE_SHAPE_L4, GATE_ORIENTATION_270}, + {12, 20, GATE_SHAPE_T1, GATE_ORIENTATION_90}, +}; + +static const u8 sRotatingGateTiles_1[] = INCBIN_U8("graphics/rotating_gates/1.4bpp"); +static const u8 sRotatingGateTiles_2[] = INCBIN_U8("graphics/rotating_gates/2.4bpp"); +static const u8 sRotatingGateTiles_3[] = INCBIN_U8("graphics/rotating_gates/3.4bpp"); +static const u8 sRotatingGateTiles_5[] = INCBIN_U8("graphics/rotating_gates/5.4bpp"); +static const u8 sRotatingGateTiles_6[] = INCBIN_U8("graphics/rotating_gates/6.4bpp"); +static const u8 sRotatingGateTiles_7[] = INCBIN_U8("graphics/rotating_gates/7.4bpp"); +static const u8 sRotatingGateTiles_0[] = INCBIN_U8("graphics/rotating_gates/0.4bpp"); +static const u8 sRotatingGateTiles_4[] = INCBIN_U8("graphics/rotating_gates/4.4bpp"); + +static const struct OamData sOamData_RotatingGateLarge = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = 0, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 2, + .paletteNum = 5, + .affineParam = 0, +}; + +static const struct OamData sOamData_RotatingGateRegular = +{ + .y = 0, + .affineMode = ST_OAM_AFFINE_NORMAL, + .objMode = 0, + .mosaic = 0, + .bpp = ST_OAM_4BPP, + .shape = ST_OAM_SQUARE, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 2, + .paletteNum = 5, + .affineParam = 0, +}; + +static const struct SpriteSheet sRotatingGatesGraphicsTable[] = +{ + {sRotatingGateTiles_0, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L1}, + {sRotatingGateTiles_1, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L2}, + {sRotatingGateTiles_2, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L3}, + {sRotatingGateTiles_3, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_L4}, + {sRotatingGateTiles_4, 0x200, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T1}, + {sRotatingGateTiles_5, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T2}, + {sRotatingGateTiles_6, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T3}, + {sRotatingGateTiles_7, 0x800, ROTATING_GATE_TILE_TAG + GATE_SHAPE_T4}, + {NULL}, +}; + +static const union AnimCmd sSpriteAnim_RotatingGateLarge[] = +{ + ANIMCMD_FRAME(0, 0), + ANIMCMD_END, +}; + +static const union AnimCmd sSpriteAnim_RotatingGateRegular[] = +{ + ANIMCMD_FRAME(0, 0), ANIMCMD_END, +}; + +static const union AnimCmd *const sSpriteAnimTable_RotatingGateLarge[] = +{ + sSpriteAnim_RotatingGateLarge, +}; + +static const union AnimCmd *const sSpriteAnimTable_RotatingGateRegular[] = +{ + sSpriteAnim_RotatingGateRegular, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_Rotated270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_JUMP(0), +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 4, 16), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise0to90Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise90to180Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise180to270Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingClockwise270to360Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, -8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise360to270Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 0, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise270to180Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, 64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise180to90Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -128, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd sSpriteAffineAnim_RotatingAnticlockwise90to0Faster[] = +{ + AFFINEANIMCMD_FRAME(0x100, 0x100, -64, 0), + AFFINEANIMCMD_FRAME(0x0, 0x0, 8, 8), + AFFINEANIMCMD_END, +}; + +static const union AffineAnimCmd *const sSpriteAffineAnimTable_RotatingGate[] = +{ + sSpriteAffineAnim_Rotated0, + sSpriteAffineAnim_Rotated90, + sSpriteAffineAnim_Rotated180, + sSpriteAffineAnim_Rotated270, + sSpriteAffineAnim_RotatingAnticlockwise360to270, + sSpriteAffineAnim_RotatingAnticlockwise90to0, + sSpriteAffineAnim_RotatingAnticlockwise180to90, + sSpriteAffineAnim_RotatingAnticlockwise270to180, + sSpriteAffineAnim_RotatingClockwise0to90, + sSpriteAffineAnim_RotatingClockwise90to180, + sSpriteAffineAnim_RotatingClockwise180to270, + sSpriteAffineAnim_RotatingClockwise270to360, + sSpriteAffineAnim_RotatingAnticlockwise360to270Faster, + sSpriteAffineAnim_RotatingAnticlockwise90to0Faster, + sSpriteAffineAnim_RotatingAnticlockwise180to90Faster, + sSpriteAffineAnim_RotatingAnticlockwise270to180Faster, + sSpriteAffineAnim_RotatingClockwise0to90Faster, + sSpriteAffineAnim_RotatingClockwise90to180Faster, + sSpriteAffineAnim_RotatingClockwise180to270Faster, + sSpriteAffineAnim_RotatingClockwise270to360Faster, +}; + +static const struct SpriteTemplate sSpriteTemplate_RotatingGateLarge = +{ + .tileTag = ROTATING_GATE_TILE_TAG, + .paletteTag = 0xFFFF, + .oam = &sOamData_RotatingGateLarge, + .anims = sSpriteAnimTable_RotatingGateLarge, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotatingGate, + .callback = SpriteCallback_RotatingGate, +}; + +static const struct SpriteTemplate sSpriteTemplate_RotatingGateRegular = +{ + .tileTag = ROTATING_GATE_TILE_TAG, + .paletteTag = 0xFFFF, + .oam = &sOamData_RotatingGateRegular, + .anims = sSpriteAnimTable_RotatingGateRegular, + .images = NULL, + .affineAnims = sSpriteAffineAnimTable_RotatingGate, + .callback = SpriteCallback_RotatingGate, +}; + +// These structures describe what happens to the gate if you hit it at +// a given coordinate in a 4x4 grid when walking in the specified +// direction. Either the gate does not rotate, or it rotates in the +// given direction. This information is compared against the gate +// "arm" layout to see if there is an arm at the position in order to +// produce the final rotation. +static const u8 sRotatingGate_RotationInfoNorth[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_CW(GATE_ARM_WEST, 1), GATE_ROT_CW(GATE_ARM_WEST, 0), GATE_ROT_ACW(GATE_ARM_EAST, 0), GATE_ROT_ACW(GATE_ARM_EAST, 1), + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoSouth[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_ACW(GATE_ARM_WEST, 1), GATE_ROT_ACW(GATE_ARM_WEST, 0), GATE_ROT_CW(GATE_ARM_EAST, 0), GATE_ROT_CW(GATE_ARM_EAST, 1), + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoWest[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_NORTH, 1), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_NORTH, 0), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_SOUTH, 0), GATE_ROT_NONE, GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_SOUTH, 1), GATE_ROT_NONE, GATE_ROT_NONE, +}; + +static const u8 sRotatingGate_RotationInfoEast[4 * 4] = +{ + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_NORTH, 1), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_CW(GATE_ARM_NORTH, 0), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_SOUTH, 0), GATE_ROT_NONE, + GATE_ROT_NONE, GATE_ROT_NONE, GATE_ROT_ACW(GATE_ARM_SOUTH, 1), GATE_ROT_NONE, +}; + +// These tables describe the relative coordinate positions the arms +// must move through in order to be rotated. +static const struct Coords8 sRotatingGate_ArmPositionsClockwiseRotation[] = { + { 0, -1 }, { 1, -2 }, { 0, 0 }, { 1, 0 }, { -1, 0 }, { -1, 1 }, { -1, -1 }, { -2, -1 }, +}; + +static const struct Coords8 sRotatingGate_ArmPositionsAntiClockwiseRotation[] = { + { -1, -1 }, { -1, -2 }, { 0, -1 }, { 1, -1 }, { 0, 0 }, { 0, 1 }, { -1, 0 }, { -2, 0 }, +}; + +// Describes where the gates "arms" are in the order north, east, south, west. +// These are adjusted using the current orientation to perform collision checking +static const u8 sRotatingGate_ArmLayout[][4 * 2] = +{ + // L-shape gates + { + 1, 0, + 1, 0, + 0, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 0, 0, + 0, 0, + }, + { + 1, 0, + 1, 1, + 0, 0, + 0, 0, + }, + { + 1, 1, + 1, 1, + 0, 0, + 0, 0, + }, + + // T-shape gates + { + 1, 0, + 1, 0, + 1, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 1, 0, + 0, 0, + }, + { + 1, 0, + 1, 1, + 1, 0, + 0, 0, + }, + { + 1, 0, + 1, 0, + 1, 1, + 0, 0, + }, + + // Unused T-shape gates + // These have 2-3 long arms and cannot actually be used anywhere + // since configuration for them is missing from the other tables. + { + 1, 1, + 1, 1, + 1, 0, + 0, 0, + }, + { + 1, 1, + 1, 0, + 1, 1, + 0, 0, + }, + { + 1, 0, + 1, 1, + 1, 1, + 0, 0, + }, + { + 1, 1, + 1, 1, + 1, 1, + 0, 0, + }, +}; + +static EWRAM_DATA u8 gRotatingGate_GateSpriteIds[ROTATING_GATE_PUZZLE_MAX] = {0}; +static EWRAM_DATA const struct RotatingGatePuzzle *gRotatingGate_PuzzleConfig = NULL; +static EWRAM_DATA u8 gRotatingGate_PuzzleCount = 0; + +static int GetCurrentMapRotatingGatePuzzleType(void) +{ + if (gSaveBlock1.location.mapGroup == MAP_GROUP_FORTREE_CITY_GYM && + gSaveBlock1.location.mapNum == MAP_ID_FORTREE_CITY_GYM) + { + return PUZZLE_FORTREE_CITY_GYM; + } + + if (gSaveBlock1.location.mapGroup == MAP_GROUP_ROUTE110_TRICK_HOUSE_PUZZLE6 && + gSaveBlock1.location.mapNum == MAP_ID_ROUTE110_TRICK_HOUSE_PUZZLE6) + { + return PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6; + } + + return PUZZLE_NONE; +} + +static void RotatingGate_ResetAllGateOrientations(void) +{ + int i; + u8 *ptr; + + ptr = (u8 *)GetVarPointer(0x4000); + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + ptr[i] = gRotatingGate_PuzzleConfig[i].orientation; + } +} + +static int RotatingGate_GetGateOrientation(u8 gateId) +{ + return ((u8 *)GetVarPointer(0x4000))[gateId]; +} + +static void RotatingGate_SetGateOrientation(u8 gateId, u8 orientation) +{ + ((u8 *)GetVarPointer(0x4000))[gateId] = orientation; +} + +static void RotatingGate_RotateInDirection(u8 gateId, u32 rotationDirection) +{ + u8 orientation = RotatingGate_GetGateOrientation(gateId); + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + { + if (orientation) + { + orientation--; + } + else + { + orientation = GATE_ORIENTATION_270; + } + } + else + { + orientation = ++orientation % GATE_ORIENTATION_MAX; + } + + RotatingGate_SetGateOrientation(gateId, orientation); +} + +static void RotatingGate_LoadPuzzleConfig(void) +{ + int puzzleType = GetCurrentMapRotatingGatePuzzleType(); + u32 i; + + switch (puzzleType) + { + case PUZZLE_FORTREE_CITY_GYM: + gRotatingGate_PuzzleConfig = sRotatingGate_FortreePuzzleConfig; + gRotatingGate_PuzzleCount = + sizeof(sRotatingGate_FortreePuzzleConfig) / sizeof(struct RotatingGatePuzzle); + break; + case PUZZLE_ROUTE110_TRICK_HOUSE_PUZZLE6: + gRotatingGate_PuzzleConfig = sRotatingGate_TrickHousePuzzleConfig; + gRotatingGate_PuzzleCount = + sizeof(sRotatingGate_TrickHousePuzzleConfig) / sizeof(struct RotatingGatePuzzle); + break; + case PUZZLE_NONE: + default: + return; + } + + for (i = 0; i < ROTATING_GATE_PUZZLE_MAX; i++) + { + gRotatingGate_GateSpriteIds[i] = MAX_SPRITES; + } +} + +static void RotatingGate_CreateGatesWithinViewport(s16 deltaX, s16 deltaY) +{ + u8 i; + + // Calculate the bounding box of the camera + // Same as RotatingGate_DestroyGatesOutsideViewport + s16 x = gSaveBlock1.pos.x - 2; + s16 x2 = gSaveBlock1.pos.x + 0x11; + s16 y = gSaveBlock1.pos.y - 2; + s16 y2 = gSaveBlock1.pos.y + 0xe; + + s16 x3, y3; + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + x3 = gRotatingGate_PuzzleConfig[i].x + 7; + y3 = gRotatingGate_PuzzleConfig[i].y + 7; + + if (y <= y3 && y2 >= y3 && x <= x3 && x2 >= x3 && + gRotatingGate_GateSpriteIds[i] == MAX_SPRITES) + { + gRotatingGate_GateSpriteIds[i] = RotatingGate_CreateGate(i, deltaX, deltaY); + } + } +} + +static u8 RotatingGate_CreateGate(u8 gateId, s16 deltaX, s16 deltaY) +{ + struct Sprite *sprite; + struct SpriteTemplate template; + const struct RotatingGatePuzzle *gate; + u8 spriteId; + s16 x, y; + + gate = &gRotatingGate_PuzzleConfig[gateId]; + + if (gate->shape == GATE_SHAPE_L1 || gate->shape == GATE_SHAPE_T1) + template = sSpriteTemplate_RotatingGateRegular; + else + template = sSpriteTemplate_RotatingGateLarge; + + template.tileTag = gate->shape + ROTATING_GATE_TILE_TAG; + + spriteId = CreateSprite(&template, 0, 0, 0x94); + if (spriteId == MAX_SPRITES) + return MAX_SPRITES; + + x = gate->x + 7; + y = gate->y + 7; + + sprite = &gSprites[spriteId]; + sprite->data0 = gateId; + sprite->coordOffsetEnabled = 1; + + sub_8060388(x + deltaX, y + deltaY, &sprite->pos1.x, &sprite->pos1.y); + RotatingGate_HideGatesOutsideViewport(sprite); + StartSpriteAffineAnim(sprite, RotatingGate_GetGateOrientation(gateId)); + + return spriteId; +} + +static void SpriteCallback_RotatingGate(struct Sprite *sprite) +{ + u8 rotationDirection; + u8 orientation; + u8 affineAnimation; + + rotationDirection = sprite->data1; + orientation = sprite->data2; + + RotatingGate_HideGatesOutsideViewport(sprite); + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + { + affineAnimation = orientation + 4; + + if (GetPlayerSpeed() != 1) + affineAnimation += 8; + + PlaySE(SE_HI_TURUN); + StartSpriteAffineAnim(sprite, affineAnimation); + } + else if (rotationDirection == ROTATE_CLOCKWISE) + { + affineAnimation = orientation + 8; + + if (GetPlayerSpeed() != 1) + affineAnimation += 8; + + PlaySE(SE_HI_TURUN); + StartSpriteAffineAnim(sprite, affineAnimation); + } + + sprite->data1 = ROTATE_NONE; +} + +static void RotatingGate_HideGatesOutsideViewport(struct Sprite *sprite) +{ + u16 x; + s16 x2; + u16 y; + s16 y2; + + sprite->invisible = FALSE; + x = sprite->pos1.x + sprite->pos2.x + sprite->centerToCornerVecX + gSpriteCoordOffsetX; + y = sprite->pos1.y + sprite->pos2.y + sprite->centerToCornerVecY + gSpriteCoordOffsetY; + + x2 = x + 0x40; // Dimensions of the rotating gate + y2 = y + 0x40; + + if ((s16)x > DISPLAY_WIDTH + 0x10 - 1 || x2 < -0x10) + { + sprite->invisible = TRUE; + } + + if ((s16)y > DISPLAY_HEIGHT + 0x10 - 1 || y2 < -0x10) + { + sprite->invisible = TRUE; + } +} + +static void LoadRotatingGatePics(void) +{ + LoadSpriteSheets(sRotatingGatesGraphicsTable); +} + +static void RotatingGate_DestroyGatesOutsideViewport(void) +{ + s16 x; + s16 x2; + s16 y; + s16 y2; + s16 xGate; + s16 yGate; + int i; + struct Sprite *sprite; + + // Same as RotatingGate_CreateGatesWithinViewport + x = gSaveBlock1.pos.x - 2; + x2 = gSaveBlock1.pos.x + 0x11; + y = gSaveBlock1.pos.y - 2; + y2 = gSaveBlock1.pos.y + 0xe; + + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + xGate = gRotatingGate_PuzzleConfig[i].x + 7; + yGate = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gRotatingGate_GateSpriteIds[i] == MAX_SPRITES) + continue; + + if (xGate < x || xGate > x2 || yGate < y || yGate > y2) + { + sprite = &gSprites[gRotatingGate_GateSpriteIds[i]]; + FreeSpriteOamMatrix(sprite); + DestroySprite(sprite); + gRotatingGate_GateSpriteIds[i] = MAX_SPRITES; + } + } +} + +#ifdef NONMATCHING +static int RotatingGate_CanRotate(u8 gateId, int rotationDirection) +{ + const struct Coords8 *armPos; + u8 orientation; + s16 x; + s16 y; + int shape; + int i; + int j; + int armOrientation; + const u8 *gateArmCollisionData; + u8 armIndex; + + if (rotationDirection == ROTATE_ANTICLOCKWISE) + armPos = sRotatingGate_ArmPositionsAntiClockwiseRotation; + else if (rotationDirection == ROTATE_CLOCKWISE) + armPos = sRotatingGate_ArmPositionsClockwiseRotation; + else + return 0; + + orientation = RotatingGate_GetGateOrientation(gateId); + + shape = gRotatingGate_PuzzleConfig[gateId].shape; + x = gRotatingGate_PuzzleConfig[gateId].x + 7; + y = gRotatingGate_PuzzleConfig[gateId].y + 7; + + // Loop through the gate's "arms" clockwise (north, south, east, west) + for (i = GATE_ARM_NORTH; i <= GATE_ARM_WEST; i++) + { + armOrientation = orientation + i; + gateArmCollisionData = sRotatingGate_ArmLayout[shape][i]; + + // Ensure that no part of the arm collides with the map + for (j = 0; j < GATE_ARM_MAX_LENGTH; j++) + { + armIndex = 2 * (armOrientation % 4) + j; + + if (*gateArmCollisionData) + { + if (MapGridIsImpassableAt( + armPos[armIndex].deltaX + x, armPos[armIndex].deltaY + y) == 1) + return 0; + } + gateArmCollisionData++; + } + } + + return 1; +} +#else +__attribute__((naked)) +static int RotatingGate_CanRotate(u8 a, int puzzleType) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0xC\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + cmp r1, 0x1\n\ + bne _080C7EAC\n\ + ldr r0, _080C7EA8 @ =sRotatingGate_ArmPositionsAntiClockwiseRotation\n\ + mov r10, r0\n\ + b _080C7EB8\n\ + .align 2, 0\n\ +_080C7EA8: .4byte sRotatingGate_ArmPositionsAntiClockwiseRotation\n\ +_080C7EAC:\n\ + cmp r1, 0x2\n\ + beq _080C7EB4\n\ +_080C7EB0:\n\ + movs r0, 0\n\ + b _080C7F48\n\ +_080C7EB4:\n\ + ldr r1, _080C7F58 @ =sRotatingGate_ArmPositionsClockwiseRotation\n\ + mov r10, r1\n\ +_080C7EB8:\n\ + adds r0, r4, 0\n\ + bl RotatingGate_GetGateOrientation\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp]\n\ + ldr r0, _080C7F5C @ =gRotatingGate_PuzzleConfig\n\ + ldr r1, [r0]\n\ + lsls r0, r4, 3\n\ + adds r0, r1\n\ + ldrb r2, [r0, 0x4]\n\ + ldrh r1, [r0]\n\ + adds r1, 0x7\n\ + ldrh r0, [r0, 0x2]\n\ + adds r0, 0x7\n\ + movs r3, 0\n\ + lsls r2, 3\n\ + str r2, [sp, 0x4]\n\ + lsls r1, 16\n\ + asrs r1, 16\n\ + mov r9, r1\n\ + lsls r0, 16\n\ + asrs r0, 16\n\ + mov r8, r0\n\ +_080C7EE8:\n\ + movs r6, 0\n\ + ldr r2, [sp]\n\ + adds r7, r2, r3\n\ + lsls r0, r3, 1\n\ + adds r5, r7, 0\n\ + ldr r1, [sp, 0x4]\n\ + adds r0, r1\n\ + ldr r2, _080C7F60 @ =sRotatingGate_ArmLayout\n\ + adds r4, r0, r2\n\ +_080C7EFA:\n\ + adds r0, r5, 0\n\ + cmp r5, 0\n\ + bge _080C7F02\n\ + adds r0, r7, 0x3\n\ +_080C7F02:\n\ + asrs r0, 2\n\ + lsls r0, 2\n\ + subs r0, r5, r0\n\ + lsls r0, 1\n\ + adds r0, r6\n\ + lsls r0, 24\n\ + lsrs r1, r0, 24\n\ + ldrb r0, [r4]\n\ + cmp r0, 0\n\ + beq _080C7F38\n\ + lsls r1, 2\n\ + add r1, r10\n\ + movs r0, 0\n\ + ldrsb r0, [r1, r0]\n\ + add r0, r9\n\ + ldrb r1, [r1, 0x1]\n\ + lsls r1, 24\n\ + asrs r1, 24\n\ + add r1, r8\n\ + str r3, [sp, 0x8]\n\ + bl MapGridIsImpassableAt\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + ldr r3, [sp, 0x8]\n\ + cmp r0, 0x1\n\ + beq _080C7EB0\n\ +_080C7F38:\n\ + adds r4, 0x1\n\ + adds r6, 0x1\n\ + cmp r6, 0x1\n\ + ble _080C7EFA\n\ + adds r3, 0x1\n\ + cmp r3, 0x3\n\ + ble _080C7EE8\n\ + movs r0, 0x1\n\ +_080C7F48:\n\ + add sp, 0xC\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r1}\n\ + bx r1\n\ + .align 2, 0\n\ +_080C7F58: .4byte sRotatingGate_ArmPositionsClockwiseRotation\n\ +_080C7F5C: .4byte gRotatingGate_PuzzleConfig\n\ +_080C7F60: .4byte sRotatingGate_ArmLayout\n\ +.syntax divided\n"); +} +#endif + +static int RotatingGate_HasArm(u8 gateId, u8 armInfo) +{ + int isLongArm; + s8 armOrientation; + int arm; + int shape; + + arm = armInfo >> 1; + isLongArm = armInfo & 1; + + armOrientation = (arm - RotatingGate_GetGateOrientation(gateId) + 4) % 4; + shape = gRotatingGate_PuzzleConfig[gateId].shape; + return sRotatingGate_ArmLayout[shape][armOrientation * 2 + isLongArm]; +} + +static void RotatingGate_TriggerRotationAnimation(u8 gateId, int rotationDirection) +{ + struct Sprite *sprite; + + if (gRotatingGate_GateSpriteIds[gateId] != MAX_SPRITES) + { + sprite = &gSprites[gRotatingGate_GateSpriteIds[gateId]]; + sprite->data1 = rotationDirection; + sprite->data2 = RotatingGate_GetGateOrientation(gateId); + } +} + +static u8 RotatingGate_GetRotationInfo(u8 direction, s16 x, s16 y) +{ + register const u8 *ptr; + + if (direction == DIR_NORTH) + ptr = sRotatingGate_RotationInfoNorth; + else if (direction == DIR_SOUTH) + ptr = sRotatingGate_RotationInfoSouth; + else if (direction == DIR_WEST) + ptr = sRotatingGate_RotationInfoWest; + else if (direction == DIR_EAST) + ptr = sRotatingGate_RotationInfoEast; + else + return GATE_ROT_NONE; + + return ptr[y * 4 + x]; +} + +void RotatingGate_InitPuzzle(void) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + RotatingGate_LoadPuzzleConfig(); + RotatingGate_ResetAllGateOrientations(); + } +} + +void RotatingGatePuzzleCameraUpdate(u16 deltaX, u16 deltaY) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + RotatingGate_CreateGatesWithinViewport(deltaX, deltaY); + RotatingGate_DestroyGatesOutsideViewport(); + } +} + +void RotatingGate_InitPuzzleAndGraphics(void) +{ + if (GetCurrentMapRotatingGatePuzzleType()) + { + LoadRotatingGatePics(); + RotatingGate_LoadPuzzleConfig(); + RotatingGate_CreateGatesWithinViewport(0, 0); + } +} + +bool8 CheckForRotatingGatePuzzleCollision(u8 direction, s16 x, s16 y) +{ + int i; + + if (!GetCurrentMapRotatingGatePuzzleType()) + return FALSE; + for (i = 0; i < gRotatingGate_PuzzleCount; i++) + { + s16 gateX = gRotatingGate_PuzzleConfig[i].x + 7; + s16 gateY = gRotatingGate_PuzzleConfig[i].y + 7; + + if (gateX - 2 <= x && x <= gateX + 1 && gateY - 2 <= y && y <= gateY + 1) + { + s16 centerX = x - gateX + 2; + s16 centerY = y - gateY + 2; + u8 rotationInfo = RotatingGate_GetRotationInfo(direction, centerX, centerY); + + if (rotationInfo != GATE_ROT_NONE) + { + u8 rotationDirection = ((rotationInfo & 0xF0) >> 4); + u8 armInfo = rotationInfo & 0xF; + + if (RotatingGate_HasArm(i, armInfo)) + { + if (RotatingGate_CanRotate(i, rotationDirection)) + { + RotatingGate_TriggerRotationAnimation(i, rotationDirection); + RotatingGate_RotateInDirection(i, rotationDirection); + return FALSE; + } + return TRUE; + } + } + } + } + return FALSE; +} diff --git a/src/field/safari_zone.c b/src/field/safari_zone.c new file mode 100644 index 000000000..14fd1ddc4 --- /dev/null +++ b/src/field/safari_zone.c @@ -0,0 +1,253 @@ +#include "global.h" +#include "safari_zone.h" +#include "event_data.h" +#include "field_fadetransition.h" +#include "field_player_avatar.h" +#include "main.h" +#include "overworld.h" +#include "script.h" +#include "string_util.h" +#include "text.h" + +struct PokeblockFeeder +{ + /*0x00*/ s16 x; + /*0x02*/ s16 y; + /*0x04*/ s8 mapNum; + /*0x05*/ u8 stepCounter; + /*0x08*/ struct Pokeblock pokeblock; +}; + +#define NUM_POKEBLOCK_FEEDERS 10 + +static void ClearAllPokeblockFeeders(void); +static void DecrementFeederStepCounters(void); + +extern u8 gBattleOutcome; + +EWRAM_DATA u8 gNumSafariBalls = 0; +EWRAM_DATA static u16 gSafariZoneStepCounter = 0; +EWRAM_DATA static struct PokeblockFeeder gPokeblockFeeders[NUM_POKEBLOCK_FEEDERS] = {0}; + +extern void (*gFieldCallback)(void); + +extern u8 gUnknown_081C340A; +extern u8 gUnknown_081C342D; +extern u8 gUnknown_081C3448; +extern u8 gUnknown_081C3459; +extern u8 *gPokeblockNames[]; + +extern u16 gScriptResult; + +bool32 GetSafariZoneFlag(void) +{ + return FlagGet(SYS_SAFARI_MODE); +} + +void SetSafariZoneFlag(void) +{ + FlagSet(SYS_SAFARI_MODE); +} + +void ResetSafariZoneFlag(void) +{ + FlagClear(SYS_SAFARI_MODE); +} + +void EnterSafariMode(void) +{ + IncrementGameStat(0x11); + SetSafariZoneFlag(); + ClearAllPokeblockFeeders(); + gNumSafariBalls = 30; + gSafariZoneStepCounter = 500; +} + +void ExitSafariMode(void) +{ + ResetSafariZoneFlag(); + ClearAllPokeblockFeeders(); + gNumSafariBalls = 0; + gSafariZoneStepCounter = 0; +} + +bool8 SafariZoneTakeStep(void) +{ + if (GetSafariZoneFlag() == FALSE) + { + return FALSE; + } + + DecrementFeederStepCounters(); + gSafariZoneStepCounter--; + if (gSafariZoneStepCounter == 0) + { + ScriptContext1_SetupScript(&gUnknown_081C3448); + return TRUE; + } + return FALSE; +} + +void SafariZoneRetirePrompt(void) +{ + ScriptContext1_SetupScript(&gUnknown_081C342D); +} + +void sub_80C824C(void) +{ + if (gNumSafariBalls != 0) + { + SetMainCallback2(c2_exit_to_overworld_2_switch); + } + else if (gBattleOutcome == 8) + { + ScriptContext2_RunNewScript(&gUnknown_081C340A); + warp_in(); + gFieldCallback = sub_8080E44; + SetMainCallback2(CB2_LoadMap); + } + else if (gBattleOutcome == 7) + { + ScriptContext1_SetupScript(&gUnknown_081C3459); + ScriptContext1_Stop(); + SetMainCallback2(c2_exit_to_overworld_1_continue_scripts_restart_music); + } +} + +static void ClearPokeblockFeeder(u8 index) +{ + memset(&gPokeblockFeeders[index], 0, sizeof(struct PokeblockFeeder)); +} + +static void ClearAllPokeblockFeeders(void) +{ + memset(gPokeblockFeeders, 0, sizeof(gPokeblockFeeders)); +} + +void SafariZoneGetPokeblockNameInFeeder(void) +{ + s16 x, y; + u16 i; + + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + + for (i = 0; i < NUM_POKEBLOCK_FEEDERS; i++) + { + if (gSaveBlock1.location.mapNum == gPokeblockFeeders[i].mapNum + && gPokeblockFeeders[i].x == x + && gPokeblockFeeders[i].y == y) + { + gScriptResult = i; + StringCopy(gStringVar1, gPokeblockNames[gPokeblockFeeders[i].pokeblock.color]); + return; + } + } + + gScriptResult = -1; +} + +static void GetPokeblockFeederWithinRange(void) +{ + s16 x, y; + u16 i; + + PlayerGetDestCoords(&x, &y); + + for (i = 0; i < NUM_POKEBLOCK_FEEDERS; i++) + { + if (gSaveBlock1.location.mapNum == gPokeblockFeeders[i].mapNum) + { + //Get absolute value of x and y distance from Pokeblock feeder on current map + x -= gPokeblockFeeders[i].x; + y -= gPokeblockFeeders[i].y; + if (x < 0) + x *= -1; + if (y < 0) + y *= -1; + if ((x + y) <= 5) + { + gScriptResult = i; + return; + } + } + } + + gScriptResult = -1; +} + +struct Pokeblock *unref_sub_80C8418(void) +{ + SafariZoneGetPokeblockNameInFeeder(); + + if (gScriptResult == 0xFFFF) + return NULL; + else + return &gPokeblockFeeders[gScriptResult].pokeblock; +} + + +struct Pokeblock *SafariZoneGetActivePokeblock(void) +{ + GetPokeblockFeederWithinRange(); + + if (gScriptResult == 0xFFFF) + return NULL; + else + return &gPokeblockFeeders[gScriptResult].pokeblock; +} + + +void SafariZoneActivatePokeblockFeeder(u8 pokeblock_index) +{ + s16 x, y; + u8 i; + + for (i = 0; i < NUM_POKEBLOCK_FEEDERS; i++) + { + //Find free entry in gPokeblockFeeders + if (gPokeblockFeeders[i].mapNum == 0 + && gPokeblockFeeders[i].x == 0 + && gPokeblockFeeders[i].y == 0) + { + //Initialize Pokeblock feeder + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + gPokeblockFeeders[i].mapNum = gSaveBlock1.location.mapNum; + gPokeblockFeeders[i].pokeblock = gSaveBlock1.pokeblocks[pokeblock_index]; + gPokeblockFeeders[i].stepCounter = 100; + gPokeblockFeeders[i].x = x; + gPokeblockFeeders[i].y = y; + break; + } + } +} + +static void DecrementFeederStepCounters(void) +{ + u8 i; + + for (i = 0; i < NUM_POKEBLOCK_FEEDERS; i++) + { + if (gPokeblockFeeders[i].stepCounter != 0) + { + gPokeblockFeeders[i].stepCounter--; + if (gPokeblockFeeders[i].stepCounter == 0) + ClearPokeblockFeeder(i); + } + } +} + +bool8 unref_sub_80C853C(void) +{ + SafariZoneGetPokeblockNameInFeeder(); + + if (gScriptResult == 0xFFFF) + { + return FALSE; + } + + ConvertIntToDecimalStringN(gStringVar2, + gPokeblockFeeders[gScriptResult].stepCounter, + STR_CONV_MODE_LEADING_ZEROS, 3); + + return TRUE; +} diff --git a/src/field/scrcmd.c b/src/field/scrcmd.c new file mode 100644 index 000000000..28584d4d0 --- /dev/null +++ b/src/field/scrcmd.c @@ -0,0 +1,2020 @@ +#include "global.h" +#include "battle_setup.h" +#include "berry.h" +#include "clock.h" +#include "coins.h" +#include "contest_link_80C2020.h" +#include "contest_painting.h" +#include "data2.h" +#include "decoration.h" +#include "decoration_inventory.h" +#include "event_data.h" +#include "field_door.h" +#include "field_effect.h" +#include "field_fadetransition.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "field_message_box.h" +#include "field_player_avatar.h" +#include "field_screen_effect.h" +#include "field_specials.h" +#include "field_tasks.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "item.h" +#include "main.h" +#include "map_obj_lock.h" +#include "menu.h" +#include "money.h" +#include "mystery_event_script.h" +#include "palette.h" +#include "party_menu.h" +#include "pokemon.h" +#include "rng.h" +#include "overworld.h" +#include "rtc.h" +#include "script.h" +#include "script_menu.h" +#include "script_movement.h" +#include "script_pokemon_80C4.h" +#include "script_pokemon_80F9.h" +#include "shop.h" +#include "slot_machine.h" +#include "sound.h" +#include "string_util.h" +#include "tv.h" + +typedef u16 (*SpecialFunc)(void); +typedef void (*NativeFunc)(void); + +extern u32 gUnknown_0202E8AC; + +static EWRAM_DATA u32 gUnknown_0202E8B0 = 0; +static EWRAM_DATA u16 sPauseCounter = 0; +static EWRAM_DATA u16 sMovingNpcId = 0; +static EWRAM_DATA u16 sMovingNpcMapBank = 0; +static EWRAM_DATA u16 sMovingNpcMapId = 0; +static EWRAM_DATA u16 sFieldEffectScriptId = 0; + +extern u16 gSpecialVar_0x8000; +extern u16 gSpecialVar_0x8001; +extern u16 gSpecialVar_0x8002; +extern u16 gSpecialVar_0x8004; + +extern u16 gScriptResult; + +extern u16 gScriptContestCategory; + +extern SpecialFunc gSpecials[]; +extern u8 *gStdScripts[]; +extern u8 *gStdScripts_End[]; + +// This is defined in here so the optimizer can't see its value when compiling +// script.c. +void * const gNullScriptPtr = NULL; + +static const u8 sScriptConditionTable[6][3] = +{ +// < = > + 1, 0, 0, // < + 0, 1, 0, // = + 0, 0, 1, // > + 1, 1, 0, // <= + 0, 1, 1, // >= + 1, 0, 1, // != +}; + +static u8 * const sScriptStringVars[] = +{ + gStringVar1, + gStringVar2, + gStringVar3, +}; + +bool8 ScrCmd_nop(struct ScriptContext *ctx) +{ + return FALSE; +} + +bool8 ScrCmd_nop1(struct ScriptContext *ctx) +{ + return FALSE; +} + +bool8 ScrCmd_end(struct ScriptContext *ctx) +{ + StopScript(ctx); + return FALSE; +} + +bool8 ScrCmd_gotonative(struct ScriptContext *ctx) +{ + bool8 (*addr)(void) = (bool8 (*)(void))ScriptReadWord(ctx); + + SetupNativeScript(ctx, addr); + return TRUE; +} + +bool8 ScrCmd_special(struct ScriptContext *ctx) +{ + u16 index = ScriptReadHalfword(ctx); + + gSpecials[index](); + return FALSE; +} + +bool8 ScrCmd_specialvar(struct ScriptContext *ctx) +{ + u16 *var = GetVarPointer(ScriptReadHalfword(ctx)); + + *var = gSpecials[ScriptReadHalfword(ctx)](); + return FALSE; +} + +bool8 ScrCmd_callnative(struct ScriptContext *ctx) +{ + NativeFunc func = (NativeFunc)ScriptReadWord(ctx); + + func(); + return FALSE; +} + +bool8 ScrCmd_waitstate(struct ScriptContext *ctx) +{ + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_goto(struct ScriptContext *ctx) +{ + u8 *ptr = (u8 *)ScriptReadWord(ctx); + + ScriptJump(ctx, ptr); + return FALSE; +} + +bool8 ScrCmd_return(struct ScriptContext *ctx) +{ + ScriptReturn(ctx); + return FALSE; +} + +bool8 ScrCmd_call(struct ScriptContext *ctx) +{ + u8 *ptr = (u8 *)ScriptReadWord(ctx); + + ScriptCall(ctx, ptr); + return FALSE; +} + +bool8 ScrCmd_goto_if(struct ScriptContext *ctx) +{ + u8 condition = ScriptReadByte(ctx); + u8 *ptr = (u8 *)ScriptReadWord(ctx); + + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) + ScriptJump(ctx, ptr); + return FALSE; +} + +bool8 ScrCmd_call_if(struct ScriptContext *ctx) +{ + u8 condition = ScriptReadByte(ctx); + u8 *ptr = (u8 *)ScriptReadWord(ctx); + + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) + ScriptCall(ctx, ptr); + return FALSE; +} + +bool8 ScrCmd_setvaddress(struct ScriptContext *ctx) +{ + u32 addr1 = (u32)ctx->scriptPtr - 1; + u32 addr2 = ScriptReadWord(ctx); + + gUnknown_0202E8B0 = addr2 - addr1; + return FALSE; +} + +bool8 ScrCmd_vgoto(struct ScriptContext *ctx) +{ + u32 addr = ScriptReadWord(ctx); + + ScriptJump(ctx, (u8 *)(addr - gUnknown_0202E8B0)); + return FALSE; +} + +bool8 ScrCmd_vcall(struct ScriptContext *ctx) +{ + u32 addr = ScriptReadWord(ctx); + + ScriptCall(ctx, (u8 *)(addr - gUnknown_0202E8B0)); + return FALSE; +} + +bool8 ScrCmd_vgoto_if(struct ScriptContext *ctx) +{ + u8 condition = ScriptReadByte(ctx); + u8 *ptr = (u8 *)(ScriptReadWord(ctx) - gUnknown_0202E8B0); + + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) + ScriptJump(ctx, ptr); + return FALSE; +} + +bool8 ScrCmd_vcall_if(struct ScriptContext *ctx) +{ + u8 condition = ScriptReadByte(ctx); + u8 *ptr = (u8 *)(ScriptReadWord(ctx) - gUnknown_0202E8B0); + + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) + ScriptCall(ctx, ptr); + return FALSE; +} + +bool8 ScrCmd_gotostd(struct ScriptContext *ctx) +{ + u8 index = ScriptReadByte(ctx); + u8 **ptr = &gStdScripts[index]; + + if (ptr < gStdScripts_End) + ScriptJump(ctx, *ptr); + return FALSE; +} + +bool8 ScrCmd_callstd(struct ScriptContext *ctx) +{ + u8 index = ScriptReadByte(ctx); + u8 **ptr = &gStdScripts[index]; + + if (ptr < gStdScripts_End) + ScriptCall(ctx, *ptr); + return FALSE; +} + +bool8 ScrCmd_gotostd_if(struct ScriptContext *ctx) +{ + u8 condition = ScriptReadByte(ctx); + u8 index = ScriptReadByte(ctx); + + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) + { + u8 **ptr = &gStdScripts[index]; + if (ptr < gStdScripts_End) + ScriptJump(ctx, *ptr); + } + return FALSE; +} + +bool8 ScrCmd_callstd_if(struct ScriptContext *ctx) +{ + u8 condition = ScriptReadByte(ctx); + u8 index = ScriptReadByte(ctx); + + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) + { + u8 **ptr = &gStdScripts[index]; + if (ptr < gStdScripts_End) + ScriptCall(ctx, *ptr); + } + return FALSE; +} + +bool8 ScrCmd_gotoram(struct ScriptContext *ctx) +{ + ScriptJump(ctx, (u8 *)gUnknown_0202E8AC); + return FALSE; +} + +bool8 ScrCmd_killscript(struct ScriptContext *ctx) +{ + ClearRamScript(); + StopScript(ctx); + return TRUE; +} + +bool8 ScrCmd_setmysteryeventstatus(struct ScriptContext *ctx) +{ + u8 value = ScriptReadByte(ctx); + + SetMysteryEventScriptStatus(value); + return FALSE; +} + +bool8 ScrCmd_loadword(struct ScriptContext *ctx) +{ + u8 index = ScriptReadByte(ctx); + + ctx->data[index] = ScriptReadWord(ctx); + return FALSE; +} + +bool8 ScrCmd_loadbytefromaddr(struct ScriptContext *ctx) +{ + u8 index = ScriptReadByte(ctx); + + ctx->data[index] = *(u8 *)ScriptReadWord(ctx); + return FALSE; +} + +bool8 ScrCmd_writebytetoaddr(struct ScriptContext *ctx) +{ + u8 value = ScriptReadByte(ctx); + + *(u8 *)ScriptReadWord(ctx) = value; + return FALSE; +} + +bool8 ScrCmd_loadbyte(struct ScriptContext *ctx) +{ + u8 index = ScriptReadByte(ctx); + + ctx->data[index] = ScriptReadByte(ctx); + return FALSE; +} + +bool8 ScrCmd_setptrbyte(struct ScriptContext *ctx) +{ + u8 index = ScriptReadByte(ctx); + + *(u8 *)ScriptReadWord(ctx) = ctx->data[index]; + return FALSE; +} + +bool8 ScrCmd_copylocal(struct ScriptContext *ctx) +{ + u8 destIndex = ScriptReadByte(ctx); + u8 srcIndex = ScriptReadByte(ctx); + + ctx->data[destIndex] = ctx->data[srcIndex]; + return FALSE; +} + +bool8 ScrCmd_copybyte(struct ScriptContext *ctx) +{ + u8 *ptr = (u8 *)ScriptReadWord(ctx); + *ptr = *(u8 *)ScriptReadWord(ctx); + return FALSE; +} + +bool8 ScrCmd_setvar(struct ScriptContext *ctx) +{ + u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + *ptr = ScriptReadHalfword(ctx); + return FALSE; +} + +bool8 ScrCmd_copyvar(struct ScriptContext *ctx) +{ + u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + *ptr = *GetVarPointer(ScriptReadHalfword(ctx)); + return FALSE; +} + +bool8 ScrCmd_setorcopyvar(struct ScriptContext *ctx) +{ + u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + *ptr = VarGet(ScriptReadHalfword(ctx)); + return FALSE; +} + +u8 compare_012(u16 a1, u16 a2) +{ + if (a1 < a2) + return 0; + if (a1 == a2) + return 1; + return 2; +} + +// comparelocaltolocal +bool8 ScrCmd_compare_local_to_local(struct ScriptContext *ctx) +{ + u8 value1 = ctx->data[ScriptReadByte(ctx)]; + u8 value2 = ctx->data[ScriptReadByte(ctx)]; + + ctx->comparisonResult = compare_012(value1, value2); + return FALSE; +} + +// comparelocaltoimm +bool8 ScrCmd_compare_local_to_value(struct ScriptContext *ctx) +{ + u8 value1 = ctx->data[ScriptReadByte(ctx)]; + u8 value2 = ScriptReadByte(ctx); + + ctx->comparisonResult = compare_012(value1, value2); + return FALSE; +} + +bool8 ScrCmd_compare_local_to_addr(struct ScriptContext *ctx) +{ + u8 value1 = ctx->data[ScriptReadByte(ctx)]; + u8 value2 = *(u8 *)ScriptReadWord(ctx); + + ctx->comparisonResult = compare_012(value1, value2); + return FALSE; +} + +bool8 ScrCmd_compare_addr_to_local(struct ScriptContext *ctx) +{ + u8 value1 = *(u8 *)ScriptReadWord(ctx); + u8 value2 = ctx->data[ScriptReadByte(ctx)]; + + ctx->comparisonResult = compare_012(value1, value2); + return FALSE; +} + +bool8 ScrCmd_compare_addr_to_value(struct ScriptContext *ctx) +{ + u8 value1 = *(u8 *)ScriptReadWord(ctx); + u8 value2 = ScriptReadByte(ctx); + + ctx->comparisonResult = compare_012(value1, value2); + return FALSE; +} + +bool8 ScrCmd_compare_addr_to_addr(struct ScriptContext *ctx) +{ + u8 value1 = *(u8 *)ScriptReadWord(ctx); + u8 value2 = *(u8 *)ScriptReadWord(ctx); + + ctx->comparisonResult = compare_012(value1, value2); + return FALSE; +} + +bool8 ScrCmd_compare_var_to_value(struct ScriptContext *ctx) +{ + u16 value1 = *GetVarPointer(ScriptReadHalfword(ctx)); + u16 value2 = ScriptReadHalfword(ctx); + + ctx->comparisonResult = compare_012(value1, value2); + return FALSE; +} + +bool8 ScrCmd_compare_var_to_var(struct ScriptContext *ctx) +{ + u16 *ptr1 = GetVarPointer(ScriptReadHalfword(ctx)); + u16 *ptr2 = GetVarPointer(ScriptReadHalfword(ctx)); + + ctx->comparisonResult = compare_012(*ptr1, *ptr2); + return FALSE; +} + +bool8 ScrCmd_addvar(struct ScriptContext *ctx) +{ + u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + *ptr += ScriptReadHalfword(ctx); + return FALSE; +} + +bool8 ScrCmd_subvar(struct ScriptContext *ctx) +{ + u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + *ptr -= VarGet(ScriptReadHalfword(ctx)); + return FALSE; +} + +bool8 ScrCmd_random(struct ScriptContext *ctx) +{ + u16 max = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = Random() % max; + return FALSE; +} + +bool8 ScrCmd_additem(struct ScriptContext *ctx) +{ + u16 itemId = VarGet(ScriptReadHalfword(ctx)); + u32 quantity = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = AddBagItem(itemId, (u8)quantity); + return FALSE; +} + +bool8 ScrCmd_removeitem(struct ScriptContext *ctx) +{ + u16 itemId = VarGet(ScriptReadHalfword(ctx)); + u32 quantity = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = RemoveBagItem(itemId, (u8)quantity); + return FALSE; +} + +bool8 ScrCmd_checkitemspace(struct ScriptContext *ctx) +{ + u16 itemId = VarGet(ScriptReadHalfword(ctx)); + u32 quantity = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = CheckBagHasSpace(itemId, (u8)quantity); + return FALSE; +} + +bool8 ScrCmd_checkitem(struct ScriptContext *ctx) +{ + u16 itemId = VarGet(ScriptReadHalfword(ctx)); + u32 quantity = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = CheckBagHasItem(itemId, (u8)quantity); + return FALSE; +} + +bool8 ScrCmd_checkitemtype(struct ScriptContext *ctx) +{ + u16 itemId = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = GetPocketByItemId(itemId); + return FALSE; +} + +bool8 ScrCmd_addpcitem(struct ScriptContext *ctx) +{ + u16 itemId = VarGet(ScriptReadHalfword(ctx)); + u16 quantity = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = AddPCItem(itemId, quantity); + return FALSE; +} + +bool8 ScrCmd_checkpcitem(struct ScriptContext *ctx) +{ + u16 itemId = VarGet(ScriptReadHalfword(ctx)); + u16 quantity = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = CheckPCHasItem(itemId, quantity); + return FALSE; +} + +bool8 ScrCmd_adddecor(struct ScriptContext *ctx) +{ + u32 decorId = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = IsThereStorageSpaceForDecoration(decorId); + return FALSE; +} + +bool8 ScrCmd_removedecor(struct ScriptContext *ctx) +{ + u32 decorId = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = sub_81340A8(decorId); + return FALSE; +} + +bool8 ScrCmd_checkdecor(struct ScriptContext *ctx) +{ + u32 decorId = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = sub_8134074(decorId); + return FALSE; +} + +bool8 ScrCmd_hasdecor(struct ScriptContext *ctx) +{ + u32 decorId = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = sub_8133FE4(decorId); + return FALSE; +} + +bool8 ScrCmd_setflag(struct ScriptContext *ctx) +{ + FlagSet(ScriptReadHalfword(ctx)); + return FALSE; +} + +bool8 ScrCmd_clearflag(struct ScriptContext *ctx) +{ + FlagClear(ScriptReadHalfword(ctx)); + return FALSE; +} + +bool8 ScrCmd_checkflag(struct ScriptContext *ctx) +{ + ctx->comparisonResult = FlagGet(ScriptReadHalfword(ctx)); + return FALSE; +} + +bool8 ScrCmd_incrementgamestat(struct ScriptContext *ctx) +{ + IncrementGameStat(ScriptReadByte(ctx)); + return FALSE; +} + +bool8 ScrCmd_animdarklevel(struct ScriptContext *ctx) +{ + sub_8081594(ScriptReadByte(ctx)); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_setdarklevel(struct ScriptContext *ctx) +{ + u16 flashLevel = VarGet(ScriptReadHalfword(ctx)); + + Overworld_SetFlashLevel(flashLevel); + return FALSE; +} + +bool8 IsPaletteNotActive(void) +{ + if (!gPaletteFade.active) + return TRUE; + else + return FALSE; +} + +bool8 ScrCmd_fadescreen(struct ScriptContext *ctx) +{ + fade_screen(ScriptReadByte(ctx), 0); + SetupNativeScript(ctx, IsPaletteNotActive); + return TRUE; +} + +bool8 ScrCmd_fadescreendelay(struct ScriptContext *ctx) +{ + u8 duration = ScriptReadByte(ctx); + u8 delay = ScriptReadByte(ctx); + + fade_screen(duration, delay); + SetupNativeScript(ctx, IsPaletteNotActive); + return TRUE; +} + +bool8 s28_pause_asm() +{ + sPauseCounter--; + + if (sPauseCounter == 0) + return TRUE; + else + return FALSE; +} + +bool8 ScrCmd_delay(struct ScriptContext *ctx) +{ + sPauseCounter = ScriptReadHalfword(ctx); + SetupNativeScript(ctx, s28_pause_asm); + return TRUE; +} + +bool8 ScrCmd_initclock(struct ScriptContext *ctx) +{ + u8 hour = VarGet(ScriptReadHalfword(ctx)); + u8 minute = VarGet(ScriptReadHalfword(ctx)); + + RtcInitLocalTimeOffset(hour, minute); + return FALSE; +} + +bool8 ScrCmd_dodailyevents(struct ScriptContext *ctx) +{ + DoTimeBasedEvents(); + return FALSE; +} + +bool8 ScrCmd_gettime(struct ScriptContext *ctx) +{ + RtcCalcLocalTime(); + gSpecialVar_0x8000 = gLocalTime.hours; + gSpecialVar_0x8001 = gLocalTime.minutes; + gSpecialVar_0x8002 = gLocalTime.seconds; + return FALSE; +} + +bool8 ScrCmd_setweather(struct ScriptContext *ctx) +{ + u16 weather = VarGet(ScriptReadHalfword(ctx)); + + SetSav1Weather(weather); + return FALSE; +} + +bool8 ScrCmd_resetweather(struct ScriptContext *ctx) +{ + sub_80806E4(); + return FALSE; +} + +bool8 ScrCmd_doweather(struct ScriptContext *ctx) +{ + DoCurrentWeather(); + return FALSE; +} + +bool8 ScrCmd_tileeffect(struct ScriptContext *ctx) +{ + ActivatePerStepCallback(ScriptReadByte(ctx)); + return FALSE; +} + +bool8 ScrCmd_setmaplayoutindex(struct ScriptContext *ctx) +{ + u16 value = VarGet(ScriptReadHalfword(ctx)); + + sub_8053D14(value); + return FALSE; +} + +bool8 ScrCmd_warp(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y); + sub_8080E88(); + player_avatar_init_params_reset(); + return TRUE; +} + +bool8 ScrCmd_warpsilent(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y); + sp13E_warp_to_last_warp(); + player_avatar_init_params_reset(); + return TRUE; +} + +bool8 ScrCmd_warpdoor(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y); + sub_8080EF0(); + player_avatar_init_params_reset(); + return TRUE; +} + +bool8 ScrCmd_warphole(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u16 x; + u16 y; + + PlayerGetDestCoords(&x, &y); + if (mapGroup == 0xFF && mapNum == 0xFF) + sub_8053720(x - 7, y - 7); + else + Overworld_SetWarpDestination(mapGroup, mapNum, -1, x - 7, y - 7); + sp13F_fall_to_last_warp(); + player_avatar_init_params_reset(); + return TRUE; +} + +bool8 ScrCmd_warpteleport(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y); + sub_8080F68(); + player_avatar_init_params_reset(); + return TRUE; +} + +bool8 ScrCmd_setwarp(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + Overworld_SetWarpDestination(mapGroup, mapNum, warpId, x, y); + return FALSE; +} + +bool8 ScrCmd_setdynamicwarp(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + saved_warp2_set_2(0, mapGroup, mapNum, warpId, x, y); + return FALSE; +} + +bool8 ScrCmd_setdivewarp(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + sub_8053690(mapGroup, mapNum, warpId, x, y); + return FALSE; +} + +bool8 ScrCmd_setholewarp(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + sub_80536E4(mapGroup, mapNum, warpId, x, y); + return FALSE; +} + +bool8 ScrCmd_setescapewarp(struct ScriptContext *ctx) +{ + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 warpId = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + sub_805363C(mapGroup, mapNum, warpId, x, y); + return FALSE; +} + +bool8 ScrCmd_getplayerxy(struct ScriptContext *ctx) +{ + u16 *pX = GetVarPointer(ScriptReadHalfword(ctx)); + u16 *pY = GetVarPointer(ScriptReadHalfword(ctx)); + + *pX = gSaveBlock1.pos.x; + *pY = gSaveBlock1.pos.y; + return FALSE; +} + +bool8 ScrCmd_countpokemon(struct ScriptContext *ctx) +{ + gScriptResult = CalculatePlayerPartyCount(); + return FALSE; +} + +bool8 ScrCmd_playse(struct ScriptContext *ctx) +{ + PlaySE(ScriptReadHalfword(ctx)); + return FALSE; +} + +static bool8 WaitForSoundEffectFinish() +{ + if (!IsSEPlaying()) + return TRUE; + else + return FALSE; +} + +bool8 ScrCmd_waitse(struct ScriptContext *ctx) +{ + SetupNativeScript(ctx, WaitForSoundEffectFinish); + return TRUE; +} + +bool8 ScrCmd_playfanfare(struct ScriptContext *ctx) +{ + PlayFanfare(ScriptReadHalfword(ctx)); + return FALSE; +} + +static bool8 WaitForFanfareFinish() +{ + return IsFanfareTaskInactive(); +} + +bool8 ScrCmd_waitfanfare(struct ScriptContext *ctx) +{ + SetupNativeScript(ctx, WaitForFanfareFinish); + return TRUE; +} + +bool8 ScrCmd_playbgm(struct ScriptContext *ctx) +{ + u16 songId = ScriptReadHalfword(ctx); + bool8 val = ScriptReadByte(ctx); + + if (val == TRUE) + Overworld_SetSavedMusic(songId); + PlayNewMapMusic(songId); + return FALSE; +} + +bool8 ScrCmd_savebgm(struct ScriptContext *ctx) +{ + Overworld_SetSavedMusic(ScriptReadHalfword(ctx)); + return FALSE; +} + +bool8 ScrCmd_fadedefaultbgm(struct ScriptContext *ctx) +{ + Overworld_ChangeMusicToDefault(); + return FALSE; +} + +bool8 ScrCmd_fadenewbgm(struct ScriptContext *ctx) +{ + Overworld_ChangeMusicTo(ScriptReadHalfword(ctx)); + return FALSE; +} + +bool8 ScrCmd_fadeoutbgm(struct ScriptContext *ctx) +{ + u8 speed = ScriptReadByte(ctx); + + if (speed != 0) + FadeOutBGMTemporarily(4 * speed); + else + FadeOutBGMTemporarily(4); + SetupNativeScript(ctx, IsBGMPausedOrStopped); + return TRUE; +} + +bool8 ScrCmd_fadeinbgm(struct ScriptContext *ctx) +{ + u8 speed = ScriptReadByte(ctx); + + if (speed != 0) + FadeInBGM(4 * speed); + else + FadeInBGM(4); + return FALSE; +} + +bool8 ScrCmd_applymovement(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + void *movementScript = (void *)ScriptReadWord(ctx); + + ScriptMovement_StartObjectMovementScript(localId, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, movementScript); + sMovingNpcId = localId; + return FALSE; +} + +bool8 ScrCmd_applymovement_at(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + void *movementScript = (void *)ScriptReadWord(ctx); + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + + ScriptMovement_StartObjectMovementScript(localId, mapNum, mapGroup, movementScript); + sMovingNpcId = localId; + return FALSE; +} + +static bool8 WaitForMovementFinish(void) +{ + return ScriptMovement_IsObjectMovementFinished(sMovingNpcId, sMovingNpcMapId, sMovingNpcMapBank); +} + +bool8 ScrCmd_waitmovement(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + + if (localId != 0) + sMovingNpcId = localId; + sMovingNpcMapBank = gSaveBlock1.location.mapGroup; + sMovingNpcMapId = gSaveBlock1.location.mapNum; + SetupNativeScript(ctx, WaitForMovementFinish); + return TRUE; +} + +bool8 ScrCmd_waitmovement_at(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u8 mapBank; + u8 mapId; + + if (localId != 0) + sMovingNpcId = localId; + mapBank = ScriptReadByte(ctx); + mapId = ScriptReadByte(ctx); + sMovingNpcMapBank = mapBank; + sMovingNpcMapId = mapId; + SetupNativeScript(ctx, WaitForMovementFinish); + return TRUE; +} + +bool8 ScrCmd_removeobject(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + + RemoveFieldObjectByLocalIdAndMap(localId, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + return FALSE; +} + +bool8 ScrCmd_removeobject_at(struct ScriptContext *ctx) +{ + u16 objectId = VarGet(ScriptReadHalfword(ctx)); + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + + RemoveFieldObjectByLocalIdAndMap(objectId, mapNum, mapGroup); + return FALSE; +} + +bool8 ScrCmd_addobject(struct ScriptContext *ctx) +{ + u16 objectId = VarGet(ScriptReadHalfword(ctx)); + + show_sprite(objectId, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + return FALSE; +} + +bool8 ScrCmd_addobject_at(struct ScriptContext *ctx) +{ + u16 objectId = VarGet(ScriptReadHalfword(ctx)); + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + + show_sprite(objectId, mapNum, mapGroup); + return FALSE; +} + +bool8 ScrCmd_setobjectxy(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + sub_805C0F8(localId, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, x, y); + return FALSE; +} + +bool8 ScrCmd_setobjectxyperm(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + Overworld_SetMapObjTemplateCoords(localId, x, y); + return FALSE; +} + +bool8 ScrCmd_moveobjectoffscreen(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + + sub_805C78C(localId, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + return FALSE; +} + +bool8 ScrCmd_showobject(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + + npc_by_local_id_and_map_set_field_1_bit_x20(localId, mapNum, mapGroup, 0); + return FALSE; +} + +bool8 ScrCmd_hideobject(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + + npc_by_local_id_and_map_set_field_1_bit_x20(localId, mapNum, mapGroup, 1); + return FALSE; +} + +bool8 ScrCmd_setobjectpriority(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + u8 priority = ScriptReadByte(ctx); + + sub_805BCF0(localId, mapNum, mapGroup, priority + 83); + return FALSE; +} + +bool8 ScrCmd_resetobjectpriority(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u8 mapGroup = ScriptReadByte(ctx); + u8 mapNum = ScriptReadByte(ctx); + + sub_805BD48(localId, mapNum, mapGroup); + return FALSE; +} + +bool8 ScrCmd_faceplayer(struct ScriptContext *ctx) +{ + if (gMapObjects[gSelectedMapObject].active) + { + FieldObjectFaceOppositeDirection(&gMapObjects[gSelectedMapObject], + player_get_direction_lower_nybble()); + } + return FALSE; +} + +bool8 ScrCmd_turnobject(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u8 direction = ScriptReadByte(ctx); + + FieldObjectTurnByLocalIdAndMap(localId, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, direction); + return FALSE; +} + +bool8 ScrCmd_setobjectmovementtype(struct ScriptContext *ctx) +{ + u16 localId = VarGet(ScriptReadHalfword(ctx)); + u8 movementType = ScriptReadByte(ctx); + + Overworld_SetMapObjTemplateMovementType(localId, movementType); + return FALSE; +} + +bool8 ScrCmd_createvobject(struct ScriptContext *ctx) +{ + u8 graphicsId = ScriptReadByte(ctx); + u8 v2 = ScriptReadByte(ctx); + u16 x = VarGet(ScriptReadHalfword(ctx)); + u32 y = VarGet(ScriptReadHalfword(ctx)); + u8 elevation = ScriptReadByte(ctx); + u8 direction = ScriptReadByte(ctx); + + sub_805B410(graphicsId, v2, x, y, elevation, direction); + return FALSE; +} + +bool8 ScrCmd_turnvobject(struct ScriptContext *ctx) +{ + u8 v1 = ScriptReadByte(ctx); + u8 direction = ScriptReadByte(ctx); + + sub_8064990(v1, direction); + return FALSE; +} + +bool8 ScrCmd_lockall(struct ScriptContext *ctx) +{ + if (is_c1_link_related_active()) + { + return FALSE; + } + else + { + ScriptFreezeMapObjects(); + SetupNativeScript(ctx, sub_8064CFC); + return TRUE; + } +} + +bool8 ScrCmd_lock(struct ScriptContext *ctx) +{ + if (is_c1_link_related_active()) + { + return FALSE; + } + else + { + if (gMapObjects[gSelectedMapObject].active) + { + LockSelectedMapObject(); + SetupNativeScript(ctx, sub_8064DB4); + } + else + { + ScriptFreezeMapObjects(); + SetupNativeScript(ctx, sub_8064CFC); + } + return TRUE; + } +} + +bool8 ScrCmd_releaseall(struct ScriptContext *ctx) +{ + u8 objectId; + + HideFieldMessageBox(); + objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]); + sub_80A2178(); + UnfreezeMapObjects(); + return FALSE; +} + +bool8 ScrCmd_release(struct ScriptContext *ctx) +{ + u8 objectId; + + HideFieldMessageBox(); + if (gMapObjects[gSelectedMapObject].active) + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[gSelectedMapObject]); + objectId = GetFieldObjectIdByLocalIdAndMap(0xFF, 0, 0); + FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[objectId]); + sub_80A2178(); + UnfreezeMapObjects(); + return FALSE; +} + +bool8 ScrCmd_message(struct ScriptContext *ctx) +{ + u8 *msg = (u8 *)ScriptReadWord(ctx); + + if (msg == NULL) + msg = (u8 *)ctx->data[0]; + ShowFieldMessage(msg); + return FALSE; +} + +bool8 ScrCmd_messageautoscroll(struct ScriptContext *ctx) +{ + u8 *msg = (u8 *)ScriptReadWord(ctx); + + if (msg == NULL) + msg = (u8 *)ctx->data[0]; + ShowFieldAutoScrollMessage(msg); + return FALSE; +} + +bool8 ScrCmd_waitmessage(struct ScriptContext *ctx) +{ + SetupNativeScript(ctx, IsFieldMessageBoxHidden); + return TRUE; +} + +bool8 ScrCmd_closemessage(struct ScriptContext *ctx) +{ + HideFieldMessageBox(); + return FALSE; +} + +static bool8 WaitForAorBPress(void) +{ + if (gMain.newKeys & A_BUTTON) + return TRUE; + if (gMain.newKeys & B_BUTTON) + return TRUE; + return FALSE; +} + +bool8 ScrCmd_waitbutton(struct ScriptContext *ctx) +{ + SetupNativeScript(ctx, WaitForAorBPress); + return TRUE; +} + +bool8 ScrCmd_yesnobox(struct ScriptContext *ctx) +{ + u8 left = ScriptReadByte(ctx); + u8 top = ScriptReadByte(ctx); + + if (ScriptMenu_YesNo(left, top) == TRUE) + { + ScriptContext1_Stop(); + return TRUE; + } + else + { + return FALSE; + } +} + +bool8 ScrCmd_multichoice(struct ScriptContext *ctx) +{ + u8 left = ScriptReadByte(ctx); + u8 top = ScriptReadByte(ctx); + u8 multichoiceId = ScriptReadByte(ctx); + u8 ignoreBPress = ScriptReadByte(ctx); + + if (ScriptMenu_Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE) + { + ScriptContext1_Stop(); + return TRUE; + } + else + { + return FALSE; + } +} + +bool8 ScrCmd_multichoicedefault(struct ScriptContext *ctx) +{ + u8 left = ScriptReadByte(ctx); + u8 top = ScriptReadByte(ctx); + u8 multichoiceId = ScriptReadByte(ctx); + u8 defaultChoice = ScriptReadByte(ctx); + u8 ignoreBPress = ScriptReadByte(ctx); + + if (ScriptMenu_MultichoiceWithDefault(left, top, multichoiceId, ignoreBPress, defaultChoice) == TRUE) + { + ScriptContext1_Stop(); + return TRUE; + } + else + { + return FALSE; + } +} + +bool8 ScrCmd_drawbox(struct ScriptContext *ctx) +{ + u8 left = ScriptReadByte(ctx); + u8 top = ScriptReadByte(ctx); + u8 right = ScriptReadByte(ctx); + u8 bottom = ScriptReadByte(ctx); + + MenuDrawTextWindow(left, top, right, bottom); + return FALSE; +} + +bool8 ScrCmd_multichoicegrid(struct ScriptContext *ctx) +{ + u8 left = ScriptReadByte(ctx); + u8 top = ScriptReadByte(ctx); + u8 multichoiceId = ScriptReadByte(ctx); + u8 numColumns = ScriptReadByte(ctx); + u8 ignoreBPress = ScriptReadByte(ctx); + + if (ScriptMenu_MultichoiceGrid(left, top, multichoiceId, ignoreBPress, numColumns) == TRUE) + { + ScriptContext1_Stop(); + return TRUE; + } + else + { + return FALSE; + } +} + +bool8 ScrCmd_erasebox(struct ScriptContext *ctx) +{ + u8 left = ScriptReadByte(ctx); + u8 top = ScriptReadByte(ctx); + u8 right = ScriptReadByte(ctx); + u8 bottom = ScriptReadByte(ctx); + + MenuZeroFillWindowRect(left, top, right, bottom); + return FALSE; +} + +// unused +bool8 ScrCmd_drawboxtext(struct ScriptContext *ctx) +{ + u8 left = ScriptReadByte(ctx); + u8 top = ScriptReadByte(ctx); + u8 multichoiceId = ScriptReadByte(ctx); + u8 ignoreBPress = ScriptReadByte(ctx); + + if (Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE) + { + ScriptContext1_Stop(); + return TRUE; + } + else + { + return FALSE; + } +} + +bool8 ScrCmd_drawpokepic(struct ScriptContext *ctx) +{ + u16 species = VarGet(ScriptReadHalfword(ctx)); + u8 x = ScriptReadByte(ctx); + u8 y = ScriptReadByte(ctx); + + ScriptMenu_ShowPokemonPic(species, x, y); + return FALSE; +} + +bool8 ScrCmd_erasepokepic(struct ScriptContext *ctx) +{ + bool8 (*func)(void) = ScriptMenu_GetPicboxWaitFunc(); + + if (func == NULL) + return FALSE; + SetupNativeScript(ctx, func); + return TRUE; +} + +bool8 ScrCmd_drawcontestwinner(struct ScriptContext *ctx) +{ + u8 v1 = ScriptReadByte(ctx); + + if (v1) + sub_8106630(v1); + ShowContestWinner(); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_braillemessage(struct ScriptContext *ctx) +{ + u8 *ptr = (u8 *)ScriptReadWord(ctx); + + u8 v2 = ptr[0]; + u8 v3 = ptr[1]; + u8 v4 = ptr[2]; + u8 v5 = ptr[3]; + u8 v6 = ptr[4]; + u8 v7 = ptr[5]; + StringBraille(gStringVar4, ptr + 6); + MenuDrawTextWindow(v2, v3, v4, v5); + MenuPrint(gStringVar4, v6, v7); + return FALSE; +} + +bool8 ScrCmd_vmessage(struct ScriptContext *ctx) +{ + u32 v1 = ScriptReadWord(ctx); + + ShowFieldMessage((u8 *)(v1 - gUnknown_0202E8B0)); + return FALSE; +} + +bool8 ScrCmd_getspeciesname(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u16 species = VarGet(ScriptReadHalfword(ctx)); + + StringCopy(sScriptStringVars[stringVarIndex], gSpeciesNames[species]); + return FALSE; +} + +bool8 ScrCmd_getfirstpartypokename(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + + u8 *dest = sScriptStringVars[stringVarIndex]; + u8 partyIndex = GetLeadMonIndex(); + u32 species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL); + StringCopy(dest, gSpeciesNames[species]); + return FALSE; +} + +bool8 ScrCmd_getpartypokename(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u16 partyIndex = VarGet(ScriptReadHalfword(ctx)); + + GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, sScriptStringVars[stringVarIndex]); + StringGetEnd10(sScriptStringVars[stringVarIndex]); + return FALSE; +} + +bool8 ScrCmd_getitemname(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u16 itemId = VarGet(ScriptReadHalfword(ctx)); + + CopyItemName(itemId, sScriptStringVars[stringVarIndex]); + return FALSE; +} + +bool8 ScrCmd_getdecorname(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u16 decorId = VarGet(ScriptReadHalfword(ctx)); + + StringCopy(sScriptStringVars[stringVarIndex], gDecorations[decorId].name); + return FALSE; +} + +bool8 ScrCmd_getmovename(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u16 moveId = VarGet(ScriptReadHalfword(ctx)); + + StringCopy(sScriptStringVars[stringVarIndex], gMoveNames[moveId]); + return FALSE; +} + +bool8 ScrCmd_getnumberstring(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u16 v1 = VarGet(ScriptReadHalfword(ctx)); + u8 v2 = sub_80BF0B8(v1); + + ConvertIntToDecimalStringN(sScriptStringVars[stringVarIndex], v1, 0, v2); + return FALSE; +} + +bool8 ScrCmd_getstdstring(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u16 index = VarGet(ScriptReadHalfword(ctx)); + + StringCopy(sScriptStringVars[stringVarIndex], gUnknown_083CE048[index]); + return FALSE; +} + +bool8 ScrCmd_getstring(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u8 *text = (u8 *)ScriptReadWord(ctx); + + StringCopy(sScriptStringVars[stringVarIndex], text); + return FALSE; +} + +bool8 ScrCmd_vloadword(struct ScriptContext *ctx) +{ + u8 *ptr = (u8 *)(ScriptReadWord(ctx) - gUnknown_0202E8B0); + + StringExpandPlaceholders(gStringVar4, ptr); + return FALSE; +} + +bool8 ScrCmd_vgetstring(struct ScriptContext *ctx) +{ + u8 stringVarIndex = ScriptReadByte(ctx); + u32 addr = ScriptReadWord(ctx); + + u8 *src = (u8 *)(addr - gUnknown_0202E8B0); + u8 *dest = sScriptStringVars[stringVarIndex]; + StringCopy(dest, src); + return FALSE; +} + +bool8 ScrCmd_givepoke(struct ScriptContext *ctx) +{ + u16 species = VarGet(ScriptReadHalfword(ctx)); + u8 level = ScriptReadByte(ctx); + u16 item = VarGet(ScriptReadHalfword(ctx)); + u32 unkParam1 = ScriptReadWord(ctx); + u32 unkParam2 = ScriptReadWord(ctx); + u8 unkParam3 = ScriptReadByte(ctx); + + gScriptResult = ScriptGiveMon(species, level, item, unkParam1, unkParam2, unkParam3); + return FALSE; +} + +bool8 ScrCmd_giveegg(struct ScriptContext *ctx) +{ + u16 species = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = ScriptGiveEgg(species); + return FALSE; +} + +bool8 ScrCmd_setpokemove(struct ScriptContext *ctx) +{ + u8 partyIndex = ScriptReadByte(ctx); + u8 slot = ScriptReadByte(ctx); + u16 move = ScriptReadHalfword(ctx); + + ScriptSetMonMoveSlot(partyIndex, move, slot); + return FALSE; +} + +bool8 ScrCmd_checkpokemove(struct ScriptContext *ctx) +{ + u8 i; + u16 moveId = ScriptReadHalfword(ctx); + + gScriptResult = 6; + for (i = 0; i < 6; i++) + { + u16 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES, NULL); + if (!species) + break; + // UB: GetMonData() arguments don't match function definition + if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG) && pokemon_has_move(&gPlayerParty[i], moveId) == TRUE) + { + gScriptResult = i; + gSpecialVar_0x8004 = species; + break; + } + } + return FALSE; +} + +bool8 ScrCmd_givemoney(struct ScriptContext *ctx) +{ + u32 amount = ScriptReadWord(ctx); + u8 ignore = ScriptReadByte(ctx); + + if (!ignore) + AddMoney(&gSaveBlock1.money, amount); + return FALSE; +} + +bool8 ScrCmd_takemoney(struct ScriptContext *ctx) +{ + u32 amount = ScriptReadWord(ctx); + u8 ignore = ScriptReadByte(ctx); + + if (!ignore) + RemoveMoney(&gSaveBlock1.money, amount); + return FALSE; +} + +bool8 ScrCmd_checkmoney(struct ScriptContext *ctx) +{ + u32 amount = ScriptReadWord(ctx); + u8 ignore = ScriptReadByte(ctx); + + if (!ignore) + gScriptResult = IsEnoughMoney(gSaveBlock1.money, amount); + return FALSE; +} + +bool8 ScrCmd_showmoneybox(struct ScriptContext *ctx) +{ + u8 x = ScriptReadByte(ctx); + u8 y = ScriptReadByte(ctx); + u8 ignore = ScriptReadByte(ctx); + + if (!ignore) + OpenMoneyWindow(gSaveBlock1.money, x, y); + return FALSE; +} + +bool8 ScrCmd_hidemoneybox(struct ScriptContext *ctx) +{ + u8 x = ScriptReadByte(ctx); + u8 y = ScriptReadByte(ctx); + + CloseMoneyWindow(x, y); + return FALSE; +} + +bool8 ScrCmd_updatemoneybox(struct ScriptContext *ctx) +{ + u8 x = ScriptReadByte(ctx); + u8 y = ScriptReadByte(ctx); + u8 ignore = ScriptReadByte(ctx); + + if (!ignore) + UpdateMoneyWindow(gSaveBlock1.money, x, y); + return FALSE; +} + +bool8 ScrCmd_showcoinsbox(struct ScriptContext *ctx) +{ + u8 x = ScriptReadByte(ctx); + u8 y = ScriptReadByte(ctx); + + ShowCoinsWindow(gSaveBlock1.coins, x, y); + return FALSE; +} + +bool8 ScrCmd_hidecoinsbox(struct ScriptContext *ctx) +{ + u8 x = ScriptReadByte(ctx); + u8 y = ScriptReadByte(ctx); + + HideCoinsWindow(x, y); + return FALSE; +} + +bool8 ScrCmd_updatecoinsbox(struct ScriptContext *ctx) +{ + u8 x = ScriptReadByte(ctx); + u8 y = ScriptReadByte(ctx); + + UpdateCoinsWindow(gSaveBlock1.coins, x, y); + return FALSE; +} + +bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) +{ + ctx->scriptPtr = BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr); + return FALSE; +} + +bool8 ScrCmd_battlebegin(struct ScriptContext *ctx) +{ + BattleSetup_StartTrainerBattle(); + return TRUE; +} + +bool8 ScrCmd_ontrainerbattleend(struct ScriptContext *ctx) +{ + ctx->scriptPtr = BattleSetup_GetScriptAddrAfterBattle(); + return FALSE; +} + +bool8 ScrCmd_ontrainerbattleendgoto(struct ScriptContext *ctx) +{ + ctx->scriptPtr = BattleSetup_GetTrainerPostBattleScript(); + return FALSE; +} + +bool8 ScrCmd_checktrainerflag(struct ScriptContext *ctx) +{ + u16 index = VarGet(ScriptReadHalfword(ctx)); + + ctx->comparisonResult = HasTrainerAlreadyBeenFought(index); + return FALSE; +} + +bool8 ScrCmd_settrainerflag(struct ScriptContext *ctx) +{ + u16 index = VarGet(ScriptReadHalfword(ctx)); + + trainer_flag_set(index); + return FALSE; +} + +bool8 ScrCmd_cleartrainerflag(struct ScriptContext *ctx) +{ + u16 index = VarGet(ScriptReadHalfword(ctx)); + + trainer_flag_clear(index); + return FALSE; +} + +bool8 ScrCmd_setwildbattle(struct ScriptContext *ctx) +{ + u16 species = ScriptReadHalfword(ctx); + u8 level = ScriptReadByte(ctx); + u16 item = ScriptReadHalfword(ctx); + + CreateScriptedWildMon(species, level, item); + return FALSE; +} + +bool8 ScrCmd_dowildbattle(struct ScriptContext *ctx) +{ + BattleSetup_StartScriptedWildBattle(); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_pokemart(struct ScriptContext *ctx) +{ + void *ptr = (void *)ScriptReadWord(ctx); + + CreatePokemartMenu(ptr); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_pokemartdecor(struct ScriptContext *ctx) +{ + void *ptr = (void *)ScriptReadWord(ctx); + + CreateDecorationShop1Menu(ptr); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_pokemartbp(struct ScriptContext *ctx) +{ + void *ptr = (void *)ScriptReadWord(ctx); + + CreateDecorationShop2Menu(ptr); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_playslotmachine(struct ScriptContext *ctx) +{ + u8 v2 = VarGet(ScriptReadHalfword(ctx)); + + PlaySlotMachine(v2, c2_exit_to_overworld_1_continue_scripts_restart_music); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_plantberrytree(struct ScriptContext *ctx) +{ + u8 treeId = ScriptReadByte(ctx); + u8 berry = ScriptReadByte(ctx); + u8 growthStage = ScriptReadByte(ctx); + + if (berry == 0) + PlantBerryTree(treeId, 0, growthStage, FALSE); + else + PlantBerryTree(treeId, berry, growthStage, FALSE); + return FALSE; +} + +bool8 ScrCmd_getpricereduction(struct ScriptContext *ctx) +{ + u16 value = VarGet(ScriptReadHalfword(ctx)); + + gScriptResult = GetPriceReduction(value); + return FALSE; +} + +bool8 ScrCmd_choosecontestpkmn(struct ScriptContext *ctx) +{ + sub_80F99CC(); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_startcontest(struct ScriptContext *ctx) +{ + sub_80C48C8(); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_showcontestresults(struct ScriptContext *ctx) +{ + sub_80C4940(); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_contestlinktransfer(struct ScriptContext *ctx) +{ + sub_80C4980(gScriptContestCategory); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_dofieldeffect(struct ScriptContext *ctx) +{ + u16 effectId = VarGet(ScriptReadHalfword(ctx)); + + sFieldEffectScriptId = effectId; + FieldEffectStart(sFieldEffectScriptId); + return FALSE; +} + +bool8 ScrCmd_setfieldeffect(struct ScriptContext *ctx) +{ + u8 argNum = ScriptReadByte(ctx); + + gFieldEffectArguments[argNum] = (s16)VarGet(ScriptReadHalfword(ctx)); + return FALSE; +} + +static bool8 sub_8067B48() +{ + if (!FieldEffectActiveListContains(sFieldEffectScriptId)) + return TRUE; + else + return FALSE; +} + +bool8 ScrCmd_waitfieldeffect(struct ScriptContext *ctx) +{ + sFieldEffectScriptId = VarGet(ScriptReadHalfword(ctx)); + SetupNativeScript(ctx, sub_8067B48); + return TRUE; +} + +bool8 ScrCmd_sethealplace(struct ScriptContext *ctx) +{ + u16 healLocationId = VarGet(ScriptReadHalfword(ctx)); + + Overworld_SetHealLocationWarp(healLocationId); + return FALSE; +} + +bool8 ScrCmd_checkplayergender(struct ScriptContext *ctx) +{ + gScriptResult = gSaveBlock2.playerGender; + return FALSE; +} + +bool8 ScrCmd_playpokecry(struct ScriptContext *ctx) +{ + u16 species = VarGet(ScriptReadHalfword(ctx)); + u16 mode = VarGet(ScriptReadHalfword(ctx)); + + PlayCry5(species, mode); + return FALSE; +} + +bool8 ScrCmd_waitpokecry(struct ScriptContext *ctx) +{ + SetupNativeScript(ctx, IsCryFinished); + return TRUE; +} + +bool8 ScrCmd_setmaptile(struct ScriptContext *ctx) +{ + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + u16 tileId = VarGet(ScriptReadHalfword(ctx)); + u16 v8 = VarGet(ScriptReadHalfword(ctx)); + + x += 7; + y += 7; + if (!v8) + MapGridSetMetatileIdAt(x, y, tileId); + else + MapGridSetMetatileIdAt(x, y, tileId | 0xC00); + return FALSE; +} + +bool8 ScrCmd_opendoor(struct ScriptContext *ctx) +{ + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + x += 7; + y += 7; + PlaySE(GetDoorSoundEffect(x, y)); + FieldAnimateDoorOpen(x, y); + return FALSE; +} + +bool8 ScrCmd_closedoor(struct ScriptContext *ctx) +{ + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + x += 7; + y += 7; + FieldAnimateDoorClose(x, y); + return FALSE; +} + +static bool8 IsDoorAnimationStopped() +{ + if (!FieldIsDoorAnimationRunning()) + return TRUE; + else + return FALSE; +} + +bool8 ScrCmd_waitdooranim(struct ScriptContext *ctx) +{ + SetupNativeScript(ctx, IsDoorAnimationStopped); + return TRUE; +} + +bool8 ScrCmd_setdooropen(struct ScriptContext *ctx) +{ + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + x += 7; + y += 7; + FieldSetDoorOpened(x, y); + return FALSE; +} + +bool8 ScrCmd_setdoorclosed(struct ScriptContext *ctx) +{ + u16 x = VarGet(ScriptReadHalfword(ctx)); + u16 y = VarGet(ScriptReadHalfword(ctx)); + + x += 7; + y += 7; + FieldSetDoorClosed(x, y); + return FALSE; +} + +bool8 ScrCmd_addelevmenuitem(struct ScriptContext *ctx) +{ + u8 v3 = ScriptReadByte(ctx); + u16 v5 = VarGet(ScriptReadHalfword(ctx)); + u16 v7 = VarGet(ScriptReadHalfword(ctx)); + u16 v9 = VarGet(ScriptReadHalfword(ctx)); + + ScriptAddElevatorMenuItem(v3, v5, v7, v9); + return FALSE; +} + +bool8 ScrCmd_showelevmenu(struct ScriptContext *ctx) +{ + ScriptShowElevatorMenu(); + ScriptContext1_Stop(); + return TRUE; +} + +bool8 ScrCmd_checkcoins(struct ScriptContext *ctx) +{ + u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + *ptr = GetCoins(); + return FALSE; +} + +bool8 ScrCmd_givecoins(struct ScriptContext *ctx) +{ + u16 coins = VarGet(ScriptReadHalfword(ctx)); + + if (GiveCoins(coins) == TRUE) + gScriptResult = 0; + else + gScriptResult = 1; + return FALSE; +} + +bool8 ScrCmd_takecoins(struct ScriptContext *ctx) +{ + u16 coins = VarGet(ScriptReadHalfword(ctx)); + + if (TakeCoins(coins) == TRUE) + gScriptResult = 0; + else + gScriptResult = 1; + return FALSE; +} diff --git a/src/field/script_menu.c b/src/field/script_menu.c new file mode 100644 index 000000000..e25e74d8c --- /dev/null +++ b/src/field/script_menu.c @@ -0,0 +1,1178 @@ +#include "global.h" +#include "script.h" +#include "script_menu.h" +#include "event_data.h" +#include "field_effect.h" +#include "menu.h" +#include "palette.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "strings.h" +#include "task.h" + +// multichoice lists +const struct MenuAction MultichoiceList_00[] = +{ + {OtherText_Petalburg, NULL}, + {OtherText_Slateport, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_02[] = +{ + {OtherText_Enter, NULL}, + {OtherText_Info3, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_03[] = +{ + {OtherText_WhatsAContest, NULL}, + {OtherText_TypesOfContest, NULL}, + {OtherText_Ranks, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_04[] = +{ + {OtherText_CoolContest, NULL}, + {OtherText_BeautyContest, NULL}, + {OtherText_CuteContest, NULL}, + {OtherText_SmartContest, NULL}, + {OtherText_ToughContest, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_06[] = +{ + {OtherText_Decoration, NULL}, + {OtherText_PackUp, NULL}, + {OtherText_Registry, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_05[] = +{ + {OtherText_Decoration, NULL}, + {OtherText_PackUp, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_07[] = +{ + {OtherText_Register, NULL}, + {OtherText_Registry, NULL}, + {OtherText_Information, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_12[] = +{ + {OtherText_Mach, NULL}, + {OtherText_Acro, NULL}, +}; + +const struct MenuAction MultichoiceList_13[] = +{ + {OtherText_Poison, NULL}, + {OtherText_Paralysis, NULL}, + {OtherText_Sleep, NULL}, + {OtherText_Burn, NULL}, + {OtherText_Frozen, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_14[] = +{ + {OtherText_Dewford, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_16[] = +{ + {OtherText_SawIt, NULL}, + {OtherText_NotYet, NULL}, +}; + +const struct MenuAction MultichoiceList_17[] = +{ + {OtherText_Yes, NULL}, + {OtherText_No, NULL}, + {OtherText_Info3, NULL}, +}; + +const struct MenuAction MultichoiceList_18[] = +{ + {OtherText_SingleBattle, NULL}, + {OtherText_DoubleBattle, NULL}, + {OtherText_MultiBattle, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_19[] = +{ + {OtherText_Littleroot, NULL}, + {OtherText_Slateport, NULL}, + {OtherText_Lilycove, NULL}, +}; + +const struct MenuAction MultichoiceList_20[] = +{ + {OtherText_Yes, NULL}, + {OtherText_No, NULL}, + {OtherText_Info3, NULL}, +}; + +const struct MenuAction MultichoiceList_23[] = +{ + {OtherText_MakeAChallenge, NULL}, + {OtherText_ObtainInformation, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_24[] = +{ + {OtherText_Lv50_2, NULL}, + {OtherText_Lv100_2, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_25[] = +{ + {OtherText_Zigzagoon, NULL}, + {OtherText_Nincada, NULL}, + {OtherText_Poochyena, NULL}, +}; + +const struct MenuAction MultichoiceList_26[] = +{ + {OtherText_Nincada2, NULL}, + {OtherText_Lotad, NULL}, + {OtherText_Roselia, NULL}, +}; + +const struct MenuAction MultichoiceList_27[] = +{ + {OtherText_Shroomish, NULL}, + {OtherText_Nincada3, NULL}, + {OtherText_Surskit, NULL}, +}; + +const struct MenuAction MultichoiceList_28[] = +{ + {OtherText_Treecko, NULL}, + {OtherText_Torchic, NULL}, + {OtherText_Mudkip, NULL}, +}; + +const struct MenuAction MultichoiceList_29[] = +{ + {OtherText_Seedot, NULL}, + {OtherText_Shroomish2, NULL}, + {OtherText_Spinda, NULL}, +}; + +const struct MenuAction MultichoiceList_30[] = +{ + {OtherText_Shroomish3, NULL}, + {OtherText_Zigzagoon2, NULL}, + {OtherText_Wurmple, NULL}, +}; + +const struct MenuAction MultichoiceList_31[] = +{ + {OtherText_PokeBall, NULL}, + {OtherText_SuperPotion, NULL}, + {OtherText_SamePrice, NULL}, +}; + +const struct MenuAction MultichoiceList_32[] = +{ + {OtherText_Yen135, NULL}, + {OtherText_Yen155, NULL}, + {OtherText_Yen175, NULL}, +}; + +const struct MenuAction MultichoiceList_33[] = +{ + {OtherText_CostMore, NULL}, + {OtherText_CostLess, NULL}, + {OtherText_SamePrice2, NULL}, +}; + +const struct MenuAction MultichoiceList_34[] = +{ + {OtherText_MaleSymbol, NULL}, + {OtherText_FemaleSymbol, NULL}, + {OtherText_Neither, NULL}, +}; + +const struct MenuAction MultichoiceList_35[] = +{ + {OtherText_Males, NULL}, + {OtherText_Females, NULL}, + {OtherText_SameNumber, NULL}, +}; + +const struct MenuAction MultichoiceList_36[] = +{ + {OtherText_Male, NULL}, + {OtherText_Female, NULL}, + {OtherText_ItDepends, NULL}, +}; + +const struct MenuAction MultichoiceList_37[] = +{ + {OtherText_Six2, NULL}, + {OtherText_Eight2, NULL}, + {OtherText_Ten, NULL}, +}; + +const struct MenuAction MultichoiceList_38[] = +{ + {OtherText_One, NULL}, + {OtherText_Two, NULL}, + {OtherText_Three, NULL}, +}; + +const struct MenuAction MultichoiceList_39[] = +{ + {OtherText_Six, NULL}, + {OtherText_Seven, NULL}, + {OtherText_Eight, NULL}, +}; + +const struct MenuAction MultichoiceList_42[] = +{ + {OtherText_FreshWater, NULL}, + {OtherText_SodaPop, NULL}, + {OtherText_Lemonade, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_43[] = +{ + {OtherText_HowToRide, NULL}, + {OtherText_HowToTurn, NULL}, + {OtherText_SandySlopes, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_44[] = +{ + {OtherText_Wheelies, NULL}, + {OtherText_BunnyHops, NULL}, + {OtherText_Jumping, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_45[] = +{ + {OtherText_Satisfied, NULL}, + {OtherText_Dissatisfied, NULL}, +}; + +const struct MenuAction MultichoiceList_46[] = +{ + {OtherText_Deepseatooth, NULL}, + {OtherText_Deepseascale, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_47[] = +{ + {OtherText_BlueFlute2, NULL}, + {OtherText_YellowFlute2, NULL}, + {OtherText_RedFlute2, NULL}, + {OtherText_WhiteFlute2, NULL}, + {OtherText_BlackFlute2, NULL}, + {OtherText_GlassChair, NULL}, + {OtherText_GlassDesk, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_48[] = +{ + {OtherText_TreeckoDoll, NULL}, + {OtherText_TorchicDoll, NULL}, + {OtherText_MudkipDoll, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_55[] = +{ + {OtherText_TM32, NULL}, + {OtherText_TM29, NULL}, + {OtherText_TM35, NULL}, + {OtherText_TM24, NULL}, + {OtherText_TM13, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_49[] = +{ + {OtherText_50Coins, NULL}, + {OtherText_500Coins, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_50[] = +{ + {OtherText_Excellent, NULL}, + {OtherText_NotSoHot, NULL}, +}; + +const struct MenuAction MultichoiceList_52[] = +{ + {OtherText_Lilycove, NULL}, + {OtherText_BattleTower, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_53[] = +{ + {OtherText_Slateport, NULL}, + {OtherText_Lilycove, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_54[] = +{ + {OtherText_Right, NULL}, + {OtherText_Left, NULL}, +}; + +const struct MenuAction MultichoiceList_56[] = +{ + {OtherText_Slateport, NULL}, + {OtherText_BattleTower, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_57[] = +{ + {OtherText_1F_2, NULL}, + {OtherText_2F_2, NULL}, + {OtherText_3F_2, NULL}, + {OtherText_4F_2, NULL}, + {OtherText_5F_2, NULL}, +}; + +const struct MenuAction MultichoiceList_58[] = +{ + {OtherText_RedShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_59[] = +{ + {OtherText_YellowShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_60[] = +{ + {OtherText_RedShard, NULL}, + {OtherText_YellowShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_61[] = +{ + {OtherText_BlueShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_62[] = +{ + {OtherText_RedShard, NULL}, + {OtherText_BlueShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_63[] = +{ + {OtherText_YellowShard, NULL}, + {OtherText_BlueShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_64[] = +{ + {OtherText_RedShard, NULL}, + {OtherText_YellowShard, NULL}, + {OtherText_BlueShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_65[] = +{ + {OtherText_GreenShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_66[] = +{ + {OtherText_RedShard, NULL}, + {OtherText_GreenShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_67[] = +{ + {OtherText_YellowShard, NULL}, + {OtherText_GreenShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_68[] = +{ + {OtherText_RedShard, NULL}, + {OtherText_YellowShard, NULL}, + {OtherText_GreenShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_69[] = +{ + {OtherText_BlueShard, NULL}, + {OtherText_GreenShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_70[] = +{ + {OtherText_RedShard, NULL}, + {OtherText_BlueShard, NULL}, + {OtherText_GreenShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_71[] = +{ + {OtherText_YellowShard, NULL}, + {OtherText_BlueShard, NULL}, + {OtherText_GreenShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_72[] = +{ + {OtherText_RedShard, NULL}, + {OtherText_YellowShard, NULL}, + {OtherText_BlueShard, NULL}, + {OtherText_GreenShard, NULL}, + {gOtherText_CancelNoTerminator, NULL}, +}; + +const struct MenuAction MultichoiceList_01[] = +{ + {gOtherText_CancelNoTerminator, NULL}, +}; + +struct MultichoiceListStruct +{ + const struct MenuAction *list; + u8 count; +}; + +const struct MultichoiceListStruct gMultichoiceLists[] = +{ + {MultichoiceList_00, ARRAY_COUNT(MultichoiceList_00)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_02, ARRAY_COUNT(MultichoiceList_02)}, + {MultichoiceList_03, ARRAY_COUNT(MultichoiceList_03)}, + {MultichoiceList_04, ARRAY_COUNT(MultichoiceList_04)}, + {MultichoiceList_05, ARRAY_COUNT(MultichoiceList_05)}, + {MultichoiceList_06, ARRAY_COUNT(MultichoiceList_06)}, + {MultichoiceList_07, ARRAY_COUNT(MultichoiceList_07)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_12, ARRAY_COUNT(MultichoiceList_12)}, + {MultichoiceList_13, ARRAY_COUNT(MultichoiceList_13)}, + {MultichoiceList_14, ARRAY_COUNT(MultichoiceList_14)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_16, ARRAY_COUNT(MultichoiceList_16)}, + {MultichoiceList_17, ARRAY_COUNT(MultichoiceList_17)}, + {MultichoiceList_18, ARRAY_COUNT(MultichoiceList_18)}, + {MultichoiceList_19, ARRAY_COUNT(MultichoiceList_19)}, + {MultichoiceList_20, ARRAY_COUNT(MultichoiceList_20)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_23, ARRAY_COUNT(MultichoiceList_23)}, + {MultichoiceList_24, ARRAY_COUNT(MultichoiceList_24)}, + {MultichoiceList_25, ARRAY_COUNT(MultichoiceList_25)}, + {MultichoiceList_26, ARRAY_COUNT(MultichoiceList_26)}, + {MultichoiceList_27, ARRAY_COUNT(MultichoiceList_27)}, + {MultichoiceList_28, ARRAY_COUNT(MultichoiceList_28)}, + {MultichoiceList_29, ARRAY_COUNT(MultichoiceList_29)}, + {MultichoiceList_30, ARRAY_COUNT(MultichoiceList_30)}, + {MultichoiceList_31, ARRAY_COUNT(MultichoiceList_31)}, + {MultichoiceList_32, ARRAY_COUNT(MultichoiceList_32)}, + {MultichoiceList_33, ARRAY_COUNT(MultichoiceList_33)}, + {MultichoiceList_34, ARRAY_COUNT(MultichoiceList_34)}, + {MultichoiceList_35, ARRAY_COUNT(MultichoiceList_35)}, + {MultichoiceList_36, ARRAY_COUNT(MultichoiceList_36)}, + {MultichoiceList_37, ARRAY_COUNT(MultichoiceList_37)}, + {MultichoiceList_38, ARRAY_COUNT(MultichoiceList_38)}, + {MultichoiceList_39, ARRAY_COUNT(MultichoiceList_39)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_42, ARRAY_COUNT(MultichoiceList_42)}, + {MultichoiceList_43, ARRAY_COUNT(MultichoiceList_43)}, + {MultichoiceList_44, ARRAY_COUNT(MultichoiceList_44)}, + {MultichoiceList_45, ARRAY_COUNT(MultichoiceList_45)}, + {MultichoiceList_46, ARRAY_COUNT(MultichoiceList_46)}, + {MultichoiceList_47, ARRAY_COUNT(MultichoiceList_47)}, + {MultichoiceList_48, ARRAY_COUNT(MultichoiceList_48)}, + {MultichoiceList_49, ARRAY_COUNT(MultichoiceList_49)}, + {MultichoiceList_50, ARRAY_COUNT(MultichoiceList_50)}, + {MultichoiceList_01, ARRAY_COUNT(MultichoiceList_01)}, + {MultichoiceList_52, ARRAY_COUNT(MultichoiceList_52)}, + {MultichoiceList_53, ARRAY_COUNT(MultichoiceList_53)}, + {MultichoiceList_54, ARRAY_COUNT(MultichoiceList_54)}, + {MultichoiceList_55, ARRAY_COUNT(MultichoiceList_55)}, + {MultichoiceList_56, ARRAY_COUNT(MultichoiceList_56)}, + {MultichoiceList_57, ARRAY_COUNT(MultichoiceList_57)}, + {MultichoiceList_58, ARRAY_COUNT(MultichoiceList_58)}, + {MultichoiceList_59, ARRAY_COUNT(MultichoiceList_59)}, + {MultichoiceList_60, ARRAY_COUNT(MultichoiceList_60)}, + {MultichoiceList_61, ARRAY_COUNT(MultichoiceList_61)}, + {MultichoiceList_62, ARRAY_COUNT(MultichoiceList_62)}, + {MultichoiceList_63, ARRAY_COUNT(MultichoiceList_63)}, + {MultichoiceList_64, ARRAY_COUNT(MultichoiceList_64)}, + {MultichoiceList_65, ARRAY_COUNT(MultichoiceList_65)}, + {MultichoiceList_66, ARRAY_COUNT(MultichoiceList_66)}, + {MultichoiceList_67, ARRAY_COUNT(MultichoiceList_67)}, + {MultichoiceList_68, ARRAY_COUNT(MultichoiceList_68)}, + {MultichoiceList_69, ARRAY_COUNT(MultichoiceList_69)}, + {MultichoiceList_70, ARRAY_COUNT(MultichoiceList_70)}, + {MultichoiceList_71, ARRAY_COUNT(MultichoiceList_71)}, + {MultichoiceList_72, ARRAY_COUNT(MultichoiceList_72)}, +}; + +const u8 *const gUnknown_083CE048[] = +{ + OtherText_Cool2, + OtherText_Beauty3, + OtherText_Cute2, + OtherText_Smart2, + OtherText_Tough2, + OtherText_Normal, + OtherText_Super, + OtherText_Hyper, + OtherText_Master, + OtherText_Cool3, + OtherText_Beauty4, + OtherText_Cute3, + OtherText_Smart3, + OtherText_Tough3, + OtherText_Items, + OtherText_KeyItems, + OtherText_Balls, + OtherText_TMsHMs, + OtherText_Berries, +}; + +extern u8 gPCText_WhichPCShouldBeAccessed[]; + +extern u16 gScriptResult; + +static void Task_HandleMultichoiceInput(u8); +static void Task_HandleYesNoInput(u8); +static void Task_HandleMultichoiceGridInput(u8); +static u16 GetStringWidthInTilesForScriptMenu(const u8 *str); +static void DrawMultichoiceMenu(u8, u8, u8, const struct MenuAction *list, u8, u8); +static void StartScriptMenuTask(u8, u8, u8, u8, u8, u8); +static void sub_80B53B4(u8, u8, u8, const struct MenuAction *list, u8); +static bool8 IsPicboxClosed(void); + +bool8 ScriptMenu_Multichoice(u8 left, u8 top, u8 multichoiceId, u8 ignoreBPress) +{ + if (FuncIsActiveTask(Task_HandleMultichoiceInput) == TRUE) + { + return FALSE; + } + else + { + gScriptResult = 0xFF; + DrawMultichoiceMenu(left, top, gMultichoiceLists[multichoiceId].count, gMultichoiceLists[multichoiceId].list, ignoreBPress, 0); + return TRUE; + } +} + +bool8 ScriptMenu_MultichoiceWithDefault(u8 left, u8 top, u8 multichoiceId, u8 ignoreBPress, u8 defaultChoice) +{ + if (FuncIsActiveTask(Task_HandleMultichoiceInput) == TRUE) + { + return FALSE; + } + else + { + gScriptResult = 0xFF; + DrawMultichoiceMenu(left, top, gMultichoiceLists[multichoiceId].count, gMultichoiceLists[multichoiceId].list, ignoreBPress, defaultChoice); + return TRUE; + } +} + +static u16 GetStringWidthInTilesForScriptMenu(const u8 *str) +{ + // each tile on screen is 8x8, so it needs the number of tiles and not pixels, hence the division by 8. + return (GetStringWidthGivenWindowConfig((struct WindowConfig *)&gWindowConfig_81E6CE4, str) + 7) / 8; +} + +static void DrawMultichoiceMenu(u8 left, u8 top, u8 count, const struct MenuAction *list, u8 ignoreBPress, u8 cursorPos) +{ + u16 width = GetStringWidthInTilesForScriptMenu(list[0].text); + u16 newWidth; + u8 i; + u8 right; + u8 bottom; + + for (i = 1; i < count; i++) + { + newWidth = GetStringWidthInTilesForScriptMenu(list[i].text); + if (width < newWidth) + width = newWidth; + } + + right = width; + right = (right + left) + 1; + + if (right > 29) + { + left = left + (29 - right); + right = 29; + } + + bottom = top + (2 * count + 1); + + MenuDrawTextWindow(left, top, right, bottom); + PrintMenuItems(left + 1, top + 1, count, list); + InitMenu(0, left + 1, top + 1, count, cursorPos, right - left - 1); + StartScriptMenuTask(left, top, right, bottom, ignoreBPress, count); +} + +#define tLeft data[0] +#define tTop data[1] +#define tRight data[2] +#define tBottom data[3] +#define tIgnoreBPress data[4] +#define tDoWrap data[5] + +static void StartScriptMenuTask(u8 left, u8 top, u8 right, u8 bottom, u8 ignoreBPress, u8 count) +{ + u8 taskId = CreateTask(Task_HandleMultichoiceInput, 80); + + gTasks[taskId].tLeft = left; + gTasks[taskId].tTop = top; + gTasks[taskId].tRight = right; + gTasks[taskId].tBottom = bottom; + gTasks[taskId].tIgnoreBPress = ignoreBPress; + + if (count > 3) + gTasks[taskId].tDoWrap = TRUE; + else + gTasks[taskId].tDoWrap = FALSE; +} + +static void Task_HandleMultichoiceInput(u8 taskId) +{ + s8 selection; + + if (!gPaletteFade.active) + { + if (!gTasks[taskId].tDoWrap) + selection = ProcessMenuInputNoWrap(); + else + selection = ProcessMenuInput(); + + if (selection != -2) + { + if (selection == -1) + { + if (gTasks[taskId].tIgnoreBPress) + return; + PlaySE(SE_SELECT); + gScriptResult = 127; + } + else + { + gScriptResult = selection; + } + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(gTasks[taskId].tLeft, gTasks[taskId].tTop, gTasks[taskId].tRight, gTasks[taskId].tBottom); + DestroyTask(taskId); + EnableBothScriptContexts(); + } + } +} + +bool8 Multichoice(u8 left, u8 top, u8 multichoiceId, u8 ignoreBPress) +{ + if (FuncIsActiveTask(Task_HandleMultichoiceInput) == TRUE) + { + return FALSE; + } + else + { + gScriptResult = 0xFF; + sub_80B53B4(left, top, gMultichoiceLists[multichoiceId].count, gMultichoiceLists[multichoiceId].list, ignoreBPress); + return TRUE; + } +} + +static void sub_80B53B4(u8 left, u8 top, u8 count, const struct MenuAction *list, u8 ignoreBPress) +{ + u16 width = GetStringWidthInTilesForScriptMenu(list[0].text); + u16 newWidth; + u8 i; + u8 right; + u8 bottom; + + for (i = 1; i < count; i++) + { + newWidth = GetStringWidthInTilesForScriptMenu(list[i].text); + if (width < newWidth) + width = newWidth; + } + + right = width; + right = (right + left) + 2; + bottom = top + (2 * count + 1); + + PrintMenuItems(left, top, count, list); + InitMenu(0, left, top, count, 0, right - left - 1); + StartScriptMenuTask(left, top, right, bottom, ignoreBPress, count); +} + +bool8 ScriptMenu_YesNo(u8 left, u8 top) +{ + u8 taskId; + + if (FuncIsActiveTask(Task_HandleYesNoInput) == TRUE) + { + return FALSE; + } + else + { + gScriptResult = 0xFF; + DisplayYesNoMenu(left, top, 1); + taskId = CreateTask(Task_HandleYesNoInput, 0x50); + gTasks[taskId].tLeft = left; + gTasks[taskId].tTop = top; + return TRUE; + } +} + +// unused +bool8 IsScriptActive(void) +{ + if (gScriptResult == 0xFF) + return FALSE; + else + return TRUE; +} + +static void Task_HandleYesNoInput(u8 taskId) +{ + u8 left, top; + + if (gTasks[taskId].tRight < 5) + { + gTasks[taskId].tRight++; + return; + } + + switch (ProcessMenuInputNoWrap()) + { + case -2: + return; + case -1: + case 1: + PlaySE(SE_SELECT); + gScriptResult = 0; + break; + case 0: + gScriptResult = 1; + break; + } + + left = gTasks[taskId].tLeft; + top = gTasks[taskId].tTop; + + MenuZeroFillWindowRect(left, top, left + 6, top + 5); + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +bool8 ScriptMenu_MultichoiceGrid(u8 left, u8 top, u8 multichoiceId, u8 ignoreBPress, u8 columnCount) +{ + u8 bottom = 0; + + if (FuncIsActiveTask(Task_HandleMultichoiceGridInput) == TRUE) + { + return FALSE; + } + else + { + u8 taskId; + u8 width; + + gScriptResult = 0xFF; + + sub_807274C(left, top, gMultichoiceLists[multichoiceId].count, 0, gMultichoiceLists[multichoiceId].list, columnCount, 0); + + taskId = CreateTask(Task_HandleMultichoiceGridInput, 80); + + if (!((gMultichoiceLists[multichoiceId].count >> 1) < columnCount || (gMultichoiceLists[multichoiceId].count & 1)) + || columnCount == 1 || gMultichoiceLists[multichoiceId].count == columnCount) + { + bottom = (2 * (gMultichoiceLists[multichoiceId].count / columnCount)) + 1 + top; + } + else + { + bottom = (2 * (gMultichoiceLists[multichoiceId].count / columnCount)) + 3 + top; + } + + width = sub_807288C(columnCount); + gTasks[taskId].tLeft = left; + gTasks[taskId].tTop = top; + gTasks[taskId].tRight = width + left + 2; + gTasks[taskId].tBottom = bottom; + gTasks[taskId].tIgnoreBPress = ignoreBPress; + return TRUE; + } +} + +static void Task_HandleMultichoiceGridInput(u8 taskId) +{ + s8 selection = sub_80727CC(); + + if (selection != -2) + { + if (selection == -1) + { + if (gTasks[taskId].tIgnoreBPress) + return; + PlaySE(SE_SELECT); + gScriptResult = 127; + } + else + { + gScriptResult = selection; + } + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(gTasks[taskId].tLeft, gTasks[taskId].tTop, gTasks[taskId].tRight, gTasks[taskId].tBottom); + DestroyTask(taskId); + EnableBothScriptContexts(); + } +} + +#undef tLeft +#undef tTop +#undef tRight +#undef tBottom +#undef tIgnoreBPress +#undef tDoWrap + +bool8 ScrSpecial_CreatePCMenu(void) +{ + if (FuncIsActiveTask(Task_HandleMultichoiceInput) == TRUE) + { + return FALSE; + } + else + { + gScriptResult = 0xFF; + ScriptMenu_CreatePCMenu(); + return TRUE; + } +} + +#if ENGLISH +void ScriptMenu_CreatePCMenu(void) +{ + u16 playersPCWidth = GetStringWidthInTilesForScriptMenu(gPCText_PlayersPC); + u8 width; + u8 numChoices; + + if (playersPCWidth > GetStringWidthInTilesForScriptMenu(gPCText_SomeonesPC)) + width = playersPCWidth; + else + width = 8; + + if (FlagGet(SYS_GAME_CLEAR)) // player has cleared game? + { + numChoices = 4; + MenuDrawTextWindow(0, 0, width + 2, 9); + MenuPrint(gPCText_HallOfFame, 1, 5); + MenuPrint(gPCText_LogOff, 1, 7); + } + else + { + numChoices = 3; + MenuDrawTextWindow(0, 0, width + 2, 7); + MenuPrint(gPCText_LogOff, 1, 5); + } + + if (FlagGet(SYS_PC_LANETTE)) // player met lanette? + MenuPrint(gPCText_LanettesPC, 1, 1); + else + MenuPrint(gPCText_SomeonesPC, 1, 1); + + MenuPrint(gPCText_PlayersPC, 1, 3); + InitMenu(0, 1, 1, numChoices, 0, width + 1); + StartScriptMenuTask(0, 0, width + 2, 2 * numChoices + 1, 0, numChoices); +} +#elif GERMAN +__attribute__((naked)) +void ScriptMenu_CreatePCMenu(void) { + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + sub sp, 0x18\n\ + ldr r0, _080B5748 @ =0x0000084b\n\ + bl FlagGet\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080B5750\n\ + ldr r0, _080B574C @ =gPCText_LanettesPC\n\ + b _080B5752\n\ + .align 2, 0\n\ +_080B5748: .4byte 0x0000084b\n\ +_080B574C: .4byte gPCText_LanettesPC\n\ +_080B5750:\n\ + ldr r0, _080B57E8 @ =gPCText_SomeonesPC\n\ +_080B5752:\n\ + bl GetStringWidthInTilesForScriptMenu\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [sp, 0x8]\n\ + movs r4, 0x1\n\ + ldr r0, _080B57EC @ =gPCText_PlayersPC\n\ + bl GetStringWidthInTilesForScriptMenu\n\ + lsls r1, r4, 2\n\ + add r1, sp\n\ + adds r1, 0x8\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [r1]\n\ + ldr r0, _080B57F0 @ =gPCText_LogOff\n\ + bl GetStringWidthInTilesForScriptMenu\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [sp, 0x10]\n\ + movs r4, 0x3\n\ + ldr r0, _080B57F4 @ =0x00000804\n\ + bl FlagGet\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080B5798\n\ + ldr r0, _080B57F8 @ =gPCText_HallOfFame\n\ + bl GetStringWidthInTilesForScriptMenu\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + str r0, [sp, 0x14]\n\ + movs r4, 0x4\n\ +_080B5798:\n\ + movs r5, 0\n\ + cmp r5, r4\n\ + bge _080B57B4\n\ + add r2, sp, 0x8\n\ + adds r1, r4, 0\n\ +_080B57A2:\n\ + ldr r0, [r2]\n\ + cmp r5, r0\n\ + bge _080B57AC\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ +_080B57AC:\n\ + adds r2, 0x4\n\ + subs r1, 0x1\n\ + cmp r1, 0\n\ + bne _080B57A2\n\ +_080B57B4:\n\ + ldr r0, _080B57F4 @ =0x00000804\n\ + bl FlagGet\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080B57FC\n\ + movs r7, 0x4\n\ + adds r4, r5, 0x2\n\ + lsls r2, r4, 24\n\ + lsrs r2, 24\n\ + movs r0, 0\n\ + movs r1, 0\n\ + movs r3, 0x9\n\ + bl MenuDrawTextWindow\n\ + ldr r0, _080B57F8 @ =gPCText_HallOfFame\n\ + movs r1, 0x1\n\ + movs r2, 0x5\n\ + bl MenuPrint\n\ + ldr r0, _080B57F0 @ =gPCText_LogOff\n\ + movs r1, 0x1\n\ + movs r2, 0x7\n\ + bl MenuPrint\n\ + b _080B5818\n\ + .align 2, 0\n\ +_080B57E8: .4byte gPCText_SomeonesPC\n\ +_080B57EC: .4byte gPCText_PlayersPC\n\ +_080B57F0: .4byte gPCText_LogOff\n\ +_080B57F4: .4byte 0x00000804\n\ +_080B57F8: .4byte gPCText_HallOfFame\n\ +_080B57FC:\n\ + movs r7, 0x3\n\ + adds r4, r5, 0x2\n\ + lsls r2, r4, 24\n\ + lsrs r2, 24\n\ + movs r0, 0\n\ + movs r1, 0\n\ + movs r3, 0x7\n\ + bl MenuDrawTextWindow\n\ + ldr r0, _080B5834 @ =gPCText_LogOff\n\ + movs r1, 0x1\n\ + movs r2, 0x5\n\ + bl MenuPrint\n\ +_080B5818:\n\ + adds r6, r4, 0\n\ + ldr r0, _080B5838 @ =0x0000084b\n\ + bl FlagGet\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080B5840\n\ + ldr r0, _080B583C @ =gPCText_LanettesPC\n\ + movs r1, 0x1\n\ + movs r2, 0x1\n\ + bl MenuPrint\n\ + b _080B584A\n\ + .align 2, 0\n\ +_080B5834: .4byte gPCText_LogOff\n\ +_080B5838: .4byte 0x0000084b\n\ +_080B583C: .4byte gPCText_LanettesPC\n\ +_080B5840:\n\ + ldr r0, _080B5888 @ =gPCText_SomeonesPC\n\ + movs r1, 0x1\n\ + movs r2, 0x1\n\ + bl MenuPrint\n\ +_080B584A:\n\ + ldr r0, _080B588C @ =gPCText_PlayersPC\n\ + movs r1, 0x1\n\ + movs r2, 0x3\n\ + bl MenuPrint\n\ + movs r4, 0\n\ + str r4, [sp]\n\ + adds r0, r5, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + str r0, [sp, 0x4]\n\ + movs r0, 0\n\ + movs r1, 0x1\n\ + movs r2, 0x1\n\ + adds r3, r7, 0\n\ + bl InitMenu\n\ + lsls r2, r6, 24\n\ + lsrs r2, 24\n\ + lsls r3, r7, 1\n\ + adds r3, 0x1\n\ + str r4, [sp]\n\ + str r7, [sp, 0x4]\n\ + movs r0, 0\n\ + movs r1, 0\n\ + bl StartScriptMenuTask\n\ + add sp, 0x18\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080B5888: .4byte gPCText_SomeonesPC\n\ +_080B588C: .4byte gPCText_PlayersPC\n\ + .syntax divided\n"); +} +#endif + +void ScriptMenu_DisplayPCStartupPrompt(void) +{ + MenuDisplayMessageBox(); + MenuPrint(gPCText_WhichPCShouldBeAccessed, 2, 15); +} + +#define tState data[0] +#define tMonSpecies data[1] +#define tMonSpriteId data[2] +#define tWindowX data[3] +#define tWindowY data[4] + +static void Task_PokemonPicWindow(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->tState) + { + case 0: + task->tState++; + break; + case 1: + break; + case 2: + FreeResourcesAndDestroySprite(&gSprites[task->tMonSpriteId]); + task->tState++; + break; + case 3: + MenuZeroFillWindowRect(task->tWindowX, task->tWindowY, task->tWindowX + 9, task->tWindowY + 10); + DestroyTask(taskId); + break; + } +} + +bool8 ScriptMenu_ShowPokemonPic(u16 species, u8 x, u8 y) +{ + u8 taskId; + u8 spriteId; + + if (FindTaskIdByFunc(Task_PokemonPicWindow) != 0xFF) + { + return FALSE; + } + else + { + MenuDrawTextWindow(x, y, x + 9, y + 10); + taskId = CreateTask(Task_PokemonPicWindow, 0x50); + gTasks[taskId].tState = 0; + gTasks[taskId].tMonSpecies = species; + spriteId = CreateMonSprite_PicBox(species, x * 8 + 40, y * 8 + 40, 0); + gTasks[taskId].tMonSpriteId = spriteId; + gTasks[taskId].tWindowX = x; + gTasks[taskId].tWindowY = y; + gSprites[spriteId].callback = SpriteCallbackDummy; + gSprites[spriteId].oam.priority = 0; + return TRUE; + } +} + +bool8 (*ScriptMenu_GetPicboxWaitFunc(void))(void) +{ + u8 taskId = FindTaskIdByFunc(Task_PokemonPicWindow); + + if (taskId == 0xFF) + return NULL; + gTasks[taskId].tState++; + return IsPicboxClosed; +} + +static bool8 IsPicboxClosed(void) +{ + if (FindTaskIdByFunc(Task_PokemonPicWindow) == 0xFF) + return TRUE; + else + return FALSE; +} + +#undef tState +#undef tMonSpecies +#undef tMonSpriteId +#undef tWindowX +#undef tWindowY diff --git a/src/field/script_movement.c b/src/field/script_movement.c new file mode 100644 index 000000000..30e10b451 --- /dev/null +++ b/src/field/script_movement.c @@ -0,0 +1,228 @@ +#include "global.h" +#include "script_movement.h" +#include "field_map_obj.h" +#include "field_map_obj_helpers.h" +#include "task.h" +#include "util.h" + +static EWRAM_DATA u8 *gUnknown_020384F8[16] = {0}; + +static void sub_80A2198(u8); +static u8 sub_80A21E0(void); +static bool8 sub_80A21F4(u8, u8, u8 *); +static u8 sub_80A2260(u8, u8); +static bool8 sub_80A2370(u8, u8); +static void sub_80A23C8(u8, u8, u8, u8 *); +static void UnfreezeObjects(u8); +static void Task_80A244C(u8); +static void sub_80A2490(u8, u8, u8, u8 *); + +bool8 ScriptMovement_StartObjectMovementScript(u8 localId, u8 mapNum, u8 mapGroup, u8 *movementScript) +{ + u8 mapObjId; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapGroup, &mapObjId)) + return TRUE; + if (!FuncIsActiveTask(Task_80A244C)) + sub_80A2198(50); + return sub_80A21F4(sub_80A21E0(), mapObjId, movementScript); +} + +bool8 ScriptMovement_IsObjectMovementFinished(u8 localId, u8 mapNum, u8 mapBank) +{ + u8 mapObjId; + u8 r4; + u8 r1; + + if (TryGetFieldObjectIdByLocalIdAndMap(localId, mapNum, mapBank, &mapObjId)) + return TRUE; + r4 = sub_80A21E0(); + r1 = sub_80A2260(r4, mapObjId); + if (r1 == 16) + return TRUE; + return sub_80A2370(r4, r1); +} + +void sub_80A2178(void) +{ + u8 taskId; + + taskId = sub_80A21E0(); + if (taskId != 0xFF) + { + UnfreezeObjects(taskId); + DestroyTask(taskId); + } +} + +static void sub_80A2198(u8 priority) +{ + u8 taskId; + u8 i; + + taskId = CreateTask(Task_80A244C, priority); + for (i = 1; i < 16; i++) + gTasks[taskId].data[i] = 0xFFFF; +} + +static u8 sub_80A21E0(void) +{ + return FindTaskIdByFunc(Task_80A244C); +} + +static bool8 sub_80A21F4(u8 taskId, u8 mapObjId, u8 *movementScript) +{ + u8 r4; + + r4 = sub_80A2260(taskId, mapObjId); + if (r4 != 16) + { + if (sub_80A2370(taskId, r4) == 0) + { + return TRUE; + } + else + { + sub_80A23C8(taskId, r4, mapObjId, movementScript); + return FALSE; + } + } + r4 = sub_80A2260(taskId, 0xFF); + if (r4 == 16) + { + return TRUE; + } + else + { + sub_80A23C8(taskId, r4, mapObjId, movementScript); + return FALSE; + } +} + +static u8 sub_80A2260(u8 taskId, u8 b) +{ + u8 *ptr; + u8 i; + + ptr = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < 16; i++, ptr++) + { + if (*ptr == b) + return i; + } + return 16; +} + +static void sub_80A229C(u8 taskId, u8 b, u8 **c) +{ + u8 i; + + *c = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < b; i++, (*c)++) + ; +} + +static void sub_80A22D0(u8 taskId, u8 b, u8 c) +{ + u8 *ptr; + + sub_80A229C(taskId, b, &ptr); + *ptr = c; //what is this supposed to do? +} + +static void sub_80A22F4(u8 taskId, u8 b, u8 *c) +{ + u8 *ptr; + + sub_80A229C(taskId, b, &ptr); + *c = *ptr; +} + +static void sub_80A2318(u8 a, u8 b) +{ + u16 var = ~gBitTable[b]; + + gTasks[a].data[0] &= var; +} + +static void sub_80A2348(u8 taskId, u8 b) +{ + gTasks[taskId].data[0] |= gBitTable[b]; +} + +static bool8 sub_80A2370(u8 taskId, u8 b) +{ + u16 var = (u16)gTasks[taskId].data[0] & gBitTable[b]; + + if (var != 0) + return TRUE; + else + return FALSE; +} + +static void npc_obj_offscreen_culling_and_flag_update(u8 a, u8 *movementScript) +{ + gUnknown_020384F8[a] = movementScript; +} + +static u8 *sub_80A23B8(u8 a) +{ + return gUnknown_020384F8[a]; +} + +static void sub_80A23C8(u8 taskId, u8 b, u8 mapObjId, u8 *movementScript) +{ + sub_80A2318(taskId, b); + npc_obj_offscreen_culling_and_flag_update(b, movementScript); + sub_80A22D0(taskId, b, mapObjId); +} + +static void UnfreezeObjects(u8 taskId) +{ + u8 *pMapObjId; + u8 i; + + pMapObjId = (u8 *)&gTasks[taskId].data[1]; + for (i = 0; i < 16; i++, pMapObjId++) + { + if (*pMapObjId != 0xFF) + UnfreezeMapObject(&gMapObjects[*pMapObjId]); + } +} + +static void Task_80A244C(u8 taskId) +{ + u8 i; + u8 var; + + for (i = 0; i < 16; i++) + { + sub_80A22F4(taskId, i, &var); + if (var != 0xFF) + sub_80A2490(taskId, i, var, sub_80A23B8(i)); + } +} + +static void sub_80A2490(u8 taskId, u8 b, u8 mapObjId, u8 *d) +{ + u8 var; + + if (FieldObjectIsSpecialAnimActive(&gMapObjects[mapObjId]) + && !FieldObjectClearAnimIfSpecialAnimFinished(&gMapObjects[mapObjId])) + return; + + var = *d; + if (var == 0xFE) + { + sub_80A2348(taskId, b); + FreezeMapObject(&gMapObjects[mapObjId]); + } + else + { + if (!FieldObjectSetSpecialAnim(&gMapObjects[mapObjId], var)) + { + d++; + npc_obj_offscreen_culling_and_flag_update(b, d); + } + } +} diff --git a/src/field/secret_base.c b/src/field/secret_base.c new file mode 100644 index 000000000..f221d7f16 --- /dev/null +++ b/src/field/secret_base.c @@ -0,0 +1,1075 @@ +#include "global.h" +#include "secret_base.h" +#include "decoration.h" +#include "event_data.h" +#include "field_camera.h" +#include "field_fadetransition.h" +#include "field_player_avatar.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "main.h" +#include "map_constants.h" +#include "map_name_popup.h" +#include "menu.h" +#include "metatile_behavior.h" +#include "palette.h" +#include "pokemon.h" +#include "overworld.h" +#include "script.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "text.h" +#include "vars.h" + +extern u8 gUnknown_020387DC; +extern u16 gSpecialVar_0x8004; +extern u16 gSpecialVar_0x8005; +extern u16 gSpecialVar_0x8006; +extern u16 gSpecialVar_0x8007; +extern u16 gScriptResult; +extern const struct +{ + u16 unk_083D1358_0; + u16 unk_083D1358_1; +} gUnknown_083D1358[7]; +extern const u8 gUnknown_083D1374[4 * 16]; +extern void *gUnknown_0300485C; +extern const u8 gUnknown_083D13EC[12]; +extern u8 gUnknown_081A2E14[]; + + +void sub_80BB4AC(struct SecretBaseRecord *record) // 080bb4ac +{ + u16 i; + u16 j; + record->sbr_field_0 = 0; + for (i=0; i<7; i++) + record->sbr_field_2[i] = 0xff; + for (i=0; i<4; i++) + record->trainerId[i] = 0x00; + record->sbr_field_e = 0; + record->sbr_field_10 = 0; + record->sbr_field_11 = 0; + record->sbr_field_1_0 = 0; + record->gender = 0; + record->sbr_field_1_5 = 0; + record->sbr_field_1_6 = 0; + for (i=0; i<16; i++) { + record->decorations[i] = 0; + record->decorationPos[i] = 0; + } + for (i=0; i<6; i++) { + for (j=0; j<4; j++) { + record->partyMoves[i * 4 + j] = 0; + } + record->partyPersonality[i] = 0; + record->partyEVs[i] = 0; + record->partySpecies[i] = 0; + record->partyHeldItems[i] = 0; + record->partyLevels[i] = 0; + } +} + +void ResetSecretBase(u8 idx) // 80bb594 +{ + sub_80BB4AC(&(gSaveBlock1.secretBases[idx])); +} + +void ResetSecretBases(void) // 080bb5b4 +{ + u16 i; + for (i=0; i<20; i++) + ResetSecretBase(i); +} + +void sub_80BB5D0(void) // 080bb5d0 +{ + gUnknown_020387DC = gSpecialVar_0x8004; +} + +void sub_80BB5E4(void) // 80bb5e4 +{ + u16 idx; + gScriptResult = 0; + for (idx=0; idx<20; idx++) { + if (gUnknown_020387DC != gSaveBlock1.secretBases[idx].sbr_field_0) + continue; + gScriptResult = 1; + VarSet(VAR_0x4054, idx); + break; + } +} + +void sub_80BB63C(void) // 80bb63c +{ + if (gSaveBlock1.secretBases[0].sbr_field_0) + gScriptResult = 1; + else + gScriptResult = 0; +} + +u8 sub_80BB66C(void) // 80bb66c +{ + s16 x, y; + s16 v0; + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + v0 = MapGridGetMetatileBehaviorAt(x, y) & 0xFFF; + if (v0 == 0x90 || v0 == 0x91) + return 1; + else if (v0 == 0x92 || v0 == 0x93) + return 2; + else if (v0 == 0x9a || v0 == 0x9b) + return 3; + else if (v0 == 0x94 || v0 == 0x95) + return 4; + else if (v0 == 0x96 || v0 == 0x97 || v0 == 0x9c || v0 == 0x9d) + return 5; + else if (v0 == 0x98 || v0 == 0x99) + return 6; + return 0; +} + +void sub_80BB70C(void) // 80bb70c +{ + gSpecialVar_0x8007 = sub_80BB66C(); +} + +s16 unref_sub_80BB724(u16 *a0, u8 a1) +{ + u16 v2; + for (v2=0; v2<0x200; v2++) { + if ((a0[v2] & 0xFFF) == a1) + return (s16)v2; + } + return -1; +} + +void sub_80BB764(s16 *arg1, s16 *arg2, u16 arg3) +{ + s16 x, y; + for (y=0; y<gMapHeader.mapData->height; y++) { + for (x=0; x<gMapHeader.mapData->width; x++) { + if ((gMapHeader.mapData->map[y * gMapHeader.mapData->width + x] & 0x3ff) == arg3) { + *arg1 = x; + *arg2 = y; + return; + } + } + } +} + +void sub_80BB800(void) +{ + s16 x, y; + s16 tile_id; + u16 idx; + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + tile_id = MapGridGetMetatileIdAt(x, y); + for (idx=0; idx<7; idx++) { + if (gUnknown_083D1358[idx].unk_083D1358_0 == tile_id) { + MapGridSetMetatileIdAt(x, y, gUnknown_083D1358[idx].unk_083D1358_1 | 0xc00); + CurrentMapDrawMetatileAt(x, y); + return; + } + } + for (idx=0; idx<7; idx++) { + if (gUnknown_083D1358[idx].unk_083D1358_1 == tile_id) { + MapGridSetMetatileIdAt(x, y, gUnknown_083D1358[idx].unk_083D1358_0 | 0xc00); + CurrentMapDrawMetatileAt(x, y); + return; + } + } +} + +u8 sub_80BB8A8(u8 *arg1) +{ + u8 idx; + for (idx=0; idx<7; idx++) { + if (arg1[idx] == EOS) + return idx; + } + return 7; +} + +void sub_80BB8CC(void) +{ + u8 nameLength; + u16 idx; + gSaveBlock1.secretBases[0].sbr_field_0 = gUnknown_020387DC; + for (idx=0; idx<4; idx++) { + gSaveBlock1.secretBases[0].trainerId[idx] = gSaveBlock2.playerTrainerId[idx]; + } + VarSet(VAR_0x4054, 0); + nameLength = sub_80BB8A8(gSaveBlock2.playerName); + memset(gSaveBlock1.secretBases[0].sbr_field_2, 0xFF, 7); + StringCopyN(gSaveBlock1.secretBases[0].sbr_field_2, gSaveBlock2.playerName, nameLength); + gSaveBlock1.secretBases[0].gender = gSaveBlock2.playerGender; + VarSet(VAR_SECRET_BASE_MAP, gMapHeader.regionMapSectionId); +} + +void sub_80BB970(struct MapEvents *events) +{ + u16 bgevidx, idx, jdx; + s16 tile_id; + for (bgevidx=0; bgevidx<events->bgEventCount; bgevidx++) { + if (events->bgEvents[bgevidx].kind == 8) { + for (jdx=0; jdx<20; jdx++) { + if (gSaveBlock1.secretBases[jdx].sbr_field_0 == events->bgEvents[bgevidx].bgUnion.secretBaseId) { + tile_id = MapGridGetMetatileIdAt(events->bgEvents[bgevidx].x + 7, events->bgEvents[bgevidx].y + 7); + for (idx=0; idx<7; idx++) { + if (gUnknown_083D1358[idx].unk_083D1358_0 == tile_id) { + MapGridSetMetatileIdAt(events->bgEvents[bgevidx].x + 7, events->bgEvents[bgevidx].y + 7, gUnknown_083D1358[idx].unk_083D1358_1 | 0xc00); + break; + } + } + break; + } + } + } + } +} + +void sub_80BBA14(void) +{ + s8 idx = 4 * (gUnknown_020387DC / 10); + warp1_set_2(MAP_GROUP_SECRET_BASE_RED_CAVE1, gUnknown_083D1374[idx], gUnknown_083D1374[idx + 1]); +} + +void sub_80BBA48(u8 taskid) +{ + u16 curbaseid; + switch (gTasks[taskid].data[0]) { + case 0: + gTasks[taskid].data[0] = 1; + break; + case 1: + if (!gPaletteFade.active) { + gTasks[taskid].data[0] = 2; + } + break; + case 2: + curbaseid = VarGet(VAR_0x4054); + if (gSaveBlock1.secretBases[curbaseid].sbr_field_10 < 0xff) + gSaveBlock1.secretBases[curbaseid].sbr_field_10 ++; + sub_80BBA14(); + warp_in(); + gFieldCallback = sub_8080990; + SetMainCallback2(CB2_LoadMap); + DestroyTask(taskid); + break; + } +} + +void sub_80BBAF0(void) +{ + CreateTask(sub_80BBA48, 0); + fade_screen(1, 0); + saved_warp2_set(0, gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum, -1); +} + +bool8 sub_80BBB24(void) +{ + if (gMapHeader.mapType == MAP_TYPE_SECRET_BASE && VarGet(VAR_0x4097) == 0) + return FALSE; + return TRUE; +} + +void sub_80BBB50(u8 taskid) +{ + FieldObjectTurn(&(gMapObjects[gPlayerAvatar.mapObjectId]), 2); + if (sub_807D770() == 1) { + EnableBothScriptContexts(); + DestroyTask(taskid); + } +} + +void sub_80BBB90(void) +{ + s16 x, y; + ScriptContext2_Enable(); + HideMapNamePopup(); + sub_80BB764(&x, &y, 0x220); + MapGridSetMetatileIdAt(x + 7, y + 7, 0xe20); + CurrentMapDrawMetatileAt(x + 7, y + 7); + pal_fill_black(); + CreateTask(sub_80BBB50, 0); +} + +void sub_80BBBEC(u8 taskid) +{ + s8 idx; + if (!gPaletteFade.active) { + idx = 4 * (gUnknown_020387DC / 10); + Overworld_SetWarpDestination(gSaveBlock1.location.mapGroup, gSaveBlock1.location.mapNum, -1, gUnknown_083D1374[idx + 2], gUnknown_083D1374[idx + 3]); + warp_in(); + gFieldCallback = sub_80BBB90; + SetMainCallback2(CB2_LoadMap); + DestroyTask(taskid); + } +} + +void sub_80BBC78(void) +{ + u8 taskid = CreateTask(sub_80BBBEC, 0); + gTasks[taskid].data[0] = 0; + fade_screen(1, 0); +} + +bool8 CurrentMapIsSecretBase(void) +{ + if (gSaveBlock1.location.mapGroup == MAP_GROUP_SECRET_BASE_SHRUB4 && (u8)(gSaveBlock1.location.mapNum) <= MAP_ID_SECRET_BASE_SHRUB4) + return TRUE; + return FALSE; +} + +#ifdef NONMATCHING +void sub_80BBCCC(u8 flagIn) +{ + u16 curBaseId; + u16 x, y; + if (CurrentMapIsSecretBase()) { + curBaseId = VarGet(VAR_0x4054); + for (x=0; x<16; x++) { + if ((u8)(gSaveBlock1.secretBases[curBaseId].decorations[x] - 1) <= 0x77 && gDecorations[gSaveBlock1.secretBases[curBaseId].decorations[x]].decor_field_11 != 4) { + sub_80FF394((gSaveBlock1.secretBases[0].decorationPos[x] >> 4) + 7, (gSaveBlock1.secretBases[0].decorationPos[x] & 0xF) + 7, gSaveBlock1.secretBases[curBaseId].decorations[x]); + } + } + if (curBaseId != 0) { + sub_80BB764(&x, &y, 0x220); + MapGridSetMetatileIdAt(x + 7, y + 7, 0xe21); + } else if (flagIn == 1 && VarGet(VAR_0x4089) == 1) { + sub_80BB764(&x, &y, 0x220); + MapGridSetMetatileIdAt(x + 7, y + 7, 0xe0a); + } + } +} + +void sub_80BBDD0(void) +{ + u8 *roomdecor; + u8 *roomdecorpos; + u8 ndecor; + u8 decidx; + u8 objid = 0; + u8 metatile; + u16 curBase = VarGet(VAR_0x4054); + if (!CurrentMapIsSecretBase()) { + roomdecor = gSaveBlock1.playerRoomDecor; + roomdecorpos = gSaveBlock1.playerRoomDecorPos; + ndecor = 12; + } else { + roomdecor = gSaveBlock1.secretBases[curBase].decorations; + roomdecorpos = gSaveBlock1.secretBases[curBase].decorationPos; + ndecor = 16; + } + for (decidx=0; decidx<ndecor; decidx++) { + if (roomdecor[decidx] == 0) + continue; + if (gDecorations[roomdecor[decidx]].decor_field_11 != 4) + continue; + for (objid=0; objid<gMapHeader.events->mapObjectCount; objid++) { + if (gMapHeader.events->mapObjects[objid].flagId == gSpecialVar_0x8004 + 0xAE) + break; + } + if (objid != gMapHeader.events->mapObjectCount) { + gSpecialVar_0x8006 = roomdecorpos[decidx] >> 4; + gSpecialVar_0x8007 = roomdecorpos[decidx] & 0xF; + metatile = MapGridGetMetatileBehaviorAt(gSpecialVar_0x8006 + 7, gSpecialVar_0x8007 + 7); + if (sub_80572D8(metatile) == 1 || sub_80572EC(metatile) == 1) { + gScriptResult = gMapHeader.events->mapObjects[objid].graphicsId + 0x3f20; + VarSet(gScriptResult, gDecorations[roomdecor[decidx]].tiles[0]); + gScriptResult = gMapHeader.events->mapObjects[objid].localId; + FlagClear(gSpecialVar_0x8004 + 0xAE); + show_sprite(gScriptResult, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + sub_805C0F8(gScriptResult, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup, gSpecialVar_0x8006, gSpecialVar_0x8007); + sub_805C78C(gScriptResult, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); + gSpecialVar_0x8004 ++; + } + } + } +} + +#else +__attribute__((naked)) +void sub_80BBCCC(u8 flagIn) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r8\n\ + push {r7}\n\ + sub sp, 0x4\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + mov r8, r0\n\ + bl CurrentMapIsSecretBase\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + beq _080BBDBC\n\ + ldr r0, _080BBD70 @ =0x00004054\n\ + bl VarGet\n\ + lsls r0, 16\n\ + lsrs r5, r0, 16\n\ + movs r1, 0\n\ + mov r0, sp\n\ + strh r1, [r0]\n\ + ldr r6, _080BBD74 @ =gSaveBlock1\n\ + mov r4, sp\n\ + ldr r0, _080BBD78 @ =0x00001a2a\n\ + adds r7, r6, r0\n\ +_080BBCFC:\n\ + lsls r0, r5, 2\n\ + adds r0, r5\n\ + lsls r0, 5\n\ + ldrh r1, [r4]\n\ + adds r2, r0, r1\n\ + ldr r1, _080BBD7C @ =0x00001a1a\n\ + adds r0, r6, r1\n\ + adds r1, r2, r0\n\ + ldrb r0, [r1]\n\ + subs r0, 0x1\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x77\n\ + bhi _080BBD3A\n\ + ldr r0, _080BBD80 @ =gDecorations\n\ + ldrb r3, [r1]\n\ + lsls r1, r3, 5\n\ + adds r1, r0\n\ + ldrb r0, [r1, 0x11]\n\ + cmp r0, 0x4\n\ + beq _080BBD3A\n\ + adds r0, r2, r7\n\ + ldrb r2, [r0]\n\ + lsrs r0, r2, 4\n\ + adds r0, 0x7\n\ + movs r1, 0xF\n\ + ands r1, r2\n\ + adds r1, 0x7\n\ + adds r2, r3, 0\n\ + bl sub_80FF394\n\ +_080BBD3A:\n\ + ldrh r0, [r4]\n\ + adds r0, 0x1\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + strh r0, [r4]\n\ + cmp r0, 0xF\n\ + bls _080BBCFC\n\ + cmp r5, 0\n\ + beq _080BBD88\n\ + mov r4, sp\n\ + adds r4, 0x2\n\ + movs r2, 0x88\n\ + lsls r2, 2\n\ + mov r0, sp\n\ + adds r1, r4, 0\n\ + bl sub_80BB764\n\ + mov r0, sp\n\ + ldrh r0, [r0]\n\ + adds r0, 0x7\n\ + ldrh r1, [r4]\n\ + adds r1, 0x7\n\ + ldr r2, _080BBD84 @ =0x00000e21\n\ + bl MapGridSetMetatileIdAt\n\ + b _080BBDBC\n\ + .align 2, 0\n\ +_080BBD70: .4byte 0x00004054\n\ +_080BBD74: .4byte gSaveBlock1\n\ +_080BBD78: .4byte 0x00001a2a\n\ +_080BBD7C: .4byte 0x00001a1a\n\ +_080BBD80: .4byte gDecorations\n\ +_080BBD84: .4byte 0x00000e21\n\ +_080BBD88:\n\ + mov r0, r8\n\ + cmp r0, 0x1\n\ + bne _080BBDBC\n\ + ldr r0, _080BBDC8 @ =0x00004089\n\ + bl VarGet\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + cmp r0, 0x1\n\ + bne _080BBDBC\n\ + mov r4, sp\n\ + adds r4, 0x2\n\ + movs r2, 0x88\n\ + lsls r2, 2\n\ + mov r0, sp\n\ + adds r1, r4, 0\n\ + bl sub_80BB764\n\ + mov r0, sp\n\ + ldrh r0, [r0]\n\ + adds r0, 0x7\n\ + ldrh r1, [r4]\n\ + adds r1, 0x7\n\ + ldr r2, _080BBDCC @ =0x00000e0a\n\ + bl MapGridSetMetatileIdAt\n\ +_080BBDBC:\n\ + add sp, 0x4\n\ + pop {r3}\n\ + mov r8, r3\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080BBDC8: .4byte 0x00004089\n\ +_080BBDCC: .4byte 0x00000e0a\n\ +.syntax divided\n"); +} + +__attribute__((naked)) +void sub_80BBDD0(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x14\n\ + ldr r0, _080BBE00 @ =0x00004054\n\ + bl VarGet\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + bl CurrentMapIsSecretBase\n\ + lsls r0, 24\n\ + cmp r0, 0\n\ + bne _080BBE08\n\ + ldr r0, _080BBE04 @ =gSaveBlock1 + 0x2688\n\ + str r0, [sp, 0x4]\n\ + adds r0, 0xC\n\ + str r0, [sp, 0x8]\n\ + movs r1, 0xC\n\ + str r1, [sp, 0xC]\n\ + b _080BBE1E\n\ + .align 2, 0\n\ +_080BBE00: .4byte 0x00004054\n\ +_080BBE04: .4byte gSaveBlock1 + 0x2688\n\ +_080BBE08:\n\ + lsls r1, r4, 2\n\ + adds r1, r4\n\ + lsls r1, 5\n\ + ldr r0, _080BBF7C @ =gSaveBlock1 + 0x1A1A\n\ + adds r2, r1, r0\n\ + str r2, [sp, 0x4]\n\ + adds r0, 0x10\n\ + adds r1, r0\n\ + str r1, [sp, 0x8]\n\ + movs r3, 0x10\n\ + str r3, [sp, 0xC]\n\ +_080BBE1E:\n\ + movs r6, 0\n\ + ldr r4, [sp, 0xC]\n\ + cmp r6, r4\n\ + bcc _080BBE28\n\ + b _080BBF6C\n\ +_080BBE28:\n\ + ldr r5, _080BBF80 @ =gSaveBlock1\n\ + mov r10, r5\n\ +_080BBE2C:\n\ + ldr r1, [sp, 0x4]\n\ + adds r0, r1, r6\n\ + ldrb r1, [r0]\n\ + mov r9, r0\n\ + adds r2, r6, 0x1\n\ + str r2, [sp, 0x10]\n\ + cmp r1, 0\n\ + bne _080BBE3E\n\ + b _080BBF5E\n\ +_080BBE3E:\n\ + ldrb r0, [r0]\n\ + lsls r0, 5\n\ + ldr r3, _080BBF84 @ =gDecorations\n\ + adds r0, r3\n\ + ldrb r0, [r0, 0x11]\n\ + cmp r0, 0x4\n\ + beq _080BBE4E\n\ + b _080BBF5E\n\ +_080BBE4E:\n\ + movs r5, 0\n\ + ldr r0, _080BBF88 @ =gMapHeader\n\ + ldr r2, [r0, 0x4]\n\ + ldrb r3, [r2]\n\ + mov r8, r0\n\ + cmp r5, r3\n\ + bcs _080BBE8E\n\ + ldr r0, [r2, 0x4]\n\ + ldrh r1, [r0, 0x14]\n\ + ldr r4, _080BBF8C @ =gSpecialVar_0x8004\n\ + ldrh r0, [r4]\n\ + adds r0, 0xAE\n\ + adds r7, r4, 0\n\ + cmp r1, r0\n\ + beq _080BBE8E\n\ + adds r4, r2, 0\n\ + adds r2, r3, 0\n\ +_080BBE70:\n\ + adds r0, r5, 0x1\n\ + lsls r0, 24\n\ + lsrs r5, r0, 24\n\ + cmp r5, r2\n\ + bcs _080BBE8E\n\ + ldr r1, [r4, 0x4]\n\ + lsls r0, r5, 1\n\ + adds r0, r5\n\ + lsls r0, 3\n\ + adds r0, r1\n\ + ldrh r1, [r0, 0x14]\n\ + ldrh r0, [r7]\n\ + adds r0, 0xAE\n\ + cmp r1, r0\n\ + bne _080BBE70\n\ +_080BBE8E:\n\ + mov r1, r8\n\ + ldr r0, [r1, 0x4]\n\ + ldrb r0, [r0]\n\ + cmp r5, r0\n\ + beq _080BBF5E\n\ + ldr r7, _080BBF90 @ =gSpecialVar_0x8006\n\ + ldr r2, [sp, 0x8]\n\ + adds r1, r2, r6\n\ + ldrb r0, [r1]\n\ + lsrs r0, 4\n\ + strh r0, [r7]\n\ + ldr r6, _080BBF94 @ =gSpecialVar_0x8007\n\ + ldrb r1, [r1]\n\ + movs r0, 0xF\n\ + ands r0, r1\n\ + strh r0, [r6]\n\ + ldrh r0, [r7]\n\ + adds r0, 0x7\n\ + ldrh r1, [r6]\n\ + adds r1, 0x7\n\ + bl MapGridGetMetatileBehaviorAt\n\ + lsls r0, 24\n\ + lsrs r4, r0, 24\n\ + adds r0, r4, 0\n\ + bl sub_80572D8\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + beq _080BBEDA\n\ + adds r0, r4, 0\n\ + bl sub_80572EC\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + cmp r0, 0x1\n\ + bne _080BBF5E\n\ +_080BBEDA:\n\ + mov r3, r8\n\ + ldr r0, [r3, 0x4]\n\ + ldr r1, [r0, 0x4]\n\ + lsls r4, r5, 1\n\ + adds r4, r5\n\ + lsls r4, 3\n\ + adds r1, r4, r1\n\ + ldr r5, _080BBF98 @ =0x00003f20\n\ + adds r0, r5, 0\n\ + ldrb r1, [r1, 0x1]\n\ + adds r0, r1\n\ + ldr r1, _080BBF9C @ =gScriptResult\n\ + strh r0, [r1]\n\ + ldrh r0, [r1]\n\ + mov r2, r9\n\ + ldrb r1, [r2]\n\ + lsls r1, 5\n\ + ldr r3, _080BBFA0 @ =gDecorations + 0x1C\n\ + adds r1, r3\n\ + ldr r1, [r1]\n\ + ldrh r1, [r1]\n\ + bl VarSet\n\ + mov r5, r8\n\ + ldr r0, [r5, 0x4]\n\ + ldr r0, [r0, 0x4]\n\ + adds r4, r0\n\ + ldrb r0, [r4]\n\ + ldr r1, _080BBF9C @ =gScriptResult\n\ + strh r0, [r1]\n\ + ldr r2, _080BBF8C @ =gSpecialVar_0x8004\n\ + ldrh r0, [r2]\n\ + adds r0, 0xAE\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + bl FlagClear\n\ + ldr r3, _080BBF9C @ =gScriptResult\n\ + ldrb r0, [r3]\n\ + mov r4, r10\n\ + ldrb r1, [r4, 0x5]\n\ + ldrb r2, [r4, 0x4]\n\ + bl show_sprite\n\ + ldr r5, _080BBF9C @ =gScriptResult\n\ + ldrb r0, [r5]\n\ + ldrb r1, [r4, 0x5]\n\ + ldrb r2, [r4, 0x4]\n\ + movs r4, 0\n\ + ldrsh r3, [r7, r4]\n\ + movs r5, 0\n\ + ldrsh r4, [r6, r5]\n\ + str r4, [sp]\n\ + bl sub_805C0F8\n\ + ldr r1, _080BBF9C @ =gScriptResult\n\ + ldrb r0, [r1]\n\ + mov r2, r10\n\ + ldrb r1, [r2, 0x5]\n\ + ldrb r2, [r2, 0x4]\n\ + bl sub_805C78C\n\ + ldr r3, _080BBF8C @ =gSpecialVar_0x8004\n\ + ldrh r0, [r3]\n\ + adds r0, 0x1\n\ + strh r0, [r3]\n\ +_080BBF5E:\n\ + ldr r4, [sp, 0x10]\n\ + lsls r0, r4, 24\n\ + lsrs r6, r0, 24\n\ + ldr r5, [sp, 0xC]\n\ + cmp r6, r5\n\ + bcs _080BBF6C\n\ + b _080BBE2C\n\ +_080BBF6C:\n\ + add sp, 0x14\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080BBF7C: .4byte gSaveBlock1 + 0x1A1A\n\ +_080BBF80: .4byte gSaveBlock1\n\ +_080BBF84: .4byte gDecorations\n\ +_080BBF88: .4byte gMapHeader\n\ +_080BBF8C: .4byte gSpecialVar_0x8004\n\ +_080BBF90: .4byte gSpecialVar_0x8006\n\ +_080BBF94: .4byte gSpecialVar_0x8007\n\ +_080BBF98: .4byte 0x00003f20\n\ +_080BBF9C: .4byte gScriptResult\n\ +_080BBFA0: .4byte gDecorations + 0x1C\n\ +.syntax divided\n"); +} +#endif + +void sub_80BBFA4(void) +{ + int curBase = VarGet(VAR_0x4054); + VarSet(VAR_0x401F, gUnknown_083D13EC[sub_80BCCA4(curBase)]); +} + +void sub_80BBFD8(s16 *position, struct MapEvents *events) +{ + s16 bgevtidx; + for (bgevtidx=0; bgevtidx<events->bgEventCount; bgevtidx++) { + if (events->bgEvents[bgevtidx].kind == 8 && position[0] == events->bgEvents[bgevtidx].x + 7 && position[1] == events->bgEvents[bgevtidx].y + 7) { + gUnknown_020387DC = events->bgEvents[bgevtidx].bgUnion.secretBaseId; + break; + } + } +} + +void sub_80BC038(s16 *position, struct MapEvents *events) +{ + sub_80BBFD8(position, events); + sub_80BB5E4(); + ScriptContext1_SetupScript(gUnknown_081A2E14); +} + +bool8 sub_80BC050(void) +{ + sub_80BB5D0(); + sub_80BB5E4(); + if (gScriptResult == 1) + return FALSE; + return TRUE; +} + +void sub_80BC074(u8 taskid) +{ + switch (gTasks[taskid].data[0]) { + case 0: + ScriptContext2_Enable(); + gTasks[taskid].data[0] = 1; + break; + case 1: + if (!gPaletteFade.active) { + gTasks[taskid].data[0] = 2; + } + break; + case 2: + copy_saved_warp2_bank_and_enter_x_to_warp1(0x7E); + warp_in(); + gFieldCallback = mapldr_default; + SetMainCallback2(CB2_LoadMap); + ScriptContext2_Disable(); + DestroyTask(taskid); + break; + } +} + +void sub_80BC0F8(void) { + CreateTask(sub_80BC074, 0); + fade_screen(1, 0); +} + +void sub_80BC114(void) { + if (gSaveBlock1.secretBases[0].sbr_field_0 != gUnknown_020387DC) + gScriptResult = 1; + else + gScriptResult = 0; +} + +u8 sub_80BC14C(u8 sbid) +{ + s16 idx; + for (idx=0; idx<20; idx++) { + if (gSaveBlock1.secretBases[idx].sbr_field_0 == sbid) + return idx; + } + return 0; +} + +u8 *sub_80BC190(u8 *dest, u8 arg1) { // 80bc190 + u8 local1; + u8 *str; + + local1 = sub_80BB8A8(gSaveBlock1.secretBases[arg1].sbr_field_2); + + str = StringCopyN(dest, gSaveBlock1.secretBases[arg1].sbr_field_2, local1); + str[0] = EOS; + +#if ENGLISH + return StringAppend(dest, gOtherText_PlayersBase); +#elif GERMAN + return de_sub_8073174(dest, gOtherText_PlayersBase); +#endif +} + +u8 *GetSecretBaseMapName(u8 *dest) { + gUnknown_020387DC = gSaveBlock1.secretBases[VarGet(VAR_0x4054)].sbr_field_0; + return sub_80BC190(dest, VarGet(VAR_0x4054)); +} + +void sub_80BC224(void) { + u8 *var0 = gSaveBlock1.secretBases[(u8)VarGet(VAR_0x4054)].sbr_field_2; + u8 *var1 = gStringVar1; + u8 var2 = sub_80BB8A8(var0); + u8 *var3 = StringCopyN(var1, var0, var2); + *var3 = EOS; +} + +u8 sub_80BC268(u8 foo) { // 80bc268 + if (gSaveBlock1.secretBases[foo].sbr_field_1_6) + return 1; + return 0; +} + +u8 sub_80BC298(struct Pokemon *mon) { // 80bc298 + u16 evsum = GetMonData(mon, MON_DATA_HP_EV); + evsum += GetMonData(mon, MON_DATA_ATK_EV); + evsum += GetMonData(mon, MON_DATA_DEF_EV); + evsum += GetMonData(mon, MON_DATA_SPD_EV); + evsum += GetMonData(mon, MON_DATA_SPATK_EV); + evsum += GetMonData(mon, MON_DATA_SPDEF_EV); + return (u8)(evsum / 6); +} + +#ifdef NONMATCHING +void sub_80BC300(void) +{ + u16 moveidx; + u16 sbpartyidx = 0; + int resetVal = 0; + u16 partyidx = 0; + while (partyidx < 6) { + partyidx ++; + for (moveidx=0; moveidx<4; moveidx++) { + gSaveBlock1.secretBases[0].partyMoves[(partyidx - 1) * 6 + moveidx] = resetVal; + } + gSaveBlock1.secretBases[0].partySpecies[partyidx - 1] = resetVal; + gSaveBlock1.secretBases[0].partyHeldItems[partyidx - 1] = resetVal; + gSaveBlock1.secretBases[0].partyLevels[partyidx - 1] = resetVal; + gSaveBlock1.secretBases[0].partyPersonality[partyidx - 1] = resetVal; + gSaveBlock1.secretBases[0].partyEVs[partyidx - 1] = resetVal; + if (GetMonData(&(gPlayerParty[partyidx - 1]), MON_DATA_SPECIES) != 0 && !GetMonData(&(gPlayerParty[partyidx - 1]), MON_DATA_IS_EGG)) { + sbpartyidx ++; + for (moveidx=0; moveidx<4; moveidx++) { + gSaveBlock1.secretBases[0].partyMoves[(sbpartyidx - 1) * 6 + moveidx] = GetMonData(&(gPlayerParty[partyidx - 1]), MON_DATA_MOVE1 + moveidx); + } + gSaveBlock1.secretBases[0].partySpecies[sbpartyidx - 1] = GetMonData(&(gPlayerParty[partyidx - 1]), MON_DATA_SPECIES); + gSaveBlock1.secretBases[0].partyHeldItems[sbpartyidx - 1] = GetMonData(&(gPlayerParty[partyidx - 1]), MON_DATA_HELD_ITEM); + gSaveBlock1.secretBases[0].partyLevels[sbpartyidx - 1] = GetMonData(&(gPlayerParty[partyidx - 1]), MON_DATA_LEVEL); + gSaveBlock1.secretBases[0].partyPersonality[sbpartyidx - 1] = GetMonData(&(gPlayerParty[partyidx - 1]), MON_DATA_PERSONALITY); + gSaveBlock1.secretBases[0].partyEVs[sbpartyidx - 1] = sub_80BC298(&(gPlayerParty[partyidx - 1])); + } + } +} +#else +__attribute__((naked)) +void sub_80BC300(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0xC\n\ + movs r0, 0\n\ + mov r10, r0\n\ + movs r6, 0\n\ + mov r9, r6\n\ +_080BC314:\n\ + movs r4, 0\n\ + lsls r3, r6, 2\n\ + lsls r2, r6, 1\n\ + ldr r7, _080BC424 @ =gPlayerParty\n\ + adds r1, r6, 0x1\n\ + str r1, [sp]\n\ + adds r1, r3, 0\n\ +_080BC322:\n\ + adds r0, r1, r4\n\ + lsls r0, 1\n\ + ldr r5, _080BC428 @ =gSaveBlock1 + 0x1A54\n\ + adds r0, r5, r0\n\ + mov r5, r9\n\ + strh r5, [r0]\n\ + adds r0, r4, 0x1\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + cmp r4, 0x3\n\ + bls _080BC322\n\ + ldr r1, _080BC42C @ =gSaveBlock1 + 0x1A84\n\ + adds r0, r1, r2\n\ + strh r5, [r0]\n\ + ldr r5, _080BC430 @ =gSaveBlock1 + 0x1A90\n\ + adds r0, r5, r2\n\ + mov r1, r9\n\ + strh r1, [r0]\n\ + ldr r2, _080BC434 @ =gSaveBlock1 + 0x1A9C\n\ + adds r0, r2, r6\n\ + mov r5, r9\n\ + strb r5, [r0]\n\ + ldr r1, _080BC438 @ =gSaveBlock1 + 0x1A3C\n\ + adds r0, r1, r3\n\ + mov r2, r9\n\ + str r2, [r0]\n\ + ldr r3, _080BC43C @ =gSaveBlock1 + 0x1AA2\n\ + adds r0, r3, r6\n\ + strb r2, [r0]\n\ + movs r0, 0x64\n\ + adds r5, r6, 0\n\ + muls r5, r0\n\ + adds r4, r5, r7\n\ + adds r0, r4, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + beq _080BC408\n\ + adds r0, r4, 0\n\ + movs r1, 0x2D\n\ + bl GetMonData\n\ + cmp r0, 0\n\ + bne _080BC408\n\ + movs r4, 0\n\ + mov r0, r10\n\ + lsls r0, 2\n\ + mov r8, r0\n\ + mov r1, r10\n\ + lsls r7, r1, 1\n\ + adds r1, 0x1\n\ + str r1, [sp, 0x4]\n\ + ldr r2, _080BC424 @ =gPlayerParty\n\ +_080BC38E:\n\ + adds r1, r4, 0\n\ + adds r1, 0xD\n\ + adds r0, r5, r2\n\ + str r2, [sp, 0x8]\n\ + bl GetMonData\n\ + mov r3, r8\n\ + adds r1, r3, r4\n\ + lsls r1, 1\n\ + ldr r3, _080BC428 @ =gSaveBlock1 + 0x1A54\n\ + adds r1, r3, r1\n\ + strh r0, [r1]\n\ + adds r0, r4, 0x1\n\ + lsls r0, 16\n\ + lsrs r4, r0, 16\n\ + ldr r2, [sp, 0x8]\n\ + cmp r4, 0x3\n\ + bls _080BC38E\n\ + movs r0, 0x64\n\ + adds r4, r6, 0\n\ + muls r4, r0\n\ + ldr r0, _080BC424 @ =gPlayerParty\n\ + adds r4, r0\n\ + adds r0, r4, 0\n\ + movs r1, 0xB\n\ + bl GetMonData\n\ + ldr r5, _080BC42C @ =gSaveBlock1 + 0x1A84\n\ + adds r1, r5, r7\n\ + strh r0, [r1]\n\ + adds r0, r4, 0\n\ + movs r1, 0xC\n\ + bl GetMonData\n\ + ldr r2, _080BC430 @ =gSaveBlock1 + 0x1A90\n\ + adds r1, r2, r7\n\ + strh r0, [r1]\n\ + adds r0, r4, 0\n\ + movs r1, 0x38\n\ + bl GetMonData\n\ + ldr r1, _080BC434 @ =gSaveBlock1 + 0x1A9C\n\ + add r1, r10\n\ + strb r0, [r1]\n\ + adds r0, r4, 0\n\ + movs r1, 0\n\ + bl GetMonData\n\ + ldr r1, _080BC438 @ =gSaveBlock1 + 0x1A3C\n\ + add r1, r8\n\ + str r0, [r1]\n\ + adds r0, r4, 0\n\ + bl sub_80BC298\n\ + ldr r1, _080BC43C @ =gSaveBlock1 + 0x1AA2\n\ + add r1, r10\n\ + strb r0, [r1]\n\ + ldr r3, [sp, 0x4]\n\ + lsls r0, r3, 16\n\ + lsrs r0, 16\n\ + mov r10, r0\n\ +_080BC408:\n\ + ldr r5, [sp]\n\ + lsls r0, r5, 16\n\ + lsrs r6, r0, 16\n\ + cmp r6, 0x5\n\ + bls _080BC314\n\ + add sp, 0xC\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080BC424: .4byte gPlayerParty\n\ +_080BC428: .4byte gSaveBlock1 + 0x1A54\n\ +_080BC42C: .4byte gSaveBlock1 + 0x1A84\n\ +_080BC430: .4byte gSaveBlock1 + 0x1A90\n\ +_080BC434: .4byte gSaveBlock1 + 0x1A9C\n\ +_080BC438: .4byte gSaveBlock1 + 0x1A3C\n\ +_080BC43C: .4byte gSaveBlock1 + 0x1AA2\n\ +.syntax divided\n"); +} +#endif + +void sub_80BC440(void) +{ + u16 backupValue = gSaveBlock1.secretBases[0].sbr_field_e; + ResetSecretBase(0); + gSaveBlock1.secretBases[0].sbr_field_e = backupValue; + sub_80BC0F8(); +} + +void SecretBasePC_PackUp(void) +{ + IncrementGameStat(20); + sub_80BC440(); +} diff --git a/src/field/shop.c b/src/field/shop.c new file mode 100644 index 000000000..375205935 --- /dev/null +++ b/src/field/shop.c @@ -0,0 +1,1351 @@ +#include "global.h" +#include "shop.h" +#include "decompress.h" +#include "field_fadetransition.h" +#include "field_weather.h" +#include "item_menu.h" +#include "main.h" +#include "menu.h" +#include "menu_helpers.h" +#include "money.h" +#include "palette.h" +#include "script.h" +#include "sound.h" +#include "sprite.h" +#include "strings.h" +#include "task.h" +#include "tv.h" +#include "unknown_task.h" +#include "field_map_obj.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "item.h" +#include "decoration.h" +#include "items.h" +#include "songs.h" +#include "overworld.h" +#include "decoration_inventory.h" +#include "field_camera.h" + +#define ewram18000 ((u16 *)(ewram + 0x18000)) +#define ewram18300 ((u16 *)(ewram + 0x18300)) + +extern bool8 sub_80A52C4(u8, u8); + +extern u8 ewram[]; +extern u8 gBuyMenuFrame_Gfx[]; +extern u16 gBuyMenuFrame_Tilemap[]; +extern u16 gMenuMoneyPal[16]; + +void sub_80B39D0(int var1, int var2, bool32 hasControlCode); +void sub_80B3A70(void); +void sub_80B4378(u8); +void sub_80B43F0(u8); +void Task_ExitBuyMenu(u8); +void sub_80B4470(u8); +void sub_80B2EFC(u8 taskId); +void sub_80B2F30(u8 taskId); +void HandleShopMenuQuit(u8 taskId); +void sub_80B3BF4(u8 taskId); +void sub_80B3D7C(u8 taskId); + +// iwram +static struct MartInfo gMartInfo; + +// ewram +EWRAM_DATA u32 gMartTotalCost = 0; +EWRAM_DATA s16 gUnknown_020386A4[16][4] = {0}; // game freak barely uses 2d arrays wtf? +EWRAM_DATA struct ItemSlot gUnknown_02038724[3] = {0}; // tv.c uses this, so it cant be static +EWRAM_DATA u8 gUnknown_02038730 = 0; +EWRAM_DATA u8 gUnknown_02038731 = 0; + +// rodata +static const struct MenuAction2 sBuySellQuitMenuActions[] = +{ + { MartText_Buy, sub_80B2EFC }, + { MartText_Sell, sub_80B2F30 }, + { MartText_Quit2, HandleShopMenuQuit }, +}; + +static const u8 gUnknown_083CC6E8[] = {0, 1, 2}; // BUY SELL EXIT +static const u8 gUnknown_083CC6EB[] = {0, 2}; // BUY EXIT + +static const u16 gUnusedMartArray[] = {0x2, 0x3, 0x4, 0xD, 0x121, 0xE, 0xE, 0xE, 0xE, 0xE, 0xE, 0x0, 0x0}; + +static const struct YesNoFuncTable gUnknown_083CC708[] = +{ + sub_80B3BF4, + sub_80B3D7C +}; + +u8 CreateShopMenu(u8 martType) +{ + ScriptContext2_Enable(); + gMartInfo.martType = martType; + gMartInfo.cursor = 0; + + if (martType == MART_TYPE_0) + { + gMartInfo.numChoices = 2; + MenuDrawTextWindow(0, 0, 10, 7); + PrintMenuItemsReordered(1, 1, 3, sBuySellQuitMenuActions, gUnknown_083CC6E8); + } + else + { + gMartInfo.numChoices = 1; + MenuDrawTextWindow(0, 0, 10, 5); + PrintMenuItemsReordered(1, 1, 2, sBuySellQuitMenuActions, gUnknown_083CC6EB); + } + InitMenu(0, 1, 1, gMartInfo.numChoices + 1, 0, 9); // add 1 for cancel + + return CreateTask(sub_80B2E38, 8); +} + +void SetShopMenuCallback(void *callbackPtr) +{ + gMartInfo.callback = callbackPtr; +} + +void SetShopItemsForSale(u16 *items) +{ + u16 i = 0; + + gMartInfo.itemList = items; + gMartInfo.itemCount = 0; + + while (gMartInfo.itemList[i]) + { + gMartInfo.itemCount++; + i++; + } +} + +void sub_80B2E38(u8 var) +{ + const u8 local = var; + + if (gMain.newAndRepeatedKeys & DPAD_UP) + { + if (gMartInfo.cursor) // can move cursor up? + { + PlaySE(SE_SELECT); + gMartInfo.cursor = MoveMenuCursor(-1); + } + } + else if (gMain.newAndRepeatedKeys & DPAD_DOWN) + { + if (gMartInfo.cursor != gMartInfo.numChoices) // can move cursor down? + { + PlaySE(SE_SELECT); + gMartInfo.cursor = MoveMenuCursor(1); + } + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if (gMartInfo.martType == MART_TYPE_0) + { + sBuySellQuitMenuActions[gUnknown_083CC6E8[gMartInfo.cursor]].func(local); + } + else + { + sBuySellQuitMenuActions[gUnknown_083CC6EB[gMartInfo.cursor]].func(local); + } + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + HandleShopMenuQuit(local); + } +} + +void sub_80B2EFC(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)BuyMenuDrawGraphics >> 16; + gTasks[taskId].data[9] = (u32)BuyMenuDrawGraphics; + gTasks[taskId].func = sub_80B2FA0; + fade_screen(1, 0); +} + +void sub_80B2F30(u8 taskId) +{ + gTasks[taskId].data[8] = (u32)sub_80A6300 >> 16; + gTasks[taskId].data[9] = (u32)sub_80A6300; + gTasks[taskId].func = sub_80B2FA0; + fade_screen(1, 0); +} + +void HandleShopMenuQuit(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 11, 8); + sub_80BE3BC(); + ScriptContext2_Disable(); + DestroyTask(taskId); + + if (gMartInfo.callback) + gMartInfo.callback(); // run the callback if it exists. +} + +void sub_80B2FA0(u8 taskId) +{ + if (!gPaletteFade.active) + { + SetMainCallback2((void *)((u16)gTasks[taskId].data[8] << 16 | (u16)gTasks[taskId].data[9])); + DestroyTask(taskId); + } +} + +void ReturnToShopMenuAfterExitingSellMenu(u8 taskId) +{ + CreateShopMenu(gMartInfo.martType); + DestroyTask(taskId); +} + +void Task_ExitSellMenu(u8 taskId) +{ + if (sub_807D770() == 1) + { + if (gMartInfo.martType == MART_TYPE_2) + DisplayItemMessageOnField(taskId, gOtherText_CanIHelpYou, ReturnToShopMenuAfterExitingSellMenu, 0); + else + DisplayItemMessageOnField(taskId, gOtherText_AnythingElse, ReturnToShopMenuAfterExitingSellMenu, 0); + } +} + +void sub_80B3050(void) +{ + pal_fill_black(); + CreateTask(Task_ExitSellMenu, 0x8); +} + +void sub_80B3068(u8 taskId) +{ + Task_ExitSellMenu(taskId); +} + +void unref_sub_80B3078(u8 taskId) +{ + gTasks[taskId].func = Task_ExitSellMenu; +} + +void sub_80B3094(void) +{ + AnimateSprites(); + BuildOamBuffer(); + RunTasks(); + UpdatePaletteFade(); +} + +void sub_80B30AC(void) +{ + void *addr; + void *addr2; + void *addr3; + u16 *tempArr; + u16 *tempArr2; + u16 *tempArr3; + + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); + + // temp vars needed to match for some dumb reason + tempArr = gBGTilemapBuffers[1]; + addr = (void *)(VRAM + 0xE800); + DmaCopy16(3, tempArr, addr, 0x800); + tempArr2 = gBGTilemapBuffers[2]; + addr2 = (void *)(VRAM + 0xE000); + DmaCopy16(3, tempArr2, addr2, 0x800); + tempArr3 = gBGTilemapBuffers[3]; + addr3 = (void *)(VRAM + 0xF000); + DmaCopy16(3, tempArr3, addr3, 0x800); +} + +// this function is fugly. pls fix +void BuyMenuDrawGraphics(void) +{ + void *addr; + register u16 zero2 asm("r5"); + + sub_80F9438(); + remove_some_task(); + REG_BG1HOFS = (zero2 = 0); + REG_BG1VOFS = zero2; + REG_BG2HOFS = zero2; + REG_BG2VOFS = zero2; + REG_BG3HOFS = zero2; + REG_BG3VOFS = zero2; + gPaletteFade.bufferTransferDisabled = 1; + addr = (void*)OAM; + { + register const u32 zero asm("r6") = 0; + DmaFill32(3, zero, addr, OAM_SIZE); + LZDecompressVram(gBuyMenuFrame_Gfx, (void*)(VRAM + 0x7C00)); + LZDecompressWram(gBuyMenuFrame_Tilemap, (void *)0x02018000); + LoadCompressedPalette(gMenuMoneyPal, 0xC0, sizeof(gMenuMoneyPal)); + FreeAllSpritePalettes(); + ResetPaletteFade(); + ResetSpriteData(); + ResetTasks(); + SetUpWindowConfig(&gWindowConfig_81E6DFC); + InitMenuWindow(&gWindowConfig_81E6DFC); + BuyMenuDrawMapGraphics(); + gMartInfo.cursor = zero; + gMartInfo.choicesAbove = zero2; + MenuZeroFillWindowRect(0, 0, 0x20, 0x20); + OpenMoneyWindow(gSaveBlock1.money, 0, 0); + sub_80B3764(0, 7); + sub_80B37EC(); + sub_80B3270(); + CreateTask(sub_80B40E8, 0x8); + sub_80B3240(); + asm("":::"r4"); // what?? + BeginNormalPaletteFade(0xFFFFFFFF, 0, 0x10, 0, zero); + gPaletteFade.bufferTransferDisabled = 0; + SetVBlankCallback(sub_80B30AC); + SetMainCallback2(sub_80B3094); + } +} + +void sub_80B3240(void) +{ + u16 tempArr[2] = {0x41EE, 0x7FFF}; + + LoadPalette(&tempArr[1], 0xD1, 2); + LoadPalette(&tempArr[0], 0xD8, 2); +} + +void sub_80B3270(void) +{ + sub_80F944C(); + + if (gMartInfo.itemCount > 7) + { + CreateVerticalScrollIndicators(0, 172, 12); + CreateVerticalScrollIndicators(1, 172, 148); + sub_80F979C(0, 1); + } +} + +void sub_80B32A4(void) +{ + if (gMartInfo.choicesAbove == 0) + sub_80F979C(0, 1); + else + sub_80F979C(0, 0); + + if (gMartInfo.choicesAbove + 7 >= gMartInfo.itemCount) + sub_80F979C(1, 1); + else + sub_80F979C(1, 0); +} + +void sub_80B32EC(u16 *array, s16 offset1, s16 offset2) +{ + array[offset1 + offset2] = 0xC3E1; + array[offset1 + offset2 + 1] = 0xC3E1; +} + +void BuyMenuDrawMapMetatileLayer(u16 *array, s16 offset1, s16 offset2, u16 *array2) +{ + array[offset1 + offset2] = array2[0]; + array[offset1 + offset2 + 1] = array2[1]; + array[offset1 + offset2 + 32] = array2[2]; + array[offset1 + offset2 + 33] = array2[3]; +} + +void BuyMenuDrawMapMetatile(int var1, int var2, u16 *var3, s32 var4) +{ + u8 tempVar4 = var4; + s16 offset1 = var1 * 2; + s16 offset2 = (var2 * 0x40) + 0x40; + + switch (tempVar4) + { + case 0: // _080B335C + BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[2], offset1, offset2, var3); + BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[1], offset1, offset2, var3 + 4); + break; + case 1: // _080B3364 + BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[3], offset1, offset2, var3); + BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[2], offset1, offset2, var3 + 4); + break; + case 2: // _080B3398 + BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[3], offset1, offset2, var3); + BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[1], offset1, offset2, var3 + 4); + break; + } +} + +void sub_80B33D0(s16 var1, int var2, u16 *var3) +{ + s16 offset1 = var1 * 2; + s16 offset2 = (var2 * 0x40) + 0x40; + + BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[3], offset1, offset2, var3); + BuyMenuDrawMapMetatileLayer(gBGTilemapBuffers[2], offset1, offset2, var3 + 4); +} + +void sub_80B3420(void) +{ + s16 facingX; + s16 facingY; + s16 x; + s16 y; + + GetXYCoordsOneStepInFrontOfPlayer(&facingX, &facingY); + facingX -= 3; + facingY -= 3; + + for (y = 0; y < 6; y++) + { + for (x = 0; x < 7; x++) + { + u16 metatileId = MapGridGetMetatileIdAt(facingX + x, facingY + y); + + if (y != 5 && x != 6) + { + s32 r3 = MapGridGetMetatileLayerTypeAt(facingX + x, facingY + y); + + if (metatileId < 512) + BuyMenuDrawMapMetatile(x, y, (u16 *)gMapHeader.mapData->primaryTileset->metatiles + metatileId * 8, r3); + else + BuyMenuDrawMapMetatile(x, y, (u16 *)gMapHeader.mapData->secondaryTileset->metatiles + (metatileId - 512) * 8, r3); + } + else + { + if (metatileId < 512) + sub_80B33D0(x, y, (u16 *)gMapHeader.mapData->primaryTileset->metatiles + metatileId * 8); + else + sub_80B33D0(x, y, (u16 *)gMapHeader.mapData->secondaryTileset->metatiles + (metatileId - 512) * 8); + } + + if (y == 0 && x != 0 && x != 6) + sub_80B32EC(gBGTilemapBuffers[1], x * 2, 64); + } + } +} + +void BuyMenuDrawMapGraphics(void) +{ + sub_80F9020(); + sub_80B356C(); + sub_80B368C(); + sub_80B3420(); +} + +void sub_80B356C(void) +{ + s16 facingX; + s16 facingY; + u8 playerHeight; + u8 y; + u8 x; + u8 r8 = 0; + + GetXYCoordsOneStepInFrontOfPlayer(&facingX, &facingY); + playerHeight = PlayerGetZCoord(); + for (y = 0; y < 16; y++) + gUnknown_020386A4[y][MAP_OBJ_ID] = 16; + for (y = 0; y < 5; y++) + { + for (x = 0; x < 7; x++) + { + u8 mapObjId = GetFieldObjectIdByXYZ(facingX - 3 + x, facingY - 2 + y, playerHeight); + + if (mapObjId != 16) + { + gUnknown_020386A4[r8][MAP_OBJ_ID] = mapObjId; + gUnknown_020386A4[r8][X_COORD] = x; + gUnknown_020386A4[r8][Y_COORD] = y; + if (gMapObjects[mapObjId].mapobj_unk_18 == 1) + gUnknown_020386A4[r8][ANIM_NUM] = 0; + if (gMapObjects[mapObjId].mapobj_unk_18 == 2) + gUnknown_020386A4[r8][ANIM_NUM] = 1; + if (gMapObjects[mapObjId].mapobj_unk_18 == 3) + gUnknown_020386A4[r8][ANIM_NUM] = 2; + if (gMapObjects[mapObjId].mapobj_unk_18 == 4) + gUnknown_020386A4[r8][ANIM_NUM] = 3; + r8++; + } + } + } +} + +void sub_80B368C(void) +{ + u8 i; + + for (i = 0; i < 16; i++) // max objects? + { + if (gUnknown_020386A4[i][MAP_OBJ_ID] == 16) + continue; + + StartSpriteAnim(&gSprites[AddPseudoFieldObject( + gMapObjects[gUnknown_020386A4[i][MAP_OBJ_ID]].graphicsId, + SpriteCallbackDummy, + (u16)gUnknown_020386A4[i][X_COORD] * 16 + 8, + (u16)gUnknown_020386A4[i][Y_COORD] * 16 + 32, + 2)], + gUnknown_020386A4[i][ANIM_NUM]); + } +} + +void sub_80B3720(void) +{ + s16 i; + + for (i = 0; i < 0x400; i++) + { + if (ewram18000[i] != 0) + gBGTilemapBuffers[1][i] = ewram18000[i] + 0xC3E0; + } +} + +void sub_80B3764(int var1, int var2) +{ + sub_80B3720(); + sub_80B39D0(var1, var2, 0); + InitMenu(0, 0xE, 0x2, 0x8, gMartInfo.cursor, 0xF); +} + +void sub_80B379C(void) +{ + u16 i, j; + + for (i = 0; i < 8; i++) + for (j = 0; j < 14; j++) + gBGTilemapBuffers[1][32 * (i + 12) + j] = ewram18300[32 * i + j] + 0xC3E0; +} + +void sub_80B37EC(void) +{ + sub_80B3A70(); +} + +void sub_80B37F8(u8 taskId) +{ + u16 itemListIndex = gMartInfo.choicesAbove + gMartInfo.cursor; + u16 itemId = gMartInfo.itemList[itemListIndex]; + u32 price = (ItemId_GetPrice(itemId) >> GetPriceReduction(1)); + + PrintMoneyAmount(gTasks[taskId].data[1] * price, 6, 6, 11); + gStringVar1[0] = EXT_CTRL_CODE_BEGIN; + gStringVar1[1] = 0x14; + gStringVar1[2] = 0x6; + ConvertIntToDecimalStringN(&gStringVar1[3], gTasks[taskId].data[1], 1, 2); + MenuPrint(gOtherText_xString1, 1, 11); + sub_80A3FA0(gBGTilemapBuffers[1], 1, 11, 12, 2, 0xC3E1); +} + +void sub_80B389C(u16 itemId, u8 var2, bool32 hasControlCode) +{ + u8 *stringPtr = gStringVar1; + + if (hasControlCode != FALSE) + { + stringPtr[0] = EXT_CTRL_CODE_BEGIN; + stringPtr[1] = 0x1; + stringPtr[2] = 0x2; + stringPtr += 3; + } + + CopyItemName(itemId, stringPtr); + + sub_8072A18(&gStringVar1[0], 0x70, var2 << 3, 0x58, 0x1); + stringPtr = gStringVar1; + + if (hasControlCode != FALSE) + stringPtr = &gStringVar1[3]; + + GetMoneyAmountText(stringPtr, (ItemId_GetPrice(itemId) >> GetPriceReduction(1)), 0x4); + MenuPrint_PixelCoords(&gStringVar1[0], 0xCA, var2 << 3, 1); +} + +void sub_80B3930(u16 itemId, u8 var2, bool32 hasControlCode) +{ + u8 *stringPtr = gStringVar1; + + if (hasControlCode != FALSE) + { + stringPtr[0] = EXT_CTRL_CODE_BEGIN; + stringPtr[1] = 0x1; + stringPtr[2] = 0x2; + stringPtr += 3; + } + + StringCopy(stringPtr, gDecorations[itemId].name); + sub_8072A18(&gStringVar1[0], 0x70, var2 << 3, 0x58, 0x1); + stringPtr = gStringVar1; + + if (hasControlCode != FALSE) + stringPtr = &gStringVar1[3]; + + if (gDecorations[itemId].price == 10000) + { + sub_80B7B34(0x19, var2, hasControlCode); // huh??? + } + else + { + GetMoneyAmountText(stringPtr, gDecorations[itemId].price, 0x4); + MenuPrint_PixelCoords(&gStringVar1[0], 0xCA, var2 << 3, 0x1); + } +} + +void sub_80B39D0(int var1, int var2, bool32 hasControlCode) +{ + u8 i; + + for (i = var1; i <= var2 && gMartInfo.choicesAbove + i < gMartInfo.itemCount; i++) + { + if (gMartInfo.martType == MART_TYPE_0) + sub_80B389C(gMartInfo.itemList[gMartInfo.choicesAbove + i], (i << 1) + 2, hasControlCode); + else + sub_80B3930(gMartInfo.itemList[gMartInfo.choicesAbove + i], (i << 1) + 2, hasControlCode); + } + + if (i != 8 && gMartInfo.choicesAbove + i == gMartInfo.itemCount) + { + MenuFillWindowRectWithBlankTile(0xE, (i << 1) + 2, 0x1C, (i << 1) + 3); + MenuPrint(gOtherText_CancelNoTerminator, 0xE, (i << 1) + 2); + } +} + +void sub_80B3A70(void) +{ + if (gMartInfo.choicesAbove + gMartInfo.cursor != gMartInfo.itemCount) + { + if (gMartInfo.martType == MART_TYPE_0) + { + sub_8072AB0(ItemId_GetDescription(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]), + 0x4, 0x68, 0x68, 0x30, 0); + } + else + sub_8072AB0(gDecorations[gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]].description, + 0x4, 0x68, 0x68, 0x30, 0); + } + else + { + sub_8072AB0(gOtherText_QuitShopping, 0x4, 0x68, 0x68, 0x30, 0); + } +} + +void sub_80B3AEC(u8 taskId) +{ + if (gMain.newKeys & A_BUTTON || gMain.newKeys & B_BUTTON) + { + sub_80B39D0(gMartInfo.cursor, gMartInfo.cursor, 0); // huh??? + PlaySE(SE_SELECT); + + if (gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor] == ITEM_POKE_BALL && gTasks[taskId].data[1] >= 10 && AddBagItem(ITEM_PREMIER_BALL, 1) == TRUE) + DisplayItemMessageOnField(taskId, gOtherText_FreePremierBall, sub_80B4378, 0xC3E1); + else + sub_80B4378(taskId); + } +} + +void sub_80B3B80(u8 taskId) +{ + IncrementGameStat(0x26); + RemoveMoney(&gSaveBlock1.money, gMartTotalCost); + PlaySE(SE_REGI); + UpdateMoneyWindow(gSaveBlock1.money, 0, 0); + gTasks[taskId].func = sub_80B3AEC; +} + +void sub_80B3BD0(u8 taskId) +{ + sub_80B39D0(gMartInfo.cursor, gMartInfo.cursor, 0); // same thing as above? + sub_80B4378(taskId); +} + +void sub_80B3BF4(u8 taskId) +{ + MenuZeroFillWindowRect(0x7, 0x8, 0xD, 0xD); + sub_80A3FA0(gBGTilemapBuffers[1], 8, 9, 4, 4, 0); + sub_80B379C(); + sub_80B3420(); + + if (IsEnoughMoney(gSaveBlock1.money, gMartTotalCost)) + { + if (gMartInfo.martType == MART_TYPE_0) + { + if (AddBagItem(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor], gTasks[taskId].data[1])) + { + DisplayItemMessageOnField(taskId, gOtherText_HereYouGo, sub_80B3B80, 0xC3E1); + sub_80B4470(taskId); + } + else + DisplayItemMessageOnField(taskId, gOtherText_NoRoomFor, sub_80B3BD0, 0xC3E1); + } + else // a normal mart is only type 0, so types 1 and 2 are decoration marts. + { + if (IsThereStorageSpaceForDecoration(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor])) + { + if (gMartInfo.martType == MART_TYPE_1) + DisplayItemMessageOnField(taskId, gOtherText_HereYouGo2, sub_80B3B80, 0xC3E1); + else + DisplayItemMessageOnField(taskId, gOtherText_HereYouGo3, sub_80B3B80, 0xC3E1); + } + else + { + StringExpandPlaceholders(gStringVar4, gOtherText_SpaceForIsFull); + DisplayItemMessageOnField(taskId, gStringVar4, sub_80B3BD0, 0xC3E1); + } + } + } + else + DisplayItemMessageOnField(taskId, gOtherText_NotEnoughMoney, sub_80B3BD0, 0xC3E1); +} + +void sub_80B3D38(u8 taskId) +{ + DisplayYesNoMenu(7, 8, 1); + sub_80A3FA0(gBGTilemapBuffers[1], 8, 9, 4, 4, 0xC3E1); + DoYesNoFuncWithChoice(taskId, gUnknown_083CC708); +} + +void sub_80B3D7C(u8 taskId) +{ + sub_80B39D0(gMartInfo.cursor, gMartInfo.cursor, 0); + MenuZeroFillWindowRect(0x7, 0x8, 0xD, 0xD); + sub_80A3FA0(gBGTilemapBuffers[1], 0x8, 0x9, 0x4, 0x4, 0); + sub_80B4378(taskId); +} + +void sub_80B3DC8(u8 taskId) +{ + if (sub_80A52C4(taskId, gMartInfo.curItemCount) == TRUE) + sub_80B37F8(taskId); + + if (gMain.newKeys & A_BUTTON) + { + gMartTotalCost = (ItemId_GetPrice(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]) >> GetPriceReduction(1)) * gTasks[taskId].data[1]; // set total cost of your purchase. + MenuZeroFillWindowRect(0, 0xA, 0xD, 0xD); + sub_80A3FA0(gBGTilemapBuffers[1], 0x1, 0xB, 0xC, 0x2, 0); + sub_80B379C(); + sub_80B3420(); + CopyItemName(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor], gStringVar1); + ConvertIntToDecimalStringN(gStringVar2, gTasks[taskId].data[1], 0, 0x2); + ConvertIntToDecimalStringN(gStringVar3, gMartTotalCost, 0, 0x8); + StringExpandPlaceholders(gStringVar4, gOtherText_ThatWillBe); + DisplayItemMessageOnField(taskId, gStringVar4, sub_80B3D38, 0xC3E1); + } + else if (gMain.newKeys & B_BUTTON) + { + sub_80B39D0(gMartInfo.cursor, gMartInfo.cursor, 0); + sub_80B4378(taskId); + } +} + +void sub_80B3EFC(u8 taskId) +{ + u16 var; + + gTasks[taskId].data[1] = 1; + MenuDrawTextWindow(0, 0xA, 0xD, 0xD); + sub_80B37F8(taskId); + + var = gSaveBlock1.money / (ItemId_GetPrice(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]) >> GetPriceReduction(1)); + if (var > 99) + gMartInfo.curItemCount = 99; + else + gMartInfo.curItemCount = var; + + gTasks[taskId].func = sub_80B3DC8; +} + +#ifdef NONMATCHING +void sub_80B3F88(void) +{ + u16 *r1; + u16 *r2; + register u8 *r10 asm("r10"); + s32 i; + s32 j; + struct Window *r8 = &gMenuWindow; + + r1 = r8->tilemap; + r1 += 0x1EF; + r2 = r1; + r2 += 64; + r10 = r8->tileData; + + for (i = 0; i < 14; i++) + { + for (j = 0; j < 15; j++) + { + if ((r1[j] & 0x3FF) <= r8->tileDataStartOffset + 1) + r2[j] = r8->tileDataStartOffset + 1; + else + r2[j] = r1[j] + 0x3C; + } + + r1 -= 32; + r2 -= 32; + } + + { + u8 *r1 = r10 + 0x3A20; + u8 *r2 = r1 + 0x780; + for (i = 0; i < 14; i++) + { + DmaCopy16(3, r1, r2, 0x1E0); + r2 -= 0x3C0; + r1 -= 0x3C0; + } + } +} +#else +__attribute__((naked)) +void sub_80B3F88(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x4\n\ + ldr r0, _080B4020 @ =gMenuWindow\n\ + mov r8, r0\n\ + ldr r1, [r0, 0x28]\n\ + ldr r3, _080B4024 @ =0x000003de\n\ + adds r1, r3\n\ + adds r2, r1, 0\n\ + adds r2, 0x80\n\ + ldr r7, [r0, 0x24]\n\ + mov r10, r7\n\ + ldr r0, _080B4028 @ =0x000003ff\n\ + mov r9, r0\n\ + movs r6, 0xD\n\ +_080B3FAC:\n\ + adds r3, r2, 0\n\ + subs r3, 0x40\n\ + str r3, [sp]\n\ + movs r7, 0x40\n\ + negs r7, r7\n\ + adds r7, r1\n\ + mov r12, r7\n\ + adds r3, r2, 0\n\ + adds r4, r1, 0\n\ + movs r5, 0xE\n\ +_080B3FC0:\n\ + ldrh r2, [r4]\n\ + mov r1, r9\n\ + ands r1, r2\n\ + mov r7, r8\n\ + ldrh r0, [r7, 0x1A]\n\ + adds r0, 0x1\n\ + cmp r1, r0\n\ + ble _080B3FD4\n\ + adds r0, r2, 0\n\ + adds r0, 0x3C\n\ +_080B3FD4:\n\ + strh r0, [r3]\n\ + adds r3, 0x2\n\ + adds r4, 0x2\n\ + subs r5, 0x1\n\ + cmp r5, 0\n\ + bge _080B3FC0\n\ + ldr r2, [sp]\n\ + mov r1, r12\n\ + subs r6, 0x1\n\ + cmp r6, 0\n\ + bge _080B3FAC\n\ + ldr r1, _080B402C @ =0x00003a20\n\ + add r1, r10\n\ + movs r0, 0xF0\n\ + lsls r0, 3\n\ + adds r2, r1, r0\n\ + ldr r3, _080B4030 @ =0x040000d4\n\ + ldr r5, _080B4034 @ =0x800000f0\n\ + ldr r4, _080B4038 @ =0xfffffc40\n\ + movs r6, 0xD\n\ +_080B3FFC:\n\ + str r1, [r3]\n\ + str r2, [r3, 0x4]\n\ + str r5, [r3, 0x8]\n\ + ldr r0, [r3, 0x8]\n\ + adds r2, r4\n\ + adds r1, r4\n\ + subs r6, 0x1\n\ + cmp r6, 0\n\ + bge _080B3FFC\n\ + add sp, 0x4\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080B4020: .4byte gMenuWindow\n\ +_080B4024: .4byte 0x000003de\n\ +_080B4028: .4byte 0x000003ff\n\ +_080B402C: .4byte 0x00003a20\n\ +_080B4030: .4byte 0x040000d4\n\ +_080B4034: .4byte 0x800000f0\n\ +_080B4038: .4byte 0xfffffc40\n\ + .syntax divided"); +} +#endif + +#ifdef NONMATCHING +void sub_80B403C(void) +{ + u16 *r1; + u16 *r2; + u8 *r10; + s32 i; + s32 j; + struct Window *r8 = &gMenuWindow; + + r1 = r8->tilemap; + r1 += 0x4F; + r2 = r1; + r2 += 64; + r10 = r8->tileData; + + for (i = 0; i < 14; i++) + { + for (j = 0; j < 15; j++) + { + if ((r1[j] & 0x3FF) <= r8->tileDataStartOffset + 1) + r2[j] = r8->tileDataStartOffset + 1; + else + r2[j] = r1[j] + 0x3C; + } + + r1 += 32; + r2 += 32; + } + + { + register u8 *r1 asm("r1") = r10 + 0x960; + register u8 *r2 asm("r2") = r1; + + r1 += 0x780; + for (i = 0; i < 14; i++) + { + DmaCopy16(3, r1, r2, 0x1E0); + r1 += 0x3C0; + r2 += 0x3C0; + } + } +} +#else +__attribute__((naked)) +void sub_80B403C(void) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + mov r7, r10\n\ + mov r6, r9\n\ + mov r5, r8\n\ + push {r5-r7}\n\ + sub sp, 0x4\n\ + ldr r0, _080B40D8 @ =gMenuWindow\n\ + mov r8, r0\n\ + ldr r2, [r0, 0x28]\n\ + adds r1, r2, 0\n\ + adds r1, 0x9E\n\ + adds r2, r1, 0\n\ + adds r1, 0x80\n\ + ldr r3, [r0, 0x24]\n\ + mov r10, r3\n\ + ldr r7, _080B40DC @ =0x000003ff\n\ + mov r9, r7\n\ + movs r6, 0xD\n\ +_080B4060:\n\ + adds r0, r2, 0\n\ + adds r0, 0x40\n\ + str r0, [sp]\n\ + movs r3, 0x40\n\ + adds r3, r1\n\ + mov r12, r3\n\ + adds r3, r2, 0\n\ + adds r4, r1, 0\n\ + movs r5, 0xE\n\ +_080B4072:\n\ + ldrh r2, [r4]\n\ + mov r1, r9\n\ + ands r1, r2\n\ + mov r7, r8\n\ + ldrh r0, [r7, 0x1A]\n\ + adds r0, 0x1\n\ + cmp r1, r0\n\ + ble _080B4086\n\ + adds r0, r2, 0\n\ + subs r0, 0x3C\n\ +_080B4086:\n\ + strh r0, [r3]\n\ + adds r3, 0x2\n\ + adds r4, 0x2\n\ + subs r5, 0x1\n\ + cmp r5, 0\n\ + bge _080B4072\n\ + ldr r2, [sp]\n\ + mov r1, r12\n\ + subs r6, 0x1\n\ + cmp r6, 0\n\ + bge _080B4060\n\ + movs r1, 0x96\n\ + lsls r1, 4\n\ + add r1, r10\n\ + adds r2, r1, 0\n\ + movs r0, 0xF0\n\ + lsls r0, 3\n\ + adds r1, r0\n\ + ldr r3, _080B40E0 @ =0x040000d4\n\ + ldr r5, _080B40E4 @ =0x800000f0\n\ + movs r4, 0xF0\n\ + lsls r4, 2\n\ + movs r6, 0xD\n\ +_080B40B4:\n\ + str r1, [r3]\n\ + str r2, [r3, 0x4]\n\ + str r5, [r3, 0x8]\n\ + ldr r0, [r3, 0x8]\n\ + adds r2, r4\n\ + adds r1, r4\n\ + subs r6, 0x1\n\ + cmp r6, 0\n\ + bge _080B40B4\n\ + add sp, 0x4\n\ + pop {r3-r5}\n\ + mov r8, r3\n\ + mov r9, r4\n\ + mov r10, r5\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_080B40D8: .4byte gMenuWindow\n\ +_080B40DC: .4byte 0x000003ff\n\ +_080B40E0: .4byte 0x040000d4\n\ +_080B40E4: .4byte 0x800000f0\n\ + .syntax divided"); +} +#endif + +void sub_80B40E8(u8 taskId) // Mart_DoCursorAction +{ + if (!gPaletteFade.active) + { + if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_UP) // only up can be pressed + { + if (gMartInfo.cursor == 0) + { + if (gMartInfo.choicesAbove == 0) // if there are no choices above, dont bother + return; + + PlaySE(SE_SELECT); + gMartInfo.choicesAbove--; // since cursor is at the top and there are choices above the top, scroll the menu up by updating choicesAbove. + sub_80B3F88(); + sub_80B39D0(0, 0, 0); + sub_80B3A70(); + sub_80B32A4(); + } + else // if the cursor is not 0, choicesAbove cannot be updated yet since the cursor is at the top of the menu, so update cursor. + { + PlaySE(SE_SELECT); + gMartInfo.cursor = MoveMenuCursor(-1); // move cursor up + sub_80B3A70(); + } + } + else if ((gMain.newAndRepeatedKeys & DPAD_ANY) == DPAD_DOWN) // only down can be pressed + { + if (gMartInfo.cursor == 7) // are you at the bottom of the menu? + { + if (gMartInfo.choicesAbove + gMartInfo.cursor == gMartInfo.itemCount) // are you at cancel? + return; + + PlaySE(SE_SELECT); + gMartInfo.choicesAbove++; + sub_80B403C(); + sub_80B39D0(7, 7, 0); + sub_80B3A70(); + sub_80B32A4(); + } + else if (gMartInfo.cursor != gMartInfo.itemCount) + { + PlaySE(SE_SELECT); + gMartInfo.cursor = MoveMenuCursor(1); + sub_80B3A70(); + } + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + + if (gMartInfo.choicesAbove + gMartInfo.cursor != gMartInfo.itemCount) // did you not hit CANCEL? + { + PauseVerticalScrollIndicator(0); + PauseVerticalScrollIndicator(1); + sub_80F979C(1, 1); + sub_80B39D0(gMartInfo.cursor, gMartInfo.cursor, 1); + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0xC, 0xD, 0x13); + + if (gMartInfo.martType == MART_TYPE_0) + { + gMartTotalCost = (ItemId_GetPrice(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]) >> GetPriceReduction(1)); // set 1x price + if (!IsEnoughMoney(gSaveBlock1.money, gMartTotalCost)) + { + DisplayItemMessageOnField(taskId, gOtherText_NotEnoughMoney, sub_80B3BD0, 0xC3E1); // tail merge + } + else // _080B42BA + { + CopyItemName(gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor], gStringVar1); + StringExpandPlaceholders(gStringVar4, gOtherText_HowManyYouWant); + DisplayItemMessageOnField(taskId, gStringVar4, sub_80B3EFC, 0xC3E1); + } + } + else // _080B428C + { + gMartTotalCost = gDecorations[gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]].price; + + if (!IsEnoughMoney(gSaveBlock1.money, gMartTotalCost)) + { + DisplayItemMessageOnField(taskId, gOtherText_NotEnoughMoney, sub_80B3BD0, 0xC3E1); // tail merge + } + else + { + StringCopy(gStringVar1, gDecorations[gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]].name); + ConvertIntToDecimalStringN(gStringVar2, gMartTotalCost, 0, 0x8); + + if (gMartInfo.martType == MART_TYPE_1) + { + StringExpandPlaceholders(gStringVar4, gOtherText_ThatWillBe2); + } + else + { + StringExpandPlaceholders(gStringVar4, gOtherText_ThatWillBe3); + } + DisplayItemMessageOnField(taskId, gStringVar4, sub_80B3D38, 0xC3E1); + } + } + } + else + sub_80B43F0(taskId); + } + else if (gMain.newKeys & B_BUTTON) // go back to buy/sell/exit menu + { + PlaySE(SE_SELECT); + sub_80B43F0(taskId); + } + } +} + +void sub_80B4378(u8 taskId) +{ + MenuZeroFillWindowRect(0, 0xE, 0x1D, 0x13); + MenuZeroFillWindowRect(0, 0xA, 0xD, 0xD); + sub_80A3FA0(gBGTilemapBuffers[1], 0x1, 0xB, 0xC, 0x2, 0); + sub_80B3420(); + sub_80B3764(6, 7); + sub_80B37EC(); + StartVerticalScrollIndicators(0); + StartVerticalScrollIndicators(1); + sub_80B32A4(); + gTasks[taskId].func = sub_80B40E8; +} + +void sub_80B43F0(u8 taskId) +{ + gFieldCallback = sub_80B3050; + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + gTasks[taskId].func = Task_ExitBuyMenu; +} + +void Task_ExitBuyMenu(u8 taskId) +{ + if (!gPaletteFade.active) + { + CloseMoneyWindow(0, 0); + BuyMenuFreeMemory(); + SetMainCallback2(c2_exit_to_overworld_2_switch); + DestroyTask(taskId); + } +} + +void sub_80B4470(u8 taskId) +{ + u16 i; + + for (i = 0; i < 3; i++) + { + if (gUnknown_02038724[i].itemId == gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor] + && gUnknown_02038724[i].quantity != 0) + { + if (gUnknown_02038724[i].quantity + gTasks[taskId].data[1] > 255) + gUnknown_02038724[i].quantity = 255; + else + gUnknown_02038724[i].quantity += gTasks[taskId].data[1]; + return; + } + } + + if (gUnknown_02038730 < 3) + { + gUnknown_02038724[gUnknown_02038730].itemId = gMartInfo.itemList[gMartInfo.choicesAbove + gMartInfo.cursor]; + gUnknown_02038724[gUnknown_02038730].quantity = gTasks[taskId].data[1]; + gUnknown_02038730++; + } +} + +void ClearItemPurchases(void) +{ + gUnknown_02038730 = 0; + ClearItemSlots(gUnknown_02038724, 3); +} + +void CreatePokemartMenu(u16 *itemList) +{ + CreateShopMenu(MART_TYPE_0); + SetShopItemsForSale(itemList); + ClearItemPurchases(); + SetShopMenuCallback(EnableBothScriptContexts); +} + +void CreateDecorationShop1Menu(u16 *itemList) +{ + CreateShopMenu(MART_TYPE_1); + SetShopItemsForSale(itemList); + SetShopMenuCallback(EnableBothScriptContexts); +} + +void CreateDecorationShop2Menu(u16 *itemList) +{ + CreateShopMenu(MART_TYPE_2); + SetShopItemsForSale(itemList); + SetShopMenuCallback(EnableBothScriptContexts); +} + +void sub_80B45B4(u8 taskId, const s16 *list, u16 c) +{ + s16 r5 = gTasks[taskId].data[4] - 1; + s16 r3 = gTasks[taskId].data[5] - 1; + s16 r4 = gTasks[taskId].data[1]; + s16 y; + s16 x; + + if (gTasks[taskId].data[2] == 0) + { + for (y = 0; y < 3; y++) + { + for (x = 0; x < 3; x++) + { + s16 metatileId = MapGridGetMetatileIdAt(r5 + x, r3 + y); + + if (list[r4] == metatileId) + { + if (r4 != 2) + MapGridSetMetatileIdAt(r5 + x, r3 + y, c | list[r4 + 1]); + else + MapGridSetMetatileIdAt(r5 + x, r3 + y, c | list[0]); + } + } + } + } + else + { + for (y = 0; y < 3; y++) + { + for (x = 0; x < 3; x++) + { + s16 metatileId = MapGridGetMetatileIdAt(r5 + x, r3 + y); + + if (list[2 - r4] == metatileId) + { + if (r4 != 2) + MapGridSetMetatileIdAt(r5 + x, r3 + y, c | list[1 - r4]); + else + MapGridSetMetatileIdAt(r5 + x, r3 + y, c | list[2]); + } + } + } + } +} + +static const u16 gUnknown_083CC714[] = {0x284, 0x282, 0x280}; +static const u16 gUnknown_083CC71A[] = {0x285, 0x283, 0x281}; +static const u16 gUnknown_083CC720[] = {0x28C, 0x28A, 0x288}; +static const u16 gUnknown_083CC726[] = {0x28D, 0x28B, 0x289}; +static const u16 gUnknown_083CC72C[] = {0x2A0, 0x2A2, 0x2A4}; +static const u16 gUnknown_083CC732[] = {0x2A1, 0x2A3, 0x2A5}; +static const u16 gUnknown_083CC738[] = {0x2A8, 0x2AA, 0x2AC}; + +void sub_80B4710(u8 taskId) +{ + s16 *data = gTasks[taskId].data; + + data[3] = 1; + + switch (data[0]) + { + case 0: + sub_80B45B4(taskId, gUnknown_083CC714, 0); + break; + case 1: + sub_80B45B4(taskId, gUnknown_083CC71A, 0); + break; + case 2: + sub_80B45B4(taskId, gUnknown_083CC720, 0xC00); + break; + case 3: + sub_80B45B4(taskId, gUnknown_083CC726, 0); + break; + case 4: + sub_80B45B4(taskId, gUnknown_083CC72C, 0xC00); + break; + case 5: + sub_80B45B4(taskId, gUnknown_083CC732, 0); + break; + case 6: + sub_80B45B4(taskId, gUnknown_083CC738, 0); + break; + } + + data[0] = (data[0] + 1) & 7; + if (!data[0]) + { + DrawWholeMapView(); + data[1] = (data[1] + 1) % 3; + data[3] = 0; + } +} + +u8 sub_80B47D8(u16 var) +{ + u8 taskId = CreateTask(sub_80B4710, 0); + s16 *data = gTasks[taskId].data; + + PlayerGetDestCoords(&data[4], &data[5]); + data[0] = 0; + data[1] = 0; + data[2] = var; + sub_80B4710(taskId); + return taskId; +} + +void sub_80B4824(u8 var) +{ + gUnknown_02038731 = sub_80B47D8(var); +} + +void sub_80B483C(void) +{ + DestroyTask(gUnknown_02038731); +} + +bool8 sub_80B4850(void) +{ + if (gTasks[gUnknown_02038731].data[3] == 0 && gTasks[gUnknown_02038731].data[1] == 2) + return FALSE; + else + return TRUE; +} diff --git a/src/field/slot_machine.c b/src/field/slot_machine.c new file mode 100644 index 000000000..e8e4f271b --- /dev/null +++ b/src/field/slot_machine.c @@ -0,0 +1,150 @@ +#include "global.h" +#include "slot_machine.h" +#include "decompress.h" +#include "palette.h" +#include "task.h" + +struct UnkStruct2000000 { + /*0x00*/ u8 filler00[61]; + /*0x3D*/ u8 unk3D; +}; + +struct UnkStruct1 { + /*0x00*/ u8 unk00; + /*0x01*/ u8 unk01; + /*0x02*/ s16 unk02; +}; + +extern struct UnkStruct2000000 unk_2000000; + +extern struct UnkStruct1 *gUnknown_083ED048[]; +extern const u16 gPalette_83EDE24[]; + +extern const u8 gSlotMachine_Gfx[]; +#if ENGLISH +#define SLOTMACHINE_GFX_TILES 233 +#elif GERMAN +#define SLOTMACHINE_GFX_TILES 236 +#endif + +extern const u16 gUnknown_08E95A18[]; + +extern u16 gUnknown_08E95AB8[]; +extern u16 gUnknown_08E95FB8[]; + +static void LoadSlotMachineWheelOverlay(void); + +void sub_8104CAC(u8 arg0) { + u8 i; + struct Task *task; + + sub_8104DA4(); + + task = &gTasks[unk_2000000.unk3D]; + task->data[1] = arg0; + + i = 0; + while (gUnknown_083ED048[arg0][i].unk00 != 0xFF) + { + u8 spriteId; + spriteId = sub_8105BB4( + gUnknown_083ED048[arg0][i].unk00, + gUnknown_083ED048[arg0][i].unk01, + gUnknown_083ED048[arg0][i].unk02 + ); + task->data[4 + i] = spriteId; + +#ifdef GERMAN + if (arg0 == 5 && i <= 2) + { + gSprites[spriteId].invisible = TRUE; + } +#endif + + i += 1; + } +} + +asm(".section .text_b"); + +void sub_8106448(void) { + u32 offsetRead, offsetWrite; + u32 size; + + LZDecompressWram(gSlotMachine_Gfx, (void *) 0x02010000); + + offsetRead = 0x02010000; + offsetWrite = BG_VRAM; + size = SLOTMACHINE_GFX_TILES * 32; + while (TRUE) + { + DmaCopy16(3, offsetRead, (void *) (offsetWrite), 0x1000); + offsetRead += 0x1000; + offsetWrite += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaCopy16(3, offsetRead, (void *) (offsetWrite), size); + break; + } + } + + LoadPalette(gUnknown_08E95A18, 0, 160); + LoadPalette(gPalette_83EDE24, 208, 32); +} + +void sub_81064B8(void) { + CpuCopy16(gUnknown_08E95AB8, (void *) BG_SCREEN_ADDR(29), 20 * 32 * 2); + LoadSlotMachineWheelOverlay(); +} + +static void LoadSlotMachineWheelOverlay(void) { + s16 x, y, dx; + u16 *screen; + + screen = (u16 *) BG_SCREEN_ADDR(30); + + for (x = 4; x < 18; x += 5) + { + for (dx = 0; dx < 4; dx++) + { + screen[5 * 32 + dx + x] = 0x2051; + screen[13 * 32 + dx + x] = 0x2851; + screen[6 * 32 + dx + x] = 0x2061; + screen[12 * 32 + dx + x] = 0x2861; + } + + screen[6 * 32 + x] = 0x20BE; + screen[12 * 32 + x] = 0x28BE; + + for (y = 7; y <= 11; y++) + { + screen[y * 32 + x] = 0x20BF; + } + } +} + +void sub_81065A8(s16 arg0, u16 arg1, u16 arg2, u16 arg3, u16 arg4) { + u16 *vram = (u16 *) BG_SCREEN_ADDR(29); + + vram[15 * 32 + arg0] = arg1; + vram[15 * 32 + 1 + arg0] = arg2; + vram[16 * 32 + arg0] = arg3; + vram[16 * 32 + 1 + arg0] = arg4; +} + +void sub_81065DC(void) { + s16 y, x; + u16 *screen; + + CpuCopy16(gUnknown_08E95FB8, (void *) BG_SCREEN_ADDR(29), 20 * 32 * 2); + + screen = (u16 *) BG_SCREEN_ADDR(30); + for (y = 0; y < 20; y++) + { + for (x = 0; x < 30; x++) + { + screen[x + y * 32] = 0; + } + } +} diff --git a/src/field/start_menu.c b/src/field/start_menu.c new file mode 100644 index 000000000..6e44090df --- /dev/null +++ b/src/field/start_menu.c @@ -0,0 +1,850 @@ +#include "global.h" +#include "start_menu.h" +#include "event_data.h" +#include "field_map_obj_helpers.h" +#include "field_player_avatar.h" +#include "field_weather.h" +#include "fieldmap.h" +#include "item_menu.h" +#include "load_save.h" +#include "main.h" +#include "map_obj_lock.h" +#include "menu.h" +#include "option_menu.h" +#include "palette.h" +#include "pokedex.h" +#include "pokemon_menu.h" +#include "pokenav.h" +#include "overworld.h" +#include "safari_zone.h" +#include "save.h" +#include "save_menu_util.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "sprite.h" +#include "string_util.h" +#include "strings.h" +#include "strings2.h" +#include "task.h" +#include "trainer_card.h" +#include "unknown_task.h" + +//Menu actions +enum { + MENU_ACTION_POKEDEX, + MENU_ACTION_POKEMON, + MENU_ACTION_BAG, + MENU_ACTION_POKENAV, + MENU_ACTION_PLAYER, + MENU_ACTION_SAVE, + MENU_ACTION_OPTION, + MENU_ACTION_EXIT, + MENU_ACTION_RETIRE, + MENU_ACTION_PLAYER_LINK +}; + +static u8 (*saveDialogCallback)(void); +static u8 saveDialogTimer; //Number of frames to keep the window on screen after save was completed +static bool8 savingComplete; + +extern bool8 gDifferentSaveFile; +extern u16 gSaveFileStatus; +extern u16 gScriptResult; + +extern u8 gUnknown_03004860; + +u8 (*gCallback_03004AE8)(void); + +EWRAM_DATA static u8 sStartMenuCursorPos = 0; +EWRAM_DATA static u8 sNumStartMenuActions = 0; +EWRAM_DATA static u8 sCurrentStartMenuActions[10] = {0}; + +//Text strings +extern u8 gSaveText_PlayerSavedTheGame[]; +extern u8 gSaveText_DontTurnOff[]; +extern u8 gSaveText_ThereIsAlreadyAFile[]; +extern u8 gSaveText_ThereIsADifferentFile[]; +extern u8 gSaveText_WouldYouLikeToSave[]; + +static u8 StartMenu_PokedexCallback(void); +static u8 StartMenu_PokemonCallback(void); +static u8 StartMenu_BagCallback(void); +static u8 StartMenu_PokenavCallback(void); +static u8 StartMenu_PlayerCallback(void); +static u8 StartMenu_SaveCallback(void); +static u8 StartMenu_OptionCallback(void); +static u8 StartMenu_ExitCallback(void); +static u8 StartMenu_RetireCallback(void); +static u8 StartMenu_PlayerLinkCallback(void); + +static const struct MenuAction sStartMenuItems[] = +{ + { SystemText_Pokedex, StartMenu_PokedexCallback }, + { SystemText_Pokemon, StartMenu_PokemonCallback }, + { SystemText_BAG, StartMenu_BagCallback }, + { SystemText_Pokenav, StartMenu_PokenavCallback }, + { SystemText_Player, StartMenu_PlayerCallback }, + { SystemText_Save, StartMenu_SaveCallback }, + { SystemText_Option, StartMenu_OptionCallback }, + { SystemText_Exit, StartMenu_ExitCallback }, + { SystemText_Retire, StartMenu_RetireCallback }, + { SystemText_Player, StartMenu_PlayerLinkCallback }, +}; + +//Private functions +static void BuildStartMenuActions(void); +static void AddStartMenuAction(u8 action); +static void BuildStartMenuActions_Normal(void); +static void BuildStartMenuActions_SafariZone(void); +static void BuildStartMenuActions_Link(void); +static void DisplaySafariBallsWindow(void); +static bool32 PrintStartMenuItemsMultistep(s16 *a, u32 b); +static bool32 InitStartMenuMultistep(s16 *a, s16 *b); +static void Task_StartMenu(u8 taskId); +static u8 StartMenu_InputProcessCallback(void); +static u8 SaveCallback1(void); +static u8 SaveCallback2(void); +static void sub_807160C(void); +static u8 RunSaveDialogCallback(void); +static void DisplaySaveMessageWithCallback(const u8 *ptr, u8 (*func)(void)); +static void Task_SaveDialog(u8 taskId); +static void sub_8071700(void); +static void HideSaveDialog(void); +static void SaveDialogStartTimeout(void); +static u8 SaveDialogCheckForTimeoutOrKeypress(void); +static u8 SaveDialogCheckForTimeoutAndKeypress(void); +static u8 SaveDialogCheckForTimeoutAndKeypress(void); +static u8 SaveDialogCB_DisplayConfirmMessage(void); +static u8 SaveDialogCB_DisplayConfirmYesNoMenu(void); +static u8 SaveDialogCB_ProcessConfirmYesNoMenu(void); +static u8 SaveDialogCB_SaveFileExists(void); +static u8 SaveDialogCB_DisplayOverwriteYesNoMenu(void); +static u8 SaveDialogCB_ProcessOverwriteYesNoMenu(void); +static u8 SaveDialogCB_DisplaySavingMessage(void); +static u8 SaveDialogCB_DoSave(void); +static u8 SaveDialogCB_SaveSuccess(void); +static u8 SaveDialogCB_ReturnSuccess(void); +static u8 SaveDialogCB_SaveError(void); +static u8 SaveDialogCB_ReturnError(void); +static void sub_80719F0(void); +static bool32 sub_80719FC(u8 *ptr); +static void sub_8071B54(void); +static void Task_8071B64(u8 taskId); + + +static void BuildStartMenuActions(void) +{ + sNumStartMenuActions = 0; + if (is_c1_link_related_active() == TRUE) + BuildStartMenuActions_Link(); + else + { + if (GetSafariZoneFlag() == TRUE) + BuildStartMenuActions_SafariZone(); + else + BuildStartMenuActions_Normal(); + } +} + +static void AddStartMenuAction(u8 action) +{ + AppendToList(sCurrentStartMenuActions, &sNumStartMenuActions, action); +} + +static void BuildStartMenuActions_Normal(void) +{ + if (FlagGet(SYS_POKEDEX_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKEDEX); + if (FlagGet(SYS_POKEMON_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_BAG); + if (FlagGet(SYS_POKENAV_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKENAV); + AddStartMenuAction(MENU_ACTION_PLAYER); + AddStartMenuAction(MENU_ACTION_SAVE); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +static void BuildStartMenuActions_SafariZone(void) +{ + AddStartMenuAction(MENU_ACTION_RETIRE); + AddStartMenuAction(MENU_ACTION_POKEDEX); + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_BAG); + AddStartMenuAction(MENU_ACTION_PLAYER); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +static void BuildStartMenuActions_Link(void) +{ + AddStartMenuAction(MENU_ACTION_POKEMON); + AddStartMenuAction(MENU_ACTION_BAG); + if (FlagGet(SYS_POKENAV_GET) == TRUE) + AddStartMenuAction(MENU_ACTION_POKENAV); + AddStartMenuAction(MENU_ACTION_PLAYER_LINK); + AddStartMenuAction(MENU_ACTION_OPTION); + AddStartMenuAction(MENU_ACTION_EXIT); +} + +//Show number of safari balls left +static void DisplaySafariBallsWindow(void) +{ + sub_8072C44(gStringVar1, gNumSafariBalls, 12, 1); + MenuDrawTextWindow(0, 0, 10, 5); + MenuPrint(gOtherText_SafariStock, 1, 1); +} + +//Prints n menu items starting at *index +static bool32 PrintStartMenuItemsMultistep(s16 *index, u32 n) +{ + int _index = *index; + + do + { + MenuPrint(sStartMenuItems[sCurrentStartMenuActions[_index]].text, 23, 2 + _index * 2); + _index++; + if (_index >= sNumStartMenuActions) + { + *index = _index; + return TRUE; + } + } + while (--n != 0); + *index = _index; + return FALSE; +} + +static bool32 InitStartMenuMultistep(s16 *step, s16 *index) +{ + switch (*step) + { + case 1: + BuildStartMenuActions(); + (*step)++; + break; + case 2: + MenuDrawTextWindow(22, 0, 29, sNumStartMenuActions * 2 + 3); + *index = 0; + (*step)++; + break; + case 3: + if (GetSafariZoneFlag()) + DisplaySafariBallsWindow(); + (*step)++; + break; + case 4: + if (PrintStartMenuItemsMultistep(index, 2)) + (*step)++; + break; + case 0: + (*step)++; + break; + case 5: + sStartMenuCursorPos = InitMenu(0, 0x17, 2, sNumStartMenuActions, sStartMenuCursorPos, 6); + return TRUE; + } + return FALSE; +} + +static void InitStartMenu(void) +{ + s16 step = 0; + s16 index = 0; + + while (InitStartMenuMultistep(&step, &index) == FALSE) + ; +} + +static void Task_StartMenu(u8 taskId) +{ + if (InitStartMenuMultistep(gTasks[taskId].data, gTasks[taskId].data + 1) == TRUE) + { + *gTasks[taskId].data = 0; + SwitchTaskToFollowupFunc(taskId); + } +} + +void CreateStartMenuTask(void (*func)(u8)) +{ + u8 taskId; + + InitMenuWindow(&gWindowConfig_81E6CE4); + taskId = CreateTask(Task_StartMenu, 0x50); + SetTaskFuncWithFollowupFunc(taskId, Task_StartMenu, func); +} + +void sub_80712B4(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + + switch (task->data[0]) + { + case 0: + gCallback_03004AE8 = StartMenu_InputProcessCallback; + task->data[0]++; + break; + case 1: + if (gCallback_03004AE8() == 1) + DestroyTask(taskId); + break; + } +} + +void sub_8071310(void) +{ + if (!is_c1_link_related_active()) + { + FreezeMapObjects(); + sub_80594C0(); + sub_80597F4(); + } + CreateStartMenuTask(sub_80712B4); + ScriptContext2_Enable(); +} + +static u8 StartMenu_InputProcessCallback(void) +{ + if (gMain.newKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + sStartMenuCursorPos = MoveMenuCursor(-1); + } + if (gMain.newKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + sStartMenuCursorPos = MoveMenuCursor(1); + } + if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if (sStartMenuItems[sCurrentStartMenuActions[sStartMenuCursorPos]].func == StartMenu_PokedexCallback) + { + if (GetNationalPokedexCount(0) == 0) + return 0; + } + gCallback_03004AE8 = sStartMenuItems[sCurrentStartMenuActions[sStartMenuCursorPos]].func; + if (gCallback_03004AE8 != StartMenu_SaveCallback && + gCallback_03004AE8 != StartMenu_ExitCallback && + gCallback_03004AE8 != StartMenu_RetireCallback) + fade_screen(1, 0); + return 0; + } + if (gMain.newKeys & (START_BUTTON | B_BUTTON)) + { + CloseMenu(); + return 1; + } + return 0; +} + +//When player selects POKEDEX +static u8 StartMenu_PokedexCallback(void) +{ + if (!gPaletteFade.active) + { + IncrementGameStat(0x29); + PlayRainSoundEffect(); + SetMainCallback2(CB2_InitPokedex); + return 1; + } + return 0; +} + +//When player selects POKEMON +static u8 StartMenu_PokemonCallback(void) +{ + if (!gPaletteFade.active) + { + PlayRainSoundEffect(); + SetMainCallback2(sub_8089A70); + return 1; + } + return 0; +} + +//When player selects BAG +static u8 StartMenu_BagCallback(void) +{ + if (!gPaletteFade.active) + { + PlayRainSoundEffect(); + SetMainCallback2(sub_80A53F8); + return 1; + } + return 0; +} + +//When player selects POKENAV +static u8 StartMenu_PokenavCallback(void) +{ + if (!gPaletteFade.active) + { + PlayRainSoundEffect(); + SetMainCallback2(sub_80EBA5C); + return 1; + } + return 0; +} + +//When player selects his/her name +static u8 StartMenu_PlayerCallback(void) +{ + if (!gPaletteFade.active) + { + PlayRainSoundEffect(); + sub_8093110(sub_805469C); + return 1; + } + return 0; +} + +//When player selects SAVE +static u8 StartMenu_SaveCallback(void) +{ + HandleDestroyMenuCursors(); + gCallback_03004AE8 = SaveCallback1; + return 0; +} + +//When player selects OPTION +static u8 StartMenu_OptionCallback(void) +{ + if (!gPaletteFade.active) + { + PlayRainSoundEffect(); + SetMainCallback2(CB2_InitOptionMenu); + gMain.savedCallback = sub_805469C; + return 1; + } + return 0; +} + +//When player selects EXIT +static u8 StartMenu_ExitCallback(void) +{ + CloseMenu(); + return 1; +} + +//When player selects RETIRE +static u8 StartMenu_RetireCallback(void) +{ + CloseMenu(); + SafariZoneRetirePrompt(); + return 1; +} + +//When player selects their name in multiplayer mode +static u8 StartMenu_PlayerLinkCallback(void) +{ + if (!gPaletteFade.active) + { + PlayRainSoundEffect(); + sub_8093130(gUnknown_03004860, sub_805469C); + return 1; + } + return 0; +} + +//Save dialog status +enum +{ + SAVE_IN_PROGRESS, + SAVE_SUCCESS, + SAVE_CANCELED, + SAVE_ERROR, +}; + +static u8 SaveCallback1(void) +{ + sub_807160C(); + gCallback_03004AE8 = SaveCallback2; + return FALSE; +} + +static u8 SaveCallback2(void) +{ + switch (RunSaveDialogCallback()) + { + case SAVE_IN_PROGRESS: + return FALSE; + case SAVE_CANCELED: + //Go back to start menu + MenuZeroFillScreen(); + InitStartMenu(); + gCallback_03004AE8 = StartMenu_InputProcessCallback; + return FALSE; + case SAVE_SUCCESS: + case SAVE_ERROR: + MenuZeroFillScreen(); + sub_8064E2C(); + ScriptContext2_Disable(); + return TRUE; + } + return FALSE; +} + +static void sub_807160C(void) +{ + save_serialize_map(); + saveDialogCallback = SaveDialogCB_DisplayConfirmMessage; + savingComplete = FALSE; +} + +static u8 RunSaveDialogCallback(void) +{ + if (savingComplete) + { + if (!MenuUpdateWindowText()) + return 0; + } + savingComplete = FALSE; + return saveDialogCallback(); +} + +void ScrSpecial_DoSaveDialog(void) +{ + sub_807160C(); + CreateTask(Task_SaveDialog, 0x50); +} + +static void DisplaySaveMessageWithCallback(const u8 *ptr, u8 (*func)(void)) +{ + StringExpandPlaceholders(gStringVar4, ptr); + MenuDisplayMessageBox(); + MenuPrintMessageDefaultCoords(gStringVar4); + savingComplete = TRUE; + saveDialogCallback = func; +} + +static void Task_SaveDialog(u8 taskId) +{ + u8 status = RunSaveDialogCallback(); + + switch (status) + { + case SAVE_CANCELED: + case SAVE_ERROR: + gScriptResult = 0; + break; + case SAVE_SUCCESS: + gScriptResult = status; + break; + case SAVE_IN_PROGRESS: + return; + } + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +static void sub_8071700(void) +{ + HandleCloseSaveWindow(0, 0); +} + +static void HideSaveDialog(void) +{ + MenuZeroFillWindowRect(20, 8, 26, 13); +} + +static void SaveDialogStartTimeout(void) +{ + saveDialogTimer = 60; +} + +static bool8 SaveDialogCheckForTimeoutOrKeypress(void) +{ + saveDialogTimer--; + if (gMain.heldKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + return TRUE; + } + else if (saveDialogTimer == 0) + return TRUE; + return FALSE; +} + +static bool8 SaveDialogCheckForTimeoutAndKeypress(void) +{ + if (saveDialogTimer != 0) + saveDialogTimer--; + else if (gMain.heldKeys & A_BUTTON) + return TRUE; + return FALSE; +} + +static u8 SaveDialogCB_DisplayConfirmMessage(void) +{ + MenuZeroFillScreen(); + HandleDrawSaveWindowInfo(0, 0); + DisplaySaveMessageWithCallback(gSaveText_WouldYouLikeToSave, SaveDialogCB_DisplayConfirmYesNoMenu); + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_DisplayConfirmYesNoMenu(void) +{ + DisplayYesNoMenu(20, 8, 1); + saveDialogCallback = SaveDialogCB_ProcessConfirmYesNoMenu; + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_ProcessConfirmYesNoMenu(void) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: //YES + HideSaveDialog(); + switch (gSaveFileStatus) + { + case 0: + case 2: + if (gDifferentSaveFile == FALSE) + { + saveDialogCallback = SaveDialogCB_SaveFileExists; + return SAVE_IN_PROGRESS; + } + saveDialogCallback = SaveDialogCB_DisplaySavingMessage; + return SAVE_IN_PROGRESS; + default: + saveDialogCallback = SaveDialogCB_SaveFileExists; + return SAVE_IN_PROGRESS; + } + break; + case -1: //B button + case 1: //NO + HideSaveDialog(); + sub_8071700(); + return SAVE_CANCELED; + } + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_SaveFileExists(void) +{ + DisplaySaveMessageWithCallback( + gDifferentSaveFile == TRUE ? gSaveText_ThereIsADifferentFile : gSaveText_ThereIsAlreadyAFile, + SaveDialogCB_DisplayOverwriteYesNoMenu); + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_DisplayOverwriteYesNoMenu(void) +{ + DisplayYesNoMenu(20, 8, 1); + saveDialogCallback = SaveDialogCB_ProcessOverwriteYesNoMenu; + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_ProcessOverwriteYesNoMenu(void) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: //YES + HideSaveDialog(); + saveDialogCallback = SaveDialogCB_DisplaySavingMessage; + break; + case -1: //B button + case 1: //NO + HideSaveDialog(); + sub_8071700(); + return SAVE_CANCELED; + } + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_DisplaySavingMessage(void) +{ + //"SAVING... DON'T TURN OFF THE POWER." + DisplaySaveMessageWithCallback(gSaveText_DontTurnOff, SaveDialogCB_DoSave); + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_DoSave(void) +{ + bool8 saveSucceeded; + + IncrementGameStat(0); + if (gDifferentSaveFile == TRUE) + { + saveSucceeded = TrySavingData(DIFFERENT_FILE_SAVE); + gDifferentSaveFile = FALSE; + } + else + { + saveSucceeded = TrySavingData(NORMAL_SAVE); + } + + if (saveSucceeded == TRUE) + { + //"(Player) saved the game." + DisplaySaveMessageWithCallback(gSaveText_PlayerSavedTheGame, SaveDialogCB_SaveSuccess); + } + else + { + //"Save error. Please exchange the backup memory." + DisplaySaveMessageWithCallback(gSystemText_SaveErrorExchangeBackup, SaveDialogCB_SaveError); + } + + SaveDialogStartTimeout(); + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_SaveSuccess(void) +{ + if (MenuUpdateWindowText()) + { + PlaySE(SE_SAVE); + saveDialogCallback = SaveDialogCB_ReturnSuccess; + } + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_ReturnSuccess(void) +{ + if (!IsSEPlaying() && SaveDialogCheckForTimeoutOrKeypress()) + { + sub_8071700(); + return SAVE_SUCCESS; + } + else + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_SaveError(void) +{ + if (MenuUpdateWindowText()) + { + PlaySE(SE_BOO); + saveDialogCallback = SaveDialogCB_ReturnError; + } + return SAVE_IN_PROGRESS; +} + +static u8 SaveDialogCB_ReturnError(void) +{ + if (!SaveDialogCheckForTimeoutAndKeypress()) + return SAVE_IN_PROGRESS; + else + { + sub_8071700(); + return SAVE_ERROR; + } +} + +static void sub_80719F0(void) +{ + TransferPlttBuffer(); +} + +static bool32 sub_80719FC(u8 *step) +{ + switch (*step) + { + case 0: + { + u8 *addr; + u32 size; + + REG_DISPCNT = 0; + SetVBlankCallback(NULL); + remove_some_task(); + DmaClear16(3, PLTT, PLTT_SIZE); + addr = (void *)VRAM; + size = 0x18000; + while (1) + { + DmaFill16(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill16(3, 0, addr, size); + break; + } + } + break; + } + case 1: + ResetSpriteData(); + ResetTasks(); + ResetPaletteFade(); + dp12_8087EA4(); + break; + case 2: + SetUpWindowConfig(&gWindowConfig_81E6CE4); + InitMenuWindow(&gWindowConfig_81E6CE4); + REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_BG0_ON; + break; + case 3: + { + u32 savedIme; + + BlendPalettes(-1, 0x10, 0); + SetVBlankCallback(sub_80719F0); + savedIme = REG_IME; + REG_IME = 0; + REG_IE |= 1; + REG_IME = savedIme; + break; + } + case 4: + return TRUE; + } + (*step)++; + return FALSE; +} + +void sub_8071B28(void) +{ + if (sub_80719FC(&gMain.state)) + { + CreateTask(Task_8071B64, 0x50); + SetMainCallback2(sub_8071B54); + } +} + +static void sub_8071B54(void) +{ + RunTasks(); + UpdatePaletteFade(); +} + +static void Task_8071B64(u8 taskId) +{ + s16 *step = gTasks[taskId].data; + + if (!gPaletteFade.active) + { + switch (*step) + { + case 0: + MenuDisplayMessageBox(); + MenuPrint(gSystemText_Saving, 2, 15); + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + (*step)++; + break; + case 1: + SetSecretBase2Field_9_AndHideBG(); + sub_8125E2C(); + (*step)++; + break; + case 2: + if (!sub_8125E6C()) + break; + ClearSecretBase2Field_9_2(); + (*step)++; + break; + case 3: + BeginNormalPaletteFade(-1, 0, 0, 0x10, 0); + (*step)++; + break; + case 4: + SetMainCallback2(gMain.savedCallback); + DestroyTask(taskId); + break; + } + } +} diff --git a/src/field/starter_choose.c b/src/field/starter_choose.c new file mode 100644 index 000000000..2b28df4f0 --- /dev/null +++ b/src/field/starter_choose.c @@ -0,0 +1,757 @@ +#include "global.h" +#include "starter_choose.h" +#include "data2.h" +#include "decompress.h" +#include "main.h" +#include "menu.h" +#include "palette.h" +#include "pokedex.h" +#include "songs.h" +#include "sound.h" +#include "species.h" +#include "sprite.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" +#include "trig.h" +#include "unknown_task.h" + +extern u16 gScriptResult; +extern struct SpriteTemplate gUnknown_02024E8C; + +//-------------------------------------------------- +// Graphics Data +//-------------------------------------------------- + +const u16 gBirchBagGrassPal[2][16] = +{ + INCBIN_U16("graphics/misc/birch_bag.gbapal"), + INCBIN_U16("graphics/misc/birch_grass.gbapal"), +}; +static const u16 gBirchBallarrow_Pal[] = INCBIN_U16("graphics/misc/birch_ballarrow.gbapal"); +static const u16 gBirchCircle_Pal[] = INCBIN_U16("graphics/misc/birch_circle.gbapal"); +const u8 gBirchBagTilemap[] = INCBIN_U8("graphics/misc/birch_bag_map.bin.lz"); +const u8 gBirchGrassTilemap[] = INCBIN_U8("graphics/misc/birch_grass_map.bin.lz"); +const u8 gBirchHelpGfx[] = INCBIN_U8("graphics/misc/birch_help.4bpp.lz"); +static const u8 gBirchBallarrow_Gfx[] = INCBIN_U8("graphics/misc/birch_ballarrow.4bpp.lz"); +static const u8 gBirchCircle_Gfx[] = INCBIN_U8("graphics/misc/birch_circle.4bpp.lz"); +static const u8 gStarterChoose_PokeballCoords[][2] = +{ + {60, 64}, + {120, 88}, + {180, 64}, +}; +static const u8 gStarterChoose_LabelCoords[][2] = +{ + {0, 9}, + {16, 10}, + {8, 4}, +}; +static const u16 sStarterMons[] = {SPECIES_TREECKO, SPECIES_TORCHIC, SPECIES_MUDKIP}; +static const struct OamData gOamData_83F76CC = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; +static const struct OamData gOamData_83F76D4 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 2, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; +static const struct OamData gOamData_83F76DC = +{ + .y = 160, + .affineMode = 3, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; +static const u8 gUnknown_083F76E4[][2] = +{ + {60, 32}, + {120, 56}, + {180, 32}, + {0, 0}, +}; +static const union AnimCmd gSpriteAnim_83F76EC[] = +{ + ANIMCMD_FRAME(48, 30), + ANIMCMD_END, +}; +static const union AnimCmd gSpriteAnim_83F76F4[] = +{ + ANIMCMD_FRAME(0, 30), + ANIMCMD_END, +}; +static const union AnimCmd gSpriteAnim_83F76FC[] = +{ + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(16, 4), + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(32, 4), + ANIMCMD_FRAME(0, 4), + ANIMCMD_FRAME(0, 32), + ANIMCMD_FRAME(16, 8), + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(32, 8), + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(16, 8), + ANIMCMD_FRAME(0, 8), + ANIMCMD_FRAME(32, 8), + ANIMCMD_FRAME(0, 8), + ANIMCMD_JUMP(0), +}; +static const union AnimCmd gSpriteAnim_83F7744[] = +{ + ANIMCMD_FRAME(0, 8), + ANIMCMD_END, +}; +static const union AnimCmd *const gSpriteAnimTable_83F774C[] = +{ + gSpriteAnim_83F76EC, +}; +static const union AnimCmd *const gSpriteAnimTable_83F7750[] = +{ + gSpriteAnim_83F76F4, + gSpriteAnim_83F76FC, +}; +static const union AnimCmd *const gSpriteAnimTable_83F7758[] = +{ + gSpriteAnim_83F7744, +}; +static const union AffineAnimCmd gSpriteAffineAnim_83F775C[] = +{ + AFFINEANIMCMD_FRAME(16, 16, 0, 0), + AFFINEANIMCMD_FRAME(16, 16, 0, 15), + AFFINEANIMCMD_END, +}; +static const union AffineAnimCmd gSpriteAffineAnim_83F7774[] = +{ + AFFINEANIMCMD_FRAME(20, 20, 0, 0), + AFFINEANIMCMD_FRAME(20, 20, 0, 15), + AFFINEANIMCMD_END, +}; +static const union AffineAnimCmd *const gSpriteAffineAnimTable_83F778C[] = +{ + gSpriteAffineAnim_83F775C, +}; +static const union AffineAnimCmd *const gSpriteAffineAnimTable_83F7790[] = +{ + gSpriteAffineAnim_83F7774, +}; +static const struct CompressedSpriteSheet gUnknown_083F7794[] = +{ + {gBirchBallarrow_Gfx, 0x0800, 0x1000}, + {NULL}, +}; +static const struct CompressedSpriteSheet gUnknown_083F77A4[] = +{ + {gBirchCircle_Gfx, 0x0800, 0x1001}, + {NULL}, +}; +const struct SpritePalette gUnknown_083F77B4[] = +{ + {gBirchBallarrow_Pal, 0x1000}, + {gBirchCircle_Pal, 0x1001}, + {NULL}, +}; +static void sub_810A62C(struct Sprite *sprite); +static const struct SpriteTemplate gSpriteTemplate_83F77CC = +{ + .tileTag = 4096, + .paletteTag = 4096, + .oam = &gOamData_83F76CC, + .anims = gSpriteAnimTable_83F774C, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810A62C, +}; +static void sub_810A68C(struct Sprite *sprite); +static const struct SpriteTemplate gSpriteTemplate_83F77E4 = +{ + .tileTag = 4096, + .paletteTag = 4096, + .oam = &gOamData_83F76D4, + .anims = gSpriteAnimTable_83F7750, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810A68C, +}; +static void StarterPokemonSpriteAnimCallback(struct Sprite *sprite); +static const struct SpriteTemplate gSpriteTemplate_83F77FC = +{ + .tileTag = 4097, + .paletteTag = 4097, + .oam = &gOamData_83F76DC, + .anims = gSpriteAnimTable_83F7758, + .images = NULL, + .affineAnims = gSpriteAffineAnimTable_83F7790, + .callback = StarterPokemonSpriteAnimCallback, +}; + +static void MainCallback2(void); +static void Task_StarterChoose1(u8 taskId); +static void Task_StarterChoose2(u8 taskId); +static void Task_StarterChoose3(u8 taskId); +static void Task_StarterChoose4(u8 taskId); +static void Task_StarterChoose5(u8 taskId); +static void Task_StarterChoose6(u8 taskId); + +static void CreateStarterPokemonLabel(u8, u8); +static u8 CreatePokemonFrontSprite(u16, u8, u8); + +//Position of the sprite of the selected starter Pokemon +#define STARTER_PKMN_POS_X 120 +#define STARTER_PKMN_POS_Y 64 + +//Retrieves one of the available starter Pokemon +u16 GetStarterPokemon(u16 n) +{ + if (n > 3) + n = 0; + return sStarterMons[n]; +} + +static void VblankCallback(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +#define tStarterSelection data[0] +#define tPkmnSpriteId data[1] +#define tCircleSpriteId data[2] + +void CB2_ChooseStarter(void) +{ + u16 savedIme; + u8 taskId; + u8 spriteId; + + SetVBlankCallback(NULL); + + REG_DISPCNT = 0; + REG_BG3CNT = 0; + REG_BG2CNT = 0; + REG_BG1CNT = 0; + REG_BG0CNT = 0; + REG_BG3HOFS = 0; + REG_BG3VOFS = 0; + REG_BG2HOFS = 0; + REG_BG2VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + + DmaFill16(3, 0, VRAM, VRAM_SIZE); + DmaFill32(3, 0, OAM, OAM_SIZE); + DmaFill16(3, 0, PLTT, PLTT_SIZE); + + LZ77UnCompVram(&gBirchHelpGfx, (void *)VRAM); + LZ77UnCompVram(&gBirchBagTilemap, (void *)(VRAM + 0x3000)); + LZ77UnCompVram(&gBirchGrassTilemap, (void *)(VRAM + 0x3800)); + remove_some_task(); + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + FreeAllSpritePalettes(); + LoadPalette(gBirchBagGrassPal, 0, sizeof(gBirchBagGrassPal)); + LoadCompressedObjectPic(&gUnknown_083F7794[0]); + LoadCompressedObjectPic(&gUnknown_083F77A4[0]); + LoadSpritePalettes(gUnknown_083F77B4); + SetUpWindowConfig(&gWindowConfig_81E6C3C); + InitMenuWindow(&gWindowConfig_81E6CE4); + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + + savedIme = REG_IME; + REG_IME = 0; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = savedIme; + REG_DISPSTAT |= DISPSTAT_VBLANK_INTR; + + SetVBlankCallback(VblankCallback); + SetMainCallback2(MainCallback2); + + REG_WININ = 0x3F; + REG_WINOUT = 0x1F; + REG_WIN0H = 0; + REG_WIN0V = 0; + REG_BLDCNT = 0xFE; + REG_BLDALPHA = 0; + REG_BLDY = 0x7; + REG_BG3CNT = BGCNT_PRIORITY(3) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(7) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_BG2CNT = BGCNT_PRIORITY(2) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(6) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_BG0CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(2) | BGCNT_SCREENBASE(31) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | DISPCNT_BG2_ON | DISPCNT_BG3_ON | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON; + + taskId = CreateTask(Task_StarterChoose1, 0); + gTasks[taskId].tStarterSelection = 1; + + //Create hand sprite + spriteId = CreateSprite(&gSpriteTemplate_83F77CC, 120, 56, 2); + gSprites[spriteId].data0 = taskId; + + //Create three Pokeball sprites + spriteId = CreateSprite( + &gSpriteTemplate_83F77E4, + gStarterChoose_PokeballCoords[0][0], gStarterChoose_PokeballCoords[0][1], 2); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].data1 = 0; + spriteId = CreateSprite( + &gSpriteTemplate_83F77E4, + gStarterChoose_PokeballCoords[1][0], gStarterChoose_PokeballCoords[1][1], 2); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].data1 = 1; + spriteId = CreateSprite( + &gSpriteTemplate_83F77E4, + gStarterChoose_PokeballCoords[2][0], gStarterChoose_PokeballCoords[2][1], 2); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].data1 = 2; +} + +static void MainCallback2(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void Task_StarterChoose1(u8 taskId) +{ + CreateStarterPokemonLabel(0xFF, gTasks[taskId].tStarterSelection); + MenuDrawTextWindow(2, 14, 27, 19); + MenuPrint(gOtherText_BirchInTrouble, 3, 15); + gTasks[taskId].func = Task_StarterChoose2; +} + +static void Task_StarterChoose2(u8 taskId) +{ + u8 selection = gTasks[taskId].tStarterSelection; + + if (gMain.newKeys & A_BUTTON) + { + u8 spriteId; + + MenuZeroFillWindowRect( + gStarterChoose_LabelCoords[selection][0], + gStarterChoose_LabelCoords[selection][1], + gStarterChoose_LabelCoords[selection][0] + 13, + gStarterChoose_LabelCoords[selection][1] + 3); + + REG_WIN0H = 0; + REG_WIN0V = 0; + + //Create white circle background + spriteId = CreateSprite( + &gSpriteTemplate_83F77FC, + gStarterChoose_PokeballCoords[selection][0], + gStarterChoose_PokeballCoords[selection][1], + 1); + gTasks[taskId].tCircleSpriteId = spriteId; + + //Create Pokemon sprite + spriteId = CreatePokemonFrontSprite( + GetStarterPokemon(gTasks[taskId].tStarterSelection), + gStarterChoose_PokeballCoords[selection][0], + gStarterChoose_PokeballCoords[selection][1]); + gSprites[spriteId].affineAnims = gSpriteAffineAnimTable_83F778C; + gSprites[spriteId].callback = StarterPokemonSpriteAnimCallback; + gTasks[taskId].tPkmnSpriteId = spriteId; + + gTasks[taskId].func = Task_StarterChoose3; + } + else + { + if ((gMain.newKeys & DPAD_LEFT) && selection > 0) + { + gTasks[taskId].tStarterSelection--; + CreateStarterPokemonLabel(selection, gTasks[taskId].tStarterSelection); + } + else if ((gMain.newKeys & DPAD_RIGHT) && selection < 2) + { + gTasks[taskId].tStarterSelection++; + CreateStarterPokemonLabel(selection, gTasks[taskId].tStarterSelection); + } + } +} + +static void Task_StarterChoose3(u8 taskId) +{ + if (gSprites[gTasks[taskId].tCircleSpriteId].affineAnimEnded && + gSprites[gTasks[taskId].tCircleSpriteId].pos1.x == STARTER_PKMN_POS_X && + gSprites[gTasks[taskId].tCircleSpriteId].pos1.y == STARTER_PKMN_POS_Y) + { + gTasks[taskId].func = Task_StarterChoose4; + } +} + +static void Task_StarterChoose4(u8 taskId) +{ + PlayCry1(GetStarterPokemon(gTasks[taskId].tStarterSelection), 0); + MenuDrawTextWindow(2, 14, 27, 19); + //"Do you choose this POKEMON?" + MenuPrint(gOtherText_DoYouChoosePoke, 3, 15); + DisplayYesNoMenu(21, 7, 1); + gTasks[taskId].func = Task_StarterChoose5; +} + +static void Task_StarterChoose5(u8 taskId) +{ + u8 spriteId; + + switch (ProcessMenuInputNoWrap_()) + { + case 0: // YES + //Return the starter choice and exit. + gScriptResult = gTasks[taskId].tStarterSelection; + SetMainCallback2(gMain.savedCallback); + break; + case 1: // NO + case -1: // B button + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(21, 7, 27, 12); + + spriteId = gTasks[taskId].tPkmnSpriteId; + FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(gSprites[spriteId].oam.paletteNum)); + FreeOamMatrix(gSprites[spriteId].oam.matrixNum); + DestroySprite(&gSprites[spriteId]); + + spriteId = gTasks[taskId].tCircleSpriteId; + FreeOamMatrix(gSprites[spriteId].oam.matrixNum); + DestroySprite(&gSprites[spriteId]); + gTasks[taskId].func = Task_StarterChoose6; + break; + } +} + +static void Task_StarterChoose6(u8 taskId) +{ + gTasks[taskId].func = Task_StarterChoose1; +} + +void AddTextColorCtrlCode(u8 *string, u8 bgColor, u8 textColor, u8 shadowColor) +{ + *(string++) = EXT_CTRL_CODE_BEGIN; + *(string++) = 4; + *(string++) = textColor; + *(string++) = bgColor; + *(string++) = shadowColor; +} + +#define SET_CHAR(str, index, c) \ +{ \ + u8 *p = str + index; \ + *p = c; \ +} + + +#if ENGLISH +static void CreateStarterPokemonLabel(u8 prevSelection, u8 selection) +{ + u8 labelText[72]; + const u8 *category; + u8 srcIndex; + u8 dstIndex; + u16 species; + + u8 labelLeft; + u8 labelRight; + u8 labelTop; + u8 labelBottom; + + if (prevSelection != 0xFF) + { + //Remove the old Pokemon label + MenuZeroFillWindowRect( + gStarterChoose_LabelCoords[prevSelection][0], + gStarterChoose_LabelCoords[prevSelection][1], + gStarterChoose_LabelCoords[prevSelection][0] + 13, + gStarterChoose_LabelCoords[prevSelection][1] + 3); + REG_WIN0H = 0; + REG_WIN0V = 0; + } + species = GetStarterPokemon(selection); + category = GetPokemonCategory(SpeciesToNationalPokedexNum(species)); + AddTextColorCtrlCode(labelText, 0, 15, 8); + dstIndex = 5; + SET_CHAR(labelText, 5, EXT_CTRL_CODE_BEGIN); + SET_CHAR(labelText, 6, 0x11); + SET_CHAR(labelText, 7, dstIndex); + + //Copy category string to label + dstIndex = 8; + srcIndex = 0; + while (category[srcIndex] != EOS && srcIndex <= 10) + { + labelText[dstIndex] = category[srcIndex]; + srcIndex++; + dstIndex++; + } + labelText[dstIndex++] = CHAR_SPACE; + + //Copy POKEMON string to label + StringCopy(labelText + dstIndex, gOtherText_Poke); + MenuPrint( + labelText, + gStarterChoose_LabelCoords[selection][0], + gStarterChoose_LabelCoords[selection][1]); + AddTextColorCtrlCode(labelText, 0, 15, 8); + + //Copy Pokemon name to label + sub_8072C74(labelText + 5, gSpeciesNames[species], 0x6B, 1); + MenuPrint( + labelText, + gStarterChoose_LabelCoords[selection][0], + gStarterChoose_LabelCoords[selection][1] + 2); + + labelLeft = gStarterChoose_LabelCoords[selection][0] * 8 + 4; + labelRight = (gStarterChoose_LabelCoords[selection][0] + 13) * 8 + 4; + labelTop = gStarterChoose_LabelCoords[selection][1] * 8; + labelBottom = (gStarterChoose_LabelCoords[selection][1] + 4) * 8; + REG_WIN0H = WIN_RANGE(labelLeft, labelRight); + REG_WIN0V = WIN_RANGE(labelTop, labelBottom); +} +#elif GERMAN +__attribute__((naked)) +static void CreateStarterPokemonLabel(u8 prevSelection, u8 selection) +{ + asm(".syntax unified\n\ + push {r4-r7,lr}\n\ + sub sp, 0x48\n\ + lsls r0, 24\n\ + lsrs r0, 24\n\ + lsls r1, 24\n\ + lsrs r5, r1, 24\n\ + cmp r0, 0xFF\n\ + beq _0810A872\n\ + ldr r1, _0810A960 @ =gStarterChoose_LabelCoords\n\ + lsls r2, r0, 1\n\ + adds r0, r2, r1\n\ + ldrb r0, [r0]\n\ + adds r1, 0x1\n\ + adds r2, r1\n\ + ldrb r1, [r2]\n\ + adds r2, r0, 0\n\ + adds r2, 0xD\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + adds r3, r1, 0x3\n\ + lsls r3, 24\n\ + lsrs r3, 24\n\ + bl MenuZeroFillWindowRect\n\ + ldr r0, _0810A964 @ =0x04000040\n\ + movs r1, 0\n\ + strh r1, [r0]\n\ + adds r0, 0x4\n\ + strh r1, [r0]\n\ +_0810A872:\n\ + adds r0, r5, 0\n\ + bl GetStarterPokemon\n\ + lsls r0, 16\n\ + lsrs r6, r0, 16\n\ + adds r0, r6, 0\n\ + bl SpeciesToNationalPokedexNum\n\ + lsls r0, 16\n\ + lsrs r0, 16\n\ + bl GetPokemonCategory\n\ + adds r4, r0, 0\n\ + mov r0, sp\n\ + movs r1, 0\n\ + movs r2, 0xF\n\ + movs r3, 0x8\n\ + bl AddTextColorCtrlCode\n\ + movs r2, 0x8\n\ + movs r3, 0\n\ + ldrb r0, [r4]\n\ + lsls r5, 1\n\ + mov r7, sp\n\ + adds r7, 0x5\n\ + cmp r0, 0xFF\n\ + beq _0810A8CA\n\ +_0810A8A8:\n\ + mov r0, sp\n\ + adds r1, r0, r2\n\ + adds r0, r4, r3\n\ + ldrb r0, [r0]\n\ + strb r0, [r1]\n\ + adds r0, r3, 0x1\n\ + lsls r0, 24\n\ + lsrs r3, r0, 24\n\ + adds r0, r2, 0x1\n\ + lsls r0, 24\n\ + lsrs r2, r0, 24\n\ + adds r0, r4, r3\n\ + ldrb r0, [r0]\n\ + cmp r0, 0xFF\n\ + beq _0810A8CA\n\ + cmp r3, 0xA\n\ + bls _0810A8A8\n\ +_0810A8CA:\n\ + mov r0, sp\n\ + adds r1, r0, r2\n\ + movs r0, 0xFF\n\ + strb r0, [r1]\n\ + mov r1, sp\n\ + movs r0, 0xFC\n\ + strb r0, [r1, 0x5]\n\ + movs r0, 0x11\n\ + strb r0, [r1, 0x6]\n\ + mov r2, sp\n\ + lsls r1, r3, 1\n\ + adds r1, r3\n\ + lsls r1, 1\n\ + movs r0, 0x70\n\ + subs r0, r1\n\ + asrs r0, 1\n\ + strb r0, [r2, 0x7]\n\ + ldr r0, _0810A960 @ =gStarterChoose_LabelCoords\n\ + adds r1, r5, r0\n\ + ldrb r4, [r1]\n\ + adds r0, 0x1\n\ + adds r0, r5, r0\n\ + ldrb r5, [r0]\n\ + mov r0, sp\n\ + adds r1, r4, 0\n\ + adds r2, r5, 0\n\ + bl MenuPrint\n\ + mov r0, sp\n\ + movs r1, 0\n\ + movs r2, 0xF\n\ + movs r3, 0x8\n\ + bl AddTextColorCtrlCode\n\ + movs r0, 0xB\n\ + adds r1, r6, 0\n\ + muls r1, r0\n\ + ldr r0, _0810A968 @ =gSpeciesNames\n\ + adds r1, r0\n\ + adds r0, r7, 0\n\ + movs r2, 0x70\n\ + movs r3, 0x2\n\ + bl sub_8072C74\n\ + adds r2, r5, 0x2\n\ + lsls r2, 24\n\ + lsrs r2, 24\n\ + mov r0, sp\n\ + adds r1, r4, 0\n\ + bl MenuPrint\n\ + lsls r0, r4, 3\n\ + adds r0, 0x4\n\ + lsls r0, 24\n\ + adds r4, 0xD\n\ + lsls r4, 3\n\ + adds r4, 0x4\n\ + lsls r4, 24\n\ + lsrs r4, 24\n\ + lsls r1, r5, 27\n\ + adds r5, 0x4\n\ + lsls r5, 27\n\ + lsrs r5, 24\n\ + ldr r2, _0810A964 @ =0x04000040\n\ + lsrs r0, 16\n\ + orrs r0, r4\n\ + strh r0, [r2]\n\ + ldr r0, _0810A96C @ =0x04000044\n\ + lsrs r1, 16\n\ + orrs r1, r5\n\ + strh r1, [r0]\n\ + add sp, 0x48\n\ + pop {r4-r7}\n\ + pop {r0}\n\ + bx r0\n\ + .align 2, 0\n\ +_0810A960: .4byte gStarterChoose_LabelCoords\n\ +_0810A964: .4byte 0x04000040\n\ +_0810A968: .4byte gSpeciesNames\n\ +_0810A96C: .4byte 0x04000044\n\ + .syntax divided\n"); +} +#endif + +static void nullsub_72(struct Sprite *sprite) +{ +} + +static u8 CreatePokemonFrontSprite(u16 species, u8 x, u8 y) +{ + u8 spriteId; + + DecompressPicFromTable_2( + &gMonFrontPicTable[species], + gMonFrontPicCoords[species].coords, gMonFrontPicCoords[species].y_offset, + gUnknown_081FAF4C[0], gUnknown_081FAF4C[1], + species); + LoadCompressedObjectPalette(&gMonPaletteTable[species]); + GetMonSpriteTemplate_803C56C(species, 1); + spriteId = CreateSprite(&gUnknown_02024E8C, x, y, 0); + gSprites[spriteId].callback = nullsub_72; + gSprites[spriteId].oam.priority = 0; + return spriteId; +} + +//Sprite callback +static void sub_810A62C(struct Sprite *sprite) +{ + sprite->pos1.x = gUnknown_083F76E4[gTasks[sprite->data0].tStarterSelection][0]; + sprite->pos1.y = gUnknown_083F76E4[gTasks[sprite->data0].tStarterSelection][1]; + sprite->pos2.y = Sin(sprite->data1, 8); + sprite->data1 = (u8)sprite->data1 + 4; +} + +//Sprite callback +static void sub_810A68C(struct Sprite *sprite) +{ + if (gTasks[sprite->data0].tStarterSelection == sprite->data1) + StartSpriteAnimIfDifferent(sprite, 1); + else + StartSpriteAnimIfDifferent(sprite, 0); +} + +//Sprite callback +static void StarterPokemonSpriteAnimCallback(struct Sprite *sprite) +{ + //Move sprite to upper center of screen + if (sprite->pos1.x > STARTER_PKMN_POS_X) + sprite->pos1.x -= 4; + if (sprite->pos1.x < STARTER_PKMN_POS_X) + sprite->pos1.x += 4; + if (sprite->pos1.y > STARTER_PKMN_POS_Y) + sprite->pos1.y -= 2; + if (sprite->pos1.y < STARTER_PKMN_POS_Y) + sprite->pos1.y += 2; +} diff --git a/src/field/trader.c b/src/field/trader.c new file mode 100644 index 000000000..61f48fad8 --- /dev/null +++ b/src/field/trader.c @@ -0,0 +1,262 @@ +#include "global.h" +#include "decoration.h" +#include "decoration_inventory.h" +#include "event_data.h" +#include "main.h" +#include "mauville_man.h" +#include "menu.h" +#include "menu_helpers.h" +#include "script.h" +#include "songs.h" +#include "sound.h" +#include "string_util.h" +#include "strings.h" +#include "task.h" + +extern u16 gSpecialVar_0x8004; +extern u16 gSpecialVar_0x8005; +extern u16 gSpecialVar_0x8006; + +static const u8 * const gUnknown_083F62D8[] = +{ + SecretBaseText_Tristan, + SecretBaseText_Philip, + SecretBaseText_Dennis, + SecretBaseText_Roberto, +}; + +static const u8 gTraderDecorations[] = +{ + DECOR_DUSKULL_DOLL, + DECOR_BALL_CUSHION, + DECOR_TIRE, + DECOR_PRETTY_FLOWERS, +}; + +void sub_810993C(void) +{ + u8 i, j; + u8 buffer[12]; + struct MauvilleManTrader *trader = &gSaveBlock1.mauvilleMan.trader; + + for (i = 0; i < 3; i++) + { + for (j = i + 1; j < 4; j++) + { + if (trader->unk1[i] == 0) + { + u8 temp = trader->unk1[i]; + trader->unk1[i] = trader->unk1[j]; + trader->unk1[j] = temp; + StringCopy(buffer, trader->unk5[i]); + StringCopy(trader->unk5[i], trader->unk5[j]); + StringCopy(trader->unk5[j], buffer); + } + } + } +} + +void TraderSetup(void) +{ + u8 i; + struct MauvilleManTrader *trader = &gSaveBlock1.mauvilleMan.trader; + + trader->id = MAUVILLE_MAN_TRADER; + trader->alreadyTraded = FALSE; + + for (i = 0; i < 4; i++) + { + StringCopy(trader->unk5[i], gUnknown_083F62D8[i]); + trader->unk1[i] = gTraderDecorations[i]; + } + + sub_810993C(); +} + +void sub_8109A20(void) +{ + struct MauvilleManTrader *trader = &gSaveBlock1.mauvilleMan.trader; + trader->alreadyTraded = FALSE; +} + +void sub_8109A30(u8 value) +{ + VarSet(VAR_RECYCLE_GOODS, value); +} + +void CreateAvailableDecorationsMenu(u8 taskId) +{ + u8 i; + u8 numChoices = 1; + u8 numDecorations = 0; + struct MauvilleManTrader *trader = &gSaveBlock1.mauvilleMan.trader; + + for (i = 0; i < 4; i++) + { + if (trader->unk1[i]) + { + numChoices++; + } + } + + MenuDrawTextWindow(0, 1, 12, numChoices * 2 + 2); + + for (i = 0; i < 4; i++) + { + if (trader->unk1[i]) + { + if (trader->unk1[i] > DECOR_REGISTEEL_DOLL) + { + MenuPrint(gOtherText_FiveQuestionsAndSlash, 1, numDecorations * 2 + 2); + } + else + { + MenuPrint(gDecorations[trader->unk1[i]].name, 1, numDecorations * 2 + 2); + } + + numDecorations++; + } + } + + MenuPrint(gOtherText_CancelNoTerminator, 1, numDecorations * 2 + 2); + InitMenu(0, 1, 2, numChoices, 0, 11); + gTasks[taskId].data[1] = numDecorations; +} + +void sub_8109B34(u8 taskId, u8 decorationId) +{ + if (decorationId > DECOR_REGISTEEL_DOLL) + { + gSpecialVar_0x8004 = 0xFFFF; + } + else + { + gSpecialVar_0x8004 = decorationId; + } + + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 1, 12, 12); + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +void Task_HandleGetDecorationMenuInput(u8 taskId) +{ + struct MauvilleManTrader *trader = &gSaveBlock1.mauvilleMan.trader; + + if (gMain.newKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + MoveMenuCursor(-1); + } + else if (gMain.newKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + MoveMenuCursor(1); + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + gSpecialVar_0x8005 = GetMenuCursorPos(); + if (gTasks[taskId].data[1] == gSpecialVar_0x8005) + { + sub_8109B34(taskId, 0); + } + else + { + StringCopy(gStringVar1, trader->unk5[gSpecialVar_0x8005]); + sub_8109B34(taskId, trader->unk1[gSpecialVar_0x8005]); + } + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + sub_8109B34(taskId, 0); + } +} + +void ScrSpecial_GetTraderTradedFlag(void) +{ + struct MauvilleManTrader *trader = &gSaveBlock1.mauvilleMan.trader; + gScriptResult = trader->alreadyTraded; +} + +void ScrSpecial_DoesPlayerHaveNoDecorations(void) +{ + u8 i; + + for (i = 0; i < 8; i++) + { + if (sub_8134194(i)) + { + gScriptResult = FALSE; + return; + } + } + gScriptResult = TRUE; +} + +void ScrSpecial_IsDecorationFull(void) +{ + gScriptResult = FALSE; + if (gDecorations[gSpecialVar_0x8004].category != gDecorations[gSpecialVar_0x8006].category + && sub_8133F9C(gDecorations[gSpecialVar_0x8004].category) == -1) + { + sub_80FE7D4(gStringVar2, gDecorations[gSpecialVar_0x8004].category); + gScriptResult = TRUE; + } +} + +void ScrSpecial_TraderMenuGiveDecoration(void) +{ + CreateTask(sub_80FE7A8, 0); +} + +void sub_8109D04(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 29, 19); + DestroyVerticalScrollIndicator(0); + DestroyVerticalScrollIndicator(1); + sub_80F9520(gUnknown_020388F7, 8); + BuyMenuFreeMemory(); + if (sub_80FEFA4() == TRUE) + { + gSpecialVar_0x8006 = gUnknown_020388D0[gUnknown_020388F5]; + StringCopy(gStringVar3, gDecorations[gSpecialVar_0x8004].name); + StringCopy(gStringVar2, gDecorations[gSpecialVar_0x8006].name); + } + else + { + gSpecialVar_0x8006 = 0xFFFF; + } + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +void sub_8109DAC(u8 taskId) +{ + HandleDestroyMenuCursors(); + MenuZeroFillWindowRect(0, 0, 29, 19); + gSpecialVar_0x8006 = 0; + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +void ScrSpecial_TraderDoDecorationTrade(void) +{ + struct MauvilleManTrader *trader = &gSaveBlock1.mauvilleMan.trader; + + sub_81340A8(gSpecialVar_0x8006); + IsThereStorageSpaceForDecoration(gSpecialVar_0x8004); + StringCopy(trader->unk5[gSpecialVar_0x8005], gSaveBlock2.playerName); + trader->unk1[gSpecialVar_0x8005] = gSpecialVar_0x8006; + sub_810993C(); + trader->alreadyTraded = TRUE; +} + +void ScrSpecial_TraderMenuGetDecoration(void) +{ + u8 taskId = CreateTask(Task_HandleGetDecorationMenuInput, 0); + CreateAvailableDecorationsMenu(taskId); +} diff --git a/src/field/trainer_see.c b/src/field/trainer_see.c new file mode 100644 index 000000000..5a8ebbafc --- /dev/null +++ b/src/field/trainer_see.c @@ -0,0 +1,519 @@ +#include "global.h" +#include "trainer_see.h" +#include "battle_setup.h" +#include "field_effect.h" +#include "field_map_obj.h" +#include "field_player_avatar.h" +#include "script.h" +#include "sprite.h" +#include "task.h" +#include "util.h" + +const u8 gSpriteImage_839B308[] = INCBIN_U8("graphics/unknown_sprites/839B4E0/0.4bpp"); +const u8 gSpriteImage_839B388[] = INCBIN_U8("graphics/unknown_sprites/839B4E0/1.4bpp"); +const u8 gSpriteImage_839B408[] = INCBIN_U8("graphics/unknown_sprites/839B408.4bpp"); + +u8 GetTrainerApproachDistanceSouth(struct MapObject *trainerObj, s16 range, s16 x, s16 y); +u8 GetTrainerApproachDistanceNorth(struct MapObject *trainerObj, s16 range, s16 x, s16 y); +u8 GetTrainerApproachDistanceWest(struct MapObject *trainerObj, s16 range, s16 x, s16 y); +u8 GetTrainerApproachDistanceEast(struct MapObject *trainerObj, s16 range, s16 x, s16 y); + +static u8 (*const sDirectionalApproachDistanceFuncs[])(struct MapObject *, s16, s16, s16) = +{ + GetTrainerApproachDistanceSouth, + GetTrainerApproachDistanceNorth, + GetTrainerApproachDistanceWest, + GetTrainerApproachDistanceEast, +}; + +extern struct SpriteTemplate gSpriteTemplate_839B510; +extern struct SpriteTemplate gSpriteTemplate_839B528; + +bool8 CheckTrainers(void) +{ + u8 mapObjId; + + for (mapObjId = 0; mapObjId < 16; mapObjId++) + { + if (gMapObjects[mapObjId].active + && (gMapObjects[mapObjId].trainerType == 1 || gMapObjects[mapObjId].trainerType == 3) + && CheckTrainer(mapObjId)) + return TRUE; + } + return FALSE; +} + +bool8 CheckTrainer(u8 mapObjId) +{ + u8 *scriptPtr = GetFieldObjectScriptPointerByFieldObjectId(mapObjId); + + if (GetTrainerFlagFromScriptPointer(scriptPtr)) + { + return FALSE; + } + else + { + struct MapObject *trainerObj = &gMapObjects[mapObjId]; + bool8 canApproach = TrainerCanApproachPlayer(trainerObj); + + if (canApproach) + { + TrainerWantsBattle(mapObjId, scriptPtr); + sub_80842C8(trainerObj, (canApproach - 1)); + return TRUE; + } + else + { + return FALSE; + } + } +} + +bool8 TrainerCanApproachPlayer(struct MapObject *trainerObj) +{ + s16 x, y; + u8 i; + u8 approachDistance; + + PlayerGetDestCoords(&x, &y); + if (trainerObj->trainerType == 1) // can only see in one direction + { + approachDistance = sDirectionalApproachDistanceFuncs[trainerObj->mapobj_unk_18 - 1](trainerObj, trainerObj->trainerRange_berryTreeId, x, y); + return CheckPathBetweenTrainerAndPlayer((struct MapObject2 *)trainerObj, approachDistance, trainerObj->mapobj_unk_18); + } + else // can see in all directions + { + for (i = 0; i < 4; i++) + { + approachDistance = sDirectionalApproachDistanceFuncs[i](trainerObj, trainerObj->trainerRange_berryTreeId, x, y); + if (CheckPathBetweenTrainerAndPlayer((struct MapObject2 *)trainerObj, approachDistance, i + 1)) // directions are 1-4 instead of 0-3. south north west east + return approachDistance; + } + } + return FALSE; +} + +// Returns how far south the player is from trainer. 0 if out of trainer's sight. +u8 GetTrainerApproachDistanceSouth(struct MapObject *trainerObj, s16 range, s16 x, s16 y) +{ + if (trainerObj->coords2.x == x + && y > trainerObj->coords2.y + && y <= trainerObj->coords2.y + range) + return (y - trainerObj->coords2.y); + else + return 0; +} + +// Returns how far north the player is from trainer. 0 if out of trainer's sight. +u8 GetTrainerApproachDistanceNorth(struct MapObject *trainerObj, s16 range, s16 x, s16 y) +{ + if (trainerObj->coords2.x == x + && y < trainerObj->coords2.y + && y >= trainerObj->coords2.y - range) + return (trainerObj->coords2.y - y); + else + return 0; +} + +// Returns how far west the player is from trainer. 0 if out of trainer's sight. +u8 GetTrainerApproachDistanceWest(struct MapObject *trainerObj, s16 range, s16 x, s16 y) +{ + if (trainerObj->coords2.y == y + && x < trainerObj->coords2.x + && x >= trainerObj->coords2.x - range) + return (trainerObj->coords2.x - x); + else + return 0; +} + +// Returns how far east the player is from trainer. 0 if out of trainer's sight. +u8 GetTrainerApproachDistanceEast(struct MapObject *trainerObj, s16 range, s16 x, s16 y) +{ + if (trainerObj->coords2.y == y + && x > trainerObj->coords2.x + && x <= trainerObj->coords2.x + range) + return (x - trainerObj->coords2.x); + else + return 0; +} + +#ifdef BUGFIX_TRAINERAPPROACH +#define COLLISION_MASK ~1 +#else +#define COLLISION_MASK 1 +#endif + +bool8 CheckPathBetweenTrainerAndPlayer(struct MapObject2 *trainerObj, u8 approachDistance, u8 direction) +{ + s16 x, y; + u8 unk19_temp; + u8 unk19b_temp; + u8 i; + u8 collision; + + if (approachDistance == 0) + return FALSE; + + x = trainerObj->coords2.x; + y = trainerObj->coords2.y; + + for (i = 0; i <= approachDistance - 1; i++, MoveCoords(direction, &x, &y)) + { + collision = sub_8060024((struct MapObject *)trainerObj, x, y, direction); + if (collision != 0 && (collision & COLLISION_MASK)) + return FALSE; + } + + // preserve mapobj_unk_19 before clearing. + unk19_temp = trainerObj->mapobj_unk_19; + unk19b_temp = trainerObj->mapobj_unk_19b; + trainerObj->mapobj_unk_19 = 0; + trainerObj->mapobj_unk_19b = 0; + + collision = npc_block_way((struct MapObject *)trainerObj, x, y, direction); + + trainerObj->mapobj_unk_19 = unk19_temp; + trainerObj->mapobj_unk_19b = unk19b_temp; + if (collision == 4) + return approachDistance; + + return FALSE; +} + +#define tTrainerObjHi data[1] +#define tTrainerObjLo data[2] + +void sub_80842C8(struct MapObject *trainerObj, u8 b) +{ + u8 taskId = CreateTask(RunTrainerSeeFuncList, 0x50); + struct Task *task = &gTasks[taskId]; + + task->tTrainerObjHi = (u32)(trainerObj) >> 16; + task->tTrainerObjLo = (u32)(trainerObj); + task->data[3] = b; +} + +void sub_80842FC(TaskFunc followupFunc) +{ + TaskFunc taskFunc = RunTrainerSeeFuncList; + u8 taskId = FindTaskIdByFunc(taskFunc); + + SetTaskFuncWithFollowupFunc(taskId, taskFunc, followupFunc); + gTasks[taskId].data[0] = 1; + taskFunc(taskId); +} + +static bool8 sub_8084394(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_8084398(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_80843DC(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_808441C(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_8084478(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_8084534(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_8084578(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_80845AC(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_80845C8(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_80845FC(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_8084654(u8 taskId, struct Task *task, struct MapObject *trainerObj); +static bool8 sub_80846C8(u8 taskId, struct Task *task, struct MapObject *trainerObj); + +static bool8 (*const gTrainerSeeFuncList[])(u8 taskId, struct Task *task, struct MapObject *trainerObj) = +{ + sub_8084394, + sub_8084398, + sub_80843DC, + sub_808441C, + sub_8084478, + sub_8084534, + sub_8084578, + sub_80845AC, + sub_80845C8, + sub_80845FC, + sub_8084654, + sub_80846C8, +}; + +void RunTrainerSeeFuncList(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + struct MapObject *trainerObj = (struct MapObject *)((task->tTrainerObjHi << 16) | (task->tTrainerObjLo)); + + if (!trainerObj->active) + { + SwitchTaskToFollowupFunc(taskId); + } + else + { + while (gTrainerSeeFuncList[task->data[0]](taskId, task, trainerObj)) + ; + } +} + +static bool8 sub_8084394(u8 taskId, struct Task *task, struct MapObject *trainerObj) // cant be void because it is called with RunTrainerSeeFuncList with arguments. +{ + return FALSE; +} + +static bool8 sub_8084398(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + u8 direction; + + FieldObjectGetLocalIdAndMap(trainerObj, (u8 *)&gFieldEffectArguments[0], (u8 *)&gFieldEffectArguments[1], (u8 *)&gFieldEffectArguments[2]); + FieldEffectStart(FLDEFF_EXCLAMATION_MARK_ICON_1); + direction = GetFaceDirectionAnimId(trainerObj->mapobj_unk_18); + FieldObjectSetSpecialAnim(trainerObj, direction); + task->data[0]++; + return TRUE; +} + +static bool8 sub_80843DC(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + if (FieldEffectActiveListContains(0)) + { + return FALSE; + } + else + { + task->data[0]++; + if (trainerObj->animPattern == 57 || trainerObj->animPattern == 58) + task->data[0] = 6; + if (trainerObj->animPattern == 63) + task->data[0] = 8; + return TRUE; + } +} + +static bool8 sub_808441C(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + if (!(FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(trainerObj)) || FieldObjectClearAnimIfSpecialAnimFinished(trainerObj)) + { + if (task->data[3]) + { + FieldObjectSetSpecialAnim(trainerObj, GetGoSpeed0AnimId(trainerObj->mapobj_unk_18)); + task->data[3]--; + } + else + { + FieldObjectSetSpecialAnim(trainerObj, 0x3E); + task->data[0]++; + } + } + return FALSE; +} + +static bool8 sub_8084478(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + struct MapObject *playerObj; + + if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(trainerObj) && !FieldObjectClearAnimIfSpecialAnimFinished(trainerObj)) + return FALSE; + + npc_set_running_behaviour_etc(trainerObj, npc_running_behaviour_by_direction(trainerObj->mapobj_unk_18)); + sub_805C774(trainerObj, npc_running_behaviour_by_direction(trainerObj->mapobj_unk_18)); + sub_805C754(trainerObj); + + playerObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + if (FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(playerObj) && !FieldObjectClearAnimIfSpecialAnimFinished(playerObj)) + return FALSE; + + sub_80597E8(); + FieldObjectSetSpecialAnim(&gMapObjects[gPlayerAvatar.mapObjectId], GetFaceDirectionAnimId(GetOppositeDirection(trainerObj->mapobj_unk_18))); + task->data[0]++; + return FALSE; +} + +static bool8 sub_8084534(u8 taskId, struct Task *task, struct MapObject *trainerObj) // technically only 1 parameter, but needs all 3 for TrainerSeeFuncList call. +{ + struct MapObject *playerObj = &gMapObjects[gPlayerAvatar.mapObjectId]; + + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(playerObj) + || FieldObjectClearAnimIfSpecialAnimFinished(playerObj)) + SwitchTaskToFollowupFunc(taskId); + return FALSE; +} + +static bool8 sub_8084578(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(trainerObj) + || FieldObjectClearAnimIfSpecialAnimFinished(trainerObj)) + { + FieldObjectSetSpecialAnim(trainerObj, 0x59); + task->data[0]++; + } + return FALSE; +} + +static bool8 sub_80845AC(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + if (FieldObjectClearAnimIfSpecialAnimFinished(trainerObj)) + task->data[0] = 3; + + return FALSE; +} + +static bool8 sub_80845C8(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + if (!FieldObjectIsSpecialAnimOrDirectionSequenceAnimActive(trainerObj) + || FieldObjectClearAnimIfSpecialAnimFinished(trainerObj)) + { + FieldObjectSetSpecialAnim(trainerObj, 0x3E); + task->data[0]++; + } + return FALSE; +} + +static bool8 sub_80845FC(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + if (FieldObjectCheckIfSpecialAnimFinishedOrInactive(trainerObj)) + { + gFieldEffectArguments[0] = trainerObj->coords2.x; + gFieldEffectArguments[1] = trainerObj->coords2.y; + gFieldEffectArguments[2] = gSprites[trainerObj->spriteId].subpriority - 1; + gFieldEffectArguments[3] = 2; + task->data[4] = FieldEffectStart(FLDEFF_POP_OUT_OF_ASH); + task->data[0]++; + } + return FALSE; +} + +static bool8 sub_8084654(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + struct Sprite *sprite; + + if (gSprites[task->data[4]].animCmdIndex == 2) + { + trainerObj->mapobj_bit_26 = 0; + trainerObj->mapobj_bit_2 = 1; + + sprite = &gSprites[trainerObj->spriteId]; + sprite->oam.priority = 2; + FieldObjectClearAnimIfSpecialAnimFinished(trainerObj); + FieldObjectSetSpecialAnim(trainerObj, sub_806084C(trainerObj->mapobj_unk_18)); + task->data[0]++; + } + return FALSE; +} + +static bool8 sub_80846C8(u8 taskId, struct Task *task, struct MapObject *trainerObj) +{ + if (!FieldEffectActiveListContains(49)) + task->data[0] = 3; + + return FALSE; +} + +static bool8 (*const gTrainerSeeFuncList2[])(u8, struct Task *, struct MapObject *) = +{ + sub_80845C8, + sub_80845FC, + sub_8084654, + sub_80846C8, +}; + +void sub_80846E4(u8 taskId) +{ + struct Task *task = &gTasks[taskId]; + struct MapObject *mapObj; + + // another mapObj loaded into by loadword? + LoadWordFromTwoHalfwords(&task->data[1], (u32 *)&mapObj); + if (!task->data[7]) + { + FieldObjectClearAnim(mapObj); + task->data[7]++; + } + gTrainerSeeFuncList2[task->data[0]](taskId, task, mapObj); + if (task->data[0] == 3 && !FieldEffectActiveListContains(49)) + { + npc_set_running_behaviour_etc(mapObj, npc_running_behaviour_by_direction(mapObj->mapobj_unk_18)); + sub_805C774(mapObj, npc_running_behaviour_by_direction(mapObj->mapobj_unk_18)); + DestroyTask(taskId); + } + else + mapObj->mapobj_bit_7 = 0; +} + +void sub_8084794(struct MapObject *var) +{ + StoreWordInTwoHalfwords(&gTasks[CreateTask(sub_80846E4, 0)].data[1], (u32)var); +} + +static void Task_DestroyTrainerApproachTask(u8); + +void ScrSpecial_EndTrainerApproach(void) +{ + sub_80842FC(Task_DestroyTrainerApproachTask); +} + +static void Task_DestroyTrainerApproachTask(u8 taskId) +{ + DestroyTask(taskId); + EnableBothScriptContexts(); +} + +u8 FldEff_ExclamationMarkIcon1(void) +{ + u8 spriteId = CreateSpriteAtEnd(&gSpriteTemplate_839B510, 0, 0, 0x53); + + if (spriteId != 64) + sub_8084894(&gSprites[spriteId], 0, 0); + + return 0; +} + +u8 FldEff_ExclamationMarkIcon2(void) +{ + u8 spriteId = CreateSpriteAtEnd(&gSpriteTemplate_839B510, 0, 0, 0x52); + + if (spriteId != 64) + sub_8084894(&gSprites[spriteId], 33, 1); + + return 0; +} + +u8 FldEff_HeartIcon(void) +{ + u8 spriteId = CreateSpriteAtEnd(&gSpriteTemplate_839B528, 0, 0, 0x52); + + if (spriteId != 64) + sub_8084894(&gSprites[spriteId], 46, 0); + + return 0; +} + +void sub_8084894(struct Sprite *sprite, u16 a2, u8 a3) +{ + sprite->oam.priority = 1; + sprite->coordOffsetEnabled = 1; + + sprite->data0 = gFieldEffectArguments[0]; + sprite->data1 = gFieldEffectArguments[1]; + sprite->data2 = gFieldEffectArguments[2]; + sprite->data3 = -5; + sprite->data7 = a2; + + StartSpriteAnim(sprite, a3); +} + +void objc_exclamation_mark_probably(struct Sprite *sprite) +{ + u8 mapObjId; + + if (TryGetFieldObjectIdByLocalIdAndMap(sprite->data0, sprite->data1, sprite->data2, &mapObjId) + || sprite->animEnded) + { + FieldEffectStop(sprite, (u8)sprite->data7); + } + else + { + struct Sprite *mapObjSprite = &gSprites[gMapObjects[mapObjId].spriteId]; + sprite->data4 += sprite->data3; + sprite->pos1.x = mapObjSprite->pos1.x; + sprite->pos1.y = mapObjSprite->pos1.y - 16; + sprite->pos2.x = mapObjSprite->pos2.x; + sprite->pos2.y = mapObjSprite->pos2.y + sprite->data4; + if (sprite->data4) + sprite->data3++; + else + sprite->data3 = 0; + } +} diff --git a/src/field/tv.c b/src/field/tv.c new file mode 100644 index 000000000..e9b5e850d --- /dev/null +++ b/src/field/tv.c @@ -0,0 +1,3259 @@ +#include "global.h" +#include "tv.h" +#include "battle_tower.h" +#include "contest_painting.h" +#include "data2.h" +#include "easy_chat.h" +#include "event_data.h" +#include "fieldmap.h" +#include "field_message_box.h" +#include "field_camera.h" +#include "flags.h" +#include "rng.h" +#include "string_util.h" +#include "text.h" +#include "species.h" +#include "pokedex.h" +#include "naming_screen.h" +#include "overworld.h" +#include "map_constants.h" +#include "strings.h" +#include "battle.h" +#include "link.h" +#include "easy_chat.h" +#include "field_map_obj.h" +#include "field_specials.h" +#include "item.h" +#include "items.h" +#include "link.h" +#include "map_constants.h" +#include "naming_screen.h" +#include "pokedex.h" +#include "region_map.h" +#include "rng.h" +#include "overworld.h" +#include "rtc.h" +#include "script_menu.h" +#include "species.h" +#include "string_util.h" +#include "strings.h" +#include "text.h" + +struct UnkTvStruct +{ + s8 var0; +}; + +extern u8 gUnknown_0300430A[11]; + +struct OutbreakPokemon +{ + /*0x00*/ u16 species; + /*0x02*/ u16 moves[4]; + /*0x0A*/ u8 level; + /*0x0B*/ u8 location; +}; + +struct TVSaleItem { + u16 item_id; + u16 item_amount; +}; + +extern u8 gUnknown_02038694; + +extern struct TVSaleItem gUnknown_02038724[3]; + +struct UnkTvStruct gUnknown_03005D38; + +extern u8 *gTVBravoTrainerTextGroup[]; +extern u8 *gTVBravoTrainerBattleTowerTextGroup[]; +extern u8 *gTVSmartShopperTextGroup[]; +extern u8 *gTVNameRaterTextGroup[]; +extern u8 *gTVPokemonTodayTextGroup[]; +extern u8 *gTVPokemonTodayFailedCaptureTextGroup[]; +extern u8 *gTVFanClubTextGroup[]; +extern u8 *gTVRecentHappeningsTextGroup[]; +extern u8 *gTVFanClubOpinionsTextGroup[]; +extern u8 *gTVPokemonOutbreakTextGroup[]; +extern u8 *gTVGabbyAndTyTextGroup[]; +extern u8 *gTVFishingGuruAdviceTextGroup[]; +extern u8 *gTVWorldOfMastersTextGroup[]; +extern struct OutbreakPokemon gPokeOutbreakSpeciesList[5]; + + + +extern const u8 *gTVNewsTextGroup1[]; +extern const u8 *gTVNewsTextGroup2[]; +extern const u8 *gTVNewsTextGroup3[]; + +extern u16 gScriptLastTalked; + +extern u8 gScriptContestCategory; +extern u8 gScriptContestRank; +extern u8 gUnknown_03004316[11]; +extern u8 gBattleOutcome; + +extern u16 gLastUsedItem; + +extern u8 ewram[]; +#define gUnknown_02007000 (*(ewramStruct_02007000 *)(ewram + 0x7000)) + +static EWRAM_DATA u16 gUnknown_020387E0 = 0; +static EWRAM_DATA u16 gUnknown_020387E2 = 0; +static EWRAM_DATA u8 gUnknown_020387E4 = 0; +static EWRAM_DATA ALIGNED(4) u8 gUnknown_020387E8 = 0; // why is this aligned to a 4-byte boundary? + +static u8 gUnknown_03000720; +static u8 gUnknown_03000721; +static s8 gUnknown_03000722; + +void ClearTVShowData(void) +{ + u8 showidx; + u8 extradataidx; + for (showidx=0; showidx<25; showidx++) { + gSaveBlock1.tvShows[showidx].common.var00 = 0; + gSaveBlock1.tvShows[showidx].common.var01 = 0; + for (extradataidx=0; extradataidx<34; extradataidx++) { + gSaveBlock1.tvShows[showidx].common.pad02[extradataidx] = 0; + } + } + sub_80BEBF4(); +} + +bool8 sub_80BF1B4(u8); +void sub_80BF20C(void); +extern u16 sub_8135D3C(u8); +extern u8 gScriptContestCategory; +extern u8 gScriptContestRank; +extern u8 gUnknown_03004316[11]; +extern u8 gBattleOutcome; + +void sub_80BF334(void); +void sub_80BF3A4(void); +void sub_80BF3DC(void); +void sub_80BF46C(void); +void sub_80BF478(void); +void sub_80BF484(void); +void sub_80BF4BC(void); + +void sub_80BE028(void); +void sub_80BE074(void); +void sub_80BE778(void); +void sub_80BEB20(void); + +u8 sub_80BFB54(u8); + +s8 sub_80BF74C(TVShow tvShow[]); + +void sub_80BF55C(TVShow tvShow[], u8 showidx); +void sub_80BEA88(void); + +void sub_80BE138(TVShow *show); +void sub_80BE160(TVShow *show); +extern u16 gLastUsedItem; + +void sub_80BE5FC(void); +void sub_80BE65C(void); +void sub_80BE6A0(void); +void nullsub_21(void); +void sub_80BE188(void); +void sub_80BE320(void); + +u8 special_0x44(void) +{ + u8 i; + u8 j; + +#ifndef NONMATCHING + asm("":::"r5"); +#endif + + for (i = 5; i < 24; i++) + { + if (gSaveBlock1.tvShows[i].common.var00 == 0) + break; + } + i = Random() % i; + j = i; + do + { + if (sub_80BFB54(gSaveBlock1.tvShows[i].common.var00) != 4) + { + if (gSaveBlock1.tvShows[i].common.var01 == 1) + return i; + } + else + { + struct TVShowMassOutbreak *massOutbreak = &gSaveBlock1.tvShows[i].massOutbreak; + + if (massOutbreak->var16 == 0 && massOutbreak->var01 == 1) + return i; + } + + if (i == 0) + i = 23; + else + i--; + } while (i != j); + return 0xFF; +} + +u8 sub_80BDA30(void); + +u8 sub_80BD8B8(void) +{ + u8 retval = special_0x44(); + + if (retval == 0xff) + return 0xff; + if (gSaveBlock1.outbreakPokemonSpecies != 0 && gSaveBlock1.tvShows[retval].common.var00 == TVSHOW_MASS_OUTBREAK) + return sub_80BDA30(); + return retval; +} + +u8 CheckForBigMovieOrEmergencyNewsOnTV(void); +void SetTVMetatilesOnMap(int, int, u16); +bool8 sub_80BECA0(void); +bool8 IsTVShowInSearchOfTrainersAiring(void); + +void UpdateTVScreensOnMap(int width, int height) +{ + FlagSet(SYS_TV_WATCH); + switch (CheckForBigMovieOrEmergencyNewsOnTV()) + { + case 1: + SetTVMetatilesOnMap(width, height, 0x3); + break; + case 2: + break; + default: + if (gSaveBlock1.location.mapGroup == MAP_GROUP_LILYCOVE_CITY_COVE_LILY_MOTEL_1F + && gSaveBlock1.location.mapNum == MAP_ID_LILYCOVE_CITY_COVE_LILY_MOTEL_1F) + { + SetTVMetatilesOnMap(width, height, 0x3); + } + else if (FlagGet(SYS_TV_START) && (sub_80BD8B8() != 0xff || sub_80BECA0() != 0xff || IsTVShowInSearchOfTrainersAiring())) + { + FlagClear(SYS_TV_WATCH); + SetTVMetatilesOnMap(width, height, 0x3); + } + break; + } +} + +void SetTVMetatilesOnMap(int width, int height, u16 tileId) +{ + int x; + int y; + + for (y=0; y<height; y++) + { + for (x=0; x<width; x++) + { + if (MapGridGetMetatileBehaviorAt(x, y) == 0x86) + MapGridSetMetatileIdAt(x, y, tileId | 0xc00); + } + } +} + +void TurnOffTVScreen(void) +{ + SetTVMetatilesOnMap(gUnknown_03004870.width, gUnknown_03004870.height, 0x2); + DrawWholeMapView(); +} + +u8 sub_80BDA0C(void) +{ + return gSaveBlock1.tvShows[gSpecialVar_0x8004].common.var00; +} + +u8 sub_80BDA30(void) +{ + u8 showIdx; + for (showIdx=0; showIdx<24; showIdx++) + { + if (gSaveBlock1.tvShows[showIdx].common.var00 != 0 && gSaveBlock1.tvShows[showIdx].common.var00 != TVSHOW_MASS_OUTBREAK && gSaveBlock1.tvShows[showIdx].common.var01 == 1) + return showIdx; + } + return 0xff; +} + +u8 special_0x4a(void) +{ + TVShow *tvShow; + tvShow = &gSaveBlock1.tvShows[gSpecialVar_0x8004]; + if (tvShow->common.var00 == TVSHOW_MASS_OUTBREAK && gSaveBlock1.outbreakPokemonSpecies) + return sub_80BDA30(); + return gSpecialVar_0x8004; +} + +void ResetGabbyAndTy(void) +{ + gSaveBlock1.gabbyAndTyData.mon1 = 0; + gSaveBlock1.gabbyAndTyData.mon2 = 0; + gSaveBlock1.gabbyAndTyData.lastMove = 0; + gSaveBlock1.gabbyAndTyData.quote = 0xffff; + gSaveBlock1.gabbyAndTyData.valA_0 = 0; + gSaveBlock1.gabbyAndTyData.valA_1 = 0; + gSaveBlock1.gabbyAndTyData.valA_2 = 0; + gSaveBlock1.gabbyAndTyData.valA_3 = 0; + gSaveBlock1.gabbyAndTyData.valA_4 = 0; + gSaveBlock1.gabbyAndTyData.valA_5 = 0; + gSaveBlock1.gabbyAndTyData.valB_0 = 0; + gSaveBlock1.gabbyAndTyData.valB_1 = 0; + gSaveBlock1.gabbyAndTyData.valB_2 = 0; + gSaveBlock1.gabbyAndTyData.valB_3 = 0; + gSaveBlock1.gabbyAndTyData.valB_4 = 0; + gSaveBlock1.gabbyAndTyData.valB_5 = 0; + gSaveBlock1.gabbyAndTyData.mapnum = 0; + gSaveBlock1.gabbyAndTyData.battleNum = 0; +} + +void TakeTVShowInSearchOfTrainersOffTheAir(void); + +void GabbyAndTyBeforeInterview(void) +{ + u8 i; + + gSaveBlock1.gabbyAndTyData.mon1 = gBattleResults.poke1Species; + gSaveBlock1.gabbyAndTyData.mon2 = gBattleResults.opponentSpecies; + gSaveBlock1.gabbyAndTyData.lastMove = gBattleResults.lastUsedMove; + if (gSaveBlock1.gabbyAndTyData.battleNum != 0xff) + gSaveBlock1.gabbyAndTyData.battleNum ++; + gSaveBlock1.gabbyAndTyData.valA_0 = gBattleResults.unk5_0; + + if (gBattleResults.playerFaintCounter) + gSaveBlock1.gabbyAndTyData.valA_1 = 1; + else + gSaveBlock1.gabbyAndTyData.valA_1 = 0; + + if (gBattleResults.unk3) + gSaveBlock1.gabbyAndTyData.valA_2 = 1; + else + gSaveBlock1.gabbyAndTyData.valA_2 = 0; + + if (!gBattleResults.unk5_1) + { + for (i=0; i<11; i++) + { + if (gBattleResults.unk36[i] != 0) + { + gSaveBlock1.gabbyAndTyData.valA_3 = 1; + break; + } + } + } + else + { + gSaveBlock1.gabbyAndTyData.valA_3 = 1; + } + + TakeTVShowInSearchOfTrainersOffTheAir(); + if (gSaveBlock1.gabbyAndTyData.lastMove == 0) + FlagSet(1); +} + +void sub_80BDC14(void) +{ + gSaveBlock1.gabbyAndTyData.valB_0 = gSaveBlock1.gabbyAndTyData.valA_0; + gSaveBlock1.gabbyAndTyData.valB_1 = gSaveBlock1.gabbyAndTyData.valA_1; + gSaveBlock1.gabbyAndTyData.valB_2 = gSaveBlock1.gabbyAndTyData.valA_2; + gSaveBlock1.gabbyAndTyData.valB_3 = gSaveBlock1.gabbyAndTyData.valA_3; + gSaveBlock1.gabbyAndTyData.valA_4 = 1; + gSaveBlock1.gabbyAndTyData.mapnum = gMapHeader.regionMapSectionId; + IncrementGameStat(GAME_STAT_GOT_INTERVIEWED); +} + +void TakeTVShowInSearchOfTrainersOffTheAir(void) +{ + gSaveBlock1.gabbyAndTyData.valA_4 = 0; +} + +u8 GabbyAndTyGetBattleNum(void) +{ + if (gSaveBlock1.gabbyAndTyData.battleNum >= 6) + return (gSaveBlock1.gabbyAndTyData.battleNum % 3) + 6; + else + return gSaveBlock1.gabbyAndTyData.battleNum; +} + +bool8 IsTVShowInSearchOfTrainersAiring(void) +{ + return gSaveBlock1.gabbyAndTyData.valA_4; +} + +bool8 GabbyAndTyGetLastQuote(void) +{ + if (gSaveBlock1.gabbyAndTyData.quote == 0xffff) + return FALSE; + + EasyChat_GetWordText(gStringVar1, gSaveBlock1.gabbyAndTyData.quote); + gSaveBlock1.gabbyAndTyData.quote |= 0xffff; + return TRUE; +} + +u8 sub_80BDD18(void) +{ + if (!gSaveBlock1.gabbyAndTyData.valB_0) + return 1; + if (gSaveBlock1.gabbyAndTyData.valB_3) + return 2; + if (gSaveBlock1.gabbyAndTyData.valB_2) + return 3; + if (gSaveBlock1.gabbyAndTyData.valB_1) + return 4; + return 0; +} + +void GabbyAndTySetScriptVarsToFieldObjectLocalIds(void) +{ + switch (GabbyAndTyGetBattleNum()) + { + case 1: + gSpecialVar_0x8004 = 0xE; + gSpecialVar_0x8005 = 0xD; + break; + case 2: + gSpecialVar_0x8004 = 0x5; + gSpecialVar_0x8005 = 0x6; + break; + case 3: + gSpecialVar_0x8004 = 0x12; + gSpecialVar_0x8005 = 0x11; + break; + case 4: + gSpecialVar_0x8004 = 0x15; + gSpecialVar_0x8005 = 0x16; + break; + case 5: + gSpecialVar_0x8004 = 0x8; + gSpecialVar_0x8005 = 0x9; + break; + case 6: + gSpecialVar_0x8004 = 0x13; + gSpecialVar_0x8005 = 0x14; + break; + case 7: + gSpecialVar_0x8004 = 0x17; + gSpecialVar_0x8005 = 0x18; + break; + case 8: + gSpecialVar_0x8004 = 0xA; + gSpecialVar_0x8005 = 0xB; + break; + } +} + +void sub_80BDE48(void) +{ + switch (gSpecialVar_0x8005) + { + case TVSHOW_FAN_CLUB_LETTER: + sub_80BE5FC(); + break; + case TVSHOW_RECENT_HAPPENINGS: + sub_80BE65C(); + break; + case TVSHOW_PKMN_FAN_CLUB_OPINIONS: + sub_80BE6A0(); + break; + case TVSHOW_UNKN_SHOWTYPE_04: + nullsub_21(); + break; + case TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE: + sub_80BE188(); + break; + case TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE: + sub_80BE320(); + break; + } +} + +u8 sub_80BDEAC(u8 *a0) +{ + u8 lang = GAME_LANGUAGE; + + if (a0[0] == EXT_CTRL_CODE_BEGIN && a0[1] == 0x15) + lang = LANGUAGE_JAPANESE; + return lang; +} + +void sub_80BDEC8(void) +{ + u8 i; + u16 total; + u16 item; + + total = 0; + sub_80BEB20(); + sub_80BE778(); + + if (gBattleResults.caughtPoke == 0) + { + sub_80BE074(); + } + else + { + sub_80BE028(); + if (sub_80BF77C(0xffff) == 0 && StringCompareWithoutExtCtrlCodes(gSpeciesNames[gBattleResults.caughtPoke], gBattleResults.caughtNick) != 0) + { + gUnknown_03005D38.var0 = sub_80BF74C(gSaveBlock1.tvShows); + if (gUnknown_03005D38.var0 != -1 && sub_80BF1B4(TVSHOW_POKEMON_TODAY_CAUGHT) != 1) + { + for (i = 0; i < 11; i++) + total += gBattleResults.unk36[i]; + if (total != 0 || gBattleResults.unk5_1 != 0) + { + struct TVShowPokemonToday *pokemonToday; + + total = 0; + pokemonToday = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].pokemonToday; + pokemonToday->var00 = TVSHOW_POKEMON_TODAY_CAUGHT; + pokemonToday->var01 = total; + if (gBattleResults.unk5_1 != 0) + { + total = 1; + item = ITEM_MASTER_BALL; + } + else + { + for (i = 0; i < 11; i++) + total += gBattleResults.unk36[i]; + if (total > 0xff) + total = 0xff; + item = gLastUsedItem; + } + pokemonToday->var12 = total; + pokemonToday->ball = item; + StringCopy(pokemonToday->playerName, gSaveBlock2.playerName); + StringCopy(pokemonToday->nickname, gBattleResults.caughtNick); + pokemonToday->species = gBattleResults.caughtPoke; + sub_80BE138((TVShow *)pokemonToday); + pokemonToday->language = GAME_LANGUAGE; + pokemonToday->language2 = sub_80BDEAC(pokemonToday->nickname); + StripExtCtrlCodes(pokemonToday->nickname); + } + } + } + } +} + +void sub_80BE028(void) +{ + struct TVShowWorldOfMasters *worldOfMasters = &gSaveBlock1.tvShows[24].worldOfMasters; + + if (worldOfMasters->var00 != TVSHOW_WORLD_OF_MASTERS) + { + sub_80BF55C(gSaveBlock1.tvShows, 24); + worldOfMasters->var06 = GetGameStat(GAME_STAT_STEPS); + worldOfMasters->var00 = TVSHOW_WORLD_OF_MASTERS; + } + worldOfMasters->var02++; + worldOfMasters->var04 = gBattleResults.caughtPoke; + worldOfMasters->var08 = gBattleResults.poke1Species; + worldOfMasters->var0a = gMapHeader.regionMapSectionId; +} + +void sub_80BE074(void) +{ + u8 i; + u16 total; + u8 zero = 0; + + if (sub_80BF77C(0xffff) == 0) + { + for (i = 0, total = 0; i < ARRAY_COUNT(gUnknown_03004316); i++) + total += gUnknown_03004316[i]; + if (total > 0xff) + total = 0xff; + if (total > 2 && gBattleOutcome == 1) + { + gUnknown_03005D38.var0 = sub_80BF74C(gSaveBlock1.tvShows); + if (gUnknown_03005D38.var0 != -1 && sub_80BF1B4(TVSHOW_POKEMON_TODAY_FAILED) != 1) + { + struct TVShowPokemonTodayFailed *pokemonTodayFailed = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].pokemonTodayFailed; + + zero = 0; + pokemonTodayFailed->var00 = TVSHOW_POKEMON_TODAY_FAILED; + pokemonTodayFailed->var01 = zero; + pokemonTodayFailed->species = gBattleResults.poke1Species; + pokemonTodayFailed->species2 = gBattleResults.lastOpponentSpecies; + pokemonTodayFailed->var10 = total; + pokemonTodayFailed->var11 = gBattleOutcome; + pokemonTodayFailed->var12 = gMapHeader.regionMapSectionId; + StringCopy(pokemonTodayFailed->playerName, gSaveBlock2.playerName); + sub_80BE138((TVShow *)pokemonTodayFailed); + pokemonTodayFailed->language = GAME_LANGUAGE; + } + } + } +} + + +void sub_80BE138(TVShow *show) +{ + u32 playerId = GetPlayerTrainerId(); + + show->common.srcTrainerId2Lo = playerId & 0xFF; + show->common.srcTrainerId2Hi = playerId >> 8; + show->common.srcTrainerIdLo = playerId & 0xFF; + show->common.srcTrainerIdHi = playerId >> 8; + show->common.trainerIdLo = playerId & 0xFF; + show->common.trainerIdHi = playerId >> 8; +} + +void sub_80BE160(TVShow *show) +{ + u32 playerId = GetPlayerTrainerId(); + + show->common.srcTrainerIdLo = playerId & 0xFF; + show->common.srcTrainerIdHi = playerId >> 8; + show->common.trainerIdLo = playerId & 0xFF; + show->common.trainerIdHi = playerId >> 8; +} + +void sub_80BE188(void) +{ + struct TVShowBravoTrainerPokemonProfiles *bravoTrainerSrc = &gSaveBlock1.tvShows[24].bravoTrainer; + + if (bravoTrainerSrc->var00 == TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE) + { + struct TVShowBravoTrainerPokemonProfiles *bravoTrainerNew = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].bravoTrainer; + + bravoTrainerNew->var00 = TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE; + bravoTrainerNew->var01 = 1; + bravoTrainerNew->species = bravoTrainerSrc->species; + StringCopy(bravoTrainerNew->playerName, gSaveBlock2.playerName); + StringCopy(bravoTrainerNew->pokemonNickname, bravoTrainerSrc->pokemonNickname); + bravoTrainerNew->contestCategory = bravoTrainerSrc->contestCategory; + bravoTrainerNew->contestRank = bravoTrainerSrc->contestRank; + bravoTrainerNew->var14 = bravoTrainerSrc->var14; + bravoTrainerNew->contestResult = bravoTrainerSrc->contestResult; + bravoTrainerNew->contestCategory = bravoTrainerSrc->contestCategory; + sub_80BE160((TVShow *)bravoTrainerNew); + bravoTrainerNew->language = GAME_LANGUAGE; + bravoTrainerNew->var1f = sub_80BDEAC(bravoTrainerNew->pokemonNickname); + StripExtCtrlCodes(bravoTrainerNew->pokemonNickname); + } +} + +void sub_80BE23C(u16 a0) +{ + struct TVShowBravoTrainerPokemonProfiles *bravoTrainer = &gSaveBlock1.tvShows[24].bravoTrainer; + + sub_80BF484(); + gUnknown_03005D38.var0 = sub_80BF720(gSaveBlock1.tvShows); + if (gUnknown_03005D38.var0 != -1) + { + sub_80BF55C(gSaveBlock1.tvShows, 24); + bravoTrainer->var14 = a0; + bravoTrainer->var00 = TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE; + } +} + +void sub_80BE284(u8 a0) +{ + struct TVShowBravoTrainerPokemonProfiles *bravoTrainer = &gSaveBlock1.tvShows[24].bravoTrainer; + + gUnknown_03005D38.var0 = sub_80BF720(gSaveBlock1.tvShows); + if (gUnknown_03005D38.var0 != -1) + { + bravoTrainer->contestResult = a0; + bravoTrainer->contestCategory = gScriptContestCategory; + bravoTrainer->contestRank = gScriptContestRank; + bravoTrainer->species = GetMonData(&gPlayerParty[gUnknown_02038694], MON_DATA_SPECIES, NULL); + GetMonData(&gPlayerParty[gUnknown_02038694], MON_DATA_NICKNAME, bravoTrainer->pokemonNickname); + } +} + +void sub_80BE320(void) +{ + struct TVShowBravoTrainerBattleTowerSpotlight *bravoTrainerTower = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].bravoTrainerTower; + + bravoTrainerTower->var00 = TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE; + bravoTrainerTower->var01 = 1; + StringCopy(bravoTrainerTower->trainerName, gSaveBlock2.playerName); + StringCopy(bravoTrainerTower->pokemonName, gSaveBlock2.filler_A8.filler_3DC); + bravoTrainerTower->species = gSaveBlock2.filler_A8.var_480; + bravoTrainerTower->defeatedSpecies = gSaveBlock2.filler_A8.var_482; + bravoTrainerTower->var16 = sub_8135D3C(gSaveBlock2.filler_A8.var_4D0); + bravoTrainerTower->var1c = gSaveBlock2.filler_A8.var_4AD; + if (gSaveBlock2.filler_A8.var_4D0 == 0) + bravoTrainerTower->btLevel = 50; + else + bravoTrainerTower->btLevel = 100; + bravoTrainerTower->var1b = gSpecialVar_0x8004; + sub_80BE160((TVShow *)bravoTrainerTower); + bravoTrainerTower->language = GAME_LANGUAGE; +} + +void sub_80BE3BC(void) +{ + u8 rval; + u8 i; + + rval = sub_80BF77C(0x5555); + if (rval == 0) + { + gUnknown_03005D38.var0 = sub_80BF74C(gSaveBlock1.tvShows); + if (gUnknown_03005D38.var0 != -1 && sub_80BF1B4(TVSHOW_SMART_SHOPPER) != 1) + { + sub_80BF20C(); + if (gUnknown_02038724[0].item_amount >= 20) + { + struct TVShowSmartShopper *smartShopper = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].smartshopperShow; + + smartShopper->var00 = TVSHOW_SMART_SHOPPER; + smartShopper->var01 = rval; + smartShopper->shopLocation = gMapHeader.regionMapSectionId; + for (i=0; i<3; i++) + { + smartShopper->itemIds[i] = gUnknown_02038724[i].item_id; + smartShopper->itemAmounts[i] = gUnknown_02038724[i].item_amount; + } + smartShopper->priceReduced = GetPriceReduction(1); + StringCopy(smartShopper->playerName, gSaveBlock2.playerName); + sub_80BE138((TVShow *)smartShopper); + smartShopper->language = GAME_LANGUAGE; + } + } + } +} + +void sub_80BE478(void) +{ + sub_80BF478(); + if (gScriptResult == 1) + return; + + GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, gStringVar1); + if (StringLength(gSaveBlock2.playerName) > 1 && StringLength(gStringVar1) > 1) + { + struct TVShowNameRaterShow *nameRaterShow = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].nameRaterShow; + + nameRaterShow->var00 = TVSHOW_NAME_RATER_SHOW; + nameRaterShow->var01 = 1; + nameRaterShow->species = GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPECIES, NULL); + nameRaterShow->random = Random() % 3; + nameRaterShow->random2 = Random() % 2; + nameRaterShow->var1C = sub_80BF674(nameRaterShow->species); + StringCopy(nameRaterShow->trainerName, gSaveBlock2.playerName); + GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_NICKNAME, nameRaterShow->pokemonName); + sub_80BE160((TVShow *)nameRaterShow); + nameRaterShow->language = GAME_LANGUAGE; + nameRaterShow->pokemonNameLanguage = sub_80BDEAC(nameRaterShow->pokemonName); + StripExtCtrlCodes(nameRaterShow->pokemonName); + } +} + +void StartMassOutbreak(void) +{ + struct TVShowMassOutbreak *massOutbreak = &gSaveBlock1.tvShows[gSpecialVar_0x8004].massOutbreak; + + gSaveBlock1.outbreakPokemonSpecies = massOutbreak->species; + gSaveBlock1.outbreakLocationMapNum = massOutbreak->locationMapNum; + gSaveBlock1.outbreakLocationMapGroup = massOutbreak->locationMapGroup; + gSaveBlock1.outbreakPokemonLevel = massOutbreak->level; + gSaveBlock1.outbreakUnk1 = massOutbreak->var02; + gSaveBlock1.outbreakUnk2 = massOutbreak->var0E; + gSaveBlock1.outbreakPokemonMoves[0] = massOutbreak->moves[0]; + gSaveBlock1.outbreakPokemonMoves[1] = massOutbreak->moves[1]; + gSaveBlock1.outbreakPokemonMoves[2] = massOutbreak->moves[2]; + gSaveBlock1.outbreakPokemonMoves[3] = massOutbreak->moves[3]; + gSaveBlock1.outbreakUnk4 = massOutbreak->var03; + gSaveBlock1.outbreakPokemonProbability = massOutbreak->probability; + gSaveBlock1.outbreakUnk5 = 2; +} + +void sub_80BE5FC(void) +{ + struct TVShowFanClubLetter *fanclubLetter = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].fanclubLetter; + + fanclubLetter->var00 = TVSHOW_FAN_CLUB_LETTER; + fanclubLetter->var01 = 1; + StringCopy(fanclubLetter->playerName, gSaveBlock2.playerName); + fanclubLetter->species = GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SPECIES, NULL); + sub_80BE160((TVShow *)fanclubLetter); + fanclubLetter->language = GAME_LANGUAGE; +} + +void sub_80BE65C(void) +{ + struct TVShowRecentHappenings *recentHappenings = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].recentHappenings; + + recentHappenings->var00 = TVSHOW_RECENT_HAPPENINGS; + recentHappenings->var01 = 1; + StringCopy(recentHappenings->playerName, gSaveBlock2.playerName); + recentHappenings->var02 = 0; + sub_80BE160((TVShow *)recentHappenings); + recentHappenings->language = GAME_LANGUAGE; +} + +void sub_80BE6A0(void) +{ + u8 monIndex; + struct TVShowFanclubOpinions *fanclubOpinions = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].fanclubOpinions; + + fanclubOpinions->var00 = TVSHOW_PKMN_FAN_CLUB_OPINIONS; + fanclubOpinions->var01 = 1; + monIndex = GetLeadMonIndex(); + fanclubOpinions->var04A = GetMonData(&gPlayerParty[monIndex], MON_DATA_FRIENDSHIP, NULL) / 16; + fanclubOpinions->var04B = gSpecialVar_0x8007; + StringCopy(fanclubOpinions->playerName, gSaveBlock2.playerName); + GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_NICKNAME, fanclubOpinions->var10); + fanclubOpinions->var02 = GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SPECIES, NULL); + sub_80BE160((TVShow *)fanclubOpinions); + fanclubOpinions->language = GAME_LANGUAGE; + fanclubOpinions->var0E = sub_80BDEAC(fanclubOpinions->var10); + StripExtCtrlCodes(fanclubOpinions->var10); +} + +void nullsub_21(void) +{ +} + +void sub_80BE778(void) +{ + if (FlagGet(SYS_GAME_CLEAR)) + { + u8 i; + + for (i = 0; i < 24; i++) + { + if (gSaveBlock1.tvShows[i].massOutbreak.var00 == TVSHOW_MASS_OUTBREAK) + return; + } + if (sub_80BF77C(0x147)) + return; + + gUnknown_03005D38.var0 = sub_80BF720(gSaveBlock1.tvShows); + if (gUnknown_03005D38.var0 != -1) + { + u16 rand = Random(); + u16 val = rand % 5; + s32 val2 = gUnknown_03005D38.var0; + struct TVShowMassOutbreak *massOutbreak = &gSaveBlock1.tvShows[val2].massOutbreak; + + massOutbreak->var00 = TVSHOW_MASS_OUTBREAK; + massOutbreak->var01 = 1; + massOutbreak->level = gPokeOutbreakSpeciesList[val].level; + massOutbreak->var02 = 0; + massOutbreak->var03 = 0; + massOutbreak->species = gPokeOutbreakSpeciesList[val].species; + massOutbreak->var0E = 0; + massOutbreak->moves[0] = gPokeOutbreakSpeciesList[val].moves[0]; + massOutbreak->moves[1] = gPokeOutbreakSpeciesList[val].moves[1]; + massOutbreak->moves[2] = gPokeOutbreakSpeciesList[val].moves[2]; + massOutbreak->moves[3] = gPokeOutbreakSpeciesList[val].moves[3]; + massOutbreak->locationMapNum = gPokeOutbreakSpeciesList[val].location; + massOutbreak->locationMapGroup = 0; + massOutbreak->var12 = 0; + massOutbreak->probability = 0x32; + massOutbreak->var15 = 0; + massOutbreak->var16 = 0x01; + sub_80BE160((TVShow *)massOutbreak); + massOutbreak->language = GAME_LANGUAGE; + } + } +} + +void EndMassOutbreak(void) +{ + gSaveBlock1.outbreakPokemonSpecies = 0; + gSaveBlock1.outbreakLocationMapNum = 0; + gSaveBlock1.outbreakLocationMapGroup = 0; + gSaveBlock1.outbreakPokemonLevel = 0; + gSaveBlock1.outbreakUnk1 = 0; + gSaveBlock1.outbreakUnk2 = 0; + gSaveBlock1.outbreakPokemonMoves[0] = 0; + gSaveBlock1.outbreakPokemonMoves[1] = 0; + gSaveBlock1.outbreakPokemonMoves[2] = 0; + gSaveBlock1.outbreakPokemonMoves[3] = 0; + gSaveBlock1.outbreakUnk4 = 0; + gSaveBlock1.outbreakPokemonProbability = 0; + gSaveBlock1.outbreakUnk5 = 0; +} + +void UpdateTVShowsPerDay(u16 arg0) +{ + sub_80BE8EC(arg0); + UpdateMassOutbreakTimeLeft(arg0); + sub_80BEE84(arg0); + sub_80BEA5C(arg0); +} + +void sub_80BE8EC(u16 arg0) +{ + u8 showidx; + + if (gSaveBlock1.outbreakPokemonSpecies == 0) + { + for (showidx=0; showidx<24; showidx++) + { + if (gSaveBlock1.tvShows[showidx].massOutbreak.var00 == TVSHOW_MASS_OUTBREAK + && gSaveBlock1.tvShows[showidx].massOutbreak.var01 == 0x01) + { + struct TVShowMassOutbreak *massOutbreak = &gSaveBlock1.tvShows[showidx].massOutbreak; + + if (massOutbreak->var16 < arg0) + massOutbreak->var16 = 0; + else + massOutbreak->var16 -= arg0; + break; + } + } + } +} + +void UpdateMassOutbreakTimeLeft(u16 arg0) +{ + if (gSaveBlock1.outbreakUnk5 <= arg0) + EndMassOutbreak(); + else + gSaveBlock1.outbreakUnk5 -= arg0; +} + +void sub_80BE97C(bool8 flag) +{ + u8 var0, var1; + + if (flag) + { + var0 = gUnknown_020387E2 >> 8; + if (var0 > 4) + sub_80BE9D4(); + gUnknown_020387E2 &= 0xFF; + var1 = gUnknown_020387E2 & 0xFF; + if (var1 != 0xFF) + gUnknown_020387E2++; + } + else + { + var0 = gUnknown_020387E2 & 0xFF; + if (var0 > 4) + sub_80BE9D4(); + gUnknown_020387E2 &= 0xFF00; + var1 = gUnknown_020387E2 >> 8; + if (var1 != 0xFF) + gUnknown_020387E2 += 0x100; + } +} + +void sub_80BE9D4(void) +{ + gUnknown_03005D38.var0 = sub_80BF74C(gSaveBlock1.tvShows); + if (gUnknown_03005D38.var0 != -1 && sub_80BF1B4(TVSHOW_FISHING_ADVICE) != 1) + { + struct TVShowPokemonAngler *pokemonAngler = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].pokemonAngler; + register u8 zero asm("r1") = 0; + + asm(""::"r"(zero)); + pokemonAngler->var00 = TVSHOW_FISHING_ADVICE; + pokemonAngler->var01 = zero; + pokemonAngler->var02 = gUnknown_020387E2 & 0xFF; + pokemonAngler->var03 = gUnknown_020387E2 >> 8; + pokemonAngler->var04 = gUnknown_020387E0; + StringCopy(pokemonAngler->playerName, gSaveBlock2.playerName); + sub_80BE138((TVShow *)pokemonAngler); + pokemonAngler->language = GAME_LANGUAGE; + } +} + +void sub_80BEA50(u16 var) +{ + gUnknown_020387E0 = var; +} + +void sub_80BEA88(void); + +void sub_80BEA5C(u16 arg0) +{ + struct TVShowWorldOfMasters *worldOfMasters = &gSaveBlock1.tvShows[24].worldOfMasters; + + if (worldOfMasters->var00 == TVSHOW_WORLD_OF_MASTERS) + { + if (worldOfMasters->var02 < 20) + sub_80BF55C(gSaveBlock1.tvShows, 0x18); + else + sub_80BEA88(); + } +} +void sub_80BEA88(void) +{ + struct TVShowWorldOfMasters *worldOfMastersSrc = &gSaveBlock1.tvShows[24].worldOfMasters; + + if (sub_80BF77C(0xFFFF) == 0) + { + gUnknown_03005D38.var0 = sub_80BF74C(gSaveBlock1.tvShows); + if (gUnknown_03005D38.var0 != -1 && sub_80BF1B4(TVSHOW_WORLD_OF_MASTERS) != 1) + { + struct TVShowWorldOfMasters *worldOfMastersDst = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].worldOfMasters; + + worldOfMastersDst->var00 = TVSHOW_WORLD_OF_MASTERS; + worldOfMastersDst->var01 = 0; + worldOfMastersDst->var02 = worldOfMastersSrc->var02; + worldOfMastersDst->var06 = GetGameStat(GAME_STAT_STEPS) - worldOfMastersSrc->var06; + worldOfMastersDst->var04 = worldOfMastersSrc->var04; + worldOfMastersDst->var08 = worldOfMastersSrc->var08; + worldOfMastersDst->var0a = worldOfMastersSrc->var0a; + StringCopy(worldOfMastersDst->playerName, gSaveBlock2.playerName); + sub_80BE138((TVShow *)worldOfMastersDst); + worldOfMastersDst->language = GAME_LANGUAGE; + } + } +} + +void sub_80BEB20(void) +{ + u16 rval; + + if (FlagGet(SYS_GAME_CLEAR) != 0) + { + gUnknown_03005D38.var0 = sub_80BEBC8(gSaveBlock1.unknown_2ABC); + if (gUnknown_03005D38.var0 != -1 && sub_80BF77C(0x28f) != 1) + { + rval = (Random() % 3) + 1; + if (sub_80BEE48(rval) != 1) + { + gSaveBlock1.unknown_2ABC[gUnknown_03005D38.var0].val0 = rval; + gSaveBlock1.unknown_2ABC[gUnknown_03005D38.var0].val2 = 4; + gSaveBlock1.unknown_2ABC[gUnknown_03005D38.var0].val1 = 1; + } + } + } +} + +int sub_80BEBC8(struct UnknownSaveStruct2ABC *arg0) +{ + s8 i; + + for (i = 0; i < 16; i++) + { + if (arg0[i].val0 == 0) + return i; + } + return -1; +} + +void sub_80BEBF4(void) +{ + u8 i; + + for (i = 0; i < 16; i++) + sub_80BEC10(i); +} + +void sub_80BEC10(u8 arg0) +{ + gSaveBlock1.unknown_2ABC[arg0].val0 = 0; + gSaveBlock1.unknown_2ABC[arg0].val1 = 0; + gSaveBlock1.unknown_2ABC[arg0].val2 = 0; +} + +void sub_80BEC40(void) +{ + u8 i, j; + + for (i = 0; i < 15; i++) + { + if (gSaveBlock1.unknown_2ABC[i].val0 == 0) + { + for (j = i + 1; j < 16; j++) + { + if (gSaveBlock1.unknown_2ABC[j].val0 != 0) + { + gSaveBlock1.unknown_2ABC[i] = gSaveBlock1.unknown_2ABC[j]; + sub_80BEC10(j); + break; + } + } + } + } +} + +u8 sub_80BECA0(void) +{ + u8 i; + for (i = 0; i < 16; i++) + { + if (gSaveBlock1.unknown_2ABC[i].val0 != 0 + && gSaveBlock1.unknown_2ABC[i].val1 == 1 + && gSaveBlock1.unknown_2ABC[i].val2 < 3) + return i; + } + return 0xFF; +} + +void sub_80BECE8(void) +{ + u8 arg0; + arg0 = sub_80BECA0(); + if (arg0 == 0xff) + { + gScriptResult = 0; + return; + } + if (gSaveBlock1.unknown_2ABC[arg0].val2 == 0) + { + gSaveBlock1.unknown_2ABC[arg0].val1 = 2; + if (gLocalTime.hours < 20) + ShowFieldMessage(gTVNewsTextGroup2[gSaveBlock1.unknown_2ABC[arg0].val0]); + else + ShowFieldMessage(gTVNewsTextGroup3[gSaveBlock1.unknown_2ABC[arg0].val0]); + } + else + { + u16 value = gSaveBlock1.unknown_2ABC[arg0].val2; + + ConvertIntToDecimalStringN(gStringVar1, value, 0, 1); + gSaveBlock1.unknown_2ABC[arg0].val1 = 0; + ShowFieldMessage(gTVNewsTextGroup1[gSaveBlock1.unknown_2ABC[arg0].val0]); + } + gScriptResult = 1; +} + +bool8 GetPriceReduction(u8 arg0) +{ + u8 i; + + if (arg0 == 0) + return FALSE; + for (i=0; i<16; i++) + { + if (gSaveBlock1.unknown_2ABC[i].val0 == arg0) + { + if (gSaveBlock1.unknown_2ABC[i].val1 == 2 && IsPriceDiscounted(arg0) != 0) + return TRUE; + else + return FALSE; + } + } + return FALSE; +} + +bool8 IsPriceDiscounted(u8 arg0) +{ + switch (arg0) + { + case 1: + if (gSaveBlock1.location.mapGroup == MAP_GROUP_SLATEPORT_CITY + && gSaveBlock1.location.mapNum == MAP_ID_SLATEPORT_CITY + && gScriptLastTalked == 0x1a) + return TRUE; + else + return FALSE; + break; + case 3: + if (gSaveBlock1.location.mapGroup == MAP_GROUP_LILYCOVE_CITY_DEPARTMENT_STORE_ROOFTOP + && gSaveBlock1.location.mapNum == MAP_ID_LILYCOVE_CITY_DEPARTMENT_STORE_ROOFTOP) + return TRUE; + else + return FALSE; + break; + default: + return TRUE; + } +} + +bool8 sub_80BEE48(u8 arg0) +{ + u8 i; + + if (arg0 == 0) + return TRUE; + for (i=0; i<16; i++) + { + if (gSaveBlock1.unknown_2ABC[i].val0 == arg0) + return TRUE; + } + return FALSE; +} + +void sub_80BEE84(u16 var0) +{ + u8 i; + + for (i=0; i<16; i++) + { + if (gSaveBlock1.unknown_2ABC[i].val0) + { + if (gSaveBlock1.unknown_2ABC[i].val2 < var0) + { + sub_80BEC10(i); + } + else + { + if (!gSaveBlock1.unknown_2ABC[i].val1 && FlagGet(SYS_GAME_CLEAR) == 1) + gSaveBlock1.unknown_2ABC[i].val1 = 1; + gSaveBlock1.unknown_2ABC[i].val2 -= var0; + } + } + } + sub_80BEC40(); +} + +void sub_80BEF10(u8 strvaridx, u8 rank) +{ + switch (rank) + { + case NORMAL_RANK: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[NORMAL_RANK + 5]); + break; + case SUPER_RANK: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[SUPER_RANK + 5]); + break; + case HYPER_RANK: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[HYPER_RANK + 5]); + break; + case MASTER_RANK: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[MASTER_RANK + 5]); + break; + } +} + +void CopyContestCategoryToStringVar(u8 strvaridx, u8 category) +{ + switch (category) + { + case CONTEST_COOL: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[CONTEST_COOL]); + break; + case CONTEST_BEAUTY: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[CONTEST_BEAUTY]); + break; + case CONTEST_CUTE: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[CONTEST_CUTE]); + break; + case CONTEST_SMART: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[CONTEST_SMART]); + break; + case CONTEST_TOUGH: + StringCopy(gUnknown_083D1464[strvaridx], gUnknown_083CE048[CONTEST_TOUGH]); + break; + } +} + +void SetContestCategoryStringVarForInterview(void) +{ + struct TVShowBravoTrainerPokemonProfiles *bravoTrainer = &gSaveBlock1.tvShows[gSpecialVar_0x8004].bravoTrainer; + + CopyContestCategoryToStringVar(1, bravoTrainer->contestCategory); +} + +void sub_80BF088(u8 arg0, s32 price) +{ + size_t log10val = sub_80BF0B8(price); + + ConvertIntToDecimalStringN(gUnknown_083D1464[arg0], price, 0, log10val); +} + +size_t sub_80BF0B8(int value) +{ + if (value / 10 == 0) + return 1; + else if (value / 100 == 0) + return 2; + else if (value / 1000 == 0) + return 3; + else if (value / 10000 == 0) + return 4; + else if (value / 100000 == 0) + return 5; + else if (value / 1000000 == 0) + return 6; + else if (value / 10000000 == 0) + return 7; + else if (value / 100000000 == 0) + return 8; + else + return 1; +} + +void sub_80BF154(u8 arg0, struct TVShowSmartShopper *arg1) +{ + u8 i; + s32 price; + price = 0; + + for (i = 0; i < 3; i++) + { + if (arg1->itemIds[i]) + price += ItemId_GetPrice(arg1->itemIds[i]) * arg1->itemAmounts[i]; + } + if (arg1->priceReduced == 1) + sub_80BF088(arg0, price >> 1); + else + sub_80BF088(arg0, price); +} + +bool8 sub_80BF1B4(u8 showIdx) +{ + u8 i; + //TVShow *tvShows; + TVShow *tvShows = gSaveBlock1.tvShows; + u32 trainerId = GetPlayerTrainerId(); + + for (i = 5; i < 24; i++) + { + if (tvShows[i].common.var00 == showIdx) + { + if ((trainerId & 0xFF) == tvShows[i].common.trainerIdLo && ((trainerId >> 8) & 0xFF) == tvShows[i].common.trainerIdHi) + return TRUE; + } + } + return FALSE; +} + +void sub_80BF20C(void) +{ + u8 i, j; + u16 tmpId, tmpAmount; + + for (i = 0; i < 2; i++) + { + for (j = i + 1; j < 3; j++) + { + if (gUnknown_02038724[i].item_amount < gUnknown_02038724[j].item_amount) + { + tmpId = gUnknown_02038724[i].item_id; + tmpAmount = gUnknown_02038724[i].item_amount; + gUnknown_02038724[i].item_id = gUnknown_02038724[j].item_id; + gUnknown_02038724[i].item_amount = gUnknown_02038724[j].item_amount; + gUnknown_02038724[j].item_id = tmpId; + gUnknown_02038724[j].item_amount = tmpAmount; + } + } + } +} + +void sub_80BF25C(u8 showType) +{ + u8 i; + + for (i = 0; i < 5; i++) + { + if (gSaveBlock1.tvShows[i].common.var00 == showType) + { + if(gSaveBlock1.tvShows[i].common.var01 == 1) + { + gScriptResult = 1; + } + else + { + sub_80BF55C(gSaveBlock1.tvShows, i); + sub_80BF588(gSaveBlock1.tvShows); + sub_80BF6D8(); + } + return; + } + } + sub_80BF6D8(); +} + +void sub_80BF2C4(void) +{ + gScriptResult = 0; + switch (gSpecialVar_0x8005) + { + case TVSHOW_FAN_CLUB_LETTER: + sub_80BF334(); + break; + case TVSHOW_RECENT_HAPPENINGS: + sub_80BF3A4(); + break; + case TVSHOW_PKMN_FAN_CLUB_OPINIONS: + sub_80BF3DC(); + break; + case TVSHOW_UNKN_SHOWTYPE_04: + sub_80BF46C(); + break; + case TVSHOW_NAME_RATER_SHOW: + sub_80BF478(); + break; + case TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE: + sub_80BF484(); + break; + case TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE: + sub_80BF4BC(); + break; + } +} + +void sub_80BF334(void) +{ + struct TVShowFanClubLetter *fanclubLetter; + + sub_80BF25C(TVSHOW_FAN_CLUB_LETTER); + if (gScriptResult == 0) + { + StringCopy(gStringVar1, gSpeciesNames[GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SPECIES, 0)]); + fanclubLetter = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].fanclubLetter; + sub_80EB6FC(fanclubLetter->pad04, 6); + } +} + +void sub_80BF3A4(void) +{ + struct TVShowRecentHappenings *recentHappenings; + + sub_80BF25C(TVSHOW_RECENT_HAPPENINGS); + if (gScriptResult == 0) + { + recentHappenings = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].recentHappenings; + sub_80EB6FC(recentHappenings->var04, 6); + } +} + +void sub_80BF3DC(void) +{ + struct TVShowFanclubOpinions *fanclubOpinions; + + sub_80BF25C(TVSHOW_PKMN_FAN_CLUB_OPINIONS); + if (gScriptResult == 0) + { + StringCopy(gStringVar1, gSpeciesNames[GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_SPECIES, 0)]); + GetMonData(&gPlayerParty[GetLeadMonIndex()], MON_DATA_NICKNAME, gStringVar2); + StringGetEnd10(gStringVar2); + fanclubOpinions = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].fanclubOpinions; + sub_80EB6FC(fanclubOpinions->var1C, 2); + } +} + +void sub_80BF46C(void) +{ + gScriptResult = 1; +} + +void sub_80BF478(void) +{ + sub_80BF25C(TVSHOW_NAME_RATER_SHOW); +} + +void sub_80BF484(void) +{ + struct TVShowBravoTrainerPokemonProfiles *bravoTrainer; + + sub_80BF25C(TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE); + if (gScriptResult == 0) + { + bravoTrainer = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].bravoTrainer; + sub_80EB6FC(bravoTrainer->var04, 2); + } +} + +void sub_80BF4BC(void) +{ + struct TVShowBravoTrainerBattleTowerSpotlight *bravoTrainerTower; + + sub_80BF25C(TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE); + if (gScriptResult == 0) + { + bravoTrainerTower = &gSaveBlock1.tvShows[gUnknown_03005D38.var0].bravoTrainerTower; + sub_80EB6FC(bravoTrainerTower->var18, 1); // wrong struct ident, fix later + } +} + +#if ENGLISH +u8 sub_80BF4F4(u8 arg0) +{ + u32 species; + + GetMonData(&gPlayerParty[arg0], MON_DATA_NICKNAME, &gStringVar1); + species = GetMonData(&gPlayerParty[arg0], MON_DATA_SPECIES, NULL); + if (StringCompareWithoutExtCtrlCodes(gSpeciesNames[species], gStringVar1) == FALSE) + return FALSE; + + return TRUE; +} +#elif GERMAN +u8 sub_80BF4F4(u8 arg0) +{ + u8 langData[4]; + u32 species; + u8 *tmp; + + GetMonData(&gPlayerParty[arg0], MON_DATA_NICKNAME, &gStringVar1); + + tmp = langData; + tmp[0] = GetMonData(&gPlayerParty[arg0], MON_DATA_LANGUAGE, &langData); + if (tmp[0] != GAME_LANGUAGE) + return TRUE; + + species = GetMonData(&gPlayerParty[arg0], MON_DATA_SPECIES, NULL); + if (StringCompareWithoutExtCtrlCodes(gSpeciesNames[species], gStringVar1)) + return TRUE; + + return FALSE; +} +#endif + +u8 sub_80BF544(void) +{ + return sub_80BF4F4(GetLeadMonIndex()); +} + +void sub_80BF55C(TVShow tvShow[], u8 showidx) +{ + u8 idx; + + tvShow[showidx].common.var00 = 0; + tvShow[showidx].common.var01 = 0; + for (idx = 0; idx < 34; idx++) + tvShow[showidx].common.pad02[idx] = 0; +} + +void sub_80BF588(TVShow tvShow[]) +{ + u8 showidx; + u8 showidx2; + + for (showidx = 0; showidx < 4; showidx++) + { + if (tvShow[showidx].common.var00 == 0) + { + for (showidx2 = showidx + 1; showidx2 < 5; showidx2++) + { + if (tvShow[showidx2].common.var00 != 0) + { + tvShow[showidx] = tvShow[showidx2]; + sub_80BF55C(tvShow, showidx2); + break; + } + } + } + } + for (showidx = 5; showidx < 24; showidx++) + { + if (tvShow[showidx].common.var00 == 0) + { + for (showidx2 = showidx + 1; showidx2 < 24; showidx2++) + { + if (tvShow[showidx2].common.var00 != 0) + { + tvShow[showidx] = tvShow[showidx2]; + sub_80BF55C(gSaveBlock1.tvShows, showidx2); + break; + } + } + } + } +} + +u16 sub_80BF638(u8 arg0, u16 arg1) +{ + u16 retval = sub_80BF674(arg1); + + StringCopy(gUnknown_083D1464[arg0], gSpeciesNames[retval]); + return retval; +} + +u16 sub_80BF674(u16 species) +{ + u16 rspecies; + u16 cspecies; + + rspecies = (Random() % (NUM_SPECIES - 1)) + 1; + cspecies = rspecies; + while (GetSetPokedexFlag(SpeciesToNationalPokedexNum(cspecies), 0) != 1 || cspecies == species) + { + if (cspecies == SPECIES_BULBASAUR) + cspecies = NUM_SPECIES - 1; + else + cspecies --; + if (cspecies == rspecies) + { + cspecies = species; + return cspecies; + } + } + return cspecies; +} + +void sub_80BF6D8(void) +{ + gUnknown_03005D38.var0 = sub_80BF720(gSaveBlock1.tvShows); + gSpecialVar_0x8006 = gUnknown_03005D38.var0; + if (gUnknown_03005D38.var0 == -1) + gScriptResult = 1; + else + gScriptResult = 0; +} + +s8 sub_80BF720(TVShow tvShow[]) +{ + u8 idx; + + for (idx = 0; idx < 5; idx++) + { + if (tvShow[idx].common.var00 == 0) + return idx; + } + return -1; +} + +s8 sub_80BF74C(TVShow tvShow[]) +{ + s8 idx; + + for (idx = 5; idx < 24; idx++) + { + if (tvShow[idx].common.var00 == 0) + return idx; + } + return -1; +} + +bool8 sub_80BF77C(u16 value) +{ + if (Random() <= value) + return FALSE; + return TRUE; +} + +void sub_80BF79C(TVShow *arg0) +{ + u8 i = Random() % 6; + + while (1) + { + if (i == 6) + i = 0; + if (arg0->recentHappenings.var04[i] != 0xFFFF) + break; + i++; + } + EasyChat_GetWordText(gStringVar3, arg0->recentHappenings.var04[i]); +} + +u8 sub_80BF7E8(struct TVShowNameRaterShow *arg0) +{ + u16 flagsum = 0; + u8 i = 0; + + if (arg0->pokemonName[0] != 0xFF) + { + while (i < 11 && arg0->pokemonName[i] != 0xFF) + { + flagsum += arg0->pokemonName[i]; + i++; + } + } + return flagsum & 0x7; +} + + +void sub_80BF820(u8 arg0, u8 arg1, u8 arg2, u16 arg3, u16 arg4, struct TVShowNameRaterShow *tvShow) +{ + u8 flags[3]; + u16 nameLength; + u8 i; + + for (i = 0; i < 3; i++) + flags[i] = EOS; + + if (arg3 == 0) + { + nameLength = StringLength(tvShow->trainerName); + if (arg2 == 0) + { + flags[0] = tvShow->trainerName[arg1]; + } + else if (arg2 == 1) + { + flags[0] = tvShow->trainerName[nameLength - arg1]; + } + else if (arg2 == 2) { + flags[0] = tvShow->trainerName[arg1]; + flags[1] = tvShow->trainerName[arg1 + 1]; + } + else + { + flags[0] = tvShow->trainerName[nameLength - (arg1 + 2)]; + flags[1] = tvShow->trainerName[nameLength - (arg1 + 1)]; + } + } + else if (arg3 == 1) + { + nameLength = StringLength(tvShow->pokemonName); + if (arg2 == 0) + { + flags[0] = tvShow->pokemonName[arg1]; + } + else if (arg2 == 1) + { + flags[0] = tvShow->pokemonName[nameLength - arg1]; + } + else if (arg2 == 2) + { + flags[0] = tvShow->pokemonName[arg1]; + flags[1] = tvShow->pokemonName[arg1 + 1]; + } + else + { + flags[0] = tvShow->pokemonName[nameLength - (arg1 + 2)]; + flags[1] = tvShow->pokemonName[nameLength - (arg1 + 1)]; + } + } + else + { + nameLength = StringLength(gSpeciesNames[arg4]); + if (arg2 == 0) + { + flags[0] = gSpeciesNames[arg4][arg1]; + } + else if (arg2 == 1) + { + flags[0] = gSpeciesNames[arg4][nameLength - arg1]; + } + else if (arg2 == 2) + { + flags[0] = gSpeciesNames[arg4][arg1]; + flags[1] = gSpeciesNames[arg4][arg1 + 1]; + } + else + { + flags[0] = gSpeciesNames[arg4][nameLength - (arg1 + 2)]; + flags[1] = gSpeciesNames[arg4][nameLength - (arg1 + 1)]; + } + } + StringCopy(gUnknown_083D1464[arg0], flags); +} + +bool8 sub_80BF974(void) +{ + u8 i; + + for (i = 0; i < 5; i++) + { + if (gSaveBlock1.tvShows[i].common.var00 == gSpecialVar_0x8004) + return TRUE; + } + return FALSE; +} + +bool8 sub_80BF9B4(void) +{ + GetMonData(&(gPlayerParty[gSpecialVar_0x8004]), MON_DATA_NICKNAME, &gStringVar1); + if (!StringCompareWithoutExtCtrlCodes(gStringVar3, gStringVar1)) + return FALSE; + sub_80BE478(); + return TRUE; +} + +void c2_080CC144(void); + +void sub_80BF9F8(void) +{ + u16 spec; + u16 gender; + u32 pval; + + GetMonData(&(gPlayerParty[gSpecialVar_0x8004]), MON_DATA_NICKNAME, &gStringVar3); + GetMonData(&(gPlayerParty[gSpecialVar_0x8004]), MON_DATA_NICKNAME, &gStringVar2); + spec = GetMonData(&(gPlayerParty[gSpecialVar_0x8004]), MON_DATA_SPECIES, 0); + gender = GetMonGender(&(gPlayerParty[gSpecialVar_0x8004])); + pval = GetMonData(&(gPlayerParty[gSpecialVar_0x8004]), MON_DATA_PERSONALITY, 0); + DoNamingScreen(3, gStringVar2, spec, gender, pval, c2_080CC144); +} + +void c2_080CC144(void) +{ + SetMonData(&(gPlayerParty[gSpecialVar_0x8004]), MON_DATA_NICKNAME, gStringVar2); + c2_exit_to_overworld_1_continue_scripts_restart_music(); +} + +void sub_80BFAE0(void) +{ + GetMonData(&(gPlayerParty[gSpecialVar_0x8004]), MON_DATA_NICKNAME, &gStringVar1); + StringGetEnd10(gStringVar1); +} + +void sub_80BFB10(void) +{ + if (GetPlayerTrainerId() == GetMonData(&(gPlayerParty[gSpecialVar_0x8004]), MON_DATA_OT_ID, 0)) + gScriptResult = 0; + else + gScriptResult = 1; +} + +u8 sub_80BFB54(u8 arg0) +{ + if (arg0 == 0) + return 0; + else if (arg0 > 0 && arg0 <= 20) + return 2; + else if (arg0 > 20 && arg0 <= 40) + return 3; + else if (arg0 > 40 && arg0 <= 60) + return 4; + else + return 0; +} + +u32 GetPlayerTrainerId(void) +{ + return (gSaveBlock2.playerTrainerId[3] << 24) | (gSaveBlock2.playerTrainerId[2] << 16) | (gSaveBlock2.playerTrainerId[1] << 8) | (gSaveBlock2.playerTrainerId[0]); +} + +u8 CheckForBigMovieOrEmergencyNewsOnTV(void) +{ + if (gSaveBlock1.location.mapGroup != MAP_GROUP_LITTLEROOT_TOWN_BRENDANS_HOUSE_1F) + return 0; + if (gSaveBlock2.playerGender == MALE) + { + if (gSaveBlock1.location.mapNum != MAP_ID_LITTLEROOT_TOWN_BRENDANS_HOUSE_1F) + return 0; + } + else + { + if (gSaveBlock1.location.mapNum != MAP_ID_LITTLEROOT_TOWN_MAYS_HOUSE_1F) + return 0; + } + if (FlagGet(SYS_TV_LATI) == 1) + return 1; + if (FlagGet(SYS_TV_HOME) == 1) + return 2; + return 1; +} + +void GetMomOrDadStringForTVMessage(void) +{ + if (gSaveBlock1.location.mapGroup == MAP_GROUP_LITTLEROOT_TOWN_BRENDANS_HOUSE_1F) + { + if (gSaveBlock2.playerGender == MALE) + { + if (gSaveBlock1.location.mapNum == MAP_ID_LITTLEROOT_TOWN_BRENDANS_HOUSE_1F) + { + StringCopy(gStringVar1, gOtherText_Mom); + VarSet(VAR_0x4003, 1); + } + } + else + { + if (gSaveBlock1.location.mapNum == MAP_ID_LITTLEROOT_TOWN_MAYS_HOUSE_1F) + { + StringCopy(gStringVar1, gOtherText_Mom); + VarSet(VAR_0x4003, 1); + } + } + } + if (VarGet(VAR_0x4003) == 1) + { + StringCopy(gStringVar1, gOtherText_Mom); + } + else if (VarGet(VAR_0x4003) == 2) + { + StringCopy(gStringVar1, gOtherText_Dad); + } + else if (VarGet(VAR_0x4003) > 2) + { + if (VarGet(VAR_0x4003) % 2 == 0) + StringCopy(gStringVar1, gOtherText_Mom); + else + StringCopy(gStringVar1, gOtherText_Dad); + } + else + { + if (Random() % 2 != 0) + { + StringCopy(gStringVar1, gOtherText_Mom); + VarSet(VAR_0x4003, 1); + } + else + { + StringCopy(gStringVar1, gOtherText_Dad); + VarSet(VAR_0x4003, 2); + } + } +} + +void sub_80BFD20(void) +{ + VarSet(VAR_0x40BC, 0); + RemoveFieldObjectByLocalIdAndMap(5, gSaveBlock1.location.mapNum, gSaveBlock1.location.mapGroup); +} + +typedef union ewramStruct_02007000 +{ + TVShow tvshows[4][25]; + struct UnknownSaveStruct2ABC unknown_2abc[4][16]; +} ewramStruct_02007000; + +void sub_80BFE24(TVShow arg0[25], TVShow arg1[25], TVShow arg2[25], TVShow arg3[25]); + +void sub_80C04A0(void); +void sub_80C01D4(void); +void sub_80C0408(void); + +void sub_80BFD44(u8 *arg0, u32 arg1, u8 arg2) +{ + u8 i; + ewramStruct_02007000 *ewramTVShows; + + for (i = 0; i < 4; i++) + memcpy(&gUnknown_02007000.tvshows[i], &arg0[i * arg1], 25 * sizeof(TVShow)); + ewramTVShows = &gUnknown_02007000; + switch (arg2) + { + case 0: + sub_80BFE24(gSaveBlock1.tvShows, ewramTVShows->tvshows[1], ewramTVShows->tvshows[2], ewramTVShows->tvshows[3]); + break; + case 1: + sub_80BFE24(ewramTVShows->tvshows[0], gSaveBlock1.tvShows, ewramTVShows->tvshows[2], ewramTVShows->tvshows[3]); + break; + case 2: + sub_80BFE24(ewramTVShows->tvshows[0], ewramTVShows->tvshows[1], gSaveBlock1.tvShows, ewramTVShows->tvshows[3]); + break; + case 3: + sub_80BFE24(ewramTVShows->tvshows[0], ewramTVShows->tvshows[1], ewramTVShows->tvshows[2], gSaveBlock1.tvShows); + break; + } + sub_80BF588(gSaveBlock1.tvShows); + sub_80C04A0(); + sub_80BF588(gSaveBlock1.tvShows); + sub_80C01D4(); + sub_80C0408(); +} + +s8 sub_80C019C(TVShow tvShows[]); +bool8 sub_80BFF68(TVShow * tv1[25], TVShow * tv2[25], u8 idx); +u8 sub_80C004C(TVShow *tv1, TVShow *tv2, u8 idx); +u8 sub_80C00B4(TVShow *tv1, TVShow *tv2, u8 idx); +u8 sub_80C0134(TVShow *tv1, TVShow *tv2, u8 idx); + +void sub_80BFE24(TVShow arg0[25], TVShow arg1[25], TVShow arg2[25], TVShow arg3[25]) +{ + u8 i, j; + TVShow **argslist[4]; + + argslist[0] = &arg0; + argslist[1] = &arg1; + argslist[2] = &arg2; + argslist[3] = &arg3; + gUnknown_03000720 = GetLinkPlayerCount(); + while (1) + { + for (i=0; i<gUnknown_03000720; i++) + { + if (i == 0) + gUnknown_020387E4 = i; + gUnknown_03000722 = sub_80C019C(argslist[i][0]); + if (gUnknown_03000722 == -1) + { + gUnknown_020387E4++; + if (gUnknown_020387E4 == gUnknown_03000720) + return; + } + else + { + for (j=0; j<gUnknown_03000720-1; j++) + { + gUnknown_03005D38.var0 = sub_80BF74C(argslist[(i + j + 1) % gUnknown_03000720][0]); + if (gUnknown_03005D38.var0 != -1 + && sub_80BFF68(&argslist[(i + j + 1) % gUnknown_03000720][0], &argslist[i][0], (i + j + 1) % gUnknown_03000720) == 1) + break; + } + if (j == gUnknown_03000720 - 1) + sub_80BF55C(argslist[i][0], gUnknown_03000722); + } + } + } +} + +bool8 sub_80BFF68(TVShow * arg1[25], TVShow * arg2[25], u8 idx) +{ + u8 value; + u8 switchval; + TVShow *tv1; + TVShow *tv2; + + tv1 = *arg1; + tv2 = *arg2; + value = FALSE; + switchval = sub_80BFB54(tv2[gUnknown_03000722].common.var00); + switch (switchval) + { + case 2: + value = sub_80C004C(&tv1[gUnknown_03005D38.var0], &tv2[gUnknown_03000722], idx); + break; + case 3: + value = sub_80C00B4(&tv1[gUnknown_03005D38.var0], &tv2[gUnknown_03000722], idx); + break; + case 4: + value = sub_80C0134(&tv1[gUnknown_03005D38.var0], &tv2[gUnknown_03000722], idx); + break; + } + if (value == TRUE) + { + sub_80BF55C(tv2, gUnknown_03000722); + return TRUE; + } + else + { + return FALSE; + } +} + +u8 sub_80C004C(TVShow *tv1, TVShow *tv2, u8 idx) +{ + u32 linkTrainerId = GetLinkPlayerTrainerId(idx); + + if ((linkTrainerId & 0xFF) == tv2->common.trainerIdLo && ((linkTrainerId >> 8) & 0xFF) == tv2->common.trainerIdHi) + return FALSE; + tv2->common.trainerIdLo = tv2->common.srcTrainerIdLo; + tv2->common.trainerIdHi = tv2->common.srcTrainerIdHi; + tv2->common.srcTrainerIdLo = linkTrainerId & 0xFF; + tv2->common.srcTrainerIdHi = linkTrainerId >> 8; + *tv1 = *tv2; + tv1->common.var01 = 1; + return TRUE; +} + +u8 sub_80C00B4(TVShow *tv1, TVShow *tv2, u8 idx) +{ + u32 linkTrainerId = GetLinkPlayerTrainerId(idx); + if ((linkTrainerId & 0xFF) == tv2->common.srcTrainerIdLo && ((linkTrainerId >> 8) & 0xFF) == tv2->common.srcTrainerIdHi) + return FALSE; + if ((linkTrainerId & 0xFF) == tv2->common.trainerIdLo && ((linkTrainerId >> 8) & 0xFF) == tv2->common.trainerIdHi) + return FALSE; + tv2->common.srcTrainerIdLo = tv2->common.srcTrainerId2Lo; + tv2->common.srcTrainerIdHi = tv2->common.srcTrainerId2Hi; + tv2->common.srcTrainerId2Lo = linkTrainerId & 0xFF; + tv2->common.srcTrainerId2Hi = linkTrainerId >> 8; + *tv1 = *tv2; + tv1->common.var01 = 1; + return TRUE; +} + +u8 sub_80C0134(TVShow *tv1, TVShow *tv2, u8 idx) +{ + u32 linkTrainerId = GetLinkPlayerTrainerId(idx); + if ((linkTrainerId & 0xFF) == tv2->common.trainerIdLo && ((linkTrainerId >> 8) & 0xFF) == tv2->common.trainerIdHi) + return FALSE; + tv2->common.trainerIdLo = tv2->common.srcTrainerIdLo; + tv2->common.trainerIdHi = tv2->common.srcTrainerIdHi; + tv2->common.srcTrainerIdLo = linkTrainerId & 0xFF; + tv2->common.srcTrainerIdHi = linkTrainerId >> 8; + *tv1 = *tv2; + tv1->common.var01 = 1; + tv1->common.var16[0] = 1; + return TRUE; +} + +s8 sub_80C019C(TVShow tvShows[]) +{ + u8 i; + for (i = 0; i < 24; i++) + { + if (tvShows[i].common.var01 == 0 && (u8)(tvShows[i].common.var00 - 1) < 60) + return i; + } + return -1; +} + +#ifdef NONMATCHING +void sub_80C01D4(void) +{ + u16 i; + for (i=0; i<24; i++) + { + switch (gSaveBlock1.tvShows[i].common.var00) + { + case 0: + case TVSHOW_RECENT_HAPPENINGS: + case TVSHOW_SMART_SHOPPER: + case TVSHOW_MASS_OUTBREAK: + break; + case TVSHOW_FAN_CLUB_LETTER: + sub_80C03C8((&gSaveBlock1.tvShows[i])->fanclubLetter.species, i); + break; + case TVSHOW_PKMN_FAN_CLUB_OPINIONS: + sub_80C03C8((&gSaveBlock1.tvShows[i])->fanclubOpinions.var02, i); + break; + case TVSHOW_UNKN_SHOWTYPE_04: + sub_80C03C8((&gSaveBlock1.tvShows[i])->unkShow04.var06, i); + break; + case TVSHOW_NAME_RATER_SHOW: + sub_80C03C8((&gSaveBlock1.tvShows[i])->nameRaterShow.species, i); + sub_80C03C8((&gSaveBlock1.tvShows[i])->nameRaterShow.var1C, i); + break; + case TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE: + sub_80C03C8((&gSaveBlock1.tvShows[i])->bravoTrainer.species, i); + break; + case TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE: + sub_80C03C8((&gSaveBlock1.tvShows[i])->bravoTrainerTower.species, i); + sub_80C03C8((&gSaveBlock1.tvShows[i])->bravoTrainerTower.defeatedSpecies, i); + break; + case TVSHOW_POKEMON_TODAY_CAUGHT: + sub_80C03C8((&gSaveBlock1.tvShows[i])->pokemonToday.species, i); + break; + case TVSHOW_POKEMON_TODAY_FAILED: + sub_80C03C8((&gSaveBlock1.tvShows[i])->pokemonTodayFailed.species, i); + sub_80C03C8((&gSaveBlock1.tvShows[i])->pokemonTodayFailed.species2, i); + break; + case TVSHOW_FISHING_ADVICE: + sub_80C03C8((&gSaveBlock1.tvShows[i])->pokemonAngler.var04, i); + break; + case TVSHOW_WORLD_OF_MASTERS: + sub_80C03C8((&gSaveBlock1.tvShows[i])->worldOfMasters.var08, i); + sub_80C03C8((&gSaveBlock1.tvShows[i])->worldOfMasters.var04, i); + break; + default: + sub_80C03A8(i); + } + } +} +#else +__attribute__((naked)) +void sub_80C01D4(void) { + asm(".syntax unified\n\ + push {r4-r6,lr}\n\ + movs r6, 0\n\ +_080C01D8:\n\ + ldr r0, _080C01F8 @ =gSaveBlock1\n\ + lsls r2, r6, 3\n\ + adds r1, r2, r6\n\ + lsls r1, 2\n\ + adds r1, r0\n\ + ldr r0, _080C01FC @ =0x00002738\n\ + adds r1, r0\n\ + ldrb r0, [r1]\n\ + cmp r0, 0x29\n\ + bls _080C01EE\n\ + b _default\n\ +_080C01EE:\n\ + lsls r0, 2\n\ + ldr r1, _080C0200 @ =_080C0204\n\ + adds r0, r1\n\ + ldr r0, [r0]\n\ + mov pc, r0\n\ + .align 2, 0\n\ +_080C01F8: .4byte gSaveBlock1\n\ +_080C01FC: .4byte 0x00002738\n\ +_080C0200: .4byte _080C0204\n\ + .align 2, 0\n\ +_080C0204:\n\ + .4byte _break\n\ + .4byte _fanclubLetter @ TVSHOW_FAN_CLUB_LETTER\n\ + .4byte _break @ TVSHOW_RECENT_HAPPENINGS\n\ + .4byte _fanclubOpinions @ TVSHOW_PKMN_FAN_CLUB_OPINIONS\n\ + .4byte _showtype4 @ TVSHOW_UNKN_SHOWTYPE_04\n\ + .4byte _nameRater @ TVSHOW_NAME_RATER_SHOW\n\ + .4byte _bravoTrainerContest @ TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE\n\ + .4byte _bravoTrainerTower @ TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _pokemonTodayS @ TVSHOW_POKEMON_TODAY_CAUGHT\n\ + .4byte _break @ TVSHOW_SMART_SHOPPER\n\ + .4byte _pokemonTodayF @ TVSHOW_POKEMON_TODAY_FAILED\n\ + .4byte _fishing @ TVSHOW_FISHING_ADVICE\n\ + .4byte _worldOfMasters @ TVSHOW_WORLD_OF_MASTERS\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _default\n\ + .4byte _break @ TVSHOW_MASS_OUTBREAK\n\ +_fanclubLetter:\n\ + adds r0, r2, r6\n\ + lsls r0, 2\n\ + ldr r1, _080C02B8 @ =gSaveBlock1 + 0x2738\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x2]\n\ + b _checkSpecies1 @ sub_80C03C8(r0, i)\n\ + .align 2, 0\n\ +_080C02B8: .4byte gSaveBlock1 + 0x2738\n\ +_fanclubOpinions:\n\ + adds r0, r2, r6\n\ + lsls r0, 2\n\ + ldr r1, _080C02C8 @ =gSaveBlock1 + 0x2738\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x2]\n\ + b _checkSpecies1 @ sub_80C03C8(r0, i)\n\ + .align 2, 0\n\ +_080C02C8: .4byte gSaveBlock1 + 0x2738\n\ +_showtype4:\n\ + adds r0, r2, r6\n\ + lsls r0, 2\n\ + ldr r1, _080C02D8 @ =gSaveBlock1 + 0x2738\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x6]\n\ + b _checkSpecies1 @ sub_80C03C8(r0, i)\n\ + .align 2, 0\n\ +_080C02D8: .4byte gSaveBlock1 + 0x2738\n\ +_nameRater:\n\ + adds r4, r2, r6\n\ + lsls r4, 2\n\ + ldr r0, _080C02F4 @ =gSaveBlock1 + 0x2738\n\ + adds r4, r0\n\ + ldrh r0, [r4, 0x2]\n\ + lsls r5, r6, 24\n\ + lsrs r5, 24\n\ + adds r1, r5, 0\n\ + bl sub_80C03C8\n\ + ldrh r0, [r4, 0x1C]\n\ + b _checkSpecies2 @ sub_80C03C8(r0, i)\n\ + .align 2, 0\n\ +_080C02F4: .4byte gSaveBlock1 + 0x2738\n\ +_bravoTrainerContest:\n\ + adds r0, r2, r6\n\ + lsls r0, 2\n\ + ldr r1, _080C0304 @ =gSaveBlock1 + 0x2738\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x2]\n\ + b _checkSpecies1 @ sub_80C03C8(r0, i)\n\ + .align 2, 0\n\ +_080C0304: .4byte gSaveBlock1 + 0x2738\n\ +_bravoTrainerTower:\n\ + adds r4, r2, r6\n\ + lsls r4, 2\n\ + ldr r0, _080C0320 @ =gSaveBlock1 + 0x2738\n\ + adds r4, r0\n\ + ldrh r0, [r4, 0xA]\n\ + lsls r5, r6, 24\n\ + lsrs r5, 24\n\ + adds r1, r5, 0\n\ + bl sub_80C03C8\n\ + ldrh r0, [r4, 0x14]\n\ + b _checkSpecies2 @ sub_80C03C8(r0, i)\n\ + .align 2, 0\n\ +_080C0320: .4byte gSaveBlock1 + 0x2738\n\ +_pokemonTodayS:\n\ + adds r0, r2, r6\n\ + lsls r0, 2\n\ + ldr r1, _080C0330 @ =gSaveBlock1 + 0x2738\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x10]\n\ + b _checkSpecies1 @ sub_80C03C8(r0, i)\n\ + .align 2, 0\n\ +_080C0330: .4byte gSaveBlock1 + 0x2738\n\ +_pokemonTodayF:\n\ + adds r4, r2, r6\n\ + lsls r4, 2\n\ + ldr r0, _080C034C @ =gSaveBlock1 + 0x2738\n\ + adds r4, r0\n\ + ldrh r0, [r4, 0xC]\n\ + lsls r5, r6, 24\n\ + lsrs r5, 24\n\ + adds r1, r5, 0\n\ + bl sub_80C03C8\n\ + ldrh r0, [r4, 0xE]\n\ + b _checkSpecies2 @ sub_80C03C8(r0, i)\n\ + .align 2, 0\n\ +_080C034C: .4byte gSaveBlock1 + 0x2738\n\ +_fishing:\n\ + adds r0, r2, r6\n\ + lsls r0, 2\n\ + ldr r1, _080C0364 @ =gSaveBlock1 + 0x2738\n\ + adds r0, r1\n\ + ldrh r0, [r0, 0x4]\n\ +_checkSpecies1:\n\ + lsls r1, r6, 24\n\ + lsrs r1, 24\n\ + bl sub_80C03C8\n\ + b _break\n\ + .align 2, 0\n\ +_080C0364: .4byte gSaveBlock1 + 0x2738\n\ +_worldOfMasters:\n\ + adds r4, r2, r6\n\ + lsls r4, 2\n\ + ldr r0, _080C0388 @ =gSaveBlock1 + 0x2738\n\ + adds r4, r0\n\ + ldrh r0, [r4, 0x8]\n\ + lsls r5, r6, 24\n\ + lsrs r5, 24\n\ + adds r1, r5, 0\n\ + bl sub_80C03C8\n\ + ldrh r0, [r4, 0x4]\n\ +_checkSpecies2:\n\ + adds r1, r5, 0\n\ + bl sub_80C03C8\n\ + b _break\n\ + .align 2, 0\n\ +_080C0388: .4byte gSaveBlock1 + 0x2738\n\ +_default:\n\ + lsls r0, r6, 24\n\ + lsrs r0, 24\n\ + bl sub_80C03A8\n\ +_break:\n\ + adds r0, r6, 0x1\n\ + lsls r0, 16\n\ + lsrs r6, r0, 16\n\ + cmp r6, 0x17\n\ + bhi _080C03A0\n\ + b _080C01D8\n\ +_080C03A0:\n\ + pop {r4-r6}\n\ + pop {r0}\n\ + bx r0\n\ +.syntax divided\n"); +} +#endif + +void sub_80C03A8(u8 showidx) +{ + gSaveBlock1.tvShows[showidx].common.var01 = 0; +} + +void sub_80C03C8(u16 species, u8 showidx) +{ + if (GetSetPokedexFlag(SpeciesToNationalPokedexNum(species), 0) == 0) + gSaveBlock1.tvShows[showidx].common.var01 = 0; +} + +void sub_80C0408(void) +{ + u16 i; + + if (FlagGet(SYS_GAME_CLEAR) == TRUE) + return; + for (i = 0; i < 24; i++) + { + if (gSaveBlock1.tvShows[i].common.var00 == TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE) + gSaveBlock1.tvShows[i].common.var01 = 0; + else if (gSaveBlock1.tvShows[i].common.var00 == TVSHOW_MASS_OUTBREAK) + gSaveBlock1.tvShows[i].common.var01 = 0; + } +} + +void sub_80C045C(void) +{ + u8 i; + + for (i = 0; i < 5; i++) + { + if (sub_80BFB54(gSaveBlock1.tvShows[i].common.var00) == 2) + gSaveBlock1.tvShows[i].common.var01 = 0; + } +} + +void sub_80C04A0(void) +{ + s8 showIdx; + s8 count; + count = 0; + + for (showIdx = 5; showIdx < 24; showIdx++) + { + if (gSaveBlock1.tvShows[showIdx].common.var00 == 0) + count++; + } + for (showIdx = 0; showIdx < 5 - count; showIdx++) + sub_80BF55C(gSaveBlock1.tvShows, showIdx+5); +} + +void sub_80C05C4(struct UnknownSaveStruct2ABC[16], struct UnknownSaveStruct2ABC[16], struct UnknownSaveStruct2ABC[16], struct UnknownSaveStruct2ABC[16]); +void sub_80C0750(void); +void sub_80C0788(void); +s8 sub_80C0730(struct UnknownSaveStruct2ABC[16], u8); +void sub_80C06BC(struct UnknownSaveStruct2ABC *[16], struct UnknownSaveStruct2ABC *[16]); + +void sub_80C0514(void *a0, u32 a1, u8 a2) +{ + ewramStruct_02007000 *struct02007000; + u8 i; + + for (i = 0; i < 4; i++) + memcpy(gUnknown_02007000.unknown_2abc[i], a0 + i * a1, 64); + struct02007000 = &gUnknown_02007000; + switch (a2) + { + case 0: + sub_80C05C4(gSaveBlock1.unknown_2ABC, struct02007000->unknown_2abc[1], struct02007000->unknown_2abc[2], struct02007000->unknown_2abc[3]); + break; + case 1: + sub_80C05C4(struct02007000->unknown_2abc[0], gSaveBlock1.unknown_2ABC, struct02007000->unknown_2abc[2], struct02007000->unknown_2abc[3]); + break; + case 2: + sub_80C05C4(struct02007000->unknown_2abc[0], struct02007000->unknown_2abc[1], gSaveBlock1.unknown_2ABC, struct02007000->unknown_2abc[3]); + break; + case 3: + sub_80C05C4(struct02007000->unknown_2abc[0], struct02007000->unknown_2abc[1], struct02007000->unknown_2abc[2], gSaveBlock1.unknown_2ABC); + break; + } + sub_80C0750(); + sub_80C0788(); +} + +void sub_80C05C4(struct UnknownSaveStruct2ABC a0[16], struct UnknownSaveStruct2ABC a1[16], struct UnknownSaveStruct2ABC a2[16], struct UnknownSaveStruct2ABC a3[16]) +{ + u8 i; + u8 j; + u8 k; + struct UnknownSaveStruct2ABC ** arglist[4]; + + arglist[0] = &a0; + arglist[1] = &a1; + arglist[2] = &a2; + arglist[3] = &a3; + gUnknown_03000721 = GetLinkPlayerCount(); + for (i = 0; i < 16; i++) + { + for (j = 0; j < gUnknown_03000721; j++) + { + gUnknown_03000722 = sub_80C0730(*arglist[j], i); + if (gUnknown_03000722 != -1) + { + for (k = 0; k < gUnknown_03000721-1; k++) + { + gUnknown_03005D38.var0 = sub_80BEBC8(*arglist[(j + k + 1) % gUnknown_03000721]); + if (gUnknown_03005D38.var0 != -1) + sub_80C06BC(arglist[(j + k + 1) % gUnknown_03000721], arglist[j]); + } + } + } + } +} + +void sub_80C06BC(struct UnknownSaveStruct2ABC *arg0[16], struct UnknownSaveStruct2ABC *arg1[16]) +{ + struct UnknownSaveStruct2ABC *str0; + struct UnknownSaveStruct2ABC *str1; + + str0 = arg0[0]; + str1 = arg1[0]; + str1 += gUnknown_03000722; + sub_80C06E8(str0, str1, gUnknown_03005D38.var0); +} + +bool8 sub_80C06E8(struct UnknownSaveStruct2ABC *arg0, struct UnknownSaveStruct2ABC *arg1, s8 arg2) +{ + u8 i; + + if (arg1->val0 == 0) + return FALSE; + for (i = 0; i < 16; i++) + { + if (arg0[i].val0 == arg1->val0) + return FALSE; + } + arg0[arg2].val0 = arg1->val0; + arg0[arg2].val1 = 1; + arg0[arg2].val2 = arg1->val2; + return TRUE; +} + +s8 sub_80C0730(struct UnknownSaveStruct2ABC *arg0, u8 arg1) +{ + if (arg0[arg1].val0 == 0) + return -1; + return arg1; +} + +void sub_80C0750(void) +{ + u8 i; + + for (i = 0; i < 16; i++) + { + if (gSaveBlock1.unknown_2ABC[i].val0 > 3) + sub_80BEC10(i); + } + sub_80BEC40(); +} + +void sub_80C0788(void) +{ + u8 i; + + if (FlagGet(SYS_GAME_CLEAR) != 1) + { + for (i = 0; i < 16; i++) + gSaveBlock1.unknown_2ABC[i].val1 = 0; + } +} + +void DoTVShow(void) +{ + if (gSaveBlock1.tvShows[gSpecialVar_0x8004].common.var01 != 0) + { + switch (gSaveBlock1.tvShows[gSpecialVar_0x8004].common.var00) + { + case TVSHOW_FAN_CLUB_LETTER: + DoTVShowPokemonFanClubLetter(); + break; + case TVSHOW_RECENT_HAPPENINGS: + DoTVShowRecentHappenings(); + break; + case TVSHOW_PKMN_FAN_CLUB_OPINIONS: + DoTVShowPokemonFanClubOpinions(); + break; + case TVSHOW_UNKN_SHOWTYPE_04: + nullsub_22(); + break; + case TVSHOW_MASS_OUTBREAK: + DoTVShowPokemonNewsMassOutbreak(); + break; + case TVSHOW_BRAVO_TRAINER_POKEMON_PROFILE: + DoTVShowBravoTrainerPokemonProfile(); + break; + case TVSHOW_BRAVO_TRAINER_BATTLE_TOWER_PROFILE: + DoTVShowBravoTrainerBattleTowerProfile(); + break; + case TVSHOW_POKEMON_TODAY_CAUGHT: + DoTVShowPokemonTodaySuccessfulCapture(); + break; + case TVSHOW_SMART_SHOPPER: + DoTVShowTodaysSmartShopper(); + break; + case TVSHOW_NAME_RATER_SHOW: + DoTVShowTheNameRaterShow(); + break; + case TVSHOW_POKEMON_TODAY_FAILED: + DoTVShowPokemonTodayFailedCapture(); + break; + case TVSHOW_FISHING_ADVICE: + DoTVShowPokemonAngler(); + break; + case TVSHOW_WORLD_OF_MASTERS: + DoTVShowTheWorldOfMasters(); + break; + } + } +} + +void TVShowConvertInternationalString(u8 *dest, u8 *src, u8 language) +{ + StringCopy(dest, src); + if (language < LANGUAGE_ENGLISH) + ConvertInternationalString(dest, LANGUAGE_JAPANESE); +} + +void DoTVShowBravoTrainerPokemonProfile(void) +{ + struct TVShowBravoTrainerPokemonProfiles *bravoTrainer = &gSaveBlock1.tvShows[gSpecialVar_0x8004].bravoTrainer; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch(state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, bravoTrainer->playerName, bravoTrainer->language); + CopyContestCategoryToStringVar(1, bravoTrainer->contestCategory); + sub_80BEF10(2, bravoTrainer->contestRank); + if (!StringCompareWithoutExtCtrlCodes(gSpeciesNames[bravoTrainer->species], bravoTrainer->pokemonNickname)) + gUnknown_020387E8 = 8; + else + gUnknown_020387E8 = 1; + break; + case 1: + StringCopy(gStringVar1, gSpeciesNames[bravoTrainer->species]); + TVShowConvertInternationalString(gStringVar2, bravoTrainer->pokemonNickname, bravoTrainer->var1f); + CopyContestCategoryToStringVar(2, bravoTrainer->contestCategory); + gUnknown_020387E8 = 2; + break; + case 2: + TVShowConvertInternationalString(gStringVar1, bravoTrainer->playerName, bravoTrainer->language); + if (bravoTrainer->contestResult == 0) // placed first + gUnknown_020387E8 = 3; + else + gUnknown_020387E8 = 4; + break; + case 3: + TVShowConvertInternationalString(gStringVar1, bravoTrainer->playerName, bravoTrainer->language); + EasyChat_GetWordText(gStringVar2, bravoTrainer->var04[0]); + sub_80BF088(2, bravoTrainer->contestResult + 1); + gUnknown_020387E8 = 5; + break; + case 4: + TVShowConvertInternationalString(gStringVar1, bravoTrainer->playerName, bravoTrainer->language); + EasyChat_GetWordText(gStringVar2, bravoTrainer->var04[0]); + sub_80BF088(2, bravoTrainer->contestResult + 1); + gUnknown_020387E8 = 5; + break; + case 5: + TVShowConvertInternationalString(gStringVar1, bravoTrainer->playerName, bravoTrainer->language); + CopyContestCategoryToStringVar(1, bravoTrainer->contestCategory); + EasyChat_GetWordText(gStringVar3, bravoTrainer->var04[1]); + if (bravoTrainer->var14) + gUnknown_020387E8 = 6; + else + gUnknown_020387E8 = 7; + break; + case 6: + StringCopy(gStringVar1, gSpeciesNames[bravoTrainer->species]); + StringCopy(gStringVar2, gMoveNames[bravoTrainer->var14]); + EasyChat_GetWordText(gStringVar3, bravoTrainer->var04[1]); + gUnknown_020387E8 = 7; + break; + case 7: + TVShowConvertInternationalString(gStringVar1, bravoTrainer->playerName, bravoTrainer->language); + StringCopy(gStringVar2, gSpeciesNames[bravoTrainer->species]); + TVShowDone(); + break; + case 8: + StringCopy(gStringVar1, gSpeciesNames[bravoTrainer->species]); + gUnknown_020387E8 = 2; + break; + } + ShowFieldMessage(gTVBravoTrainerTextGroup[state]); +} + +void DoTVShowBravoTrainerBattleTowerProfile(void) +{ + struct TVShowBravoTrainerBattleTowerSpotlight *bravoTrainerTower = &gSaveBlock1.tvShows[gSpecialVar_0x8004].bravoTrainerTower; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch(state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, bravoTrainerTower->trainerName, bravoTrainerTower->language); + StringCopy(gStringVar2, gSpeciesNames[bravoTrainerTower->species]); + if (bravoTrainerTower->var16 >= 7) + gUnknown_020387E8 = 1; + else + gUnknown_020387E8 = 2; + break; + case 1: + sub_80BF088(0, bravoTrainerTower->btLevel); + sub_80BF088(1, bravoTrainerTower->var16); + if (bravoTrainerTower->var1c == 1) + gUnknown_020387E8 = 3; + else + gUnknown_020387E8 = 4; + break; + case 2: + TVShowConvertInternationalString(gStringVar1, bravoTrainerTower->pokemonName, bravoTrainerTower->language); + sub_80BF088(1, bravoTrainerTower->var16 + 1); + if (bravoTrainerTower->var1b == 0) + gUnknown_020387E8 = 5; + else + gUnknown_020387E8 = 6; + break; + case 3: + TVShowConvertInternationalString(gStringVar1, bravoTrainerTower->pokemonName, bravoTrainerTower->language); + StringCopy(gStringVar2, gSpeciesNames[bravoTrainerTower->defeatedSpecies]); + if (bravoTrainerTower->var1b == 0) + gUnknown_020387E8 = 5; + else + gUnknown_020387E8 = 6; + break; + case 4: + TVShowConvertInternationalString(gStringVar1, bravoTrainerTower->pokemonName, bravoTrainerTower->language); + StringCopy(gStringVar2, gSpeciesNames[bravoTrainerTower->defeatedSpecies]); + if (bravoTrainerTower->var1b == 0) + gUnknown_020387E8 = 5; + else + gUnknown_020387E8 = 6; + break; + case 5: + TVShowConvertInternationalString(gStringVar1, bravoTrainerTower->pokemonName, bravoTrainerTower->language); + gUnknown_020387E8 = 11; + break; + case 6: + TVShowConvertInternationalString(gStringVar1, bravoTrainerTower->pokemonName, bravoTrainerTower->language); + gUnknown_020387E8 = 11; + break; + case 7: + gUnknown_020387E8 = 11; + break; + case 8: + case 9: + case 10: + TVShowConvertInternationalString(gStringVar1, bravoTrainerTower->trainerName, bravoTrainerTower->language); + gUnknown_020387E8 = 11; + break; + case 11: + EasyChat_GetWordText(gStringVar1, bravoTrainerTower->var18[0]); + if (bravoTrainerTower->var1b == 0) + gUnknown_020387E8 = 12; + else + gUnknown_020387E8 = 13; + break; + case 12: + case 13: + EasyChat_GetWordText(gStringVar1, bravoTrainerTower->var18[0]); + TVShowConvertInternationalString(gStringVar2, bravoTrainerTower->trainerName, bravoTrainerTower->language); + TVShowConvertInternationalString(gStringVar3, bravoTrainerTower->pokemonName, bravoTrainerTower->language); + gUnknown_020387E8 = 14; + break; + case 14: + TVShowConvertInternationalString(gStringVar1, bravoTrainerTower->trainerName, bravoTrainerTower->language); + StringCopy(gStringVar2, gSpeciesNames[bravoTrainerTower->species]); + TVShowDone(); + break; + } + ShowFieldMessage(gTVBravoTrainerBattleTowerTextGroup[state]); +} + +void DoTVShowTodaysSmartShopper(void) +{ + struct TVShowSmartShopper *smartShopper = &gSaveBlock1.tvShows[gSpecialVar_0x8004].smartshopperShow; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch(state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, smartShopper->playerName, smartShopper->language); + GetMapSectionName(gStringVar2, smartShopper->shopLocation, 0); + if (smartShopper->itemAmounts[0] >= 0xff) + gUnknown_020387E8 = 11; + else + gUnknown_020387E8 = 1; + break; + case 1: + TVShowConvertInternationalString(gStringVar1, smartShopper->playerName, smartShopper->language); + StringCopy(gStringVar2, ItemId_GetItem(smartShopper->itemIds[0])->name); + sub_80BF088(2, smartShopper->itemAmounts[0]); + gUnknown_020387E8 += (Random() % 4) + 1; + break; + case 2: + case 4: + case 5: + if (smartShopper->itemIds[1] != 0) + gUnknown_020387E8 = 6; + else + gUnknown_020387E8 = 10; + break; + case 3: + sub_80BF088(2, smartShopper->itemAmounts[0] + 1); + if (smartShopper->itemIds[1] != 0) + gUnknown_020387E8 = 6; + else + gUnknown_020387E8 = 10; + break; + case 6: + StringCopy(gStringVar2, ItemId_GetItem(smartShopper->itemIds[1])->name); + sub_80BF088(2, smartShopper->itemAmounts[1]); + if (smartShopper->itemIds[2] != 0) + gUnknown_020387E8 = 7; + else if (smartShopper->priceReduced == 1) + gUnknown_020387E8 = 8; + else + gUnknown_020387E8 = 9; + break; + case 7: + StringCopy(gStringVar2, ItemId_GetItem(smartShopper->itemIds[2])->name); + sub_80BF088(2, smartShopper->itemAmounts[2]); + if (smartShopper->priceReduced == 1) + gUnknown_020387E8 = 8; + else + gUnknown_020387E8 = 9; + break; + case 8: + if (smartShopper->itemAmounts[0] < 0xff) + gUnknown_020387E8 = 9; + else + gUnknown_020387E8 = 12; + break; + case 9: + sub_80BF154(1, smartShopper); + TVShowDone(); + break; + case 10: + if (smartShopper->priceReduced == 1) + gUnknown_020387E8 = 8; + else + gUnknown_020387E8 = 9; + break; + case 11: + TVShowConvertInternationalString(gStringVar1, smartShopper->playerName, smartShopper->language); + StringCopy(gStringVar2, ItemId_GetItem(smartShopper->itemIds[0])->name); + if (smartShopper->priceReduced == 1) + gUnknown_020387E8 = 8; + else + gUnknown_020387E8 = 12; + break; + case 12: + TVShowConvertInternationalString(gStringVar1, smartShopper->playerName, smartShopper->language); + TVShowDone(); + break; + } + ShowFieldMessage(gTVSmartShopperTextGroup[state]); +} + +void DoTVShowTheNameRaterShow(void) +{ + struct TVShowNameRaterShow *nameRaterShow = &gSaveBlock1.tvShows[gSpecialVar_0x8004].nameRaterShow; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch (state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, nameRaterShow->trainerName, nameRaterShow->language); + StringCopy(gStringVar2, gSpeciesNames[nameRaterShow->species]); + TVShowConvertInternationalString(gStringVar3, nameRaterShow->pokemonName, nameRaterShow->pokemonNameLanguage); + gUnknown_020387E8 = sub_80BF7E8(nameRaterShow) + 1; + break; + case 1: + case 3: + case 4: + case 5: + case 6: + case 7: + case 8: + if (nameRaterShow->random == 0) + gUnknown_020387E8 = 9; + else if (nameRaterShow->random == 1) + gUnknown_020387E8 = 10; + else if (nameRaterShow->random == 2) + gUnknown_020387E8 = 11; + break; + case 2: + TVShowConvertInternationalString(gStringVar1, nameRaterShow->trainerName, nameRaterShow->language); + if (nameRaterShow->random == 0) + gUnknown_020387E8 = 9; + else if (nameRaterShow->random == 1) + gUnknown_020387E8 = 10; + else if (nameRaterShow->random == 2) + gUnknown_020387E8 = 11; + break; + case 9: + case 10: + case 11: + sub_80BF820(0, 1, 0, 1, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar3, gStringVar1, nameRaterShow->pokemonNameLanguage); + sub_80BF820(0, 0, 0, 1, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar2, gStringVar1, nameRaterShow->pokemonNameLanguage); + TVShowConvertInternationalString(gStringVar1, nameRaterShow->pokemonName, nameRaterShow->pokemonNameLanguage); + gUnknown_020387E8 = 12; + break; + case 13: + sub_80BF820(0, 0, 3, 1, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar3, gStringVar1, nameRaterShow->pokemonNameLanguage); + sub_80BF820(0, 0, 2, 0, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar2, gStringVar1, nameRaterShow->language); + TVShowConvertInternationalString(gStringVar1, nameRaterShow->trainerName, nameRaterShow->language); + gUnknown_020387E8 = 14; + break; + case 14: + sub_80BF820(0, 0, 3, 0, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar3, gStringVar1, nameRaterShow->language); + sub_80BF820(0, 0, 2, 1, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar2, gStringVar1, nameRaterShow->pokemonNameLanguage); + TVShowConvertInternationalString(gStringVar1, nameRaterShow->trainerName, nameRaterShow->language); + gUnknown_020387E8 = 18; + break; + case 15: + sub_80BF820(1, 0, 2, 1, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar1, gStringVar2, nameRaterShow->pokemonNameLanguage); + StringCopy(gStringVar2, gSpeciesNames[nameRaterShow->species]); + sub_80BF820(2, 0, 3, 2, nameRaterShow->species, nameRaterShow); + gUnknown_020387E8 = 16; + break; + case 16: + sub_80BF820(0, 0, 3, 1, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar3, gStringVar1, nameRaterShow->pokemonNameLanguage); + sub_80BF820(0, 0, 2, 2, nameRaterShow->species, nameRaterShow); + gUnknown_020387E8 = 17; + break; + case 17: + sub_80BF820(1, 0, 2, 1, 0, nameRaterShow); + TVShowConvertInternationalString(gStringVar1, gStringVar2, nameRaterShow->pokemonNameLanguage); + sub_80BF820(2, 0, 3, 2, nameRaterShow->var1C, nameRaterShow); + StringCopy(gStringVar2, gSpeciesNames[nameRaterShow->var1C]); + gUnknown_020387E8 = 18; + break; + case 12: + state = 18; + gUnknown_020387E8 = 18; + case 18: + TVShowConvertInternationalString(gStringVar1, nameRaterShow->pokemonName, nameRaterShow->pokemonNameLanguage); + TVShowConvertInternationalString(gStringVar2, nameRaterShow->trainerName, nameRaterShow->language); + TVShowDone(); + break; + } + ShowFieldMessage(gTVNameRaterTextGroup[state]); +} + +void DoTVShowPokemonTodaySuccessfulCapture(void) +{ + struct TVShowPokemonToday *pokemonToday = &gSaveBlock1.tvShows[gSpecialVar_0x8004].pokemonToday; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch (state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, pokemonToday->playerName, pokemonToday->language); + StringCopy(gStringVar2, gSpeciesNames[pokemonToday->species]); + TVShowConvertInternationalString(gStringVar3, pokemonToday->nickname, pokemonToday->language2); + if (pokemonToday->ball == ITEM_MASTER_BALL) + gUnknown_020387E8 = 5; + else + gUnknown_020387E8 = 1; + break; + case 1: + gUnknown_020387E8 = 2; + break; + case 2: + StringCopy(gStringVar2, ItemId_GetItem(pokemonToday->ball)->name); + sub_80BF088(2, pokemonToday->var12); + if (pokemonToday->var12 < 4) + gUnknown_020387E8 = 3; + else + gUnknown_020387E8 = 4; + break; + case 3: + TVShowConvertInternationalString(gStringVar1, pokemonToday->playerName, pokemonToday->language); + StringCopy(gStringVar2, gSpeciesNames[pokemonToday->species]); + TVShowConvertInternationalString(gStringVar3, pokemonToday->nickname, pokemonToday->language2); + gUnknown_020387E8 = 6; + break; + case 4: + gUnknown_020387E8 = 6; + break; + case 5: + TVShowConvertInternationalString(gStringVar1, pokemonToday->playerName, pokemonToday->language); + StringCopy(gStringVar2, gSpeciesNames[pokemonToday->species]); + gUnknown_020387E8 = 6; + break; + case 6: + TVShowConvertInternationalString(gStringVar1, pokemonToday->playerName, pokemonToday->language); + StringCopy(gStringVar2, gSpeciesNames[pokemonToday->species]); + TVShowConvertInternationalString(gStringVar3, pokemonToday->nickname, pokemonToday->language2); + gUnknown_020387E8 += (Random() % 4) + 1; + break; + case 7: + case 8: + StringCopy(gStringVar1, gSpeciesNames[pokemonToday->species]); + TVShowConvertInternationalString(gStringVar2, pokemonToday->nickname, pokemonToday->language2); + sub_80BF638(2, pokemonToday->species); + gUnknown_020387E8 = 11; + break; + case 9: + case 10: + StringCopy(gStringVar1, gSpeciesNames[pokemonToday->species]); + TVShowConvertInternationalString(gStringVar2, pokemonToday->nickname, pokemonToday->language2); + gUnknown_020387E8 = 11; + break; + case 11: + TVShowDone(); + break; + } + ShowFieldMessage(gTVPokemonTodayTextGroup[state]); +} + +void DoTVShowPokemonTodayFailedCapture(void) +{ + struct TVShowPokemonTodayFailed *pokemonTodayFailed = &gSaveBlock1.tvShows[gSpecialVar_0x8004].pokemonTodayFailed; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch (state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, pokemonTodayFailed->playerName, pokemonTodayFailed->language); + StringCopy(gStringVar2, gSpeciesNames[pokemonTodayFailed->species]); + gUnknown_020387E8 = 1; + break; + case 1: + TVShowConvertInternationalString(gStringVar1, pokemonTodayFailed->playerName, pokemonTodayFailed->language); + GetMapSectionName(gStringVar2, pokemonTodayFailed->var12, 0); + StringCopy(gStringVar3, gSpeciesNames[pokemonTodayFailed->species2]); + if (pokemonTodayFailed->var11 == 1) + gUnknown_020387E8 = 3; + else + gUnknown_020387E8 = 2; + break; + case 2: + case 3: + TVShowConvertInternationalString(gStringVar1, pokemonTodayFailed->playerName, pokemonTodayFailed->language); + sub_80BF088(1, pokemonTodayFailed->var10); + if ((Random() % 3) == 0) + gUnknown_020387E8 = 5; + else + gUnknown_020387E8 = 4; + break; + case 4: + case 5: + TVShowConvertInternationalString(gStringVar1, pokemonTodayFailed->playerName, pokemonTodayFailed->language); + gUnknown_020387E8 = 6; + break; + case 6: + TVShowDone(); + break; + } + ShowFieldMessage(gTVPokemonTodayFailedCaptureTextGroup[state]); +} + +void DoTVShowPokemonFanClubLetter(void) +{ + struct TVShowFanClubLetter *fanclubLetter = &gSaveBlock1.tvShows[gSpecialVar_0x8004].fanclubLetter; + u8 state; + u16 rval; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch (state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, fanclubLetter->playerName, fanclubLetter->language); + StringCopy(gStringVar2, gSpeciesNames[fanclubLetter->species]); + gUnknown_020387E8 = 50; + break; + case 1: + rval = (Random() % 4) + 1; + if (rval == 1) + gUnknown_020387E8 = 2; + else + gUnknown_020387E8 = rval + 2; + break; + case 2: + gUnknown_020387E8 = 51; + break; + case 3: + gUnknown_020387E8 += (Random() % 3) + 1; + break; + case 4: + case 5: + case 6: + sub_80BF79C((TVShow *)fanclubLetter); + gUnknown_020387E8 = 7; + break; + case 7: + rval = (Random() % 0x1f) + 0x46; + sub_80BF088(2, rval); + TVShowDone(); + break; + case 50: + ConvertEasyChatWordsToString(gStringVar4, fanclubLetter->pad04, 2, 2); + ShowFieldMessage(gStringVar4); + gUnknown_020387E8 = 1; + return; + case 51: + ConvertEasyChatWordsToString(gStringVar4, fanclubLetter->pad04, 2, 2); + ShowFieldMessage(gStringVar4); + gUnknown_020387E8 = 3; + return; + } + ShowFieldMessage(gTVFanClubTextGroup[state]); +} + +void DoTVShowRecentHappenings(void) +{ + struct TVShowRecentHappenings *recentHappenings = &gSaveBlock1.tvShows[gSpecialVar_0x8004].recentHappenings; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch (state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, recentHappenings->playerName, recentHappenings->language); + sub_80BF79C((TVShow *)recentHappenings); + gUnknown_020387E8 = 50; + break; + case 1: + gUnknown_020387E8 += 1 + (Random() % 3); + break; + case 2: + case 3: + case 4: + gUnknown_020387E8 = 5; + break; + case 5: + TVShowDone(); + break; + case 50: + ConvertEasyChatWordsToString(gStringVar4, recentHappenings->var04, 2, 2); + ShowFieldMessage(gStringVar4); + gUnknown_020387E8 = 1; + return; + } + ShowFieldMessage(gTVRecentHappeningsTextGroup[state]); +} + +void DoTVShowPokemonFanClubOpinions(void) +{ + struct TVShowFanclubOpinions *fanclubOpinions = &gSaveBlock1.tvShows[gSpecialVar_0x8004].fanclubOpinions; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch (state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, fanclubOpinions->playerName, fanclubOpinions->language); + StringCopy(gStringVar2, gSpeciesNames[fanclubOpinions->var02]); + TVShowConvertInternationalString(gStringVar3, fanclubOpinions->var10, fanclubOpinions->var0E); + gUnknown_020387E8 = fanclubOpinions->var04B + 1; + break; + case 1: + case 2: + case 3: + TVShowConvertInternationalString(gStringVar1, fanclubOpinions->playerName, fanclubOpinions->language); + StringCopy(gStringVar2, gSpeciesNames[fanclubOpinions->var02]); + EasyChat_GetWordText(gStringVar3, fanclubOpinions->var1C[0]); + gUnknown_020387E8 = 4; + break; + case 4: + TVShowConvertInternationalString(gStringVar1, fanclubOpinions->playerName, fanclubOpinions->language); + EasyChat_GetWordText(gStringVar3, fanclubOpinions->var1C[1]); + TVShowDone(); + break; + } + ShowFieldMessage(gTVFanClubOpinionsTextGroup[state]); +} + +void nullsub_22(void) +{ +} + +void DoTVShowPokemonNewsMassOutbreak(void) +{ + struct TVShowMassOutbreak *massOutbreak = &gSaveBlock1.tvShows[gSpecialVar_0x8004].massOutbreak; + + GetMapSectionName(gStringVar1, massOutbreak->locationMapNum, 0); + StringCopy(gStringVar2, gSpeciesNames[massOutbreak->species]); + TVShowDone(); + StartMassOutbreak(); + ShowFieldMessage(gTVPokemonOutbreakTextGroup[gUnknown_020387E8]); +} + +void DoTVShowInSearchOfTrainers(void) +{ + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch (state) + { + case 0: + GetMapSectionName(gStringVar1, gSaveBlock1.gabbyAndTyData.mapnum, 0); + if (gSaveBlock1.gabbyAndTyData.battleNum > 1) + gUnknown_020387E8 = 1; + else + gUnknown_020387E8 = 2; + break; + case 1: + gUnknown_020387E8 = 2; + break; + case 2: + if (gSaveBlock1.gabbyAndTyData.valA_0 == 0) + gUnknown_020387E8 = 4; + else if (gSaveBlock1.gabbyAndTyData.valA_3 != 0) + gUnknown_020387E8 = 5; + else if (gSaveBlock1.gabbyAndTyData.valA_2 != 0) + gUnknown_020387E8 = 6; + else if (gSaveBlock1.gabbyAndTyData.valA_1 != 0) + gUnknown_020387E8 = 7; + else + gUnknown_020387E8 = 3; + break; + case 3: + StringCopy(gStringVar1, gSpeciesNames[gSaveBlock1.gabbyAndTyData.mon1]); + StringCopy(gStringVar2, gMoveNames[gSaveBlock1.gabbyAndTyData.lastMove]); + StringCopy(gStringVar3, gSpeciesNames[gSaveBlock1.gabbyAndTyData.mon2]); + gUnknown_020387E8 = 8; + break; + case 4: + case 5: + case 6: + case 7: + gUnknown_020387E8 = 8; + break; + case 8: + EasyChat_GetWordText(gStringVar1, gSaveBlock1.gabbyAndTyData.quote); + StringCopy(gStringVar2, gSpeciesNames[gSaveBlock1.gabbyAndTyData.mon1]); + StringCopy(gStringVar3, gSpeciesNames[gSaveBlock1.gabbyAndTyData.mon2]); + gScriptResult = 1; + gUnknown_020387E8 = 0;; + TakeTVShowInSearchOfTrainersOffTheAir(); + break; + } + ShowFieldMessage(gTVGabbyAndTyTextGroup[state]); +} + +void DoTVShowPokemonAngler(void) +{ + struct TVShowPokemonAngler *pokemonAngler = &gSaveBlock1.tvShows[gSpecialVar_0x8004].pokemonAngler; + u8 state; + + gScriptResult = 0; + if (pokemonAngler->var02 < pokemonAngler->var03) + gUnknown_020387E8 = 0; + else + gUnknown_020387E8 = 1; + state = gUnknown_020387E8; + switch (state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, pokemonAngler->playerName, pokemonAngler->language); + StringCopy(gStringVar2, gSpeciesNames[pokemonAngler->var04]); + sub_80BF088(2, pokemonAngler->var03); + TVShowDone(); + break; + case 1: + TVShowConvertInternationalString(gStringVar1, pokemonAngler->playerName, pokemonAngler->language); + StringCopy(gStringVar2, gSpeciesNames[pokemonAngler->var04]); + sub_80BF088(2, pokemonAngler->var02); + TVShowDone(); + break; + } + ShowFieldMessage(gTVFishingGuruAdviceTextGroup[state]); +} + +void DoTVShowTheWorldOfMasters(void) +{ + struct TVShowWorldOfMasters *worldOfMasters = &gSaveBlock1.tvShows[gSpecialVar_0x8004].worldOfMasters; + u8 state; + + gScriptResult = 0; + state = gUnknown_020387E8; + switch (state) + { + case 0: + TVShowConvertInternationalString(gStringVar1, worldOfMasters->playerName, + worldOfMasters->language); + sub_80BF088(1, worldOfMasters->var06); + sub_80BF088(2, worldOfMasters->var02); + gUnknown_020387E8 = 1; + break; + case 1: + StringCopy(gStringVar1, gSpeciesNames[worldOfMasters->var08]); + gUnknown_020387E8 = 2; + break; + case 2: + TVShowConvertInternationalString(gStringVar1, worldOfMasters->playerName, + worldOfMasters->language); + GetMapSectionName(gStringVar2, worldOfMasters->var0a, 0); + StringCopy(gStringVar3, gSpeciesNames[worldOfMasters->var04]); + TVShowDone(); + break; + } + ShowFieldMessage(gTVWorldOfMastersTextGroup[state]); +} + +void TVShowDone(void) +{ + gScriptResult = 1; + gUnknown_020387E8 = 0; + gSaveBlock1.tvShows[gSpecialVar_0x8004].common.var01 = 0; +} + +void sub_80C2014(void) +{ + gUnknown_020387E8 = 0; +} diff --git a/src/field/use_pokeblock.c b/src/field/use_pokeblock.c new file mode 100644 index 000000000..e946a9cfc --- /dev/null +++ b/src/field/use_pokeblock.c @@ -0,0 +1,905 @@ +// + +// Modified by Dizzy Egg on 8/15/17. +// + +#include "global.h" +#include "main.h" +#include "overworld.h" +#include "string_util.h" +#include "strings.h" +#include "sprite.h" +#include "pokemon.h" +#include "pokenav.h" +#include "palette.h" +#include "text.h" +#include "menu.h" +#include "sound.h" +#include "songs.h" +#include "pokeblock.h" + +#define GFX_TAG_CONDITIONUPDOWN 0 + +#ifdef GERMAN +extern const u16 ConditionUpDownPalette[16]; +extern const u32 ConditionUpDownTiles[0x80]; +#else +const u16 ConditionUpDownPalette[] = INCBIN_U16("graphics/misc/condition_up_down.gbapal"); +const u32 ConditionUpDownTiles[] = INCBIN_U32("graphics/misc/condition_up_down.4bpp"); +#endif + +static const u32 sContestStatsMonData[] = { + MON_DATA_COOL, + MON_DATA_TOUGH, + MON_DATA_SMART, + MON_DATA_CUTE, + MON_DATA_BEAUTY +}; + +static const u8 gUnknown_0840612C[] = { + 0, 4, 3, 2, 1 +}; + +static const u8 *const sContextStatNames[] = { + OtherText_Coolness, + OtherText_Toughness, + OtherText_Smartness, + OtherText_Cuteness, + OtherText_Beauty +}; + +static const struct SpriteSheet gSpriteSheet_ConditionUpDown = { + (u8 *)ConditionUpDownTiles, + sizeof ConditionUpDownTiles, + GFX_TAG_CONDITIONUPDOWN +}; + +static const struct SpritePalette gSpritePalette_ConditionUpDown = { + ConditionUpDownPalette, + GFX_TAG_CONDITIONUPDOWN +}; + +static const s16 gUnknown_08406158[][2] = { + {0x9c, 0x1e}, + {0x75, 0x35}, + {0x75, 0x70}, + {0xc5, 0x70}, + {0xc5, 0x35} +}; + +static const struct OamData gOamData_840616C = { + .shape = 1, + .size = 2, + .priority = 1 +}; + +static const union AnimCmd gSpriteAnim_8406174[] = { + ANIMCMD_FRAME(0, 5), + ANIMCMD_END +}; + +static const union AnimCmd gSpriteAnim_840617C[] = { + ANIMCMD_FRAME(8, 5), + ANIMCMD_END +}; + +static const union AnimCmd *const gSpriteAnimTable_8406184[] = { + gSpriteAnim_8406174, + gSpriteAnim_840617C +}; + +static const struct SpriteTemplate gSpriteTemplate_840618C = { + GFX_TAG_CONDITIONUPDOWN, + GFX_TAG_CONDITIONUPDOWN, + &gOamData_840616C, + gSpriteAnimTable_8406184, + NULL, + gDummySpriteAffineAnimTable, + SpriteCallbackDummy +}; + +static EWRAM_DATA struct UnkPokenavStruct_Sub1 *gUnknown_02039304 = NULL; +static EWRAM_DATA MainCallback gUnknown_02039308 = NULL; +static EWRAM_DATA struct Pokeblock *gUnknown_0203930C = NULL; +EWRAM_DATA u8 gPokeblockMonID = 0; +EWRAM_DATA s16 gPokeblockGain = 0; + +extern u16 gKeyRepeatStartDelay; +extern u16 gScriptItemId; // FIXME: remove after merge of #349 Pokeblock + +static void launch_c3_walk_stairs_and_run_once(void (*const)(void)); +static void sub_81361E4(void); +static void sub_813622C(void); +static void sub_8136244(void); +static void sub_8136264(void); +static void sub_8136294(void); +static void sub_81365A0(void); +static void sub_81365C8(void); +static void sub_8136638(void); +static void sub_81368A4(void); +void sub_8089668(void); +static void sub_8136B44(void); +static u8 sub_81370E4(u8); +static void sub_8136BB8(void); +static s8 sub_8136C40(void); +static bool8 sub_8137058(void); +static void sub_8136D60(void); +static void sub_8136808(void); +static void sub_8136D8C(void); +static u8 sub_81370A4(u8); +static void sub_81369CC(void); +static void sub_8136EF0(void); +static void sub_8137138(void); +static void sub_8136C6C(void); +static bool8 sub_8136D00(void); +static void Pokeblock_BufferEnhancedStatText(u8 *, u8, s16); +static void Pokeblock_MenuWindowTextPrint(const u8 *); +static void sub_8136F74(struct Pokeblock *, struct Pokemon *); +static void sub_81371DC(struct Sprite *); + +void sub_8136130(struct Pokeblock *pokeblock, MainCallback callback) +{ + gUnknown_02039304 = &gUnknown_083DFEC4->unkD164; + gUnknown_02039304->pokeblock = pokeblock; + gUnknown_02039304->callback = callback; + gUnknown_083DFEC4->unkD162[0] = 2; + launch_c3_walk_stairs_and_run_once(sub_8136294); + SetMainCallback2(sub_8136244); +} + +static void sub_8136174(void) +{ + gUnknown_02039304->pokeblock = gUnknown_0203930C; + gUnknown_02039304->callback = gUnknown_02039308; + gPokeblockMonID = sub_81370E4(gPokeblockMonID); + gUnknown_02039304->unk56 = gPokeblockMonID < 4 ? 0 : 1; + gUnknown_083DFEC4->unkD162[0] = 2; + launch_c3_walk_stairs_and_run_once(sub_8136294); + SetMainCallback2(sub_81361E4); +} + +static void sub_81361E4(void) +{ + gUnknown_02039304->unk0(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); + if (gUnknown_02039304->unk0 == sub_81365C8) + { + REG_DISPCNT = 0; + gUnknown_02039304->unk50 = 0; + SetMainCallback2(sub_813622C); + } +} + +static void sub_813622C(void) +{ + sub_81368A4(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void sub_8136244(void) +{ + gUnknown_02039304->unk0(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void sub_8136264(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); + sub_80F5CDC(6); + sub_8089668(); +} + +static void launch_c3_walk_stairs_and_run_once(void (*const func)(void)) +{ + gUnknown_02039304->unk0 = func; + gUnknown_02039304->unk50 = 0; +} + +static void sub_8136294(void) +{ + bool32 c1LinkRelatedActive; + switch (gUnknown_02039304->unk50) + { + case 0: + c1LinkRelatedActive = is_c1_link_related_active(); + gUnknown_083DFEC4->unk6DAC = c1LinkRelatedActive; + if ((bool8)c1LinkRelatedActive == FALSE) + { + gUnknown_02039304->unk55 = 0; + launch_c3_walk_stairs_and_run_once(sub_81365A0); + gUnknown_02039304->unk50++; + } + break; + case 1: + ResetSpriteData(); + FreeAllSpritePalettes(); + gUnknown_02039304->unk50++; + break; + case 2: + SetVBlankCallback(NULL); + gUnknown_02039304->unk50++; + break; + case 3: + SetUpWindowConfig(&gWindowConfig_81E7080); + gUnknown_02039304->unk50++; + break; + case 4: + MultistepInitMenuWindowBegin(&gWindowConfig_81E7080); + gUnknown_02039304->unk50++; + break; + case 5: + if (MultistepInitMenuWindowContinue()) + { + gUnknown_02039304->unk50++; + } + break; + case 6: + gUnknown_083DFEC4->unk76AA = 0; + gUnknown_083DFEC4->unk87E0 = NULL; + gUnknown_083DFEC4->unk030C = 0x20; + gUnknown_02039304->unk50++; + break; + case 7: + sub_80F2688(); + gUnknown_02039304->unk50++; + // fallthrough + case 8: + if (!sub_80F26BC()) + { + gUnknown_02039304->unk50++; + } + break; + case 9: + sub_80F2C80(1); + gUnknown_02039304->unk50++; + // fallthrough + case 10: + if (!sub_80F2CBC(1)) + { + gUnknown_02039304->unk50++; + } + break; + case 11: + gKeyRepeatStartDelay = 20; + gUnknown_083DFEC4->unk8828 = CalculatePlayerPartyCount(); + gUnknown_083DFEC4->unk9344 = 0; + gUnknown_083DFEC4->unk8768 = NULL; + sub_80F4BD0(); + gUnknown_083DFEC4->unkD160 = 0; + gUnknown_02039304->unk50++; + break; + case 12: + if (!sub_80F1778()) + { + REG_BG2VOFS = 6; + REG_BG3VOFS = 6; + gUnknown_02039304->unk50++; + } + break; + case 13: + sub_80F2E18(0); + gUnknown_083DFEC4->unk8768->unk26 = 0xffd8; + gUnknown_02039304->unk50++; + break; + case 14: + if (!sub_80F170C()) + { + gUnknown_02039304->unk50++; + } + break; + case 15: + sub_80F33A8(); + gUnknown_02039304->unk50++; + break; + case 16: + DmaClear32(3, BG_SCREEN_ADDR(31), 0x800); + REG_BG1VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1CNT = BGCNT_SCREENBASE(31); + gUnknown_02039304->unk50++; + break; + case 17: + sub_80F567C(&gUnknown_083DFEC4->unk8ff0, gUnknown_083DFEC4->unk9004); + sub_80F5B38(); + gUnknown_02039304->unk50++; + break; + case 18: + if (!sub_80F5B50()) + { + gUnknown_02039304->unk50++; + } + break; + case 19: + sub_80F556C(gUnknown_083DFEC4->unk9004); + gUnknown_02039304->unk50++; + break; + case 20: + sub_80F1934(); + gUnknown_02039304->unk50++; + break; + case 21: + REG_WIN0H = 0xf0; + REG_WIN1H = 0x9b; + REG_WIN0V = 0x3273; + REG_WIN1V = 0x3273; + REG_WININ = 0x3f3f; + REG_WINOUT = 0x1b; + REG_BG0VOFS = 0x28; + REG_DISPCNT = DISPCNT_OBJ_1D_MAP | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON; + // fallthrough + case 22: + gUnknown_02039304->unk55 = 1; + launch_c3_walk_stairs_and_run_once(sub_81365C8); + break; + } +} + +static void sub_81365A0(void) +{ + while (!gUnknown_02039304->unk55) + { + sub_8136294(); + } +} + +static void sub_81365C8(void) +{ + switch (gUnknown_02039304->unk50) + { + case 0: + BeginNormalPaletteFade(-1, 0, 16, 0, 0); + SetVBlankCallback(sub_8136264); + gUnknown_02039304->unk50++; + break; + case 1: + if (!gPaletteFade.active) + { + sub_80F3C94(); + sub_80F3D00(); + launch_c3_walk_stairs_and_run_once(sub_8136638); + } + break; + } +} + +static void sub_8136638(void) +{ + switch (gUnknown_02039304->unk50) + { + case 0: + if (gMain.heldKeys & DPAD_UP) + { + PlaySE(SE_SELECT); + sub_80F5060(TRUE); + move_anim_execute(); + gUnknown_02039304->unk50 = 1; + } + else if (gMain.heldKeys & DPAD_DOWN) + { + PlaySE(SE_SELECT); + sub_80F5060(FALSE); + move_anim_execute(); + gUnknown_02039304->unk50 = 1; + } + else if (gMain.newKeys & B_BUTTON) + { + PlaySE(SE_SELECT); + gUnknown_02039304->unk50 = 3; + } + else if (gMain.newKeys & A_BUTTON) + { + PlaySE(SE_SELECT); + if (gUnknown_083DFEC4->unk87DC == gUnknown_083DFEC4->unk87DA - 1) + { + gUnknown_02039304->unk50 = 3; + } + else + { + gUnknown_02039304->unk50 = 5; + } + } + break; + case 1: + if (!gpu_sync_bg_show()) + { + gUnknown_02039304->unk50++; + } + break; + case 2: + if (!sub_8055870()) + { + sub_80F1934(); + sub_80F3D00(); + gUnknown_02039304->unk50 = 0; + } + break; + case 3: + launch_c3_walk_stairs_and_run_once(sub_8136B44); + break; + case 4: + break; + case 5: + sub_8136BB8(); + gUnknown_02039304->unk50++; + break; + case 6: + switch (sub_8136C40()) + { + case 1: + case -1: + gUnknown_02039304->unk50 = 0; + break; + case 0: + if (sub_8137058()) + { + sub_8136D60(); + gUnknown_02039304->unk50 = 7; + } + else + { + launch_c3_walk_stairs_and_run_once(sub_8136808); + } + break; + } + break; + case 7: + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + { + sub_8136D8C(); + gUnknown_02039304->unk50 = 0; + } + break; + } +} + +static void sub_8136808(void) +{ + switch (gUnknown_02039304->unk50) + { + case 0: + gPokeblockMonID = sub_81370A4(gUnknown_083DFEC4->unk87DC); + gUnknown_02039308 = gUnknown_02039304->callback; + gUnknown_0203930C = gUnknown_02039304->pokeblock; + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + gUnknown_02039304->unk50++; + break; + case 1: + if (!gPaletteFade.active) + { + gMain.savedCallback = sub_8136174; + SetMainCallback2(CB2_PreparePokeblockFeedScene); + } + break; + } +} + +static void sub_81368A4(void) +{ + switch (gUnknown_02039304->unk50) + { + case 0: + if (gUnknown_083DFEC4->unk87DC != gPokeblockMonID) + { + sub_80F5060(gUnknown_02039304->unk56); + gUnknown_02039304->unk50++; + } + else + { + gUnknown_02039304->unk50 = 3; + } + break; + case 1: + if (!gpu_sync_bg_show()) + { + gUnknown_02039304->unk50++; + } + break; + case 2: + if (!sub_8055870()) + { + sub_80F1934(); + gUnknown_02039304->unk50 = 0; + } + break; + case 3: + BlendPalettes(-1, 16, 0); + gUnknown_02039304->unk50++; + break; + case 4: + REG_DISPCNT = DISPCNT_OBJ_1D_MAP | DISPCNT_BG_ALL_ON | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_WIN1_ON; + gUnknown_02039304->unk50++; + break; + case 5: + SetVBlankCallback(sub_8136264); + BeginNormalPaletteFade(-1, 0, 16, 0, 0); + gUnknown_02039304->unk50++; + break; + case 6: + if (!gPaletteFade.active) + { + sub_80F3C94(); + sub_80F3D00(); + launch_c3_walk_stairs_and_run_once(sub_81369CC); + SetMainCallback2(sub_8136244); + } + break; + } +} + +static void sub_81369CC(void) +{ + switch (gUnknown_02039304->unk50) + { + case 0: + gUnknown_02039304->pokemon = &gPlayerParty[0]; + gUnknown_02039304->pokemon = &gPlayerParty[gUnknown_083DFEC4->unk893c[gUnknown_083DFEC4->unk87DC].partyIdx]; + move_anim_execute(); + gUnknown_02039304->unk50++; + break; + case 1: + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + gUnknown_02039304->unk50++; + break; + case 2: + sub_8136EF0(); + sub_80F567C(gUnknown_02039304->unk5c, gUnknown_083DFEC4->unk9040); + sub_80F5550(gUnknown_083DFEC4->unk9004[gUnknown_083DFEC4->unk8fe9], gUnknown_083DFEC4->unk9040); + sub_8137138(); + gUnknown_02039304->unk50++; + break; + case 3: + if (!sub_80F555C()) + { + sub_80F7224(sub_81370A4(gUnknown_083DFEC4->unk87DC)); + sub_80F3D00(); + gUnknown_02039304->unk52 = 0; + gUnknown_02039304->unk50++; + } + break; + case 4: + if ((++gUnknown_02039304->unk52) > 16) + { + sub_8136C6C(); + gUnknown_02039304->unk50++; + } + break; + case 5: + if (gMain.newKeys & (A_BUTTON | B_BUTTON) && !sub_8136D00()) + { + PokeblockClearIfExists((u8)gScriptItemId); + launch_c3_walk_stairs_and_run_once(sub_8136B44); + } + break; + } +} + +static void sub_8136B44(void) +{ + switch (gUnknown_02039304->unk50) + { + case 0: + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + gUnknown_02039304->unk50++; + break; + case 1: + if (!gPaletteFade.active) + { + gUnknown_02039304->unk50 = 2; + } + break; + case 2: + sub_80F5BDC(); + gUnknown_02039304->unk50++; + break; + case 3: + SetMainCallback2(gUnknown_02039304->callback); + break; + } +} + +static void sub_8136BB8(void) +{ + GetMonData(&gPlayerParty[sub_81370A4(gUnknown_083DFEC4->unk87DC)], MON_DATA_NICKNAME, gUnknown_02039304->stringBuffer); + StringGetEnd10(gUnknown_02039304->stringBuffer); + StringAppend(gUnknown_02039304->stringBuffer, gOtherText_GetsAPokeBlock); + BasicInitMenuWindow(&gWindowConfig_81E709C); + MenuDrawTextWindow(0, 16, 29, 19); + MenuPrint(gUnknown_02039304->stringBuffer, 1, 17); + DisplayYesNoMenu(23, 10, 1); + MoveMenuCursor(0); +} + +static s8 sub_8136C40(void) +{ + s8 retval = ProcessMenuInputNoWrap(); + if ((u8)(retval + 1) < 3) + { + MenuZeroFillScreen(); + BasicInitMenuWindow(&gWindowConfig_81E7080); + } + return retval; +} + +static void sub_8136C6C(void) +{ + BasicInitMenuWindow(&gWindowConfig_81E709C); + MenuDrawTextWindow(0, 16, 29, 19); + for (gUnknown_02039304->unk53 = 0; gUnknown_02039304->unk53 < 5 && gUnknown_02039304->unk61[gUnknown_02039304->unk53] == 0; gUnknown_02039304->unk53++); + if (gUnknown_02039304->unk53 < 5) + { + Pokeblock_BufferEnhancedStatText(gUnknown_02039304->stringBuffer, gUnknown_02039304->unk53, gUnknown_02039304->unk61[gUnknown_02039304->unk53]); + } + else + { + Pokeblock_BufferEnhancedStatText(gUnknown_02039304->stringBuffer, gUnknown_02039304->unk53, 0); + } + Pokeblock_MenuWindowTextPrint(gUnknown_02039304->stringBuffer); +} + +static bool8 sub_8136D00(void) +{ + while (1) + { + gUnknown_02039304->unk53++; + if (gUnknown_02039304->unk53 < 5) + { + if (gUnknown_02039304->unk61[gUnknown_02039304->unk53] != 0) + break; + } + else + { + gUnknown_02039304->unk53 = 5; + return FALSE; + } + } + Pokeblock_BufferEnhancedStatText(gUnknown_02039304->stringBuffer, gUnknown_02039304->unk53, gUnknown_02039304->unk61[gUnknown_02039304->unk53]); + Pokeblock_MenuWindowTextPrint(gUnknown_02039304->stringBuffer); + return TRUE; +} + +static void sub_8136D60(void) +{ + BasicInitMenuWindow(&gWindowConfig_81E709C); + MenuDrawTextWindow(0, 16, 29, 19); + MenuPrint(gOtherText_WontEat, 1, 17); +} + +static void sub_8136D8C(void) +{ + MenuZeroFillScreen(); + BasicInitMenuWindow(&gWindowConfig_81E7080); +} + +static void Pokeblock_MenuWindowTextPrint(const u8 *message) +{ + MenuDrawTextWindow(0, 16, 29, 19); + MenuPrint(message, 1, 17); +} + +#ifdef NONMATCHING +static void Pokeblock_BufferEnhancedStatText(u8 *dest, u8 statID, s16 a2) +{ + if (a2 != 0) + { + StringCopy(dest, sContextStatNames[statID]); + StringAppend(dest, gOtherText_WasEnhanced); + } + else + { + StringCopy(dest, gOtherText_NothingChanged); + } +} +#else +__attribute__((naked)) +static void Pokeblock_BufferEnhancedStatText(u8 *dest, u8 a1, s16 a2) +{ + asm_unified("\tpush {r4,lr}\n" + "\tadds r4, r0, 0\n" + "\tlsls r1, 24\n" + "\tlsrs r3, r1, 24\n" + "\tlsls r2, 16\n" + "\tlsrs r0, r2, 16\n" + "\tasrs r2, 16\n" + "\tcmp r2, 0\n" + "\tbeq _08136DFC\n" + "\tcmp r2, 0\n" + "\tble _08136DD8\n" + "\tmovs r0, 0\n" + "_08136DD8:\n" + "\tlsls r0, 16\n" + "\tldr r1, _08136DF4 @ =sContextStatNames\n" + "\tlsls r0, r3, 2\n" + "\tadds r0, r1\n" + "\tldr r1, [r0]\n" + "\tadds r0, r4, 0\n" + "\tbl StringCopy\n" + "\tldr r1, _08136DF8 @ =gOtherText_WasEnhanced\n" + "\tadds r0, r4, 0\n" + "\tbl StringAppend\n" + "\tb _08136E04\n" + "\t.align 2, 0\n" + "_08136DF4: .4byte sContextStatNames\n" + "_08136DF8: .4byte gOtherText_WasEnhanced\n" + "_08136DFC:\n" + "\tldr r1, _08136E0C @ =gOtherText_NothingChanged\n" + "\tadds r0, r4, 0\n" + "\tbl StringCopy\n" + "_08136E04:\n" + "\tpop {r4}\n" + "\tpop {r0}\n" + "\tbx r0\n" + "\t.align 2, 0\n" + "_08136E0C: .4byte gOtherText_NothingChanged"); +} +#endif + +static void Pokeblock_GetMonContestStats(struct Pokemon *pokemon, u8 *data) +{ + u16 i; + for (i=0; i<5; i++) + { + data[i] = GetMonData(pokemon, sContestStatsMonData[i]); + } +} + +static void sub_8136E40(struct Pokeblock *pokeblock, struct Pokemon *pokemon) +{ + u16 i; + s16 cstat; + u8 data; + if (GetMonData(pokemon, MON_DATA_SHEEN) != 255) + { + sub_8136F74(pokeblock, pokemon); + for (i=0; i<5; i++) + { + data = GetMonData(pokemon, sContestStatsMonData[i]); + cstat = data + gUnknown_02039304->unk66[i]; + if (cstat < 0) + cstat = 0; + if (cstat > 255) + cstat = 255; + data = cstat; + SetMonData(pokemon, sContestStatsMonData[i], &data); + } + cstat = (u8)GetMonData(pokemon, MON_DATA_SHEEN); + cstat = cstat + pokeblock->feel; + if (cstat > 255) + cstat = 255; + data = cstat; + SetMonData(pokemon, MON_DATA_SHEEN, &data); + } +} + +static void sub_8136EF0(void) +{ + u16 i; + struct Pokemon *pokemon = gPlayerParty; + pokemon += gUnknown_083DFEC4->unk893c[gUnknown_083DFEC4->unk87DC].partyIdx; + Pokeblock_GetMonContestStats(pokemon, gUnknown_02039304->unk57); + sub_8136E40(gUnknown_02039304->pokeblock, pokemon); + Pokeblock_GetMonContestStats(pokemon, gUnknown_02039304->unk5c); + for (i=0; i<5; i++) + { + gUnknown_02039304->unk61[i] = gUnknown_02039304->unk5c[i] - gUnknown_02039304->unk57[i]; + } +} + +static void sub_8136F74(struct Pokeblock *pokeblock, struct Pokemon *pokemon) +{ + s8 direction; + s8 i; + s16 amount; + s8 boost; + s8 taste; + gUnknown_02039304->unk66[0] = pokeblock->spicy; + gUnknown_02039304->unk66[1] = pokeblock->sour; + gUnknown_02039304->unk66[2] = pokeblock->bitter; + gUnknown_02039304->unk66[3] = pokeblock->sweet; + gUnknown_02039304->unk66[4] = pokeblock->dry; + if (gPokeblockGain > 0) + direction = 1; + else if (gPokeblockGain < 0) + direction = -1; + else + return; + for (i=0; i<5; i++) + { + amount = gUnknown_02039304->unk66[i]; + boost = amount / 10; + if (amount % 10 >= 5) // round to the nearest + boost++; + taste = sub_8040A54(pokemon, gUnknown_0840612C[i]); + if (taste == direction) + { + gUnknown_02039304->unk66[i] += boost * taste; + } + } +} + +static bool8 sub_8137058(void) +{ + struct Pokemon *pokemon = gPlayerParty; + pokemon += gUnknown_083DFEC4->unk893c[gUnknown_083DFEC4->unk87DC].partyIdx; + if (GetMonData(pokemon, MON_DATA_SHEEN) == 255) + return TRUE; + return FALSE; +} + +static u8 sub_81370A4(u8 a0) +{ + u8 i; + for (i=0; i<PARTY_SIZE; i++) + { + if (!GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + { + if (a0 == 0) + return i; + a0--; + } + } + return 0; +} + +static u8 sub_81370E4(u8 a0) +{ + u8 ct; + u8 i; + for (i=0, ct=0; i<a0; i++) + { + if (GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + { + ct++; + } + } + return a0 - ct; +} + +u8 sub_8137124(u8 a0) +{ + return sub_81370A4(a0); +} + +static void sub_8137138(void) +{ + u16 flavor; + u8 spriteidx; + LoadSpriteSheet(&gSpriteSheet_ConditionUpDown); + LoadSpritePalette(&gSpritePalette_ConditionUpDown); + gUnknown_02039304->unk54 = 0; + for (flavor=0; flavor<5; flavor++) + { + if (gUnknown_02039304->unk61[flavor] != 0) + { + spriteidx = CreateSprite(&gSpriteTemplate_840618C, gUnknown_08406158[flavor][0], gUnknown_08406158[flavor][1], 0); + if (spriteidx != MAX_SPRITES) + { + if (gUnknown_02039304->unk61[flavor] != 0) + { + gSprites[spriteidx].callback = sub_81371DC; + } + gUnknown_02039304->unk54++; + } + } + } +} + +static void sub_81371DC(struct Sprite *sprite) +{ + if (sprite->data0 <= 5) + sprite->pos2.y -= 2; + else if (sprite->data0 <= 11) + sprite->pos2.y += 2; + if ((++sprite->data0) > 60) + { + DestroySprite(sprite); + gUnknown_02039304->unk54--; + } +} diff --git a/src/field/wallclock.c b/src/field/wallclock.c new file mode 100644 index 000000000..8db13dc2d --- /dev/null +++ b/src/field/wallclock.c @@ -0,0 +1,1061 @@ +#include "global.h" +#include "wallclock.h" +#include "decompress.h" +#include "main.h" +#include "menu.h" +#include "palette.h" +#include "rtc.h" +#include "songs.h" +#include "sound.h" +#include "strings2.h" +#include "task.h" +#include "trig.h" +#include "unknown_task.h" + +extern u16 gSpecialVar_0x8004; +extern u8 gMiscClock_Gfx[]; +extern u8 gUnknown_08E95774[]; +extern u8 gUnknown_08E954B0[]; +extern u16 gMiscClockMale_Pal[]; +extern u16 gMiscClockFemale_Pal[]; + +//-------------------------------------------------- +// Graphics Data +//-------------------------------------------------- + +static const u8 ClockGfx_Misc[] = INCBIN_U8("graphics/misc/clock_misc.4bpp.lz"); +static const struct CompressedSpriteSheet gUnknown_083F7A90[] = +{ + {ClockGfx_Misc, 0x2000, 0x1000}, + {NULL}, +}; +static const struct SpritePalette gUnknown_083F7AA0[] = +{ + {gMiscClockMale_Pal, 0x1000}, + {gMiscClockFemale_Pal, 0x1001}, + {NULL}, +}; +static const struct OamData gOamData_83F7AB8 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 3, + .tileNum = 0, + .priority = 1, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gSpriteAnim_83F7AC0[] = +{ + ANIMCMD_FRAME(0, 30), + ANIMCMD_END, +}; +static const union AnimCmd gSpriteAnim_83F7AC8[] = +{ + ANIMCMD_FRAME(64, 30), + ANIMCMD_END, +}; +static const union AnimCmd *const gSpriteAnimTable_83F7AD0[] = +{ + gSpriteAnim_83F7AC0, +}; +static const union AnimCmd *const gSpriteAnimTable_83F7AD4[] = +{ + gSpriteAnim_83F7AC8, +}; +static void sub_810B05C(struct Sprite *sprite); +static const struct SpriteTemplate gSpriteTemplate_83F7AD8 = +{ + .tileTag = 0x1000, + .paletteTag = 0x1000, + .oam = &gOamData_83F7AB8, + .anims = gSpriteAnimTable_83F7AD0, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810B05C, +}; +static void sub_810B0F4(struct Sprite *sprite); +static const struct SpriteTemplate gSpriteTemplate_83F7AF0 = +{ + .tileTag = 0x1000, + .paletteTag = 0x1000, + .oam = &gOamData_83F7AB8, + .anims = gSpriteAnimTable_83F7AD4, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810B0F4, +}; +static const struct OamData gOamData_83F7B08 = +{ + .y = 160, + .affineMode = 0, + .objMode = 0, + .mosaic = 0, + .bpp = 0, + .shape = 0, + .x = 0, + .matrixNum = 0, + .size = 1, + .tileNum = 0, + .priority = 2, + .paletteNum = 0, + .affineParam = 0, +}; +static const union AnimCmd gSpriteAnim_83F7B10[] = +{ + ANIMCMD_FRAME(132, 30), + ANIMCMD_END, +}; +static const union AnimCmd gSpriteAnim_83F7B18[] = +{ + ANIMCMD_FRAME(128, 30), + ANIMCMD_END, +}; +static const union AnimCmd *const gSpriteAnimTable_83F7B20[] = +{ + gSpriteAnim_83F7B10, +}; +static const union AnimCmd *const gSpriteAnimTable_83F7B24[] = +{ + gSpriteAnim_83F7B18, +}; +static void sub_810B18C(struct Sprite *sprite); +static const struct SpriteTemplate gSpriteTemplate_83F7B28 = +{ + .tileTag = 0x1000, + .paletteTag = 0x1000, + .oam = &gOamData_83F7B08, + .anims = gSpriteAnimTable_83F7B20, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810B18C, +}; +static void sub_810B230(struct Sprite *sprite); +static const struct SpriteTemplate gSpriteTemplate_83F7B40 = +{ + .tileTag = 0x1000, + .paletteTag = 0x1000, + .oam = &gOamData_83F7B08, + .anims = gSpriteAnimTable_83F7B24, + .images = NULL, + .affineAnims = gDummySpriteAffineAnimTable, + .callback = sub_810B230, +}; + +static void WallClockVblankCallback(void); +static void LoadWallClockGraphics(void); +static void WallClockMainCallback(void); +static void WallClockInit(void); +static void Task_SetClock1(u8 taskId); +static void Task_SetClock2(u8 taskId); +static void Task_SetClock3(u8 taskId); +static void Task_SetClock4(u8 taskId); +static void Task_SetClock5(u8 taskId); +static void Task_SetClock6(u8 taskId); +static void Task_ViewClock1(u8 taskId); +static void Task_ViewClock2(u8 taskId); +static void Task_ViewClock3(u8 taskId); +static void Task_ViewClock4(u8 taskId); +static u8 CalcMinHandDelta(u16 speed); +static u16 CalcNewMinHandAngle(u16 angle, u8 direction, u8 speed); +static u8 AdvanceClock(u8 taskId, u8 direction); +static void UpdateClockPeriod(u8 taskId, u8 direction); +static void InitClockWithRtc(u8 taskId); + +enum +{ + PERIOD_AM, + PERIOD_PM, +}; + +enum +{ + MVMT_NONE, + MVMT_BACKWARD, + MVMT_FORWARD, +}; + +static void WallClockVblankCallback(void) +{ + LoadOam(); + ProcessSpriteCopyRequests(); + TransferPlttBuffer(); +} + +static void LoadWallClockGraphics(void) +{ + u8 *addr; + u32 size; + + SetVBlankCallback(0); + REG_DISPCNT = 0; + REG_BG3CNT = 0; + REG_BG2CNT = 0; + REG_BG1CNT = 0; + REG_BG0CNT = 0; + REG_BG3HOFS = 0; + REG_BG3VOFS = 0; + REG_BG2HOFS = 0; + REG_BG2VOFS = 0; + REG_BG1HOFS = 0; + REG_BG1VOFS = 0; + REG_BG0HOFS = 0; + REG_BG0VOFS = 0; + + addr = (void *)VRAM; + size = 0x18000; + while (1) + { + DmaFill16(3, 0, addr, 0x1000); + addr += 0x1000; + size -= 0x1000; + if (size <= 0x1000) + { + DmaFill16(3, 0, addr, size); + break; + } + } + DmaClear32(3, OAM, OAM_SIZE); + DmaClear16(3, PLTT, PLTT_SIZE); + + LZ77UnCompVram(gMiscClock_Gfx, (void *)VRAM); + if (gSpecialVar_0x8004 == MALE) + LoadPalette(gMiscClockMale_Pal, 0, 32); + else + LoadPalette(gMiscClockFemale_Pal, 0, 32); + remove_some_task(); + ResetTasks(); + ResetSpriteData(); + ResetPaletteFade(); + FreeAllSpritePalettes(); + LoadCompressedObjectPic(&gUnknown_083F7A90[0]); + LoadSpritePalettes(gUnknown_083F7AA0); + SetUpWindowConfig(&gWindowConfig_81E6C3C); + InitMenuWindow(&gWindowConfig_81E6CE4); +} + +static void WallClockInit(void) +{ + u16 ime; + + BeginNormalPaletteFade(-1, 0, 0x10, 0, 0); + ime = REG_IME; + REG_IME = 0; + REG_IE |= INTR_FLAG_VBLANK; + REG_IME = ime; + REG_DISPSTAT |= DISPSTAT_VBLANK_INTR; + SetVBlankCallback(WallClockVblankCallback); + SetMainCallback2(WallClockMainCallback); + REG_BLDCNT = 0; + REG_BLDALPHA = 0; + REG_BLDY = 0; + REG_BG3CNT = BGCNT_PRIORITY(1) | BGCNT_CHARBASE(0) | BGCNT_SCREENBASE(7) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_BG0CNT = BGCNT_PRIORITY(0) | BGCNT_CHARBASE(2) | BGCNT_SCREENBASE(31) | BGCNT_16COLOR | BGCNT_TXT256x256; + REG_DISPCNT = DISPCNT_MODE_0 | DISPCNT_OBJ_1D_MAP | DISPCNT_BG0_ON | + DISPCNT_BG3_ON | DISPCNT_OBJ_ON; +} + +#define tMinuteHandAngle data[0] +#define tHourHandAngle data[1] +#define tHours data[2] +#define tMinutes data[3] +#define tMvmtDir data[4] +#define tPeriod data[5] +#define tMvmtSpeed data[6] + +//Allow player to set the clock +void CB2_StartWallClock(void) +{ + u8 taskId; + u8 spriteId; + + LoadWallClockGraphics(); + LZ77UnCompVram(&gUnknown_08E954B0, (void *)(VRAM + 0x3800)); + + taskId = CreateTask(Task_SetClock1, 0); + gTasks[taskId].tHours = 10; + gTasks[taskId].tMinutes = 0; + gTasks[taskId].tMvmtDir = MVMT_NONE; + gTasks[taskId].tPeriod = PERIOD_AM; + gTasks[taskId].tMvmtSpeed = 0; + gTasks[taskId].tMinuteHandAngle = 0; + gTasks[taskId].tHourHandAngle = 300; + + spriteId = CreateSprite(&gSpriteTemplate_83F7AD8, DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 2, 1); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL; + gSprites[spriteId].oam.matrixNum = 0; + + spriteId = CreateSprite(&gSpriteTemplate_83F7AF0, DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 2, 0); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL; + gSprites[spriteId].oam.matrixNum = 1; + + spriteId = CreateSprite(&gSpriteTemplate_83F7B28, DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 2, 2); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].data1 = 45; + + spriteId = CreateSprite(&gSpriteTemplate_83F7B40, DISPLAY_WIDTH / 2, DISPLAY_HEIGHT / 2, 2); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].data1 = 90; + + WallClockInit(); +} + +//View, but don't set, the clock +void CB2_ViewWallClock(void) +{ + u8 taskId; + s16 angle1; + s16 angle2; + u8 spriteId; + + LoadWallClockGraphics(); + LZ77UnCompVram(gUnknown_08E95774, (void *)(VRAM + 0x3800)); + + taskId = CreateTask(Task_ViewClock1, 0); + InitClockWithRtc(taskId); + if (gTasks[taskId].tPeriod == PERIOD_AM) + { + angle1 = 45; + angle2 = 90; + } + else + { + angle1 = 90; + angle2 = 135; + } + + spriteId = CreateSprite(&gSpriteTemplate_83F7AD8, 120, 80, 1); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL; + gSprites[spriteId].oam.matrixNum = 0; + + spriteId = CreateSprite(&gSpriteTemplate_83F7AF0, 120, 80, 0); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].oam.affineMode = ST_OAM_AFFINE_NORMAL; + gSprites[spriteId].oam.matrixNum = 1; + + spriteId = CreateSprite(&gSpriteTemplate_83F7B28, 120, 80, 2); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].data1 = angle1; + + spriteId = CreateSprite(&gSpriteTemplate_83F7B40, 120, 80, 2); + gSprites[spriteId].data0 = taskId; + gSprites[spriteId].data1 = angle2; + + WallClockInit(); +} + +static void WallClockMainCallback(void) +{ + RunTasks(); + AnimateSprites(); + BuildOamBuffer(); + UpdatePaletteFade(); +} + +static void Task_SetClock1(u8 taskId) +{ + if (!gPaletteFade.active) + gTasks[taskId].func = Task_SetClock2; +} + +//Handle keypresses when setting clock +static void Task_SetClock2(u8 taskId) +{ + if (gTasks[taskId].tMinuteHandAngle % 6) + { + gTasks[taskId].tMinuteHandAngle = CalcNewMinHandAngle( + gTasks[taskId].tMinuteHandAngle, + gTasks[taskId].tMvmtDir, + gTasks[taskId].tMvmtSpeed); + } + else + { + gTasks[taskId].tMinuteHandAngle = gTasks[taskId].tMinutes * 6; + gTasks[taskId].tHourHandAngle = (gTasks[taskId].tHours % 12) * 30 + (gTasks[taskId].tMinutes / 10) * 5; + if (gMain.newKeys & A_BUTTON) + { + gTasks[taskId].func = Task_SetClock3; + return; + } + else + { + gTasks[taskId].tMvmtDir = gMain.newKeys & A_BUTTON; + if (gMain.heldKeys & DPAD_LEFT) + gTasks[taskId].tMvmtDir = MVMT_BACKWARD; + if (gMain.heldKeys & DPAD_RIGHT) + gTasks[taskId].tMvmtDir = MVMT_FORWARD; + if (gTasks[taskId].tMvmtDir) + { + if (gTasks[taskId].tMvmtSpeed < 0xFF) + gTasks[taskId].tMvmtSpeed++; + gTasks[taskId].tMinuteHandAngle = CalcNewMinHandAngle( + gTasks[taskId].tMinuteHandAngle, + gTasks[taskId].tMvmtDir, + gTasks[taskId].tMvmtSpeed); + AdvanceClock(taskId, gTasks[taskId].tMvmtDir); + } + else + { + gTasks[taskId].tMvmtSpeed = 0; + } + } + } +} + +//Ask player "Is this the correct time?" +static void Task_SetClock3(u8 taskId) +{ + MenuDrawTextWindow(2, 16, 27, 19); + MenuPrint(gOtherText_CorrectTimePrompt, 3, 17); + MenuDrawTextWindow(23, 8, 29, 13); + PrintMenuItems(24, 9, 2, gMenuYesNoItems); + InitMenu(0, 24, 9, 2, 1, 5); + gTasks[taskId].func = Task_SetClock4; +} + +//Get menu selection +static void Task_SetClock4(u8 taskId) +{ + switch (ProcessMenuInputNoWrap_()) + { + case 0: //YES + PlaySE(SE_SELECT); + gTasks[taskId].func = Task_SetClock5; //Move on + return; + case -1: //B button + case 1: //NO + HandleDestroyMenuCursors(); + PlaySE(SE_SELECT); + MenuZeroFillWindowRect(23, 8, 29, 13); + MenuZeroFillWindowRect(2, 16, 27, 19); + gTasks[taskId].func = Task_SetClock2; //Go back and let player adjust clock + } +} + +//Set the time offset based on the wall clock's time +static void Task_SetClock5(u8 taskId) +{ + RtcInitLocalTimeOffset(gTasks[taskId].tHours, gTasks[taskId].tMinutes); + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + gTasks[taskId].func = Task_SetClock6; +} + +static void Task_SetClock6(u8 taskId) +{ + if (!gPaletteFade.active) + SetMainCallback2((MainCallback)gMain.savedCallback); +} + +static void Task_ViewClock1(u8 taskId) +{ + if (!gPaletteFade.active) + gTasks[taskId].func = Task_ViewClock2; +} + +//Wait for A or B press +static void Task_ViewClock2(u8 taskId) +{ + InitClockWithRtc(taskId); + if (gMain.newKeys & (A_BUTTON | B_BUTTON)) + gTasks[taskId].func = Task_ViewClock3; +} + +static void Task_ViewClock3(u8 taskId) +{ + BeginNormalPaletteFade(-1, 0, 0, 16, 0); + gTasks[taskId].func = Task_ViewClock4; +} + +static void Task_ViewClock4(u8 taskId) +{ + if (!gPaletteFade.active) + SetMainCallback2((MainCallback)gMain.savedCallback); +} + +static u8 CalcMinHandDelta(u16 speed) +{ + if (speed > 60) + return 6; + else if (speed > 30) + return 3; + else if (speed > 10) + return 2; + else + return 1; +} + +//Calculates the new angle of the minute hand when setting the clock +static u16 CalcNewMinHandAngle(u16 angle, u8 direction, u8 speed) +{ + u8 delta = CalcMinHandDelta(speed); + + switch (direction) + { + case MVMT_BACKWARD: + if (angle) + angle = angle - delta; + else + angle = 360 - delta; + break; + case MVMT_FORWARD: + if (angle < 360 - delta) + angle = angle + delta; + else + angle = 0; + break; + } + return angle; +} + +//Advances clock forward or backward by 1 minute +static u8 AdvanceClock(u8 taskId, u8 direction) +{ + switch (direction) + { + case MVMT_BACKWARD: + if (gTasks[taskId].tMinutes > 0) + gTasks[taskId].tMinutes--; + else + { + gTasks[taskId].tMinutes = 59; + if (gTasks[taskId].tHours > 0) + gTasks[taskId].tHours--; + else + gTasks[taskId].tHours = 23; + UpdateClockPeriod(taskId, direction); + } + break; + case MVMT_FORWARD: + if (gTasks[taskId].tMinutes < 59) + gTasks[taskId].tMinutes++; + else + { + gTasks[taskId].tMinutes = 0; + if (gTasks[taskId].tHours < 23) + gTasks[taskId].tHours++; + else + gTasks[taskId].tHours = 0; + UpdateClockPeriod(taskId, direction); + } + break; + } + return 0; +} + +//Updates the clock period (AM/PM) if it needs to change +static void UpdateClockPeriod(u8 taskId, u8 direction) +{ + u8 hours = gTasks[taskId].tHours; + + switch (direction) + { + case MVMT_BACKWARD: + switch (hours) + { + case 11: + gTasks[taskId].tPeriod = PERIOD_AM; + break; + case 23: + gTasks[taskId].tPeriod = PERIOD_PM; + break; + } + break; + case MVMT_FORWARD: + switch (hours) + { + case 0: + gTasks[taskId].tPeriod = PERIOD_AM; + break; + case 12: + gTasks[taskId].tPeriod = PERIOD_PM; + break; + } + break; + } +} + +static void InitClockWithRtc(u8 taskId) +{ + RtcCalcLocalTime(); + gTasks[taskId].tHours = gLocalTime.hours; + gTasks[taskId].tMinutes = gLocalTime.minutes; + gTasks[taskId].tMinuteHandAngle = gTasks[taskId].tMinutes * 6; + gTasks[taskId].tHourHandAngle = (gTasks[taskId].tHours % 12) * 30 + (gTasks[taskId].tMinutes / 10) * 5; + if (gLocalTime.hours <= 11) + gTasks[taskId].tPeriod = PERIOD_AM; + else + gTasks[taskId].tPeriod = PERIOD_PM; +} + +static const s8 gClockHandCoords[][2] = +{ + { 0, -24}, + { 1, -25}, + { 1, -25}, + { 2, -25}, + { 2, -25}, + { 2, -25}, + { 3, -24}, + { 3, -25}, + { 4, -25}, + { 4, -25}, + { 4, -25}, + { 5, -25}, + { 5, -25}, + { 6, -24}, + { 6, -24}, + { 6, -24}, + { 7, -24}, + { 7, -24}, + { 7, -24}, + { 8, -24}, + { 8, -24}, + { 9, -24}, + { 9, -24}, + { 10, -23}, + { 10, -23}, + { 11, -22}, + { 11, -22}, + { 11, -22}, + { 12, -22}, + { 12, -21}, + { 13, -21}, + { 13, -21}, + { 13, -21}, + { 14, -21}, + { 14, -21}, + { 14, -20}, + { 14, -20}, + { 15, -20}, + { 15, -19}, + { 16, -19}, + { 16, -19}, + { 16, -19}, + { 16, -18}, + { 16, -18}, + { 17, -18}, + { 17, -17}, + { 17, -17}, + { 18, -17}, + { 18, -17}, + { 18, -16}, + { 18, -16}, + { 19, -16}, + { 19, -15}, + { 19, -15}, + { 20, -15}, + { 20, -14}, + { 20, -14}, + { 20, -13}, + { 20, -13}, + { 21, -13}, + { 21, -13}, + { 21, -12}, + { 22, -12}, + { 22, -12}, + { 22, -11}, + { 22, -11}, + { 22, -10}, + { 23, -10}, + { 23, -9}, + { 23, -9}, + { 23, -9}, + { 23, -9}, + { 23, -8}, + { 23, -8}, + { 23, -7}, + { 23, -7}, + { 23, -6}, + { 24, -6}, + { 24, -6}, + { 25, -5}, + { 25, -5}, + { 24, -4}, + { 25, -4}, + { 24, -3}, + { 25, -3}, + { 25, -3}, + { 25, -2}, + { 25, -2}, + { 24, -1}, + { 25, -1}, + { 24, 0}, + { 24, 0}, + { 24, 0}, + { 24, 1}, + { 24, 1}, + { 25, 2}, + { 24, 2}, + { 25, 2}, + { 24, 3}, + { 24, 3}, + { 25, 4}, + { 24, 4}, + { 24, 5}, + { 24, 5}, + { 24, 5}, + { 24, 6}, + { 23, 6}, + { 23, 6}, + { 23, 7}, + { 23, 8}, + { 23, 8}, + { 23, 8}, + { 23, 9}, + { 23, 9}, + { 23, 10}, + { 22, 10}, + { 22, 10}, + { 22, 11}, + { 22, 11}, + { 22, 11}, + { 22, 12}, + { 21, 12}, + { 21, 12}, + { 21, 13}, + { 20, 13}, + { 20, 13}, + { 19, 13}, + { 19, 13}, + { 19, 14}, + { 19, 14}, + { 19, 15}, + { 19, 15}, + { 18, 15}, + { 18, 16}, + { 17, 16}, + { 17, 16}, + { 17, 17}, + { 17, 17}, + { 16, 17}, + { 16, 18}, + { 16, 18}, + { 15, 18}, + { 14, 18}, + { 15, 19}, + { 14, 19}, + { 14, 19}, + { 13, 19}, + { 13, 20}, + { 13, 20}, + { 13, 20}, + { 12, 20}, + { 12, 20}, + { 12, 21}, + { 11, 21}, + { 11, 21}, + { 11, 21}, + { 10, 21}, + { 10, 22}, + { 10, 22}, + { 9, 22}, + { 9, 22}, + { 8, 22}, + { 7, 22}, + { 7, 23}, + { 7, 23}, + { 6, 23}, + { 6, 23}, + { 5, 23}, + { 5, 23}, + { 5, 24}, + { 4, 24}, + { 4, 24}, + { 4, 24}, + { 3, 24}, + { 2, 24}, + { 2, 24}, + { 1, 24}, + { 1, 24}, + { 0, 24}, + { 0, 24}, + { -1, 23}, + { 0, 24}, + { 0, 24}, + { -1, 24}, + { -1, 24}, + { -2, 24}, + { -2, 24}, + { -3, 24}, + { -3, 24}, + { -4, 24}, + { -4, 24}, + { -5, 24}, + { -5, 23}, + { -5, 23}, + { -6, 23}, + { -6, 23}, + { -7, 23}, + { -7, 23}, + { -7, 23}, + { -8, 23}, + { -8, 22}, + { -9, 22}, + { -9, 22}, + {-10, 22}, + {-10, 22}, + {-10, 21}, + {-11, 21}, + {-11, 21}, + {-11, 21}, + {-11, 20}, + {-12, 20}, + {-12, 20}, + {-13, 20}, + {-13, 20}, + {-13, 19}, + {-14, 19}, + {-14, 19}, + {-14, 19}, + {-14, 18}, + {-15, 18}, + {-15, 18}, + {-15, 17}, + {-16, 17}, + {-16, 17}, + {-17, 17}, + {-17, 16}, + {-17, 16}, + {-18, 16}, + {-17, 15}, + {-18, 15}, + {-18, 15}, + {-19, 15}, + {-19, 14}, + {-19, 14}, + {-19, 13}, + {-19, 13}, + {-20, 13}, + {-20, 12}, + {-20, 12}, + {-21, 12}, + {-21, 12}, + {-21, 11}, + {-21, 11}, + {-21, 10}, + {-21, 10}, + {-21, 9}, + {-22, 9}, + {-22, 9}, + {-22, 8}, + {-22, 8}, + {-22, 7}, + {-23, 7}, + {-23, 7}, + {-23, 6}, + {-23, 6}, + {-23, 5}, + {-24, 5}, + {-23, 4}, + {-23, 4}, + {-24, 4}, + {-24, 4}, + {-24, 3}, + {-24, 3}, + {-24, 2}, + {-24, 2}, + {-24, 1}, + {-24, 1}, + {-24, 1}, + {-24, 0}, + {-25, 0}, + {-24, -1}, + {-25, -1}, + {-24, -1}, + {-24, -2}, + {-24, -2}, + {-24, -3}, + {-24, -3}, + {-24, -4}, + {-24, -4}, + {-24, -4}, + {-24, -5}, + {-24, -5}, + {-24, -6}, + {-24, -6}, + {-23, -6}, + {-23, -7}, + {-23, -7}, + {-23, -8}, + {-23, -8}, + {-23, -9}, + {-23, -9}, + {-22, -9}, + {-22, -9}, + {-22, -10}, + {-22, -10}, + {-21, -10}, + {-21, -11}, + {-22, -11}, + {-22, -12}, + {-21, -12}, + {-21, -13}, + {-21, -13}, + {-20, -13}, + {-21, -14}, + {-20, -14}, + {-20, -14}, + {-19, -14}, + {-19, -15}, + {-19, -15}, + {-18, -16}, + {-18, -16}, + {-18, -16}, + {-18, -17}, + {-18, -17}, + {-17, -17}, + {-17, -18}, + {-17, -18}, + {-16, -18}, + {-16, -18}, + {-16, -19}, + {-16, -19}, + {-15, -19}, + {-15, -19}, + {-15, -20}, + {-14, -20}, + {-14, -20}, + {-14, -21}, + {-13, -21}, + {-13, -21}, + {-13, -21}, + {-12, -21}, + {-12, -22}, + {-11, -22}, + {-11, -22}, + {-11, -22}, + {-10, -22}, + {-10, -22}, + { -9, -22}, + { -9, -23}, + { -9, -23}, + { -8, -23}, + { -8, -23}, + { -7, -23}, + { -7, -23}, + { -7, -24}, + { -6, -24}, + { -6, -24}, + { -5, -24}, + { -5, -24}, + { -4, -24}, + { -4, -24}, + { -4, -24}, + { -4, -25}, + { -3, -25}, + { -2, -25}, + { -2, -24}, + { -2, -24}, + { -1, -25}, + { -1, -25}, + { 0, -25}, +}; + +static void sub_810B05C(struct Sprite *sprite) +{ + u16 angle; + s16 sin; + s16 cos; + u16 x; + u16 y; + + angle = gTasks[sprite->data0].tMinuteHandAngle; + sin = Sin2(angle) / 16; + cos = Cos2(angle) / 16; + SetOamMatrix(0, cos, sin, -sin, cos); + x = gClockHandCoords[angle][0]; + y = gClockHandCoords[angle][1]; + + //Manual sign extension + if (x > 0x80) + x |= 0xFF00; + if (y > 0x80) + y |= 0xFF00; + + sprite->pos2.x = x; + sprite->pos2.y = y; +} + +static void sub_810B0F4(struct Sprite *sprite) +{ + u16 angle; + s16 sin; + s16 cos; + u16 x; + u16 y; + + angle = gTasks[sprite->data0].tHourHandAngle; + sin = Sin2(angle) / 16; + cos = Cos2(angle) / 16; + SetOamMatrix(1, cos, sin, -sin, cos); + x = gClockHandCoords[angle][0]; + y = gClockHandCoords[angle][1]; + + //Manual sign extension + if (x > 0x80) + x |= 0xFF00; + if (y > 0x80) + y |= 0xFF00; + + sprite->pos2.x = x; + sprite->pos2.y = y; +} + +static void sub_810B18C(struct Sprite *sprite) +{ + s16 sin; + s16 cos; + + if (gTasks[sprite->data0].tPeriod != PERIOD_AM) + { + if (sprite->data1 >= 60 && sprite->data1 < 90) + sprite->data1 += 5; + if (sprite->data1 < 60) + sprite->data1++; + } + else + { + if (sprite->data1 > 45 && sprite->data1 <= 75) + sprite->data1 -= 5; + if (sprite->data1 > 75) + sprite->data1--; + } + cos = Cos2((u16)sprite->data1); + sprite->pos2.x = cos * 30 / 4096; + sin = Sin2((u16)sprite->data1); + sprite->pos2.y = sin * 30 / 4096; +} + +static void sub_810B230(struct Sprite *sprite) +{ + s16 sin; + s16 cos; + + if (gTasks[sprite->data0].tPeriod != PERIOD_AM) + { + if (sprite->data1 >= 105 && sprite->data1 < 135) + sprite->data1 += 5; + if (sprite->data1 < 105) + sprite->data1++; + } + else + { + if (sprite->data1 > 90 && sprite->data1 <= 120) + sprite->data1 -= 5; + if (sprite->data1 > 120) + sprite->data1--; + } + cos = Cos2((u16)sprite->data1); + sprite->pos2.x = cos * 30 / 4096; + sin = Sin2((u16)sprite->data1); + sprite->pos2.y = sin * 30 / 4096; +} diff --git a/src/field/wild_encounter.c b/src/field/wild_encounter.c new file mode 100644 index 000000000..390898917 --- /dev/null +++ b/src/field/wild_encounter.c @@ -0,0 +1,3573 @@ +#include "global.h" +#include "wild_encounter.h" +#include "abilities.h" +#include "battle_setup.h" +#include "event_data.h" +#include "field_player_avatar.h" +#include "fieldmap.h" +#include "map_constants.h" +#include "metatile_behavior.h" +#include "pokeblock.h" +#include "rng.h" +#include "roamer.h" +#include "overworld.h" +#include "safari_zone.h" +#include "script.h" +#include "species.h" +#include "tv.h" + +const struct WildPokemon PetalburgCity_WaterMons [] = +{ + {20, 30, SPECIES_MARILL}, + {10, 20, SPECIES_MARILL}, + {30, 35, SPECIES_MARILL}, + {5, 10, SPECIES_MARILL}, + {5, 10, SPECIES_MARILL}, +}; +const struct WildPokemonInfo PetalburgCity_WaterMonsInfo = {1, PetalburgCity_WaterMons}; + +const struct WildPokemon PetalburgCity_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_CORPHISH}, + {25, 30, SPECIES_CORPHISH}, + {30, 35, SPECIES_CORPHISH}, + {20, 25, SPECIES_CORPHISH}, + {35, 40, SPECIES_CORPHISH}, + {40, 45, SPECIES_CORPHISH}, +}; +const struct WildPokemonInfo PetalburgCity_FishingMonsInfo = {10, PetalburgCity_FishingMons}; + +const struct WildPokemon SlateportCity_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo SlateportCity_WaterMonsInfo = {4, SlateportCity_WaterMons}; + +const struct WildPokemon SlateportCity_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo SlateportCity_FishingMonsInfo = {10, SlateportCity_FishingMons}; + +const struct WildPokemon LilycoveCity_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo LilycoveCity_WaterMonsInfo = {4, LilycoveCity_WaterMons}; + +const struct WildPokemon LilycoveCity_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_STARYU}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo LilycoveCity_FishingMonsInfo = {10, LilycoveCity_FishingMons}; + +const struct WildPokemon MossdeepCity_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo MossdeepCity_WaterMonsInfo = {4, MossdeepCity_WaterMons}; + +const struct WildPokemon MossdeepCity_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo MossdeepCity_FishingMonsInfo = {10, MossdeepCity_FishingMons}; + +const struct WildPokemon SootopolisCity_WaterMons [] = +{ + {5, 35, SPECIES_MAGIKARP}, + {10, 30, SPECIES_MAGIKARP}, + {15, 25, SPECIES_MAGIKARP}, + {25, 30, SPECIES_MAGIKARP}, + {25, 30, SPECIES_MAGIKARP}, +}; +const struct WildPokemonInfo SootopolisCity_WaterMonsInfo = {1, SootopolisCity_WaterMons}; + +const struct WildPokemon SootopolisCity_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, +#ifdef SAPPHIRE + {5, 10, SPECIES_TENTACOOL}, +#else + {10, 15, SPECIES_MAGIKARP}, +#endif + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_MAGIKARP}, + {30, 35, SPECIES_MAGIKARP}, + {30, 35, SPECIES_MAGIKARP}, + {35, 40, SPECIES_GYARADOS}, + {35, 45, SPECIES_GYARADOS}, + {5, 45, SPECIES_GYARADOS}, +}; +const struct WildPokemonInfo SootopolisCity_FishingMonsInfo = {10, SootopolisCity_FishingMons}; + +const struct WildPokemon EverGrandeCity_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo EverGrandeCity_WaterMonsInfo = {4, EverGrandeCity_WaterMons}; + +const struct WildPokemon EverGrandeCity_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_LUVDISC}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_LUVDISC}, + {30, 35, SPECIES_WAILMER}, + {30, 35, SPECIES_CORSOLA}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo EverGrandeCity_FishingMonsInfo = {10, EverGrandeCity_FishingMons}; + +const struct WildPokemon MeteorFalls_1F_1R_LandMons [] = +{ + {16, 16, SPECIES_ZUBAT}, + {17, 17, SPECIES_ZUBAT}, + {18, 18, SPECIES_ZUBAT}, + {15, 15, SPECIES_ZUBAT}, + {14, 14, SPECIES_ZUBAT}, +#ifdef SAPPHIRE + {16, 16, SPECIES_LUNATONE}, + {18, 18, SPECIES_LUNATONE}, + {14, 14, SPECIES_LUNATONE}, +#else + {16, 16, SPECIES_SOLROCK}, + {18, 18, SPECIES_SOLROCK}, + {14, 14, SPECIES_SOLROCK}, +#endif + {19, 19, SPECIES_ZUBAT}, + {20, 20, SPECIES_ZUBAT}, + {19, 19, SPECIES_ZUBAT}, + {20, 20, SPECIES_ZUBAT}, +}; +const struct WildPokemonInfo MeteorFalls_1F_1R_LandMonsInfo = {10, MeteorFalls_1F_1R_LandMons}; + +const struct WildPokemon MeteorFalls_1F_1R_WaterMons [] = +{ + {5, 35, SPECIES_ZUBAT}, + {30, 35, SPECIES_ZUBAT}, +#ifdef SAPPHIRE + {25, 35, SPECIES_LUNATONE}, + {15, 25, SPECIES_LUNATONE}, + {5, 15, SPECIES_LUNATONE}, +#else + {25, 35, SPECIES_SOLROCK}, + {15, 25, SPECIES_SOLROCK}, + {5, 15, SPECIES_SOLROCK}, +#endif +}; +const struct WildPokemonInfo MeteorFalls_1F_1R_WaterMonsInfo = {4, MeteorFalls_1F_1R_WaterMons}; + +const struct WildPokemon MeteorFalls_1F_1R_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_BARBOACH}, + {25, 30, SPECIES_BARBOACH}, + {30, 35, SPECIES_BARBOACH}, + {20, 25, SPECIES_BARBOACH}, + {35, 40, SPECIES_BARBOACH}, + {40, 45, SPECIES_BARBOACH}, +}; +const struct WildPokemonInfo MeteorFalls_1F_1R_FishingMonsInfo = {30, MeteorFalls_1F_1R_FishingMons}; + +const struct WildPokemon MeteorFalls_1F_2R_LandMons [] = +{ + {33, 33, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {35, 35, SPECIES_LUNATONE}, + {33, 33, SPECIES_LUNATONE}, + {37, 37, SPECIES_LUNATONE}, +#else + {35, 35, SPECIES_SOLROCK}, + {33, 33, SPECIES_SOLROCK}, + {37, 37, SPECIES_SOLROCK}, +#endif + {35, 35, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {39, 39, SPECIES_LUNATONE}, +#else + {39, 39, SPECIES_SOLROCK}, +#endif + {38, 38, SPECIES_GOLBAT}, + {40, 40, SPECIES_GOLBAT}, + {38, 38, SPECIES_GOLBAT}, + {40, 40, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo MeteorFalls_1F_2R_LandMonsInfo = {10, MeteorFalls_1F_2R_LandMons}; + +const struct WildPokemon MeteorFalls_1F_2R_WaterMons [] = +{ + {30, 35, SPECIES_GOLBAT}, + {30, 35, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {25, 35, SPECIES_LUNATONE}, + {15, 25, SPECIES_LUNATONE}, + {5, 15, SPECIES_LUNATONE}, +#else + {25, 35, SPECIES_SOLROCK}, + {15, 25, SPECIES_SOLROCK}, + {5, 15, SPECIES_SOLROCK}, +#endif +}; +const struct WildPokemonInfo MeteorFalls_1F_2R_WaterMonsInfo = {4, MeteorFalls_1F_2R_WaterMons}; + +const struct WildPokemon MeteorFalls_1F_2R_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_BARBOACH}, + {25, 30, SPECIES_BARBOACH}, + {30, 35, SPECIES_BARBOACH}, + {30, 35, SPECIES_WHISCASH}, + {35, 40, SPECIES_WHISCASH}, + {40, 45, SPECIES_WHISCASH}, +}; +const struct WildPokemonInfo MeteorFalls_1F_2R_FishingMonsInfo = {30, MeteorFalls_1F_2R_FishingMons}; + +const struct WildPokemon MeteorFalls_B1F_1R_LandMons [] = +{ + {33, 33, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {35, 35, SPECIES_LUNATONE}, + {33, 33, SPECIES_LUNATONE}, + {37, 37, SPECIES_LUNATONE}, +#else + {35, 35, SPECIES_SOLROCK}, + {33, 33, SPECIES_SOLROCK}, + {37, 37, SPECIES_SOLROCK}, +#endif + {35, 35, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {39, 39, SPECIES_LUNATONE}, +#else + {39, 39, SPECIES_SOLROCK}, +#endif + {38, 38, SPECIES_GOLBAT}, + {40, 40, SPECIES_GOLBAT}, + {38, 38, SPECIES_GOLBAT}, + {40, 40, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo MeteorFalls_B1F_1R_LandMonsInfo = {10, MeteorFalls_B1F_1R_LandMons}; + +const struct WildPokemon MeteorFalls_B1F_1R_WaterMons [] = +{ + {30, 35, SPECIES_GOLBAT}, + {30, 35, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {25, 35, SPECIES_LUNATONE}, + {15, 25, SPECIES_LUNATONE}, + {5, 15, SPECIES_LUNATONE}, +#else + {25, 35, SPECIES_SOLROCK}, + {15, 25, SPECIES_SOLROCK}, + {5, 15, SPECIES_SOLROCK}, +#endif +}; +const struct WildPokemonInfo MeteorFalls_B1F_1R_WaterMonsInfo = {4, MeteorFalls_B1F_1R_WaterMons}; + +const struct WildPokemon MeteorFalls_B1F_1R_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_BARBOACH}, + {25, 30, SPECIES_BARBOACH}, + {30, 35, SPECIES_BARBOACH}, + {30, 35, SPECIES_WHISCASH}, + {35, 40, SPECIES_WHISCASH}, + {40, 45, SPECIES_WHISCASH}, +}; +const struct WildPokemonInfo MeteorFalls_B1F_1R_FishingMonsInfo = {30, MeteorFalls_B1F_1R_FishingMons}; + +const struct WildPokemon MeteorFalls_B1F_2R_LandMons [] = +{ + {33, 33, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {30, 30, SPECIES_BAGON}, +#ifdef SAPPHIRE + {35, 35, SPECIES_LUNATONE}, +#else + {35, 35, SPECIES_SOLROCK}, +#endif + {35, 35, SPECIES_BAGON}, +#ifdef SAPPHIRE + {37, 37, SPECIES_LUNATONE}, +#else + {37, 37, SPECIES_SOLROCK}, +#endif + {25, 25, SPECIES_BAGON}, +#ifdef SAPPHIRE + {39, 39, SPECIES_LUNATONE}, +#else + {39, 39, SPECIES_SOLROCK}, +#endif + {38, 38, SPECIES_GOLBAT}, + {40, 40, SPECIES_GOLBAT}, + {38, 38, SPECIES_GOLBAT}, + {40, 40, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo MeteorFalls_B1F_2R_LandMonsInfo = {10, MeteorFalls_B1F_2R_LandMons}; + +const struct WildPokemon MeteorFalls_B1F_2R_WaterMons [] = +{ + {30, 35, SPECIES_GOLBAT}, + {30, 35, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {25, 35, SPECIES_LUNATONE}, + {15, 25, SPECIES_LUNATONE}, + {5, 15, SPECIES_LUNATONE}, +#else + {25, 35, SPECIES_SOLROCK}, + {15, 25, SPECIES_SOLROCK}, + {5, 15, SPECIES_SOLROCK}, +#endif +}; +const struct WildPokemonInfo MeteorFalls_B1F_2R_WaterMonsInfo = {4, MeteorFalls_B1F_2R_WaterMons}; + +const struct WildPokemon MeteorFalls_B1F_2R_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_BARBOACH}, + {25, 30, SPECIES_BARBOACH}, + {30, 35, SPECIES_BARBOACH}, + {30, 35, SPECIES_WHISCASH}, + {35, 40, SPECIES_WHISCASH}, + {40, 45, SPECIES_WHISCASH}, +}; +const struct WildPokemonInfo MeteorFalls_B1F_2R_FishingMonsInfo = {30, MeteorFalls_B1F_2R_FishingMons}; + +const struct WildPokemon RusturfTunnel_LandMons [] = +{ + {6, 6, SPECIES_WHISMUR}, + {7, 7, SPECIES_WHISMUR}, + {6, 6, SPECIES_WHISMUR}, + {6, 6, SPECIES_WHISMUR}, + {7, 7, SPECIES_WHISMUR}, + {7, 7, SPECIES_WHISMUR}, + {5, 5, SPECIES_WHISMUR}, + {8, 8, SPECIES_WHISMUR}, + {5, 5, SPECIES_WHISMUR}, + {8, 8, SPECIES_WHISMUR}, + {5, 5, SPECIES_WHISMUR}, + {8, 8, SPECIES_WHISMUR}, +}; +const struct WildPokemonInfo RusturfTunnel_LandMonsInfo = {10, RusturfTunnel_LandMons}; + +const struct WildPokemon GraniteCave_1F_LandMons [] = +{ + {7, 7, SPECIES_ZUBAT}, + {8, 8, SPECIES_MAKUHITA}, + {7, 7, SPECIES_MAKUHITA}, + {8, 8, SPECIES_ZUBAT}, + {9, 9, SPECIES_MAKUHITA}, + {8, 8, SPECIES_ABRA}, + {10, 10, SPECIES_MAKUHITA}, + {6, 6, SPECIES_MAKUHITA}, + {7, 7, SPECIES_GEODUDE}, + {8, 8, SPECIES_GEODUDE}, + {6, 6, SPECIES_GEODUDE}, + {9, 9, SPECIES_GEODUDE}, +}; +const struct WildPokemonInfo GraniteCave_1F_LandMonsInfo = {10, GraniteCave_1F_LandMons}; + +const struct WildPokemon GraniteCave_B1F_LandMons [] = +{ + {9, 9, SPECIES_ZUBAT}, + {10, 10, SPECIES_ARON}, + {9, 9, SPECIES_ARON}, + {11, 11, SPECIES_ARON}, + {10, 10, SPECIES_ZUBAT}, + {9, 9, SPECIES_ABRA}, + {10, 10, SPECIES_MAKUHITA}, + {11, 11, SPECIES_MAKUHITA}, +#ifdef SAPPHIRE + {10, 10, SPECIES_SABLEYE}, + {10, 10, SPECIES_SABLEYE}, + {9, 9, SPECIES_SABLEYE}, + {11, 11, SPECIES_SABLEYE}, +#else + {10, 10, SPECIES_MAWILE}, + {10, 10, SPECIES_MAWILE}, + {9, 9, SPECIES_MAWILE}, + {11, 11, SPECIES_MAWILE}, +#endif +}; +const struct WildPokemonInfo GraniteCave_B1F_LandMonsInfo = {10, GraniteCave_B1F_LandMons}; + +const struct WildPokemon GraniteCave_B2F_LandMons [] = +{ + {10, 10, SPECIES_ZUBAT}, + {11, 11, SPECIES_ARON}, + {10, 10, SPECIES_ARON}, + {11, 11, SPECIES_ZUBAT}, + {12, 12, SPECIES_ARON}, + {10, 10, SPECIES_ABRA}, +#ifdef SAPPHIRE + {10, 10, SPECIES_SABLEYE}, + {11, 11, SPECIES_SABLEYE}, + {12, 12, SPECIES_SABLEYE}, + {10, 10, SPECIES_SABLEYE}, + {12, 12, SPECIES_SABLEYE}, + {10, 10, SPECIES_SABLEYE}, +#else + {10, 10, SPECIES_MAWILE}, + {11, 11, SPECIES_MAWILE}, + {12, 12, SPECIES_MAWILE}, + {10, 10, SPECIES_MAWILE}, + {12, 12, SPECIES_MAWILE}, + {10, 10, SPECIES_MAWILE}, +#endif +}; +const struct WildPokemonInfo GraniteCave_B2F_LandMonsInfo = {10, GraniteCave_B2F_LandMons}; + +const struct WildPokemon GraniteCave_B2F_RockSmashMons [] = +{ + {10, 15, SPECIES_GEODUDE}, + {10, 20, SPECIES_NOSEPASS}, + {5, 10, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, +}; +const struct WildPokemonInfo GraniteCave_B2F_RockSmashMonsInfo = {20, GraniteCave_B2F_RockSmashMons}; + +const struct WildPokemon GraniteCave_StevensRoom_LandMons [] = +{ + {7, 7, SPECIES_ZUBAT}, + {8, 8, SPECIES_MAKUHITA}, + {7, 7, SPECIES_MAKUHITA}, + {8, 8, SPECIES_ZUBAT}, + {9, 9, SPECIES_MAKUHITA}, + {8, 8, SPECIES_ABRA}, + {10, 10, SPECIES_MAKUHITA}, + {6, 6, SPECIES_MAKUHITA}, + {7, 7, SPECIES_ARON}, + {8, 8, SPECIES_ARON}, + {7, 7, SPECIES_ARON}, + {8, 8, SPECIES_ARON}, +}; +const struct WildPokemonInfo GraniteCave_StevensRoom_LandMonsInfo = {10, GraniteCave_StevensRoom_LandMons}; + +const struct WildPokemon PetalburgWoods_LandMons [] = +{ + {5, 5, SPECIES_ZIGZAGOON}, + {5, 5, SPECIES_WURMPLE}, + {5, 5, SPECIES_SHROOMISH}, + {6, 6, SPECIES_ZIGZAGOON}, + {5, 5, SPECIES_SILCOON}, + {5, 5, SPECIES_CASCOON}, + {6, 6, SPECIES_WURMPLE}, + {6, 6, SPECIES_SHROOMISH}, + {5, 5, SPECIES_TAILLOW}, + {5, 5, SPECIES_SLAKOTH}, + {6, 6, SPECIES_TAILLOW}, + {6, 6, SPECIES_SLAKOTH}, +}; +const struct WildPokemonInfo PetalburgWoods_LandMonsInfo = {20, PetalburgWoods_LandMons}; + +//Jagged Pass Pokemon are 2 levels higher on Sapphire +#ifdef SAPPHIRE +#define JAGGED_PASS_LEVEL_DIFF 2 +#else +#define JAGGED_PASS_LEVEL_DIFF 0 +#endif + +const struct WildPokemon JaggedPass_LandMons [] = +{ + {19 + JAGGED_PASS_LEVEL_DIFF, 19 + JAGGED_PASS_LEVEL_DIFF, SPECIES_NUMEL}, + {19 + JAGGED_PASS_LEVEL_DIFF, 19 + JAGGED_PASS_LEVEL_DIFF, SPECIES_NUMEL}, + {19 + JAGGED_PASS_LEVEL_DIFF, 19 + JAGGED_PASS_LEVEL_DIFF, SPECIES_MACHOP}, + {18 + JAGGED_PASS_LEVEL_DIFF, 18 + JAGGED_PASS_LEVEL_DIFF, SPECIES_NUMEL}, + {18 + JAGGED_PASS_LEVEL_DIFF, 18 + JAGGED_PASS_LEVEL_DIFF, SPECIES_SPOINK}, + {18 + JAGGED_PASS_LEVEL_DIFF, 18 + JAGGED_PASS_LEVEL_DIFF, SPECIES_MACHOP}, + {19 + JAGGED_PASS_LEVEL_DIFF, 19 + JAGGED_PASS_LEVEL_DIFF, SPECIES_SPOINK}, + {20 + JAGGED_PASS_LEVEL_DIFF, 20 + JAGGED_PASS_LEVEL_DIFF, SPECIES_MACHOP}, + {20 + JAGGED_PASS_LEVEL_DIFF, 20 + JAGGED_PASS_LEVEL_DIFF, SPECIES_NUMEL}, + {20 + JAGGED_PASS_LEVEL_DIFF, 20 + JAGGED_PASS_LEVEL_DIFF, SPECIES_SPOINK}, + {20 + JAGGED_PASS_LEVEL_DIFF, 20 + JAGGED_PASS_LEVEL_DIFF, SPECIES_NUMEL}, + {20 + JAGGED_PASS_LEVEL_DIFF, 20 + JAGGED_PASS_LEVEL_DIFF, SPECIES_SPOINK}, +}; +const struct WildPokemonInfo JaggedPass_LandMonsInfo = {20, JaggedPass_LandMons}; + +const struct WildPokemon FieryPath_LandMons [] = +{ + {15, 15, SPECIES_NUMEL}, +#ifdef SAPPHIRE + {15, 15, SPECIES_GRIMER}, +#else + {15, 15, SPECIES_KOFFING}, +#endif + {16, 16, SPECIES_NUMEL}, + {15, 15, SPECIES_MACHOP}, + {15, 15, SPECIES_TORKOAL}, + {15, 15, SPECIES_SLUGMA}, +#ifdef SAPPHIRE + {16, 16, SPECIES_GRIMER}, +#else + {16, 16, SPECIES_KOFFING}, +#endif + {16, 16, SPECIES_MACHOP}, + {14, 14, SPECIES_TORKOAL}, + {16, 16, SPECIES_TORKOAL}, +#ifdef SAPPHIRE + {14, 14, SPECIES_KOFFING}, + {14, 14, SPECIES_KOFFING}, +#else + {14, 14, SPECIES_GRIMER}, + {14, 14, SPECIES_GRIMER}, +#endif +}; +const struct WildPokemonInfo FieryPath_LandMonsInfo = {10, FieryPath_LandMons}; + +const struct WildPokemon MtPyre_1F_LandMons [] = +{ +#ifdef SAPPHIRE + {27, 27, SPECIES_SHUPPET}, + {28, 28, SPECIES_SHUPPET}, + {26, 26, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {23, 23, SPECIES_SHUPPET}, + {22, 22, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, +#else + {27, 27, SPECIES_DUSKULL}, + {28, 28, SPECIES_DUSKULL}, + {26, 26, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {23, 23, SPECIES_DUSKULL}, + {22, 22, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, +#endif +}; +const struct WildPokemonInfo MtPyre_1F_LandMonsInfo = {10, MtPyre_1F_LandMons}; + +const struct WildPokemon MtPyre_2F_LandMons [] = +{ +#ifdef SAPPHIRE + {27, 27, SPECIES_SHUPPET}, + {28, 28, SPECIES_SHUPPET}, + {26, 26, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {23, 23, SPECIES_SHUPPET}, + {22, 22, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, +#else + {27, 27, SPECIES_DUSKULL}, + {28, 28, SPECIES_DUSKULL}, + {26, 26, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {23, 23, SPECIES_DUSKULL}, + {22, 22, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, +#endif +}; +const struct WildPokemonInfo MtPyre_2F_LandMonsInfo = {10, MtPyre_2F_LandMons}; + +const struct WildPokemon MtPyre_3F_LandMons [] = +{ +#ifdef SAPPHIRE + {27, 27, SPECIES_SHUPPET}, + {28, 28, SPECIES_SHUPPET}, + {26, 26, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {23, 23, SPECIES_SHUPPET}, + {22, 22, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, +#else + {27, 27, SPECIES_DUSKULL}, + {28, 28, SPECIES_DUSKULL}, + {26, 26, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {23, 23, SPECIES_DUSKULL}, + {22, 22, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, +#endif +}; +const struct WildPokemonInfo MtPyre_3F_LandMonsInfo = {10, MtPyre_3F_LandMons}; + +const struct WildPokemon MtPyre_4F_LandMons [] = +{ +#ifdef SAPPHIRE + {27, 27, SPECIES_SHUPPET}, + {28, 28, SPECIES_SHUPPET}, + {26, 26, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {23, 23, SPECIES_SHUPPET}, + {22, 22, SPECIES_SHUPPET}, + {27, 27, SPECIES_DUSKULL}, + {27, 27, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, +#else + {27, 27, SPECIES_DUSKULL}, + {28, 28, SPECIES_DUSKULL}, + {26, 26, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {23, 23, SPECIES_DUSKULL}, + {22, 22, SPECIES_DUSKULL}, + {27, 27, SPECIES_SHUPPET}, + {27, 27, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, +#endif +}; +const struct WildPokemonInfo MtPyre_4F_LandMonsInfo = {10, MtPyre_4F_LandMons}; + +const struct WildPokemon MtPyre_5F_LandMons [] = +{ +#ifdef SAPPHIRE + {27, 27, SPECIES_SHUPPET}, + {28, 28, SPECIES_SHUPPET}, + {26, 26, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {23, 23, SPECIES_SHUPPET}, + {22, 22, SPECIES_SHUPPET}, + {27, 27, SPECIES_DUSKULL}, + {27, 27, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, +#else + {27, 27, SPECIES_DUSKULL}, + {28, 28, SPECIES_DUSKULL}, + {26, 26, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {23, 23, SPECIES_DUSKULL}, + {22, 22, SPECIES_DUSKULL}, + {27, 27, SPECIES_SHUPPET}, + {27, 27, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, +#endif +}; +const struct WildPokemonInfo MtPyre_5F_LandMonsInfo = {10, MtPyre_5F_LandMons}; + +const struct WildPokemon MtPyre_6F_LandMons [] = +{ +#ifdef SAPPHIRE + {27, 27, SPECIES_SHUPPET}, + {28, 28, SPECIES_SHUPPET}, + {26, 26, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {23, 23, SPECIES_SHUPPET}, + {22, 22, SPECIES_SHUPPET}, + {27, 27, SPECIES_DUSKULL}, + {27, 27, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, +#else + {27, 27, SPECIES_DUSKULL}, + {28, 28, SPECIES_DUSKULL}, + {26, 26, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {23, 23, SPECIES_DUSKULL}, + {22, 22, SPECIES_DUSKULL}, + {27, 27, SPECIES_SHUPPET}, + {27, 27, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, +#endif +}; +const struct WildPokemonInfo MtPyre_6F_LandMonsInfo = {10, MtPyre_6F_LandMons}; + +const struct WildPokemon MtPyre_Exterior_LandMons [] = +{ +#ifdef SAPPHIRE + {27, 27, SPECIES_SHUPPET}, +#else + {27, 27, SPECIES_DUSKULL}, +#endif + {27, 27, SPECIES_MEDITITE}, +#ifdef SAPPHIRE + {28, 28, SPECIES_SHUPPET}, +#else + {28, 28, SPECIES_DUSKULL}, +#endif + {29, 29, SPECIES_MEDITITE}, +#ifdef SAPPHIRE + {29, 29, SPECIES_SHUPPET}, +#else + {29, 29, SPECIES_DUSKULL}, +#endif + {27, 27, SPECIES_VULPIX}, + {29, 29, SPECIES_VULPIX}, + {25, 25, SPECIES_VULPIX}, + {27, 27, SPECIES_WINGULL}, + {27, 27, SPECIES_WINGULL}, + {26, 26, SPECIES_WINGULL}, + {28, 28, SPECIES_WINGULL}, +}; +const struct WildPokemonInfo MtPyre_Exterior_LandMonsInfo = {10, MtPyre_Exterior_LandMons}; + +const struct WildPokemon MtPyre_Summit_LandMons [] = +{ +#ifdef SAPPHIRE + {28, 28, SPECIES_SHUPPET}, + {29, 29, SPECIES_SHUPPET}, + {27, 27, SPECIES_SHUPPET}, + {26, 26, SPECIES_SHUPPET}, + {30, 30, SPECIES_SHUPPET}, + {25, 25, SPECIES_SHUPPET}, + {24, 24, SPECIES_SHUPPET}, + {28, 28, SPECIES_DUSKULL}, + {26, 26, SPECIES_DUSKULL}, + {30, 30, SPECIES_DUSKULL}, +#else + {28, 28, SPECIES_DUSKULL}, + {29, 29, SPECIES_DUSKULL}, + {27, 27, SPECIES_DUSKULL}, + {26, 26, SPECIES_DUSKULL}, + {30, 30, SPECIES_DUSKULL}, + {25, 25, SPECIES_DUSKULL}, + {24, 24, SPECIES_DUSKULL}, + {28, 28, SPECIES_SHUPPET}, + {26, 26, SPECIES_SHUPPET}, + {30, 30, SPECIES_SHUPPET}, +#endif + {28, 28, SPECIES_CHIMECHO}, + {28, 28, SPECIES_CHIMECHO}, +}; +const struct WildPokemonInfo MtPyre_Summit_LandMonsInfo = {10, MtPyre_Summit_LandMons}; + +const struct WildPokemon SeafloorCavern_Entrance_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_ZUBAT}, + {30, 35, SPECIES_ZUBAT}, + {30, 35, SPECIES_GOLBAT}, + {30, 35, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Entrance_WaterMonsInfo = {4, SeafloorCavern_Entrance_WaterMons}; + +const struct WildPokemon SeafloorCavern_Entrance_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo SeafloorCavern_Entrance_FishingMonsInfo = {10, SeafloorCavern_Entrance_FishingMons}; + +const struct WildPokemon SeafloorCavern_Room1_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room1_LandMonsInfo = {4, SeafloorCavern_Room1_LandMons}; + +const struct WildPokemon SeafloorCavern_Room2_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room2_LandMonsInfo = {4, SeafloorCavern_Room2_LandMons}; + +const struct WildPokemon SeafloorCavern_Room3_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room3_LandMonsInfo = {4, SeafloorCavern_Room3_LandMons}; + +const struct WildPokemon SeafloorCavern_Room4_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room4_LandMonsInfo = {4, SeafloorCavern_Room4_LandMons}; + +const struct WildPokemon SeafloorCavern_Room5_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room5_LandMonsInfo = {4, SeafloorCavern_Room5_LandMons}; + +const struct WildPokemon SeafloorCavern_Room6_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room6_LandMonsInfo = {4, SeafloorCavern_Room6_LandMons}; + +const struct WildPokemon SeafloorCavern_Room6_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_ZUBAT}, + {30, 35, SPECIES_ZUBAT}, + {30, 35, SPECIES_GOLBAT}, + {30, 35, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room6_WaterMonsInfo = {4, SeafloorCavern_Room6_WaterMons}; + +const struct WildPokemon SeafloorCavern_Room6_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo SeafloorCavern_Room6_FishingMonsInfo = {10, SeafloorCavern_Room6_FishingMons}; + +const struct WildPokemon SeafloorCavern_Room7_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room7_LandMonsInfo = {4, SeafloorCavern_Room7_LandMons}; + +const struct WildPokemon SeafloorCavern_Room7_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_ZUBAT}, + {30, 35, SPECIES_ZUBAT}, + {30, 35, SPECIES_GOLBAT}, + {30, 35, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room7_WaterMonsInfo = {4, SeafloorCavern_Room7_WaterMons}; + +const struct WildPokemon SeafloorCavern_Room7_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo SeafloorCavern_Room7_FishingMonsInfo = {10, SeafloorCavern_Room7_FishingMons}; + +const struct WildPokemon SeafloorCavern_Room8_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo SeafloorCavern_Room8_LandMonsInfo = {4, SeafloorCavern_Room8_LandMons}; + +const struct WildPokemon CaveOfOrigin_Entrance_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, + {33, 33, SPECIES_ZUBAT}, + {28, 28, SPECIES_ZUBAT}, + {29, 29, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {35, 35, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo CaveOfOrigin_Entrance_LandMonsInfo = {4, CaveOfOrigin_Entrance_LandMons}; + +const struct WildPokemon CaveOfOrigin_1F_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, +#ifdef SAPPHIRE + {30, 30, SPECIES_SABLEYE}, + {32, 32, SPECIES_SABLEYE}, + {34, 34, SPECIES_SABLEYE}, +#else + {30, 30, SPECIES_MAWILE}, + {32, 32, SPECIES_MAWILE}, + {34, 34, SPECIES_MAWILE}, +#endif + {33, 33, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo CaveOfOrigin_1F_LandMonsInfo = {4, CaveOfOrigin_1F_LandMons}; + +const struct WildPokemon CaveOfOrigin_B1F_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, +#ifdef SAPPHIRE + {30, 30, SPECIES_SABLEYE}, + {32, 32, SPECIES_SABLEYE}, + {34, 34, SPECIES_SABLEYE}, +#else + {30, 30, SPECIES_MAWILE}, + {32, 32, SPECIES_MAWILE}, + {34, 34, SPECIES_MAWILE}, +#endif + {33, 33, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo CaveOfOrigin_B1F_LandMonsInfo = {4, CaveOfOrigin_B1F_LandMons}; + +const struct WildPokemon CaveOfOrigin_B2F_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, +#ifdef SAPPHIRE + {30, 30, SPECIES_SABLEYE}, + {32, 32, SPECIES_SABLEYE}, + {34, 34, SPECIES_SABLEYE}, +#else + {30, 30, SPECIES_MAWILE}, + {32, 32, SPECIES_MAWILE}, + {34, 34, SPECIES_MAWILE}, +#endif + {33, 33, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo CaveOfOrigin_B2F_LandMonsInfo = {4, CaveOfOrigin_B2F_LandMons}; + +const struct WildPokemon CaveOfOrigin_B3F_LandMons [] = +{ + {30, 30, SPECIES_ZUBAT}, + {31, 31, SPECIES_ZUBAT}, + {32, 32, SPECIES_ZUBAT}, +#ifdef SAPPHIRE + {30, 30, SPECIES_SABLEYE}, + {32, 32, SPECIES_SABLEYE}, + {34, 34, SPECIES_SABLEYE}, +#else + {30, 30, SPECIES_MAWILE}, + {32, 32, SPECIES_MAWILE}, + {34, 34, SPECIES_MAWILE}, +#endif + {33, 33, SPECIES_ZUBAT}, + {34, 34, SPECIES_ZUBAT}, + {34, 34, SPECIES_GOLBAT}, + {35, 35, SPECIES_GOLBAT}, + {33, 33, SPECIES_GOLBAT}, + {36, 36, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo CaveOfOrigin_B3F_LandMonsInfo = {4, CaveOfOrigin_B3F_LandMons}; + +const struct WildPokemon VictoryRoad_1F_LandMons [] = +{ + {40, 40, SPECIES_GOLBAT}, + {40, 40, SPECIES_HARIYAMA}, + {40, 40, SPECIES_LAIRON}, + {40, 40, SPECIES_LOUDRED}, + {36, 36, SPECIES_ZUBAT}, + {36, 36, SPECIES_MAKUHITA}, + {38, 38, SPECIES_GOLBAT}, + {38, 38, SPECIES_HARIYAMA}, + {36, 36, SPECIES_ARON}, + {36, 36, SPECIES_WHISMUR}, + {36, 36, SPECIES_ARON}, + {36, 36, SPECIES_WHISMUR}, +}; +const struct WildPokemonInfo VictoryRoad_1F_LandMonsInfo = {10, VictoryRoad_1F_LandMons}; + +const struct WildPokemon VictoryRoad_B1F_LandMons [] = +{ + {40, 40, SPECIES_GOLBAT}, + {40, 40, SPECIES_HARIYAMA}, + {40, 40, SPECIES_LAIRON}, + {40, 40, SPECIES_MEDICHAM}, + {38, 38, SPECIES_GOLBAT}, + {38, 38, SPECIES_HARIYAMA}, + {42, 42, SPECIES_GOLBAT}, + {42, 42, SPECIES_HARIYAMA}, + {42, 42, SPECIES_LAIRON}, + {38, 38, SPECIES_MEDITITE}, + {42, 42, SPECIES_LAIRON}, + {38, 38, SPECIES_MEDITITE}, +}; +const struct WildPokemonInfo VictoryRoad_B1F_LandMonsInfo = {10, VictoryRoad_B1F_LandMons}; + +const struct WildPokemon VictoryRoad_B1F_RockSmashMons [] = +{ + {30, 40, SPECIES_GRAVELER}, + {30, 40, SPECIES_GEODUDE}, + {35, 40, SPECIES_GRAVELER}, + {35, 40, SPECIES_GRAVELER}, + {35, 40, SPECIES_GRAVELER}, +}; +const struct WildPokemonInfo VictoryRoad_B1F_RockSmashMonsInfo = {20, VictoryRoad_B1F_RockSmashMons}; + +const struct WildPokemon VictoryRoad_B2F_LandMons [] = +{ + {40, 40, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {40, 40, SPECIES_SABLEYE}, +#else + {40, 40, SPECIES_MAWILE}, +#endif + {40, 40, SPECIES_LAIRON}, + {40, 40, SPECIES_MEDICHAM}, + {42, 42, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {42, 42, SPECIES_SABLEYE}, +#else + {42, 42, SPECIES_MAWILE}, +#endif + {44, 44, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {44, 44, SPECIES_SABLEYE}, +#else + {44, 44, SPECIES_MAWILE}, +#endif + {42, 42, SPECIES_LAIRON}, + {42, 42, SPECIES_MEDICHAM}, + {44, 44, SPECIES_LAIRON}, + {44, 44, SPECIES_MEDICHAM}, +}; +const struct WildPokemonInfo VictoryRoad_B2F_LandMonsInfo = {10, VictoryRoad_B2F_LandMons}; + +const struct WildPokemon VictoryRoad_B2F_WaterMons [] = +{ + {30, 35, SPECIES_GOLBAT}, + {25, 30, SPECIES_GOLBAT}, + {35, 40, SPECIES_GOLBAT}, + {35, 40, SPECIES_GOLBAT}, + {35, 40, SPECIES_GOLBAT}, +}; +const struct WildPokemonInfo VictoryRoad_B2F_WaterMonsInfo = {4, VictoryRoad_B2F_WaterMons}; + +const struct WildPokemon VictoryRoad_B2F_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_BARBOACH}, + {25, 30, SPECIES_BARBOACH}, + {30, 35, SPECIES_BARBOACH}, + {30, 35, SPECIES_WHISCASH}, + {35, 40, SPECIES_WHISCASH}, + {40, 45, SPECIES_WHISCASH}, +}; +const struct WildPokemonInfo VictoryRoad_B2F_FishingMonsInfo = {30, VictoryRoad_B2F_FishingMons}; + +const struct WildPokemon ShoalCave_LowTideEntranceRoom_LandMons [] = +{ + {26, 26, SPECIES_ZUBAT}, + {26, 26, SPECIES_SPHEAL}, + {28, 28, SPECIES_ZUBAT}, + {28, 28, SPECIES_SPHEAL}, + {30, 30, SPECIES_ZUBAT}, + {30, 30, SPECIES_SPHEAL}, + {32, 32, SPECIES_ZUBAT}, + {32, 32, SPECIES_SPHEAL}, + {32, 32, SPECIES_GOLBAT}, + {32, 32, SPECIES_SPHEAL}, + {32, 32, SPECIES_GOLBAT}, + {32, 32, SPECIES_SPHEAL}, +}; +const struct WildPokemonInfo ShoalCave_LowTideEntranceRoom_LandMonsInfo = {10, ShoalCave_LowTideEntranceRoom_LandMons}; + +const struct WildPokemon ShoalCave_LowTideEntranceRoom_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_ZUBAT}, + {25, 30, SPECIES_SPHEAL}, + {25, 30, SPECIES_SPHEAL}, + {25, 35, SPECIES_SPHEAL}, +}; +const struct WildPokemonInfo ShoalCave_LowTideEntranceRoom_WaterMonsInfo = {4, ShoalCave_LowTideEntranceRoom_WaterMons}; + +const struct WildPokemon ShoalCave_LowTideEntranceRoom_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo ShoalCave_LowTideEntranceRoom_FishingMonsInfo = {10, ShoalCave_LowTideEntranceRoom_FishingMons}; + +const struct WildPokemon ShoalCave_LowTideInnerRoom_LandMons [] = +{ + {26, 26, SPECIES_ZUBAT}, + {26, 26, SPECIES_SPHEAL}, + {28, 28, SPECIES_ZUBAT}, + {28, 28, SPECIES_SPHEAL}, + {30, 30, SPECIES_ZUBAT}, + {30, 30, SPECIES_SPHEAL}, + {32, 32, SPECIES_ZUBAT}, + {32, 32, SPECIES_SPHEAL}, + {32, 32, SPECIES_GOLBAT}, + {32, 32, SPECIES_SPHEAL}, + {32, 32, SPECIES_GOLBAT}, + {32, 32, SPECIES_SPHEAL}, +}; +const struct WildPokemonInfo ShoalCave_LowTideInnerRoom_LandMonsInfo = {10, ShoalCave_LowTideInnerRoom_LandMons}; + +const struct WildPokemon ShoalCave_LowTideInnerRoom_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_ZUBAT}, + {25, 30, SPECIES_SPHEAL}, + {25, 30, SPECIES_SPHEAL}, + {25, 35, SPECIES_SPHEAL}, +}; +const struct WildPokemonInfo ShoalCave_LowTideInnerRoom_WaterMonsInfo = {4, ShoalCave_LowTideInnerRoom_WaterMons}; + +const struct WildPokemon ShoalCave_LowTideInnerRoom_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo ShoalCave_LowTideInnerRoom_FishingMonsInfo = {10, ShoalCave_LowTideInnerRoom_FishingMons}; + +const struct WildPokemon ShoalCave_LowTideStairsRoom_LandMons [] = +{ + {26, 26, SPECIES_ZUBAT}, + {26, 26, SPECIES_SPHEAL}, + {28, 28, SPECIES_ZUBAT}, + {28, 28, SPECIES_SPHEAL}, + {30, 30, SPECIES_ZUBAT}, + {30, 30, SPECIES_SPHEAL}, + {32, 32, SPECIES_ZUBAT}, + {32, 32, SPECIES_SPHEAL}, + {32, 32, SPECIES_GOLBAT}, + {32, 32, SPECIES_SPHEAL}, + {32, 32, SPECIES_GOLBAT}, + {32, 32, SPECIES_SPHEAL}, +}; +const struct WildPokemonInfo ShoalCave_LowTideStairsRoom_LandMonsInfo = {10, ShoalCave_LowTideStairsRoom_LandMons}; + +const struct WildPokemon ShoalCave_LowTideLowerRoom_LandMons [] = +{ + {26, 26, SPECIES_ZUBAT}, + {26, 26, SPECIES_SPHEAL}, + {28, 28, SPECIES_ZUBAT}, + {28, 28, SPECIES_SPHEAL}, + {30, 30, SPECIES_ZUBAT}, + {30, 30, SPECIES_SPHEAL}, + {32, 32, SPECIES_ZUBAT}, + {32, 32, SPECIES_SPHEAL}, + {32, 32, SPECIES_GOLBAT}, + {32, 32, SPECIES_SPHEAL}, + {32, 32, SPECIES_GOLBAT}, + {32, 32, SPECIES_SPHEAL}, +}; +const struct WildPokemonInfo ShoalCave_LowTideLowerRoom_LandMonsInfo = {10, ShoalCave_LowTideLowerRoom_LandMons}; + +const struct WildPokemon ShoalCave_LowTideIceRoom_LandMons [] = +{ + {26, 26, SPECIES_ZUBAT}, + {26, 26, SPECIES_SPHEAL}, + {28, 28, SPECIES_ZUBAT}, + {28, 28, SPECIES_SPHEAL}, + {30, 30, SPECIES_ZUBAT}, + {30, 30, SPECIES_SPHEAL}, + {26, 26, SPECIES_SNORUNT}, + {32, 32, SPECIES_SPHEAL}, + {30, 30, SPECIES_GOLBAT}, + {28, 28, SPECIES_SNORUNT}, + {32, 32, SPECIES_GOLBAT}, + {30, 30, SPECIES_SNORUNT}, +}; +const struct WildPokemonInfo ShoalCave_LowTideIceRoom_LandMonsInfo = {10, ShoalCave_LowTideIceRoom_LandMons}; + +const struct WildPokemon NewMauville_Entrance_LandMons [] = +{ + {24, 24, SPECIES_VOLTORB}, + {24, 24, SPECIES_MAGNEMITE}, + {25, 25, SPECIES_VOLTORB}, + {25, 25, SPECIES_MAGNEMITE}, + {23, 23, SPECIES_VOLTORB}, + {23, 23, SPECIES_MAGNEMITE}, + {26, 26, SPECIES_VOLTORB}, + {26, 26, SPECIES_MAGNEMITE}, + {22, 22, SPECIES_VOLTORB}, + {22, 22, SPECIES_MAGNEMITE}, + {22, 22, SPECIES_VOLTORB}, + {22, 22, SPECIES_MAGNEMITE}, +}; +const struct WildPokemonInfo NewMauville_Entrance_LandMonsInfo = {10, NewMauville_Entrance_LandMons}; + +const struct WildPokemon NewMauville_Inside_LandMons [] = +{ + {24, 24, SPECIES_VOLTORB}, + {24, 24, SPECIES_MAGNEMITE}, + {25, 25, SPECIES_VOLTORB}, + {25, 25, SPECIES_MAGNEMITE}, + {23, 23, SPECIES_VOLTORB}, + {23, 23, SPECIES_MAGNEMITE}, + {26, 26, SPECIES_VOLTORB}, + {26, 26, SPECIES_MAGNEMITE}, + {22, 22, SPECIES_VOLTORB}, + {22, 22, SPECIES_MAGNEMITE}, + {26, 26, SPECIES_ELECTRODE}, + {26, 26, SPECIES_MAGNETON}, +}; +const struct WildPokemonInfo NewMauville_Inside_LandMonsInfo = {10, NewMauville_Inside_LandMons}; + +const struct WildPokemon AbandonedShip_Rooms_B1F_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_TENTACOOL}, + {30, 35, SPECIES_TENTACRUEL}, +}; +const struct WildPokemonInfo AbandonedShip_Rooms_B1F_WaterMonsInfo = {4, AbandonedShip_Rooms_B1F_WaterMons}; + +const struct WildPokemon AbandonedShip_Rooms_B1F_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_TENTACOOL}, + {25, 30, SPECIES_TENTACOOL}, + {30, 35, SPECIES_TENTACOOL}, + {30, 35, SPECIES_TENTACRUEL}, + {25, 30, SPECIES_TENTACRUEL}, + {20, 25, SPECIES_TENTACRUEL}, +}; +const struct WildPokemonInfo AbandonedShip_Rooms_B1F_FishingMonsInfo = {20, AbandonedShip_Rooms_B1F_FishingMons}; + +const struct WildPokemon AbandonedShip_HiddenFloorCorridors_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_TENTACOOL}, + {5, 35, SPECIES_TENTACOOL}, + {30, 35, SPECIES_TENTACRUEL}, +}; +const struct WildPokemonInfo AbandonedShip_HiddenFloorCorridors_WaterMonsInfo = {4, AbandonedShip_HiddenFloorCorridors_WaterMons}; + +const struct WildPokemon AbandonedShip_HiddenFloorCorridors_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_TENTACOOL}, + {25, 30, SPECIES_TENTACOOL}, + {30, 35, SPECIES_TENTACOOL}, + {30, 35, SPECIES_TENTACRUEL}, + {25, 30, SPECIES_TENTACRUEL}, + {20, 25, SPECIES_TENTACRUEL}, +}; +const struct WildPokemonInfo AbandonedShip_HiddenFloorCorridors_FishingMonsInfo = {20, AbandonedShip_HiddenFloorCorridors_FishingMons}; + +const struct WildPokemon SkyPillar_1F_LandMons [] = +{ +#ifdef SAPPHIRE + {48, 48, SPECIES_SABLEYE}, +#else + {48, 48, SPECIES_MAWILE}, +#endif + {48, 48, SPECIES_GOLBAT}, + {50, 50, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {50, 50, SPECIES_SABLEYE}, +#else + {50, 50, SPECIES_MAWILE}, +#endif + {48, 48, SPECIES_CLAYDOL}, +#ifdef SAPPHIRE + {48, 48, SPECIES_BANETTE}, + {50, 50, SPECIES_BANETTE}, +#else + {48, 48, SPECIES_DUSCLOPS}, + {50, 50, SPECIES_DUSCLOPS}, +#endif + {49, 49, SPECIES_CLAYDOL}, + {47, 47, SPECIES_CLAYDOL}, + {50, 50, SPECIES_CLAYDOL}, + {47, 47, SPECIES_CLAYDOL}, + {50, 50, SPECIES_CLAYDOL}, +}; +const struct WildPokemonInfo SkyPillar_1F_LandMonsInfo = {10, SkyPillar_1F_LandMons}; + +const struct WildPokemon SkyPillar_3F_LandMons [] = +{ +#ifdef SAPPHIRE + {51, 51, SPECIES_SABLEYE}, +#else + {51, 51, SPECIES_MAWILE}, +#endif + {51, 51, SPECIES_GOLBAT}, + {53, 53, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {53, 53, SPECIES_SABLEYE}, +#else + {53, 53, SPECIES_MAWILE}, +#endif + {51, 51, SPECIES_CLAYDOL}, +#ifdef SAPPHIRE + {51, 51, SPECIES_BANETTE}, + {53, 53, SPECIES_BANETTE}, +#else + {51, 51, SPECIES_DUSCLOPS}, + {53, 53, SPECIES_DUSCLOPS}, +#endif + {52, 52, SPECIES_CLAYDOL}, + {50, 50, SPECIES_CLAYDOL}, + {53, 53, SPECIES_CLAYDOL}, + {50, 50, SPECIES_CLAYDOL}, + {53, 53, SPECIES_CLAYDOL}, +}; +const struct WildPokemonInfo SkyPillar_3F_LandMonsInfo = {10, SkyPillar_3F_LandMons}; + +const struct WildPokemon SkyPillar_5F_LandMons [] = +{ +#ifdef SAPPHIRE + {54, 54, SPECIES_SABLEYE}, +#else + {54, 54, SPECIES_MAWILE}, +#endif + {54, 54, SPECIES_GOLBAT}, + {56, 56, SPECIES_GOLBAT}, +#ifdef SAPPHIRE + {56, 56, SPECIES_SABLEYE}, +#else + {56, 56, SPECIES_MAWILE}, +#endif + {54, 54, SPECIES_CLAYDOL}, +#ifdef SAPPHIRE + {54, 54, SPECIES_BANETTE}, + {56, 56, SPECIES_BANETTE}, +#else + {54, 54, SPECIES_DUSCLOPS}, + {56, 56, SPECIES_DUSCLOPS}, +#endif + {55, 55, SPECIES_CLAYDOL}, + {56, 56, SPECIES_CLAYDOL}, + {57, 57, SPECIES_ALTARIA}, + {54, 54, SPECIES_ALTARIA}, + {60, 60, SPECIES_ALTARIA}, +}; +const struct WildPokemonInfo SkyPillar_5F_LandMonsInfo = {10, SkyPillar_5F_LandMons}; + +const struct WildPokemon Route101_LandMons [] = +{ + {2, 2, SPECIES_WURMPLE}, + {2, 2, SPECIES_ZIGZAGOON}, + {2, 2, SPECIES_WURMPLE}, + {3, 3, SPECIES_WURMPLE}, + {3, 3, SPECIES_ZIGZAGOON}, + {3, 3, SPECIES_ZIGZAGOON}, + {3, 3, SPECIES_WURMPLE}, + {3, 3, SPECIES_ZIGZAGOON}, + {2, 2, SPECIES_POOCHYENA}, + {2, 2, SPECIES_POOCHYENA}, + {3, 3, SPECIES_POOCHYENA}, + {3, 3, SPECIES_POOCHYENA}, +}; +const struct WildPokemonInfo Route101_LandMonsInfo = {20, Route101_LandMons}; + +const struct WildPokemon Route102_LandMons [] = +{ + {3, 3, SPECIES_ZIGZAGOON}, + {3, 3, SPECIES_WURMPLE}, + {4, 4, SPECIES_ZIGZAGOON}, + {4, 4, SPECIES_WURMPLE}, +#ifdef SAPPHIRE + {3, 3, SPECIES_LOTAD}, + {4, 4, SPECIES_LOTAD}, +#else + {3, 3, SPECIES_SEEDOT}, + {4, 4, SPECIES_SEEDOT}, +#endif + {3, 3, SPECIES_POOCHYENA}, + {3, 3, SPECIES_POOCHYENA}, + {4, 4, SPECIES_POOCHYENA}, + {4, 4, SPECIES_RALTS}, + {4, 4, SPECIES_POOCHYENA}, + {3, 3, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route102_LandMonsInfo = {20, Route102_LandMons}; + +const struct WildPokemon Route102_WaterMons [] = +{ + {20, 30, SPECIES_MARILL}, + {10, 20, SPECIES_MARILL}, + {30, 35, SPECIES_MARILL}, + {5, 10, SPECIES_MARILL}, + {20, 30, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route102_WaterMonsInfo = {4, Route102_WaterMons}; + +const struct WildPokemon Route102_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_CORPHISH}, + {25, 30, SPECIES_CORPHISH}, + {30, 35, SPECIES_CORPHISH}, + {20, 25, SPECIES_CORPHISH}, + {35, 40, SPECIES_CORPHISH}, + {40, 45, SPECIES_CORPHISH}, +}; +const struct WildPokemonInfo Route102_FishingMonsInfo = {30, Route102_FishingMons}; + +const struct WildPokemon Route103_LandMons [] = +{ + {2, 2, SPECIES_ZIGZAGOON}, + {3, 3, SPECIES_ZIGZAGOON}, + {3, 3, SPECIES_ZIGZAGOON}, + {4, 4, SPECIES_ZIGZAGOON}, + {2, 2, SPECIES_POOCHYENA}, + {3, 3, SPECIES_POOCHYENA}, + {3, 3, SPECIES_POOCHYENA}, + {4, 4, SPECIES_POOCHYENA}, + {3, 3, SPECIES_WINGULL}, + {3, 3, SPECIES_WINGULL}, + {2, 2, SPECIES_WINGULL}, + {4, 4, SPECIES_WINGULL}, +}; +const struct WildPokemonInfo Route103_LandMonsInfo = {20, Route103_LandMons}; + +const struct WildPokemon Route103_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route103_WaterMonsInfo = {4, Route103_WaterMons}; + +const struct WildPokemon Route103_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route103_FishingMonsInfo = {30, Route103_FishingMons}; + +const struct WildPokemon Route104_LandMons [] = +{ + {4, 4, SPECIES_ZIGZAGOON}, + {4, 4, SPECIES_WURMPLE}, + {5, 5, SPECIES_ZIGZAGOON}, + {5, 5, SPECIES_WURMPLE}, + {4, 4, SPECIES_ZIGZAGOON}, + {5, 5, SPECIES_ZIGZAGOON}, + {4, 4, SPECIES_TAILLOW}, + {5, 5, SPECIES_TAILLOW}, + {4, 4, SPECIES_WINGULL}, + {4, 4, SPECIES_WINGULL}, + {3, 3, SPECIES_WINGULL}, + {5, 5, SPECIES_WINGULL}, +}; +const struct WildPokemonInfo Route104_LandMonsInfo = {20, Route104_LandMons}; + +const struct WildPokemon Route104_WaterMons [] = +{ + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route104_WaterMonsInfo = {4, Route104_WaterMons}; + +const struct WildPokemon Route104_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_MAGIKARP}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_MAGIKARP}, + {25, 30, SPECIES_MAGIKARP}, + {30, 35, SPECIES_MAGIKARP}, + {20, 25, SPECIES_MAGIKARP}, + {35, 40, SPECIES_MAGIKARP}, + {40, 45, SPECIES_MAGIKARP}, +}; +const struct WildPokemonInfo Route104_FishingMonsInfo = {30, Route104_FishingMons}; + +const struct WildPokemon Route105_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route105_WaterMonsInfo = {4, Route105_WaterMons}; + +const struct WildPokemon Route105_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route105_FishingMonsInfo = {30, Route105_FishingMons}; + +const struct WildPokemon Route106_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route106_WaterMonsInfo = {4, Route106_WaterMons}; + +const struct WildPokemon Route106_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route106_FishingMonsInfo = {30, Route106_FishingMons}; + +const struct WildPokemon Route107_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route107_WaterMonsInfo = {4, Route107_WaterMons}; + +const struct WildPokemon Route107_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route107_FishingMonsInfo = {30, Route107_FishingMons}; + +const struct WildPokemon Route108_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route108_WaterMonsInfo = {4, Route108_WaterMons}; + +const struct WildPokemon Route108_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route108_FishingMonsInfo = {30, Route108_FishingMons}; + +const struct WildPokemon Route109_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route109_WaterMonsInfo = {4, Route109_WaterMons}; + +const struct WildPokemon Route109_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route109_FishingMonsInfo = {30, Route109_FishingMons}; + +const struct WildPokemon Route110_LandMons [] = +{ + {12, 12, SPECIES_ZIGZAGOON}, + {12, 12, SPECIES_ELECTRIKE}, + {12, 12, SPECIES_GULPIN}, + {13, 13, SPECIES_ELECTRIKE}, +#ifdef SAPPHIRE + {13, 13, SPECIES_PLUSLE}, +#else + {13, 13, SPECIES_MINUN}, +#endif + {13, 13, SPECIES_ODDISH}, +#ifdef SAPPHIRE + {13, 13, SPECIES_PLUSLE}, +#else + {13, 13, SPECIES_MINUN}, +#endif + {13, 13, SPECIES_GULPIN}, + {12, 12, SPECIES_WINGULL}, + {12, 12, SPECIES_WINGULL}, +#ifdef SAPPHIRE + {12, 12, SPECIES_MINUN}, + {13, 13, SPECIES_MINUN}, +#else + {12, 12, SPECIES_PLUSLE}, + {13, 13, SPECIES_PLUSLE}, +#endif +}; +const struct WildPokemonInfo Route110_LandMonsInfo = {20, Route110_LandMons}; + +const struct WildPokemon Route110_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route110_WaterMonsInfo = {4, Route110_WaterMons}; + +const struct WildPokemon Route110_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route110_FishingMonsInfo = {30, Route110_FishingMons}; + +const struct WildPokemon Route111_LandMons [] = +{ + {20, 20, SPECIES_SANDSHREW}, + {20, 20, SPECIES_TRAPINCH}, + {21, 21, SPECIES_SANDSHREW}, + {21, 21, SPECIES_TRAPINCH}, + {19, 19, SPECIES_CACNEA}, + {21, 21, SPECIES_CACNEA}, + {19, 19, SPECIES_SANDSHREW}, + {19, 19, SPECIES_TRAPINCH}, + {20, 20, SPECIES_BALTOY}, + {20, 20, SPECIES_BALTOY}, + {22, 22, SPECIES_BALTOY}, + {22, 22, SPECIES_BALTOY}, +}; +const struct WildPokemonInfo Route111_LandMonsInfo = {10, Route111_LandMons}; + +const struct WildPokemon Route111_WaterMons [] = +{ + {20, 30, SPECIES_MARILL}, + {10, 20, SPECIES_MARILL}, + {30, 35, SPECIES_MARILL}, + {5, 10, SPECIES_MARILL}, + {20, 30, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route111_WaterMonsInfo = {4, Route111_WaterMons}; + +const struct WildPokemon Route111_RockSmashMons [] = +{ + {10, 15, SPECIES_GEODUDE}, + {5, 10, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, +}; +const struct WildPokemonInfo Route111_RockSmashMonsInfo = {20, Route111_RockSmashMons}; + +const struct WildPokemon Route111_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_BARBOACH}, + {25, 30, SPECIES_BARBOACH}, + {30, 35, SPECIES_BARBOACH}, + {20, 25, SPECIES_BARBOACH}, + {35, 40, SPECIES_BARBOACH}, + {40, 45, SPECIES_BARBOACH}, +}; +const struct WildPokemonInfo Route111_FishingMonsInfo = {30, Route111_FishingMons}; + +const struct WildPokemon Route112_LandMons [] = +{ + {15, 15, SPECIES_NUMEL}, + {15, 15, SPECIES_NUMEL}, + {15, 15, SPECIES_MACHOP}, + {14, 14, SPECIES_NUMEL}, + {14, 14, SPECIES_NUMEL}, + {14, 14, SPECIES_MACHOP}, + {16, 16, SPECIES_NUMEL}, + {16, 16, SPECIES_MACHOP}, + {16, 16, SPECIES_NUMEL}, + {16, 16, SPECIES_NUMEL}, + {16, 16, SPECIES_NUMEL}, + {16, 16, SPECIES_NUMEL}, +}; +const struct WildPokemonInfo Route112_LandMonsInfo = {20, Route112_LandMons}; + +const struct WildPokemon Route113_LandMons [] = +{ + {15, 15, SPECIES_SPINDA}, + {15, 15, SPECIES_SPINDA}, + {15, 15, SPECIES_SANDSHREW}, + {14, 14, SPECIES_SPINDA}, + {14, 14, SPECIES_SPINDA}, + {14, 14, SPECIES_SANDSHREW}, + {16, 16, SPECIES_SPINDA}, + {16, 16, SPECIES_SANDSHREW}, + {16, 16, SPECIES_SPINDA}, + {16, 16, SPECIES_SKARMORY}, + {16, 16, SPECIES_SPINDA}, + {16, 16, SPECIES_SKARMORY}, +}; +const struct WildPokemonInfo Route113_LandMonsInfo = {20, Route113_LandMons}; + +const struct WildPokemon Route114_LandMons [] = +{ + {16, 16, SPECIES_SWABLU}, +#ifdef SAPPHIRE + {16, 16, SPECIES_LOTAD}, +#else + {16, 16, SPECIES_SEEDOT}, +#endif + {17, 17, SPECIES_SWABLU}, + {15, 15, SPECIES_SWABLU}, +#ifdef SAPPHIRE + {15, 15, SPECIES_LOTAD}, + {16, 16, SPECIES_SEVIPER}, + {16, 16, SPECIES_LOMBRE}, + {18, 18, SPECIES_LOMBRE}, + {17, 17, SPECIES_SEVIPER}, + {15, 15, SPECIES_SEVIPER}, + {17, 17, SPECIES_SEVIPER}, +#else + {15, 15, SPECIES_SEEDOT}, + {16, 16, SPECIES_ZANGOOSE}, + {16, 16, SPECIES_NUZLEAF}, + {18, 18, SPECIES_NUZLEAF}, + {17, 17, SPECIES_ZANGOOSE}, + {15, 15, SPECIES_ZANGOOSE}, + {17, 17, SPECIES_ZANGOOSE}, +#endif + {15, 15, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route114_LandMonsInfo = {20, Route114_LandMons}; + +const struct WildPokemon Route114_WaterMons [] = +{ + {20, 30, SPECIES_MARILL}, + {10, 20, SPECIES_MARILL}, + {30, 35, SPECIES_MARILL}, + {5, 10, SPECIES_MARILL}, + {20, 30, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route114_WaterMonsInfo = {4, Route114_WaterMons}; + +const struct WildPokemon Route114_RockSmashMons [] = +{ + {10, 15, SPECIES_GEODUDE}, + {5, 10, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, +}; +const struct WildPokemonInfo Route114_RockSmashMonsInfo = {20, Route114_RockSmashMons}; + +const struct WildPokemon Route114_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_BARBOACH}, + {25, 30, SPECIES_BARBOACH}, + {30, 35, SPECIES_BARBOACH}, + {20, 25, SPECIES_BARBOACH}, + {35, 40, SPECIES_BARBOACH}, + {40, 45, SPECIES_BARBOACH}, +}; +const struct WildPokemonInfo Route114_FishingMonsInfo = {30, Route114_FishingMons}; + +const struct WildPokemon Route115_LandMons [] = +{ + {23, 23, SPECIES_SWABLU}, + {23, 23, SPECIES_TAILLOW}, + {25, 25, SPECIES_SWABLU}, + {24, 24, SPECIES_TAILLOW}, + {25, 25, SPECIES_TAILLOW}, + {25, 25, SPECIES_SWELLOW}, + {24, 24, SPECIES_JIGGLYPUFF}, + {25, 25, SPECIES_JIGGLYPUFF}, + {24, 24, SPECIES_WINGULL}, + {24, 24, SPECIES_WINGULL}, + {26, 26, SPECIES_WINGULL}, + {25, 25, SPECIES_WINGULL}, +}; +const struct WildPokemonInfo Route115_LandMonsInfo = {20, Route115_LandMons}; + +const struct WildPokemon Route115_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route115_WaterMonsInfo = {4, Route115_WaterMons}; + +const struct WildPokemon Route115_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route115_FishingMonsInfo = {30, Route115_FishingMons}; + +const struct WildPokemon Route116_LandMons [] = +{ + {6, 6, SPECIES_ZIGZAGOON}, + {6, 6, SPECIES_WHISMUR}, + {6, 6, SPECIES_NINCADA}, + {7, 7, SPECIES_WHISMUR}, + {7, 7, SPECIES_NINCADA}, + {6, 6, SPECIES_TAILLOW}, + {7, 7, SPECIES_TAILLOW}, + {8, 8, SPECIES_TAILLOW}, + {7, 7, SPECIES_ZIGZAGOON}, + {8, 8, SPECIES_ZIGZAGOON}, + {7, 7, SPECIES_SKITTY}, + {8, 8, SPECIES_SKITTY}, +}; +const struct WildPokemonInfo Route116_LandMonsInfo = {20, Route116_LandMons}; + +const struct WildPokemon Route117_LandMons [] = +{ + {13, 13, SPECIES_ZIGZAGOON}, + {13, 13, SPECIES_ROSELIA}, + {14, 14, SPECIES_ZIGZAGOON}, + {14, 14, SPECIES_ROSELIA}, + {13, 13, SPECIES_MARILL}, + {13, 13, SPECIES_ODDISH}, +#ifdef SAPPHIRE + {13, 13, SPECIES_VOLBEAT}, + {13, 13, SPECIES_VOLBEAT}, + {14, 14, SPECIES_VOLBEAT}, + {14, 14, SPECIES_VOLBEAT}, + {13, 13, SPECIES_ILLUMISE}, +#else + {13, 13, SPECIES_ILLUMISE}, + {13, 13, SPECIES_ILLUMISE}, + {14, 14, SPECIES_ILLUMISE}, + {14, 14, SPECIES_ILLUMISE}, + {13, 13, SPECIES_VOLBEAT}, +#endif + {13, 13, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route117_LandMonsInfo = {20, Route117_LandMons}; + +const struct WildPokemon Route117_WaterMons [] = +{ + {20, 30, SPECIES_MARILL}, + {10, 20, SPECIES_MARILL}, + {30, 35, SPECIES_MARILL}, + {5, 10, SPECIES_MARILL}, + {20, 30, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route117_WaterMonsInfo = {4, Route117_WaterMons}; + +const struct WildPokemon Route117_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_CORPHISH}, + {25, 30, SPECIES_CORPHISH}, + {30, 35, SPECIES_CORPHISH}, + {20, 25, SPECIES_CORPHISH}, + {35, 40, SPECIES_CORPHISH}, + {40, 45, SPECIES_CORPHISH}, +}; +const struct WildPokemonInfo Route117_FishingMonsInfo = {30, Route117_FishingMons}; + +const struct WildPokemon Route118_LandMons [] = +{ + {24, 24, SPECIES_ZIGZAGOON}, + {24, 24, SPECIES_ELECTRIKE}, + {26, 26, SPECIES_ZIGZAGOON}, + {26, 26, SPECIES_ELECTRIKE}, + {26, 26, SPECIES_LINOONE}, + {26, 26, SPECIES_MANECTRIC}, + {25, 25, SPECIES_WINGULL}, + {25, 25, SPECIES_WINGULL}, + {26, 26, SPECIES_WINGULL}, + {26, 26, SPECIES_WINGULL}, + {27, 27, SPECIES_WINGULL}, + {25, 25, SPECIES_KECLEON}, +}; +const struct WildPokemonInfo Route118_LandMonsInfo = {20, Route118_LandMons}; + +const struct WildPokemon Route118_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route118_WaterMonsInfo = {4, Route118_WaterMons}; + +const struct WildPokemon Route118_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_CARVANHA}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_CARVANHA}, + {20, 25, SPECIES_CARVANHA}, + {35, 40, SPECIES_CARVANHA}, + {40, 45, SPECIES_CARVANHA}, +}; +const struct WildPokemonInfo Route118_FishingMonsInfo = {30, Route118_FishingMons}; + +const struct WildPokemon Route119_LandMons [] = +{ + {25, 25, SPECIES_ZIGZAGOON}, + {25, 25, SPECIES_LINOONE}, + {27, 27, SPECIES_ZIGZAGOON}, + {25, 25, SPECIES_ODDISH}, + {27, 27, SPECIES_LINOONE}, + {26, 26, SPECIES_ODDISH}, + {27, 27, SPECIES_ODDISH}, + {24, 24, SPECIES_ODDISH}, + {25, 25, SPECIES_TROPIUS}, + {26, 26, SPECIES_TROPIUS}, + {27, 27, SPECIES_TROPIUS}, + {25, 25, SPECIES_KECLEON}, +}; +const struct WildPokemonInfo Route119_LandMonsInfo = {15, Route119_LandMons}; + +const struct WildPokemon Route119_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route119_WaterMonsInfo = {4, Route119_WaterMons}; + +const struct WildPokemon Route119_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_CARVANHA}, + {25, 30, SPECIES_CARVANHA}, + {30, 35, SPECIES_CARVANHA}, + {20, 25, SPECIES_CARVANHA}, + {35, 40, SPECIES_CARVANHA}, + {40, 45, SPECIES_CARVANHA}, +}; +const struct WildPokemonInfo Route119_FishingMonsInfo = {30, Route119_FishingMons}; + +const struct WildPokemon Route120_LandMons [] = +{ + {25, 25, SPECIES_ZIGZAGOON}, + {25, 25, SPECIES_LINOONE}, + {27, 27, SPECIES_LINOONE}, + {25, 25, SPECIES_ODDISH}, + {25, 25, SPECIES_MARILL}, + {26, 26, SPECIES_ODDISH}, + {27, 27, SPECIES_ODDISH}, + {27, 27, SPECIES_MARILL}, + {25, 25, SPECIES_ABSOL}, + {27, 27, SPECIES_ABSOL}, + {25, 25, SPECIES_KECLEON}, + {25, 25, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route120_LandMonsInfo = {20, Route120_LandMons}; + +const struct WildPokemon Route120_WaterMons [] = +{ + {20, 30, SPECIES_MARILL}, + {10, 20, SPECIES_MARILL}, + {30, 35, SPECIES_MARILL}, + {5, 10, SPECIES_MARILL}, + {20, 30, SPECIES_SURSKIT}, +}; +const struct WildPokemonInfo Route120_WaterMonsInfo = {4, Route120_WaterMons}; + +const struct WildPokemon Route120_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_GOLDEEN}, + {10, 30, SPECIES_BARBOACH}, + {25, 30, SPECIES_BARBOACH}, + {30, 35, SPECIES_BARBOACH}, + {20, 25, SPECIES_BARBOACH}, + {35, 40, SPECIES_BARBOACH}, + {40, 45, SPECIES_BARBOACH}, +}; +const struct WildPokemonInfo Route120_FishingMonsInfo = {30, Route120_FishingMons}; + +const struct WildPokemon Route121_LandMons [] = +{ + {26, 26, SPECIES_ZIGZAGOON}, +#ifdef SAPPHIRE + {26, 26, SPECIES_SHUPPET}, +#else + {26, 26, SPECIES_DUSKULL}, +#endif + {26, 26, SPECIES_LINOONE}, +#ifdef SAPPHIRE + {28, 28, SPECIES_SHUPPET}, +#else + {28, 28, SPECIES_DUSKULL}, +#endif + {28, 28, SPECIES_LINOONE}, + {26, 26, SPECIES_ODDISH}, + {28, 28, SPECIES_ODDISH}, + {28, 28, SPECIES_GLOOM}, + {26, 26, SPECIES_WINGULL}, + {27, 27, SPECIES_WINGULL}, + {28, 28, SPECIES_WINGULL}, + {25, 25, SPECIES_KECLEON}, +}; +const struct WildPokemonInfo Route121_LandMonsInfo = {20, Route121_LandMons}; + +const struct WildPokemon Route121_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route121_WaterMonsInfo = {4, Route121_WaterMons}; + +const struct WildPokemon Route121_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route121_FishingMonsInfo = {30, Route121_FishingMons}; + +const struct WildPokemon Route122_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route122_WaterMonsInfo = {4, Route122_WaterMons}; + +const struct WildPokemon Route122_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route122_FishingMonsInfo = {30, Route122_FishingMons}; + +const struct WildPokemon Route123_LandMons [] = +{ + {26, 26, SPECIES_ZIGZAGOON}, +#ifdef SAPPHIRE + {26, 26, SPECIES_SHUPPET}, +#else + {26, 26, SPECIES_DUSKULL}, +#endif + {26, 26, SPECIES_LINOONE}, +#ifdef SAPPHIRE + {28, 28, SPECIES_SHUPPET}, +#else + {28, 28, SPECIES_DUSKULL}, +#endif + {28, 28, SPECIES_LINOONE}, + {26, 26, SPECIES_ODDISH}, + {28, 28, SPECIES_ODDISH}, + {28, 28, SPECIES_GLOOM}, + {26, 26, SPECIES_WINGULL}, + {27, 27, SPECIES_WINGULL}, + {28, 28, SPECIES_WINGULL}, + {25, 25, SPECIES_KECLEON}, +}; +const struct WildPokemonInfo Route123_LandMonsInfo = {20, Route123_LandMons}; + +const struct WildPokemon Route123_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route123_WaterMonsInfo = {4, Route123_WaterMons}; + +const struct WildPokemon Route123_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route123_FishingMonsInfo = {30, Route123_FishingMons}; + +const struct WildPokemon Route124_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route124_WaterMonsInfo = {4, Route124_WaterMons}; + +const struct WildPokemon Route124_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route124_FishingMonsInfo = {30, Route124_FishingMons}; + +const struct WildPokemon Route125_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route125_WaterMonsInfo = {4, Route125_WaterMons}; + +const struct WildPokemon Route125_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route125_FishingMonsInfo = {30, Route125_FishingMons}; + +const struct WildPokemon Route126_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route126_WaterMonsInfo = {4, Route126_WaterMons}; + +const struct WildPokemon Route126_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route126_FishingMonsInfo = {30, Route126_FishingMons}; + +const struct WildPokemon Route127_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route127_WaterMonsInfo = {4, Route127_WaterMons}; + +const struct WildPokemon Route127_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route127_FishingMonsInfo = {30, Route127_FishingMons}; + +const struct WildPokemon Route128_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route128_WaterMonsInfo = {4, Route128_WaterMons}; + +const struct WildPokemon Route128_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_LUVDISC}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_LUVDISC}, + {30, 35, SPECIES_WAILMER}, + {30, 35, SPECIES_CORSOLA}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route128_FishingMonsInfo = {30, Route128_FishingMons}; + +const struct WildPokemon Route129_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, +#ifdef SAPPHIRE + {25, 30, SPECIES_WAILORD}, +#else + {35, 40, SPECIES_WAILORD}, +#endif +}; +const struct WildPokemonInfo Route129_WaterMonsInfo = {4, Route129_WaterMons}; + +const struct WildPokemon Route129_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route129_FishingMonsInfo = {30, Route129_FishingMons}; + +const struct WildPokemon Route130_LandMons [] = +{ + {30, 30, SPECIES_WYNAUT}, + {35, 35, SPECIES_WYNAUT}, + {25, 25, SPECIES_WYNAUT}, + {40, 40, SPECIES_WYNAUT}, + {20, 20, SPECIES_WYNAUT}, + {45, 45, SPECIES_WYNAUT}, + {15, 15, SPECIES_WYNAUT}, + {50, 50, SPECIES_WYNAUT}, + {10, 10, SPECIES_WYNAUT}, + {5, 5, SPECIES_WYNAUT}, + {10, 10, SPECIES_WYNAUT}, + {5, 5, SPECIES_WYNAUT}, +}; +const struct WildPokemonInfo Route130_LandMonsInfo = {20, Route130_LandMons}; + +const struct WildPokemon Route130_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route130_WaterMonsInfo = {4, Route130_WaterMons}; + +const struct WildPokemon Route130_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route130_FishingMonsInfo = {30, Route130_FishingMons}; + +const struct WildPokemon Route131_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route131_WaterMonsInfo = {4, Route131_WaterMons}; + +const struct WildPokemon Route131_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route131_FishingMonsInfo = {30, Route131_FishingMons}; + +const struct WildPokemon Route132_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route132_WaterMonsInfo = {4, Route132_WaterMons}; + +const struct WildPokemon Route132_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_HORSEA}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route132_FishingMonsInfo = {30, Route132_FishingMons}; + +const struct WildPokemon Route133_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route133_WaterMonsInfo = {4, Route133_WaterMons}; + +const struct WildPokemon Route133_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_HORSEA}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route133_FishingMonsInfo = {30, Route133_FishingMons}; + +const struct WildPokemon Route134_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo Route134_WaterMonsInfo = {4, Route134_WaterMons}; + +const struct WildPokemon Route134_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_HORSEA}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo Route134_FishingMonsInfo = {30, Route134_FishingMons}; + +const struct WildPokemon SafariZone_Northwest_LandMons [] = +{ + {27, 27, SPECIES_RHYHORN}, + {27, 27, SPECIES_ODDISH}, + {29, 29, SPECIES_RHYHORN}, + {29, 29, SPECIES_ODDISH}, + {27, 27, SPECIES_DODUO}, + {29, 29, SPECIES_GLOOM}, + {31, 31, SPECIES_GLOOM}, + {29, 29, SPECIES_DODUO}, + {29, 29, SPECIES_DODRIO}, + {27, 27, SPECIES_PINSIR}, + {31, 31, SPECIES_DODRIO}, + {29, 29, SPECIES_PINSIR}, +}; +const struct WildPokemonInfo SafariZone_Northwest_LandMonsInfo = {25, SafariZone_Northwest_LandMons}; + +const struct WildPokemon SafariZone_Northwest_WaterMons [] = +{ + {20, 30, SPECIES_PSYDUCK}, + {20, 30, SPECIES_PSYDUCK}, + {30, 35, SPECIES_PSYDUCK}, + {30, 35, SPECIES_GOLDUCK}, + {25, 40, SPECIES_GOLDUCK}, +}; +const struct WildPokemonInfo SafariZone_Northwest_WaterMonsInfo = {9, SafariZone_Northwest_WaterMons}; + +const struct WildPokemon SafariZone_Northwest_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 25, SPECIES_GOLDEEN}, + {10, 30, SPECIES_GOLDEEN}, + {25, 30, SPECIES_GOLDEEN}, + {30, 35, SPECIES_GOLDEEN}, + {30, 35, SPECIES_SEAKING}, + {35, 40, SPECIES_SEAKING}, + {25, 30, SPECIES_SEAKING}, +}; +const struct WildPokemonInfo SafariZone_Northwest_FishingMonsInfo = {35, SafariZone_Northwest_FishingMons}; + +const struct WildPokemon SafariZone_Northeast_LandMons [] = +{ + {27, 27, SPECIES_PHANPY}, + {27, 27, SPECIES_ODDISH}, + {29, 29, SPECIES_PHANPY}, + {29, 29, SPECIES_ODDISH}, + {27, 27, SPECIES_NATU}, + {29, 29, SPECIES_GLOOM}, + {31, 31, SPECIES_GLOOM}, + {29, 29, SPECIES_NATU}, + {29, 29, SPECIES_XATU}, + {27, 27, SPECIES_HERACROSS}, + {31, 31, SPECIES_XATU}, + {29, 29, SPECIES_HERACROSS}, +}; +const struct WildPokemonInfo SafariZone_Northeast_LandMonsInfo = {25, SafariZone_Northeast_LandMons}; + +const struct WildPokemon SafariZone_Northeast_RockSmashMons [] = +{ + {10, 15, SPECIES_GEODUDE}, + {5, 10, SPECIES_GEODUDE}, + {15, 20, SPECIES_GEODUDE}, + {20, 25, SPECIES_GEODUDE}, + {25, 30, SPECIES_GEODUDE}, +}; +const struct WildPokemonInfo SafariZone_Northeast_RockSmashMonsInfo = {25, SafariZone_Northeast_RockSmashMons}; + +const struct WildPokemon SafariZone_Southwest_LandMons [] = +{ + {25, 25, SPECIES_ODDISH}, + {27, 27, SPECIES_ODDISH}, + {25, 25, SPECIES_GIRAFARIG}, + {27, 27, SPECIES_GIRAFARIG}, + {25, 25, SPECIES_NATU}, +#ifdef SAPPHIRE + {27, 27, SPECIES_DODUO}, +#else + {25, 25, SPECIES_DODUO}, +#endif + {25, 25, SPECIES_GLOOM}, + {27, 27, SPECIES_WOBBUFFET}, + {25, 25, SPECIES_PIKACHU}, + {27, 27, SPECIES_WOBBUFFET}, + {27, 27, SPECIES_PIKACHU}, + {29, 29, SPECIES_WOBBUFFET}, +}; +const struct WildPokemonInfo SafariZone_Southwest_LandMonsInfo = {25, SafariZone_Southwest_LandMons}; + +const struct WildPokemon SafariZone_Southwest_WaterMons [] = +{ + {20, 30, SPECIES_PSYDUCK}, + {20, 30, SPECIES_PSYDUCK}, + {30, 35, SPECIES_PSYDUCK}, + {30, 35, SPECIES_PSYDUCK}, + {30, 35, SPECIES_PSYDUCK}, +}; +const struct WildPokemonInfo SafariZone_Southwest_WaterMonsInfo = {9, SafariZone_Southwest_WaterMons}; + +const struct WildPokemon SafariZone_Southwest_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_GOLDEEN}, + {10, 30, SPECIES_MAGIKARP}, + {10, 25, SPECIES_GOLDEEN}, + {10, 30, SPECIES_GOLDEEN}, + {25, 30, SPECIES_GOLDEEN}, + {30, 35, SPECIES_GOLDEEN}, + {30, 35, SPECIES_SEAKING}, + {35, 40, SPECIES_SEAKING}, + {25, 30, SPECIES_SEAKING}, +}; +const struct WildPokemonInfo SafariZone_Southwest_FishingMonsInfo = {35, SafariZone_Southwest_FishingMons}; + +const struct WildPokemon SafariZone_Southeast_LandMons [] = +{ + {25, 25, SPECIES_ODDISH}, + {27, 27, SPECIES_ODDISH}, + {25, 25, SPECIES_GIRAFARIG}, + {27, 27, SPECIES_GIRAFARIG}, + {25, 25, SPECIES_NATU}, + {25, 25, SPECIES_DODUO}, + {25, 25, SPECIES_GLOOM}, + {27, 27, SPECIES_WOBBUFFET}, + {25, 25, SPECIES_PIKACHU}, + {27, 27, SPECIES_WOBBUFFET}, + {27, 27, SPECIES_PIKACHU}, + {29, 29, SPECIES_WOBBUFFET}, +}; +const struct WildPokemonInfo SafariZone_Southeast_LandMonsInfo = {25, SafariZone_Southeast_LandMons}; + +const struct WildPokemon DewfordTown_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo DewfordTown_WaterMonsInfo = {4, DewfordTown_WaterMons}; + +const struct WildPokemon DewfordTown_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_WAILMER}, + {20, 25, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo DewfordTown_FishingMonsInfo = {10, DewfordTown_FishingMons}; + +const struct WildPokemon PacifidlogTown_WaterMons [] = +{ + {5, 35, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WINGULL}, + {15, 25, SPECIES_WINGULL}, + {25, 30, SPECIES_PELIPPER}, + {25, 30, SPECIES_PELIPPER}, +}; +const struct WildPokemonInfo PacifidlogTown_WaterMonsInfo = {4, PacifidlogTown_WaterMons}; + +const struct WildPokemon PacifidlogTown_FishingMons [] = +{ + {5, 10, SPECIES_MAGIKARP}, + {5, 10, SPECIES_TENTACOOL}, + {10, 30, SPECIES_MAGIKARP}, + {10, 30, SPECIES_TENTACOOL}, + {10, 30, SPECIES_WAILMER}, + {30, 35, SPECIES_SHARPEDO}, + {30, 35, SPECIES_WAILMER}, + {25, 30, SPECIES_WAILMER}, + {35, 40, SPECIES_WAILMER}, + {40, 45, SPECIES_WAILMER}, +}; +const struct WildPokemonInfo PacifidlogTown_FishingMonsInfo = {10, PacifidlogTown_FishingMons}; + +const struct WildPokemon Underwater1_WaterMons [] = +{ + {20, 30, SPECIES_CLAMPERL}, + {20, 30, SPECIES_CHINCHOU}, + {30, 35, SPECIES_CLAMPERL}, + {30, 35, SPECIES_RELICANTH}, + {30, 35, SPECIES_RELICANTH}, +}; +const struct WildPokemonInfo Underwater1_WaterMonsInfo = {4, Underwater1_WaterMons}; + +const struct WildPokemon Underwater2_WaterMons [] = +{ + {20, 30, SPECIES_CLAMPERL}, + {20, 30, SPECIES_CHINCHOU}, + {30, 35, SPECIES_CLAMPERL}, + {30, 35, SPECIES_RELICANTH}, + {30, 35, SPECIES_RELICANTH}, +}; +const struct WildPokemonInfo Underwater2_WaterMonsInfo = {4, Underwater2_WaterMons}; + + +extern u16 gRoute119WaterTileData[]; +extern u16 gScriptResult; +extern struct WildPokemon gWildFeebasRoute119Data; +extern u8 S_RepelWoreOff[]; + +EWRAM_DATA static u8 sWildEncountersDisabled = 0; +EWRAM_DATA static u32 sFeebasRngValue = 0; + +#define NUM_FEEBAS_SPOTS 6 + +static u16 FeebasRandom(void); +static void FeebasSeedRng(u16 seed); + +static bool8 IsWildLevelAllowedByRepel(u8 level); +static void ApplyFluteEncounterRateMod(u32 *encRate); +static void ApplyCleanseTagEncounterRateMod(u32 *encRate); + +void DisableWildEncounters(bool8 disabled) +{ + sWildEncountersDisabled = disabled; +} + +static u16 GetRoute119WaterTileNum(s16 x, s16 y, u8 section) +{ + u16 xCur; + u16 yCur; + u16 yMin = gRoute119WaterTileData[section * 3 + 0]; + u16 yMax = gRoute119WaterTileData[section * 3 + 1]; + u16 tileNum = gRoute119WaterTileData[section * 3 + 2]; + + for (yCur = yMin; yCur <= yMax; yCur++) + { + for (xCur = 0; xCur < gMapHeader.mapData->width; xCur++) + { + if (sub_805759C(MapGridGetMetatileBehaviorAt(xCur + 7, yCur + 7)) == TRUE) + { + tileNum++; + if (x == xCur && y == yCur) + return tileNum; + } + } + } + return tileNum + 1; +} + +static bool8 CheckFeebas(void) +{ + u8 i; + u16 feebasSpots[6]; + s16 x; + s16 y; + u8 route119section = 0; + u16 waterTileNum; + + if (gSaveBlock1.location.mapGroup == MAP_GROUP_ROUTE119 + && gSaveBlock1.location.mapNum == MAP_ID_ROUTE119) + { + GetXYCoordsOneStepInFrontOfPlayer(&x, &y); + x -= 7; + y -= 7; + +#ifdef NONMATCHING + if (y >= gRoute119WaterTileData[3 * 1 + 0] && y <= gRoute119WaterTileData[3 * 1 + 1]) + route119section = 1; + if (y >= gRoute119WaterTileData[3 * 2 + 0] && y <= gRoute119WaterTileData[3 * 2 + 1]) + route119section = 2; +#else + { + register u16 *arr asm("r0"); + if (y >= (arr = gRoute119WaterTileData)[3 * 1 + 0] && y <= arr[3 * 1 + 1]) + route119section = 1; + if (y >= arr[3 * 2 + 0] && y <= arr[3 * 2 + 1]) + route119section = 2; + } +#endif + + if (Random() % 100 > 49) //50% chance of encountering Feebas + return FALSE; + + FeebasSeedRng(gSaveBlock1.easyChatPairs[0].unk2); + for (i = 0; i != NUM_FEEBAS_SPOTS;) + { + feebasSpots[i] = FeebasRandom() % 447; + if (feebasSpots[i] == 0) + feebasSpots[i] = 447; + if (feebasSpots[i] < 1 || feebasSpots[i] >= 4) + i++; + } + waterTileNum = GetRoute119WaterTileNum(x, y, route119section); + for (i = 0; i < NUM_FEEBAS_SPOTS; i++) + { + if (waterTileNum == feebasSpots[i]) + return TRUE; + } + } + return FALSE; +} + +static u16 FeebasRandom(void) +{ + sFeebasRngValue = 12345 + 0x41C64E6D * sFeebasRngValue; + return sFeebasRngValue >> 16; +} + +static void FeebasSeedRng(u16 seed) +{ + sFeebasRngValue = seed; +} + +static u8 ChooseWildMonIndex_Land(void) +{ + u8 rand = Random() % 100; + + if (rand < 20) //20% chance + return 0; + if (rand >= 20 && rand < 40) //20% chance + return 1; + if (rand >= 40 && rand < 50) //10% chance + return 2; + if (rand >= 50 && rand < 60) //10% chance + return 3; + if (rand >= 60 && rand < 70) //10% chance + return 4; + if (rand >= 70 && rand < 80) //10% chance + return 5; + if (rand >= 80 && rand < 85) //5% chance + return 6; + if (rand >= 85 && rand < 90) //5% chance + return 7; + if (rand >= 90 && rand < 94) //4% chance + return 8; + if (rand >= 94 && rand < 98) //4% chance + return 9; + if (rand == 98) //1% chance + return 10; + else //1% chance + return 11; +} + +static u8 ChooseWildMonIndex_Water(void) +{ + u8 rand = Random() % 100; + + if (rand < 60) //60% chance + return 0; + if (rand >= 60 && rand < 90) //30% chance + return 1; + if (rand >= 90 && rand < 95) //5% chance + return 2; + if (rand >= 95 && rand < 99) //4% chance + return 3; + else //1% chance + return 4; +} + +enum +{ + OLD_ROD, + GOOD_ROD, + SUPER_ROD +}; + +static u8 ChooseWildMonIndex_Fishing(u8 rod) +{ + u8 wildMonIndex = 0; + u8 rand = Random() % 100; + + switch (rod) + { + case OLD_ROD: + if (rand < 70) //70% chance + wildMonIndex = 0; + else //30% chance + wildMonIndex = 1; + break; + case GOOD_ROD: + if (rand < 60) //60% chance + wildMonIndex = 2; + if (rand >= 60 && rand < 80) //20% chance + wildMonIndex = 3; + if (rand >= 80 && rand < 100) //20% chance + wildMonIndex = 4; + break; + case SUPER_ROD: + if (rand < 40) //40% chance + wildMonIndex = 5; + if (rand >= 40 && rand < 80) //40% chance + wildMonIndex = 6; + if (rand >= 80 && rand < 95) //15% chance + wildMonIndex = 7; + if (rand >= 95 && rand < 99) //4% chance + wildMonIndex = 8; + if (rand == 99) //1% chance + wildMonIndex = 9; + break; + } + return wildMonIndex; +} + +static u8 ChooseWildMonLevel(const struct WildPokemon *wildPokemon) +{ + u8 min; + u8 max; + u8 range; + u8 rand; + + //Make sure minimum level is less than maximum level + if (wildPokemon->maxLevel >= wildPokemon->minLevel) + { + min = wildPokemon->minLevel; + max = wildPokemon->maxLevel; + } + else + { + min = wildPokemon->maxLevel; + max = wildPokemon->minLevel; + } + range = max - min + 1; + rand = Random() % range; + return min + rand; +} + +static u16 GetCurrentMapWildMonHeader(void) +{ + u16 i; + + for (i = 0; gWildMonHeaders[i].mapGroup != 0xFF; i++) + { + if (gWildMonHeaders[i].mapGroup == gSaveBlock1.location.mapGroup && + gWildMonHeaders[i].mapNum == gSaveBlock1.location.mapNum) + return i; + } + return -1; +} + +static u8 PickWildMonNature(void) +{ + u8 i; + u8 j; + struct Pokeblock *safariPokeblock; + u8 natures[25]; + + if (GetSafariZoneFlag() == TRUE && Random() % 100 < 80) + { + safariPokeblock = SafariZoneGetActivePokeblock(); + if (safariPokeblock != NULL) + { + for (i = 0; i < 25; i++) + natures[i] = i; + for (i = 0; i < 24; i++) + { + for (j = i + 1; j < 25; j++) + { + if (Random() & 1) + { + u8 temp = natures[i]; + + natures[i] = natures[j]; + natures[j] = temp; + } + } + } + for (i = 0; i < 25; i++) + { + if (PokeblockGetGain(natures[i], safariPokeblock) > 0) + return natures[i]; + } + } + } + return Random() % 25; +} + +static void CreateWildMon(u16 species, u8 b) +{ + ZeroEnemyPartyMons(); + CreateMonWithNature(&gEnemyParty[0], species, b, 0x20, PickWildMonNature()); +} + +static bool8 GenerateWildMon(struct WildPokemonInfo *wildMonInfo, u8 area, bool8 checkRepel) +{ + u8 wildMonIndex = 0; + u8 level; + + switch (area) + { + case 0: + wildMonIndex = ChooseWildMonIndex_Land(); + break; + case 1: + wildMonIndex = ChooseWildMonIndex_Water(); + break; + case 2: + wildMonIndex = ChooseWildMonIndex_Water(); + break; + } + level = ChooseWildMonLevel(&wildMonInfo->wildPokemon[wildMonIndex]); + if (checkRepel == TRUE && IsWildLevelAllowedByRepel(level) == FALSE) + return FALSE; + else + { + CreateWildMon(wildMonInfo->wildPokemon[wildMonIndex].species, level); + return TRUE; + } +} + +static u16 GenerateFishingWildMon(struct WildPokemonInfo *wildMonInfo, u8 rod) +{ + u8 wildMonIndex = ChooseWildMonIndex_Fishing(rod); + u8 level = ChooseWildMonLevel(&wildMonInfo->wildPokemon[wildMonIndex]); + + CreateWildMon(wildMonInfo->wildPokemon[wildMonIndex].species, level); + return wildMonInfo->wildPokemon[wildMonIndex].species; +} + +static bool8 SetUpMassOutbreakEncounter(bool8 checkRepel) +{ + u16 i; + + if (checkRepel == TRUE && IsWildLevelAllowedByRepel(gSaveBlock1.outbreakPokemonLevel) == FALSE) + return FALSE; + else + { + CreateWildMon(gSaveBlock1.outbreakPokemonSpecies, gSaveBlock1.outbreakPokemonLevel); + for (i = 0; i < 4; i++) + SetMonMoveSlot(&gEnemyParty[0], gSaveBlock1.outbreakPokemonMoves[i], i); + return TRUE; + } +} + +static bool8 DoMassOutbreakEncounterTest(void) +{ + if (gSaveBlock1.outbreakPokemonSpecies != 0 + && gSaveBlock1.location.mapNum == gSaveBlock1.outbreakLocationMapNum + && gSaveBlock1.location.mapGroup == gSaveBlock1.outbreakLocationMapGroup) + { + if (Random() % 100 < gSaveBlock1.outbreakPokemonProbability) + return TRUE; + } + return FALSE; +} + +static bool8 DoWildEncounterRateDiceRoll(u16 encounterRate) +{ + if (Random() % 2880 < encounterRate) + return TRUE; + else + return FALSE; +} + +static bool8 DoWildEncounterTest(u32 encounterRate, bool8 ignoreAbility) +{ + encounterRate *= 16; + if (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) + encounterRate = encounterRate * 80 / 100; + ApplyFluteEncounterRateMod(&encounterRate); + ApplyCleanseTagEncounterRateMod(&encounterRate); + if (!ignoreAbility) + { + // UB: Too few arguments for function 'GetMonData' + if (!GetMonData(&gPlayerParty[0], MON_DATA_SANITY_BIT3)) + { + u32 ability = GetMonAbility(&gPlayerParty[0]); + if (ability == ABILITY_STENCH) + encounterRate /= 2; + if (ability == ABILITY_ILLUMINATE) + encounterRate *= 2; + } + } + if (encounterRate > 2880) + encounterRate = 2880; + return DoWildEncounterRateDiceRoll(encounterRate); +} + +static bool8 DoGlobalWildEncounterDiceRoll(void) +{ + if (Random() % 100 >= 60) + return FALSE; + else + return TRUE; +} + +bool8 StandardWildEncounter(u16 a, u16 b) +{ + u16 headerNum; + struct Roamer *roamer; + + if (sWildEncountersDisabled == TRUE) + return 0; + else + { + headerNum = GetCurrentMapWildMonHeader(); + if (headerNum != 0xFFFF) + { + if (MetatileBehavior_IsLandWildEncounter(a) == TRUE) + { + if (gWildMonHeaders[headerNum].landMonsInfo) + { + if (b != a && !DoGlobalWildEncounterDiceRoll()) + return 0; + + if (DoWildEncounterTest(gWildMonHeaders[headerNum].landMonsInfo->encounterRate, 0) == TRUE) + { + if (TryStartRoamerEncounter() == TRUE) + { + roamer = &gSaveBlock1.roamer; + if (IsWildLevelAllowedByRepel(roamer->level)) + { + BattleSetup_StartRoamerBattle(); + return 1; + } + } + else + { + if (DoMassOutbreakEncounterTest() == TRUE && SetUpMassOutbreakEncounter(1) == TRUE) + { + BattleSetup_StartWildBattle(); + return 1; + } + if (GenerateWildMon(gWildMonHeaders[headerNum].landMonsInfo, 0, TRUE) == TRUE) + { + goto label; + } + } + } + } + } + else if (MetatileBehavior_IsWaterWildEncounter(a) == TRUE + || (TestPlayerAvatarFlags(PLAYER_AVATAR_FLAG_SURFING) && MetatileBehavior_IsBridge(a) == TRUE)) + { + if (gWildMonHeaders[headerNum].waterMonsInfo) + { + if (b != a && !DoGlobalWildEncounterDiceRoll()) + return 0; + + if (DoWildEncounterTest(gWildMonHeaders[headerNum].waterMonsInfo->encounterRate, 0) == TRUE) + { + if (TryStartRoamerEncounter() == TRUE) + { + roamer = &gSaveBlock1.roamer; + if (IsWildLevelAllowedByRepel(roamer->level)) + { + BattleSetup_StartRoamerBattle(); + return 1; + } + } + else + { + //_08085268 + if (GenerateWildMon(gWildMonHeaders[headerNum].waterMonsInfo, 1, TRUE) == TRUE) + { + label: + //_0808527A + BattleSetup_StartWildBattle(); + return 1; + } + } + } + } + } + } + } + return 0; +} + +void ScrSpecial_RockSmashWildEncounter(void) +{ + u16 headerNum = GetCurrentMapWildMonHeader(); + + if (headerNum != 0xFFFF) + { + struct WildPokemonInfo *wildPokemonInfo = gWildMonHeaders[headerNum].rockSmashMonsInfo; + + if (wildPokemonInfo == NULL) + { + gScriptResult = 0; + return; + } + else if (DoWildEncounterTest(wildPokemonInfo->encounterRate, 1) == TRUE + && GenerateWildMon(wildPokemonInfo, 2, TRUE) == TRUE) + { + BattleSetup_StartWildBattle(); + gScriptResult = 1; + return; + } + } + gScriptResult = 0; + return; +} + +bool8 SweetScentWildEncounter(void) +{ + s16 x; + s16 y; + u16 headerNum; + struct WildPokemonInfo *wildPokemonInfo; + + PlayerGetDestCoords(&x, &y); + if ((headerNum = GetCurrentMapWildMonHeader()) != 0xFFFF) + { + if (MetatileBehavior_IsLandWildEncounter(MapGridGetMetatileBehaviorAt(x, y)) == 1) + { + wildPokemonInfo = gWildMonHeaders[headerNum].landMonsInfo; + if (wildPokemonInfo == NULL) + return FALSE; + if (TryStartRoamerEncounter() == TRUE) + { + BattleSetup_StartRoamerBattle(); + return TRUE; + } + if (DoMassOutbreakEncounterTest() == TRUE) + SetUpMassOutbreakEncounter(FALSE); + else + GenerateWildMon(wildPokemonInfo, 0, FALSE); + BattleSetup_StartWildBattle(); + return TRUE; + } + else if (MetatileBehavior_IsWaterWildEncounter(MapGridGetMetatileBehaviorAt(x, y)) == 1) + { + wildPokemonInfo = gWildMonHeaders[headerNum].waterMonsInfo; + if (wildPokemonInfo == NULL) + return FALSE; + if (TryStartRoamerEncounter() == TRUE) + { + BattleSetup_StartRoamerBattle(); + return TRUE; + } + GenerateWildMon(wildPokemonInfo, 1, FALSE); + BattleSetup_StartWildBattle(); + return TRUE; + } + } + return FALSE; +} + +bool8 DoesCurrentMapHaveFishingMons(void) +{ + u16 headerNum = GetCurrentMapWildMonHeader(); + + if (headerNum != 0xFFFF && gWildMonHeaders[headerNum].fishingMonsInfo != NULL) + return TRUE; + else + return FALSE; +} + +void FishingWildEncounter(u8 rod) +{ + u16 species; + + if (CheckFeebas() == TRUE) + { + u8 level = ChooseWildMonLevel(&gWildFeebasRoute119Data); + + species = gWildFeebasRoute119Data.species; + CreateWildMon(species, level); + } + else + { + species = GenerateFishingWildMon( + gWildMonHeaders[GetCurrentMapWildMonHeader()].fishingMonsInfo, + rod); + } + IncrementGameStat(12); + sub_80BEA50(species); + BattleSetup_StartWildBattle(); +} + +u16 GetLocalWildMon(bool8 *isWaterMon) +{ + u16 headerNum; + struct WildPokemonInfo *landMonsInfo; + struct WildPokemonInfo *waterMonsInfo; + + *isWaterMon = FALSE; + headerNum = GetCurrentMapWildMonHeader(); + if (headerNum == 0xFFFF) + return 0; + landMonsInfo = gWildMonHeaders[headerNum].landMonsInfo; + waterMonsInfo = gWildMonHeaders[headerNum].waterMonsInfo; + //Neither + if (landMonsInfo == NULL && waterMonsInfo == NULL) + return 0; + //Land Pokemon + if (landMonsInfo != NULL && waterMonsInfo == NULL) + return landMonsInfo->wildPokemon[ChooseWildMonIndex_Land()].species; + //Water Pokemon + if (landMonsInfo == NULL && waterMonsInfo != NULL) + { + *isWaterMon = TRUE; + return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species; + } + //Either land or water Pokemon + if ((Random() % 100) < 80) + return landMonsInfo->wildPokemon[ChooseWildMonIndex_Land()].species; + else + { + *isWaterMon = TRUE; + return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species; + } +} + +u16 GetLocalWaterMon(void) +{ + u16 headerNum = GetCurrentMapWildMonHeader(); + + if (headerNum != 0xFFFF) + { + struct WildPokemonInfo *waterMonsInfo = gWildMonHeaders[headerNum].waterMonsInfo; + + if (waterMonsInfo) + return waterMonsInfo->wildPokemon[ChooseWildMonIndex_Water()].species; + } + return 0; +} + +bool8 UpdateRepelCounter(void) +{ + u16 steps = VarGet(VAR_REPEL_STEP_COUNT); + + if (steps != 0) + { + steps--; + VarSet(VAR_REPEL_STEP_COUNT, steps); + if (steps == 0) + { + ScriptContext1_SetupScript(S_RepelWoreOff); + return TRUE; + } + } + return FALSE; +} + +static bool8 IsWildLevelAllowedByRepel(u8 wildLevel) +{ + u8 i; + + if (!VarGet(VAR_REPEL_STEP_COUNT)) + { + return TRUE; + } + else + { + for (i = 0; i < 6; i++) + { + // UB: Too few arguments for function 'GetMonData' + if (GetMonData(&gPlayerParty[i], MON_DATA_HP) && !GetMonData(&gPlayerParty[i], MON_DATA_IS_EGG)) + { + u8 ourLevel = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL); + + if (wildLevel < ourLevel) + return FALSE; + else + return TRUE; + } + } + return FALSE; + } +} + +static void ApplyFluteEncounterRateMod(u32 *encRate) +{ + if (FlagGet(SYS_ENC_UP_ITEM) == TRUE) + *encRate += *encRate / 2; + else if (FlagGet(SYS_ENC_DOWN_ITEM) == TRUE) + *encRate = *encRate / 2; +} + +static void ApplyCleanseTagEncounterRateMod(u32 *encRate) +{ + // UB: Too few arguments for function 'GetMonData' + if (GetMonData(&gPlayerParty[0], MON_DATA_HELD_ITEM) == 0xBE) + *encRate = *encRate * 2 / 3; +} |