summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/battle_frontier_2.c420
-rw-r--r--src/pokemon.c16
-rw-r--r--src/record_mixing.c28
3 files changed, 438 insertions, 26 deletions
diff --git a/src/battle_frontier_2.c b/src/battle_frontier_2.c
index e21e972cd..45e4a1683 100644
--- a/src/battle_frontier_2.c
+++ b/src/battle_frontier_2.c
@@ -1,23 +1,53 @@
#include "global.h"
+#include "apprentice.h"
#include "string_util.h"
#include "script.h"
#include "text.h"
#include "random.h"
#include "main.h"
+#include "malloc.h"
+#include "strings.h"
+#include "menu.h"
+#include "script_menu.h"
+#include "party_menu.h"
+#include "data2.h"
+#include "constants/items.h"
struct Unk030062ECStruct
{
u8 unk0;
u16 unk2[3][5];
+ u8 unk20[3][5];
+};
+
+struct Unk030062F0Struct
+{
+ u16 unk0;
+ u16 unk2;
+ u16 unk4;
+ u16 unk6;
};
extern struct Unk030062ECStruct *gUnknown_030062EC;
+extern struct Unk030062F0Struct *gUnknown_030062F0;
extern const u8 *const gUnknown_08611330[];
extern const u8 gUnknown_08611548[8];
+extern const u8 gUnknown_086114D3[];
+extern const bool8 gUnknown_08611370[];
+
+// text
+extern const u8 gText_Give[];
+extern const u8 gText_NoNeed[];
+extern const u8 gText_Yes[];
+extern const u8 gText_No[];
// This file's functions.
void sub_81A087C(void);
+u16 sub_819FF98(u8 arg0);
+bool8 sub_81A0194(u8 arg0, u16 moveId);
+void sub_81A0804(u8 arg0, u8 itemsCount, u8 windowId);
+u8 sub_81A0784(u8 arg0, u8 arg1, u8 arg2, u8 arg3);
void sub_819F99C(u8 id)
{
@@ -42,15 +72,15 @@ void sub_819FA50(void)
EnableBothScriptContexts();
}
-void sub_819FA5C(struct UnkRecordMixingStruct *structPtr)
+void sub_819FA5C(struct Apprentice *apprentice)
{
u8 i;
for (i = 0; i < 6; i++)
- structPtr->unk28[i] |= 0xFFFF;
+ apprentice->unk28[i] |= 0xFFFF;
- structPtr->playerName[0] = EOS;
- structPtr->field_0_0 = 16;
+ apprentice->playerName[0] = EOS;
+ apprentice->field_0_0 = 16;
}
void sub_819FAA0(void)
@@ -149,3 +179,385 @@ u8 sub_819FCF8(u8 val, u8 *arg1, u8 *arg2)
return ret;
}
+
+void sub_819FD64(void)
+{
+ u8 sp_0[10];
+ u8 sp_C[3];
+ u8 sp_10;
+ u8 i, j;
+ u8 rand1, rand2;
+ u8 id;
+
+ for (i = 0; i < 3; i++)
+ sp_C[i] = i;
+ for (i = 0; i < 10; i++)
+ {
+ u8 temp;
+ rand1 = Random() % ARRAY_COUNT(sp_C);
+ rand2 = Random() % ARRAY_COUNT(sp_C);
+ SWAP(sp_C[rand1], sp_C[rand2], temp);
+ }
+
+ for (i = 0; i < 10; i++)
+ sp_0[i] = gUnknown_086114D3[i];
+ for (i = 0; i < 50; i++)
+ {
+ u8 temp;
+ rand1 = Random() % ARRAY_COUNT(sp_0);
+ rand2 = Random() % ARRAY_COUNT(sp_0);
+ SWAP(sp_0[rand1], sp_0[rand2], temp);
+ }
+
+ gUnknown_030062EC = AllocZeroed(sizeof(*gUnknown_030062EC));
+ gUnknown_030062EC->unk0 = 0;
+ for (i = 0; i < 5; i++)
+ {
+ for (j = 0; j < 3; j++)
+ gUnknown_030062EC->unk20[j][i] = 4;
+ }
+
+ sp_10 = 0;
+ for (i = 0; i < 9; i++)
+ {
+ gSaveBlock2Ptr->field_B8[i].unk0_0 = sp_0[i];
+ if (sp_0[i] != 3)
+ {
+ gSaveBlock2Ptr->field_B8[i].unk0_1 = sub_819FCF8(sp_0[i], sp_C, &sp_10);
+ id = gSaveBlock2Ptr->field_B8[i].unk0_1;
+ if (sp_0[i] == 2)
+ {
+ do
+ {
+ rand1 = Random() % 4;
+ for (j = 0; j < gUnknown_030062EC->unk0 + 1; j++)
+ {
+ if (gUnknown_030062EC->unk20[id][j] == rand1)
+ break;
+ }
+ } while (j != gUnknown_030062EC->unk0 + 1);
+
+ gUnknown_030062EC->unk20[id][gUnknown_030062EC->unk0] = rand1;
+ gSaveBlock2Ptr->field_B8[i].unk0_2 = rand1;
+ gSaveBlock2Ptr->field_B8[i].unk2 = sub_819FF98(gSaveBlock2Ptr->field_B8[i].unk0_1);
+ }
+ }
+ }
+
+ FREE_AND_SET_NULL(gUnknown_030062EC);
+}
+
+// No idea why a do-while loop is needed, but it will not match without it.
+
+#define APPRENTICE_SPECIES_ID(speciesArrId, monId) speciesArrId = (gSaveBlock2Ptr->field_B4[monId] >> \
+ (((gSaveBlock2Ptr->field_B2_0 >> monId) & 1) << 2)) & 0xF; \
+ do {} while (0)
+
+u16 sub_819FF98(u8 arg0)
+{
+ u8 i, j;
+ u8 id;
+ u8 knownMovesCount;
+ u16 species;
+ const u16 *learnset;
+ bool32 var_24 = FALSE;
+ u16 moveId = 0;
+ bool32 valid;
+ u8 level;
+
+ if (arg0 < 3)
+ {
+ APPRENTICE_SPECIES_ID(id, arg0);
+ }
+ else
+ {
+ id = 0;
+ }
+
+ species = gApprentices[gSaveBlock2Ptr->field_B0].species[id];
+ learnset = gLevelUpLearnsets[species];
+ j = 0;
+ if (gSaveBlock2Ptr->field_B1_0 == 1)
+ level = 50;
+ else
+ level = 60;
+
+ for (j = 0; learnset[j] != 0xFFFF; j++)
+ {
+ if ((learnset[j] & 0xFE00) > (level << 9))
+ break;
+ }
+
+ knownMovesCount = j;
+ i = 0;
+ while (i < 5)
+ {
+ if (Random() % 2 == 0 || var_24 == TRUE)
+ {
+ do
+ {
+ do
+ {
+ id = Random() % (NUM_TECHNICAL_MACHINES + NUM_HIDDEN_MACHINES);
+ valid = CanSpeciesLearnTMHM(species, id);
+ }
+ while (!valid);
+
+ moveId = ItemIdToBattleMoveId(ITEM_TM01 + id);
+ valid = TRUE;
+
+ if (knownMovesCount < 5)
+ j = 0;
+ else
+ j = knownMovesCount - 4;
+
+ for (; j < knownMovesCount; j++)
+ {
+ if ((learnset[j] & 0x1FF) == moveId)
+ {
+ valid = FALSE;
+ break;
+ }
+ }
+ } while (valid != TRUE);
+ }
+ else
+ {
+ if (knownMovesCount < 5)
+ {
+ var_24 = TRUE;
+ continue;
+ }
+ else
+ {
+ do
+ {
+ u8 learnsetId = Random() % (knownMovesCount - 4);
+ moveId = learnset[learnsetId] & 0x1FF;
+ valid = TRUE;
+ for (j = knownMovesCount - 4; j < knownMovesCount; j++)
+ {
+ if ((learnset[j] & 0x1FF) == moveId)
+ {
+ valid = FALSE;
+ break;
+ }
+ }
+ } while (valid != TRUE);
+ }
+ }
+
+ if (sub_81A0194(arg0, moveId))
+ {
+ if (gUnknown_08611370[moveId])
+ break;
+ i++;
+ }
+ }
+
+ gUnknown_030062EC->unk0++;
+ return moveId;
+}
+
+bool8 sub_81A0194(u8 arg0, u16 moveId)
+{
+ u8 i;
+
+ for (i = 0; i < 5; i++)
+ {
+ if (gUnknown_030062EC->unk2[arg0][i] == moveId)
+ return FALSE;
+ }
+
+ gUnknown_030062EC->unk2[arg0][gUnknown_030062EC->unk0] = moveId;
+ return TRUE;
+}
+
+void GetLatestLearnedMoves(u16 species, u16 *moves)
+{
+ u8 i, j;
+ u8 level, knownMovesCount;
+ const u16 *learnset;
+
+ if (gSaveBlock2Ptr->field_B1_0 == 1)
+ level = 50;
+ else
+ level = 60;
+
+ learnset = gLevelUpLearnsets[species];
+ for (i = 0; learnset[i] != 0xFFFF; i++)
+ {
+ if ((learnset[i] & 0xFE00) > (level << 9))
+ break;
+ }
+
+ knownMovesCount = i;
+ if (knownMovesCount > 4)
+ knownMovesCount = 4;
+
+ for (j = 0; j < knownMovesCount; j++)
+ moves[j] = learnset[(i - 1) - j] & 0x1FF;
+}
+
+u16 sub_81A0284(u8 arg0, u8 speciesTableId, u8 arg2)
+{
+ u16 moves[4];
+ u8 i, count;
+
+ if (gSaveBlock2Ptr->field_B1_1 < 3)
+ return 0;
+
+ count = 0;
+ for (i = 0; i < 9; i++)
+ {
+ if (gSaveBlock2Ptr->field_B8[i].unk0_0 == 0)
+ break;
+ count++;
+ }
+
+ GetLatestLearnedMoves(gApprentices[gSaveBlock2Ptr->field_B0].species[speciesTableId], moves);
+ for (i = 0; i < count && i < gSaveBlock2Ptr->field_B1_1 - 3; i++)
+ {
+ if (gSaveBlock2Ptr->field_B8[i].unk0_0 == 2
+ && gSaveBlock2Ptr->field_B8[i].unk0_1 == arg0
+ && gSaveBlock2Ptr->field_B8[i].unk0_3 != 0)
+ {
+ moves[gSaveBlock2Ptr->field_B8[i].unk0_2] = gSaveBlock2Ptr->field_B8[i].unk2;
+ }
+ }
+
+ return moves[arg2];
+}
+
+void sub_81A0390(u8 arg0)
+{
+ struct ApprenticeMon *apprenticeMons[3];
+ u8 i, j;
+ u32 speciesTableId;
+
+ for (i = 0; i < 3; i++)
+ {
+ gSaveBlock2Ptr->field_DC[0].monData[i].species = 0;
+ gSaveBlock2Ptr->field_DC[0].monData[i].item = 0;
+ for (j = 0; j < 4; j++)
+ gSaveBlock2Ptr->field_DC[0].monData[i].moves[j] = 0;
+ }
+
+ j = gSaveBlock2Ptr->field_B1_2;
+ for (i = 0; i < 3; i++)
+ {
+ apprenticeMons[j] = &gSaveBlock2Ptr->field_DC[0].monData[i];
+ j = (j + 1) % 3;
+ }
+
+ for (i = 0; i < 3; i++)
+ {
+ APPRENTICE_SPECIES_ID(speciesTableId, i);
+ apprenticeMons[i]->species = gApprentices[gSaveBlock2Ptr->field_B0].species[speciesTableId];
+ GetLatestLearnedMoves(apprenticeMons[i]->species, apprenticeMons[i]->moves);
+ }
+
+ for (i = 0; i < arg0; i++)
+ {
+ u8 var1 = gSaveBlock2Ptr->field_B8[i].unk0_0;
+ u8 monId = gSaveBlock2Ptr->field_B8[i].unk0_1;
+ if (var1 == 1)
+ {
+ if (gSaveBlock2Ptr->field_B8[i].unk0_3 != 0)
+ apprenticeMons[monId]->item = gSaveBlock2Ptr->field_B8[i].unk2;
+ }
+ else if (var1 == 2)
+ {
+ if (gSaveBlock2Ptr->field_B8[i].unk0_3 != 0)
+ {
+ u32 moveSlot = gSaveBlock2Ptr->field_B8[i].unk0_2;
+ apprenticeMons[monId]->moves[moveSlot] = gSaveBlock2Ptr->field_B8[i].unk2;
+ }
+ }
+ }
+}
+
+void sub_81A04E4(u8 arg0)
+{
+ u8 i;
+ u8 windowId;
+ const u8 *strings[3];
+ u8 count = 2;
+ u8 tileWidth;
+ u8 r10;
+ u8 r6;
+ s32 pixelWidth;
+
+ switch (arg0)
+ {
+ case 0:
+ r10 = 0x12;
+ r6 = 8;
+ strings[0] = gText_Lv50;
+ strings[1] = gText_OpenLevel;
+ break;
+ case 1:
+ count = 3;
+ r10 = 0x12;
+ r6 = 6;
+ for (i = 0; i < 3; i++)
+ {
+ u16 species;
+ u32 speciesTableId;
+
+ APPRENTICE_SPECIES_ID(speciesTableId, i);
+ species = gApprentices[gSaveBlock2Ptr->field_B0].species[speciesTableId];
+ strings[i] = gSpeciesNames[species];
+ }
+ break;
+ case 2:
+ r10 = 0x12;
+ r6 = 8;
+ if (gSaveBlock2Ptr->field_B1_1 > 2)
+ return;
+ strings[1] = gSpeciesNames[gUnknown_030062F0->unk2];
+ strings[0] = gSpeciesNames[gUnknown_030062F0->unk0];
+ break;
+ case 3:
+ r10 = 0x11;
+ r6 = 8;
+ strings[0] = gMoveNames[gUnknown_030062F0->unk4];
+ strings[1] = gMoveNames[gUnknown_030062F0->unk6];
+ break;
+ case 4:
+ r10 = 0x12;
+ r6 = 8;
+ strings[0] = gText_Give;
+ strings[1] = gText_NoNeed;
+ break;
+ case 6:
+ r10 = 0x14;
+ r6 = 8;
+ strings[0] = gText_Yes;
+ strings[1] = gText_No;
+ break;
+ default:
+ r10 = 0;
+ r6 = 0;
+ break;
+ }
+
+ pixelWidth = 0;
+ for (i = 0; i < count; i++)
+ {
+ s32 width = GetStringWidth(1, strings[i], 0);
+ if (width > pixelWidth)
+ pixelWidth = width;
+ }
+
+ tileWidth = convert_pixel_width_to_tile_width(pixelWidth);
+ r10 = sub_80E2D5C(r10, tileWidth);
+ windowId = sub_81A0784(r10, r6, tileWidth, count * 2);
+ SetStandardWindowBorderStyle(windowId, 0);
+
+ for (i = 0; i < count; i++)
+ AddTextPrinterParameterized(windowId, 1, strings[i], 8, (i * 16) + 1, TEXT_SPEED_FF, NULL);
+
+ InitMenuInUpperLeftCornerPlaySoundWhenAPressed(windowId, count, 0);
+ sub_81A0804(1, count, windowId);
+}
diff --git a/src/pokemon.c b/src/pokemon.c
index 8e2e3b764..bb2fc753c 100644
--- a/src/pokemon.c
+++ b/src/pokemon.c
@@ -35,6 +35,7 @@
#include "pokenav.h"
#include "pokemon_storage_system.h"
#include "recorded_battle.h"
+#include "apprentice.h"
struct SpeciesItem
{
@@ -69,7 +70,6 @@ extern const union AnimCmd *const *const gMonAnimationsSpriteAnimsPtrTable[];
extern const union AnimCmd *const *const gTrainerBackAnimsPtrTable[];
extern const union AnimCmd *const *const gTrainerFrontAnimsPtrTable[];
extern const u8 gSpeciesNames[][POKEMON_NAME_LENGTH + 1];
-extern const struct UnknownPokemonStruct3 gUnknown_08610970[];
extern const struct CompressedSpritePalette gMonPaletteTable[];
extern const struct CompressedSpritePalette gMonShinyPaletteTable[];
extern const u8 gTrainerClassNames[][13];
@@ -2873,17 +2873,17 @@ void sub_8068338(struct Pokemon *mon, struct UnknownPokemonStruct *src, bool8 lv
CalculateMonStats(mon);
}
-void sub_8068528(struct Pokemon *mon, const struct UnknownPokemonStruct2 *src, u8 monId)
+void CreateApprenticeMon(struct Pokemon *mon, const struct Apprentice *src, u8 monId)
{
s32 i;
u16 evAmount;
u8 language;
- u32 otId = gUnknown_08610970[src->field_0_0].field_30;
- u32 personality = ((gUnknown_08610970[src->field_0_0].field_30 >> 8) | ((gUnknown_08610970[src->field_0_0].field_30 & 0xFF) << 8))
- + src->mons[monId].species + src->field_2;
+ u32 otId = gApprentices[src->field_0_0].otId;
+ u32 personality = ((gApprentices[src->field_0_0].otId >> 8) | ((gApprentices[src->field_0_0].otId & 0xFF) << 8))
+ + src->monData[monId].species + src->field_2;
CreateMon(mon,
- src->mons[monId].species,
+ src->monData[monId].species,
GetFrontierEnemyMonLevel(src->field_0_1 - 1),
0x1F,
TRUE,
@@ -2891,9 +2891,9 @@ void sub_8068528(struct Pokemon *mon, const struct UnknownPokemonStruct2 *src, u
TRUE,
otId);
- SetMonData(mon, MON_DATA_HELD_ITEM, &src->mons[monId].item);
+ SetMonData(mon, MON_DATA_HELD_ITEM, &src->monData[monId].item);
for (i = 0; i < 4; i++)
- SetMonMoveSlot(mon, src->mons[monId].moves[i], i);
+ SetMonMoveSlot(mon, src->monData[monId].moves[i], i);
evAmount = MAX_TOTAL_EVS / NUM_STATS;
for (i = 0; i < NUM_STATS; i++)
diff --git a/src/record_mixing.c b/src/record_mixing.c
index 6c6f69fa8..8d0022f17 100644
--- a/src/record_mixing.c
+++ b/src/record_mixing.c
@@ -83,7 +83,7 @@ struct PlayerRecordsEmerald
/* 0x1124 */ struct EmeraldBattleTowerRecord battleTowerRecord;
/* 0x1210 */ u16 unk_1210;
/* 0x1214 */ LilycoveLady lilycoveLady;
- /* 0x1254 */ struct UnkRecordMixingStruct unk_1254[2];
+ /* 0x1254 */ struct Apprentice apprentice[2];
/* 0x12dc */ struct UnkRecordMixingStruct2 unk_12dc;
/* 0x1434 */ u8 field_1434[0x10];
}; // 0x1444
@@ -134,8 +134,8 @@ static void sub_80E7B2C(const u8 *);
static void ReceiveDaycareMailData(struct RecordMixingDayCareMail *, size_t, u8, TVShow *);
static void sub_80E7F68(u16 *item, u8 which);
static void sub_80E7FF8(u8 taskId);
-static void sub_80E8110(struct UnkRecordMixingStruct *arg0, struct UnkRecordMixingStruct *arg1);
-static void sub_80E8468(struct UnkRecordMixingStruct *arg0, size_t arg1, u32 arg2);
+static void sub_80E8110(struct Apprentice *arg0, struct Apprentice *arg1);
+static void ReceiveApprenticeData(struct Apprentice *arg0, size_t arg1, u32 arg2);
static void sub_80E89AC(struct UnkRecordMixingStruct2 *arg0, size_t arg1, u32 arg2);
static void sub_80E89F8(struct RecordMixingDayCareMail *dst);
static void SanitizeDayCareMailForRuby(struct RecordMixingDayCareMail *src);
@@ -265,7 +265,7 @@ static void PrepareExchangePacket(void)
if (GetMultiplayerId() == 0)
sSentRecord->emerald.unk_1210 = GetRecordMixingGift();
- sub_80E8110(sSentRecord->emerald.unk_1254, gUnknown_03001154);
+ sub_80E8110(sSentRecord->emerald.apprentice, gUnknown_03001154);
sub_80E8260(&sSentRecord->emerald.unk_12dc);
}
}
@@ -298,7 +298,7 @@ static void ReceiveExchangePacket(u32 which)
ReceiveBattleTowerData(&sReceivedRecords->emerald.battleTowerRecord, sizeof(struct PlayerRecordsEmerald), which);
sub_80E7F68(&sReceivedRecords->emerald.unk_1210, which);
ReceiveLilycoveLadyData(&sReceivedRecords->emerald.lilycoveLady, sizeof(struct PlayerRecordsEmerald), which);
- sub_80E8468(sReceivedRecords->emerald.unk_1254, sizeof(struct PlayerRecordsEmerald), (u8) which);
+ ReceiveApprenticeData(sReceivedRecords->emerald.apprentice, sizeof(struct PlayerRecordsEmerald), (u8) which);
sub_80E89AC(&sReceivedRecords->emerald.unk_12dc, sizeof(struct PlayerRecordsEmerald), (u8) which);
}
}
@@ -1551,13 +1551,13 @@ static void sub_80E7FF8(u8 taskId)
// New Emerald functions
-static void sub_80E8110(struct UnkRecordMixingStruct *dst, struct UnkRecordMixingStruct *src)
+static void sub_80E8110(struct Apprentice *dst, struct Apprentice *src)
{
s32 i, id;
s32 var_2C, var_28, var_24, r8;
- dst[0].field_38[0] = 0xFF;
- dst[1].field_38[0] = 0xFF;
+ dst[0].playerName[0] = EOS;
+ dst[1].playerName[0] = EOS;
dst[0] = src[0];
@@ -1568,7 +1568,7 @@ static void sub_80E8110(struct UnkRecordMixingStruct *dst, struct UnkRecordMixin
for (i = 0; i < 2; i++)
{
id = ((i + gSaveBlock2Ptr->field_B2_1) % 3) + 1;
- if (src[id].field_38[0] != 0xFF)
+ if (src[id].playerName[0] != EOS)
{
if (ReadUnalignedWord(src[id].playerId) != ReadUnalignedWord(gSaveBlock2Ptr->playerTrainerId))
{
@@ -1646,14 +1646,14 @@ void sub_80E8260(struct UnkRecordMixingStruct2 *dst)
}
}
-static bool32 sub_80E841C(struct UnkRecordMixingStruct *arg0, struct UnkRecordMixingStruct *arg1)
+static bool32 sub_80E841C(struct Apprentice *arg0, struct Apprentice *arg1)
{
s32 i;
for (i = 0; i < 4; i++)
{
if (ReadUnalignedWord(arg0->playerId) == ReadUnalignedWord(arg1[i].playerId)
- && arg0->field_0[2] == arg1[i].field_0[2])
+ && arg0->field_2 == arg1[i].field_2)
{
return TRUE;
}
@@ -1662,10 +1662,10 @@ static bool32 sub_80E841C(struct UnkRecordMixingStruct *arg0, struct UnkRecordMi
return FALSE;
}
-static void sub_80E8468(struct UnkRecordMixingStruct *arg0, size_t arg1, u32 arg2)
+static void ReceiveApprenticeData(struct Apprentice *arg0, size_t arg1, u32 arg2)
{
s32 i, r7, r8;
- struct UnkRecordMixingStruct *structPtr;
+ struct Apprentice *structPtr;
u32 mixIndices[4];
u32 structId;
@@ -1675,7 +1675,7 @@ static void sub_80E8468(struct UnkRecordMixingStruct *arg0, size_t arg1, u32 arg
r8 = 0;
for (i = 0; i < 2; i++)
{
- if (structPtr[i].field_38[0] != 0xFF && !sub_80E841C(&structPtr[i], gSaveBlock2Ptr->field_DC))
+ if (structPtr[i].playerName[0] != EOS && !sub_80E841C(&structPtr[i], gSaveBlock2Ptr->field_DC))
{
r7++;
r8 = i;