sovereignx/src/battle_pyramid.c

2202 lines
74 KiB
C
Raw Normal View History

2018-11-17 14:30:34 +00:00
#include "global.h"
2018-11-18 16:52:22 +00:00
#include "battle_pyramid.h"
2018-11-17 14:30:34 +00:00
#include "battle_pyramid_bag.h"
#include "event_data.h"
#include "battle.h"
#include "battle_setup.h"
#include "battle_tower.h"
#include "save.h"
2018-11-27 21:45:50 +00:00
#include "strings.h"
2018-11-17 14:30:34 +00:00
#include "fieldmap.h"
2018-12-23 23:02:29 +00:00
#include "party_menu.h"
2018-11-17 14:30:34 +00:00
#include "palette.h"
2018-12-23 23:02:29 +00:00
#include "field_screen_effect.h"
2018-11-17 14:30:34 +00:00
#include "field_message_box.h"
#include "random.h"
#include "item.h"
#include "util.h"
#include "sound.h"
#include "task.h"
#include "start_menu.h"
2018-11-19 17:14:28 +00:00
#include "string_util.h"
2018-11-17 21:55:39 +00:00
#include "trainer_see.h"
#include "main.h"
#include "load_save.h"
#include "script.h"
#include "malloc.h"
2018-11-18 16:52:22 +00:00
#include "overworld.h"
2018-11-27 21:45:50 +00:00
#include "event_scripts.h"
2021-10-26 21:52:23 +01:00
#include "graphics.h"
#include "wild_encounter.h"
2018-11-17 14:30:34 +00:00
#include "constants/battle_frontier.h"
2019-10-07 01:04:30 +01:00
#include "constants/battle_pyramid.h"
2018-11-17 14:30:34 +00:00
#include "constants/event_objects.h"
2019-11-21 19:03:35 +00:00
#include "constants/event_object_movement.h"
2019-11-24 21:58:40 +00:00
#include "constants/frontier_util.h"
2018-11-18 16:52:22 +00:00
#include "constants/items.h"
2019-01-31 21:51:20 +00:00
#include "constants/layouts.h"
2021-10-09 17:12:18 +01:00
#include "constants/metatile_labels.h"
2018-11-17 21:55:39 +00:00
#include "constants/moves.h"
2019-02-07 02:01:29 +00:00
#include "constants/trainers.h"
2018-11-17 14:30:34 +00:00
2023-08-16 21:44:45 +01:00
#define NUM_LAYOUT_OFFSETS 8
2018-11-17 21:55:39 +00:00
extern const struct MapLayout *const gMapLayouts[];
2019-02-07 17:37:28 +00:00
2018-11-27 21:45:50 +00:00
struct PyramidWildMon
{
u16 species;
u8 lvl;
2019-05-14 14:22:16 +01:00
u8 abilityNum;
2019-09-08 16:53:48 +01:00
u16 moves[MAX_MON_MOVES];
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
struct PyramidFloorTemplate
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
u8 numItems;
u8 numTrainers;
2019-02-07 17:37:28 +00:00
u8 itemPositions;
u8 trainerPositions;
2018-11-27 21:45:50 +00:00
u8 runMultiplier;
u8 layoutOffsets[NUM_LAYOUT_OFFSETS];
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
struct PyramidTrainerEncounterMusic
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
u8 trainerClass;
u8 trainerEncounterMusic;
2018-11-27 21:45:50 +00:00
};
2018-11-18 16:52:22 +00:00
2018-11-17 14:30:34 +00:00
// This file's functions.
2019-02-07 23:37:41 +00:00
static void InitPyramidChallenge(void);
2019-02-07 02:01:29 +00:00
static void GetBattlePyramidData(void);
static void SetBattlePyramidData(void);
static void SavePyramidChallenge(void);
static void SetBattlePyramidPrize(void);
static void GiveBattlePyramidPrize(void);
2019-02-07 02:01:29 +00:00
static void SeedPyramidFloor(void);
static void SetPickupItem(void);
static void HidePyramidItem(void);
2019-12-11 08:28:55 +00:00
static void SetPyramidFacilityTrainers(void);
2019-02-07 02:01:29 +00:00
static void ShowPostBattleHintText(void);
static void UpdatePyramidWinStreak(void);
static void GetInBattlePyramid(void);
static void UpdatePyramidLightRadius(void);
static void ClearPyramidPartyHeldItems(void);
static void SetPyramidFloorPalette(void);
2019-12-11 08:28:55 +00:00
static void BattlePyramidStartMenu(void);
2019-02-07 17:37:28 +00:00
static void RestorePyramidPlayerParty(void);
2022-05-21 20:21:50 +01:00
static void InitPyramidBagItems(u8);
2019-02-07 02:01:29 +00:00
static u8 GetPyramidFloorTemplateId(void);
static u8 GetPostBattleDirectionHintTextIndex(int *, u8, u8);
2022-05-21 20:21:50 +01:00
static void Task_SetPyramidFloorPalette(u8);
static void MarkPyramidTrainerAsBattled(u16);
static void GetPyramidFloorLayoutOffsets(u8 *);
2019-02-07 17:37:28 +00:00
static void GetPyramidEntranceAndExitSquareIds(u8 *, u8 *);
static void SetPyramidObjectPositionsUniformly(u8);
static bool8 SetPyramidObjectPositionsInAndNearSquare(u8, u8);
static bool8 SetPyramidObjectPositionsNearSquare(u8, u8);
2022-05-21 20:21:50 +01:00
static bool8 TrySetPyramidObjectEventPositionInSquare(u8, u8 *, u8, u8);
static bool8 TrySetPyramidObjectEventPositionAtCoords(bool8, u8, u8, u8 *, u8, u8);
2018-11-17 14:30:34 +00:00
2018-11-27 21:45:50 +00:00
// Const rom data.
#define ABILITY_RANDOM 2 // For wild mons data.
#if BATTLE_PYRAMID_RANDOM_ENCOUNTERS == TRUE
#include "data/battle_frontier/battle_pyramid_wild_requirements.h"
#else
#include "data/battle_frontier/battle_pyramid_level_50_wild_mons.h"
#include "data/battle_frontier/battle_pyramid_open_level_wild_mons.h"
#endif
2018-11-27 21:45:50 +00:00
2019-02-07 02:01:29 +00:00
static const struct PyramidFloorTemplate sPyramidFloorTemplates[] =
2018-11-27 21:45:50 +00:00
{
{
2019-02-07 02:01:29 +00:00
.numItems = 7,
.numTrainers = 3,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 128,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {0, 0, 1, 1, 2, 2, 3, 3},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 6,
.numTrainers = 3,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 128,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {1, 1, 2, 2, 3, 3, 4, 4},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 5,
.numTrainers = 3,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 120,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {2, 2, 3, 3, 4, 4, 5, 5},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 4,
.numTrainers = 4,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 120,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {3, 3, 4, 4, 5, 5, 6, 6},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 4,
.numTrainers = 4,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_IN_AND_NEAR_ENTRANCE,
.runMultiplier = 112,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {4, 4, 5, 5, 6, 6, 7, 7},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 3,
.numTrainers = 5,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_IN_AND_NEAR_EXIT,
.runMultiplier = 112,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {5, 6, 7, 8, 9, 10, 11, 12},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 3,
.numTrainers = 5,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 104,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {6, 7, 8, 9, 10, 11, 12, 13},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 2,
.numTrainers = 4,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_IN_AND_NEAR_ENTRANCE,
.runMultiplier = 104,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {7, 8, 9, 10, 11, 12, 13, 14},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 4,
.numTrainers = 5,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_IN_AND_NEAR_EXIT,
.runMultiplier = 96,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {8, 9, 10, 11, 12, 13, 14, 15},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 3,
.numTrainers = 6,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
2019-02-07 17:54:51 +00:00
.trainerPositions = OBJ_POSITIONS_NEAR_EXIT,
2019-02-07 17:37:28 +00:00
.runMultiplier = 96,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {8, 9, 10, 11, 12, 13, 14, 15},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 2,
.numTrainers = 3,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 88,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {12, 13, 14, 12, 13, 14, 12, 13},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 4,
.numTrainers = 5,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 88,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {11, 11, 11, 11, 11, 11, 11, 11},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 3,
.numTrainers = 7,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 80,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {12, 12, 12, 12, 12, 12, 12, 12},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 2,
.numTrainers = 4,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 80,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {13, 13, 13, 13, 13, 13, 13, 13},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 3,
.numTrainers = 6,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 80,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {14, 14, 14, 14, 14, 14, 14, 14},
2018-11-27 21:45:50 +00:00
},
{
2019-02-07 02:01:29 +00:00
.numItems = 3,
.numTrainers = 8,
2019-02-07 17:37:28 +00:00
.itemPositions = OBJ_POSITIONS_UNIFORM,
.trainerPositions = OBJ_POSITIONS_UNIFORM,
.runMultiplier = 80,
2019-02-07 02:01:29 +00:00
.layoutOffsets = {15, 15, 15, 15, 15, 15, 15, 15},
2018-11-27 21:45:50 +00:00
}
};
2019-02-07 02:01:29 +00:00
static const u8 sPyramidFloorTemplateOptions[][2] =
{
// Floor 0
{40, 0},
{70, 1},
{90, 2},
{100, 3},
// Floor 1
{35, 1},
{55, 2},
{75, 3},
{90, 4},
{100, 10},
// Floor 2
{35, 2},
{55, 3},
{75, 4},
{90, 5},
{100, 11},
// Floor 3
{35, 3},
{55, 4},
{75, 5},
{90, 6},
{100, 12},
// Floor 4
{35, 4},
{55, 5},
{75, 6},
{90, 7},
{100, 13},
// Floor 5
{35, 5},
{55, 6},
{75, 7},
{90, 8},
{100, 14},
// Floor 6
{35, 6},
{55, 7},
{75, 8},
{90, 9},
{100, 15}
2018-11-27 21:45:50 +00:00
};
static const u8 sFloorTemplateOffsets[FRONTIER_STAGES_PER_CHALLENGE] =
2018-11-27 21:45:50 +00:00
{
0, 4, 9, 14, 19, 24, 29
2018-11-27 21:45:50 +00:00
};
2023-02-01 16:43:21 +00:00
static const u16 sPickupItemsLvl50[TOTAL_PYRAMID_ROUNDS][PICKUP_ITEMS_PER_ROUND] =
2018-11-27 21:45:50 +00:00
{
{ITEM_HYPER_POTION, ITEM_FLUFFY_TAIL, ITEM_CHERI_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_DIRE_HIT, ITEM_PECHA_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_X_ATTACK, ITEM_RAWST_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_DEFENSE, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2018-11-27 21:45:50 +00:00
{ITEM_HYPER_POTION, ITEM_X_SPEED, ITEM_CHESTO_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_X_ACCURACY, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_SP_ATK, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2018-11-27 21:45:50 +00:00
{ITEM_HYPER_POTION, ITEM_GUARD_SPEC, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_FLUFFY_TAIL, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_DIRE_HIT, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_X_ATTACK, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_DEFENSE, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2018-11-27 21:45:50 +00:00
{ITEM_HYPER_POTION, ITEM_X_SPEED, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_X_ACCURACY, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_SP_ATK, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2018-11-27 21:45:50 +00:00
{ITEM_HYPER_POTION, ITEM_GUARD_SPEC, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_FLUFFY_TAIL, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_DIRE_HIT, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_X_ATTACK, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_DEFENSE, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2018-11-27 21:45:50 +00:00
};
2023-02-01 16:43:21 +00:00
static const u16 sPickupItemsLvlOpen[TOTAL_PYRAMID_ROUNDS][PICKUP_ITEMS_PER_ROUND] =
2018-11-27 21:45:50 +00:00
{
{ITEM_HYPER_POTION, ITEM_FLUFFY_TAIL, ITEM_CHERI_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_DIRE_HIT, ITEM_PECHA_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_X_ATTACK, ITEM_RAWST_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_DEFENSE, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2018-11-27 21:45:50 +00:00
{ITEM_HYPER_POTION, ITEM_X_SPEED, ITEM_CHESTO_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_X_ACCURACY, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_SP_ATK, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2018-11-27 21:45:50 +00:00
{ITEM_HYPER_POTION, ITEM_GUARD_SPEC, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_FLUFFY_TAIL, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_DIRE_HIT, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_X_ATTACK, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_DEFENSE, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2018-11-27 21:45:50 +00:00
{ITEM_HYPER_POTION, ITEM_X_SPEED, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_X_ACCURACY, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_SP_ATK, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2018-11-27 21:45:50 +00:00
{ITEM_HYPER_POTION, ITEM_GUARD_SPEC, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_FLUFFY_TAIL, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_BRIGHT_POWDER, ITEM_SHELL_BELL, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
{ITEM_HYPER_POTION, ITEM_DIRE_HIT, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_LEFTOVERS, ITEM_CHOICE_BAND, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
{ITEM_HYPER_POTION, ITEM_X_ATTACK, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LUM_BERRY, ITEM_REVIVE, ITEM_SCOPE_LENS, ITEM_FOCUS_BAND, ITEM_MAX_REVIVE, ITEM_SACRED_ASH},
2019-04-13 12:14:45 +01:00
{ITEM_HYPER_POTION, ITEM_X_DEFENSE, ITEM_LUM_BERRY, ITEM_ETHER, ITEM_LEPPA_BERRY, ITEM_REVIVE, ITEM_QUICK_CLAW, ITEM_KINGS_ROCK, ITEM_FULL_RESTORE, ITEM_MAX_ELIXIR},
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 sPickupItemSlots[][2] =
{
// Floor 0
{ 31, 0},
{ 46, 1},
{ 61, 2},
{ 71, 3},
{ 81, 4},
{ 91, 5},
{ 94, 6},
{ 97, 7},
{100, 8},
// Floor 1
{ 15, 0},
{ 46, 1},
{ 61, 2},
{ 71, 3},
{ 81, 4},
{ 91, 5},
{ 94, 6},
{ 97, 8},
{100, 9},
// Floor 2
{ 15, 0},
{ 30, 1},
{ 61, 2},
{ 71, 3},
{ 81, 4},
{ 91, 5},
{ 94, 6},
{ 97, 7},
{100, 8},
// Floor 3
{ 28, 0},
{ 43, 1},
{ 58, 2},
{ 68, 3},
{ 78, 4},
{ 88, 5},
{ 92, 7},
{ 96, 8},
{100, 9},
// Floor 4
{ 15, 0},
{ 43, 1},
{ 58, 2},
{ 68, 3},
{ 78, 4},
{ 88, 5},
{ 92, 6},
{ 96, 7},
{100, 9},
// Floor 5
{ 15, 0},
{ 30, 1},
{ 58, 2},
{ 68, 3},
{ 78, 4},
{ 88, 5},
{ 92, 6},
{ 96, 7},
{100, 8},
// Floor 6
{ 28, 0},
{ 43, 1},
{ 58, 2},
{ 68, 3},
{ 78, 4},
{ 88, 5},
{ 92, 6},
{ 96, 8},
{100, 9},
2018-11-27 21:45:50 +00:00
};
static const u8 sPickupItemOffsets[FRONTIER_STAGES_PER_CHALLENGE] = {0, 9, 18, 27, 36, 45, 54};
2019-02-07 02:01:29 +00:00
static const struct PyramidTrainerEncounterMusic sTrainerClassEncounterMusic[54] =
{
{TRAINER_CLASS_TEAM_AQUA, TRAINER_ENCOUNTER_MUSIC_AQUA},
{TRAINER_CLASS_AQUA_ADMIN, TRAINER_ENCOUNTER_MUSIC_AQUA},
{TRAINER_CLASS_AQUA_LEADER, TRAINER_ENCOUNTER_MUSIC_AQUA},
{TRAINER_CLASS_AROMA_LADY, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_BATTLE_GIRL, TRAINER_ENCOUNTER_MUSIC_INTENSE},
{TRAINER_CLASS_SWIMMER_F, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_POKEFAN, TRAINER_ENCOUNTER_MUSIC_TWINS},
{TRAINER_CLASS_DRAGON_TAMER, TRAINER_ENCOUNTER_MUSIC_INTENSE},
{TRAINER_CLASS_COOLTRAINER, TRAINER_ENCOUNTER_MUSIC_COOL},
{TRAINER_CLASS_GUITARIST, TRAINER_ENCOUNTER_MUSIC_INTENSE},
{TRAINER_CLASS_SAILOR, TRAINER_ENCOUNTER_MUSIC_MALE},
{TRAINER_CLASS_TWINS, TRAINER_ENCOUNTER_MUSIC_TWINS},
{TRAINER_CLASS_INTERVIEWER, TRAINER_ENCOUNTER_MUSIC_INTERVIEWER},
{TRAINER_CLASS_RUIN_MANIAC, TRAINER_ENCOUNTER_MUSIC_HIKER},
{TRAINER_CLASS_GENTLEMAN, TRAINER_ENCOUNTER_MUSIC_RICH},
{TRAINER_CLASS_SWIMMER_M, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_POKEMANIAC, TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS},
{TRAINER_CLASS_BLACK_BELT, TRAINER_ENCOUNTER_MUSIC_INTENSE},
{TRAINER_CLASS_OLD_COUPLE, TRAINER_ENCOUNTER_MUSIC_INTENSE},
{TRAINER_CLASS_BUG_MANIAC, TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS},
{TRAINER_CLASS_CAMPER, TRAINER_ENCOUNTER_MUSIC_MALE},
{TRAINER_CLASS_KINDLER, TRAINER_ENCOUNTER_MUSIC_HIKER},
{TRAINER_CLASS_TEAM_MAGMA, TRAINER_ENCOUNTER_MUSIC_MAGMA},
{TRAINER_CLASS_MAGMA_ADMIN, TRAINER_ENCOUNTER_MUSIC_MAGMA},
{TRAINER_CLASS_MAGMA_LEADER, TRAINER_ENCOUNTER_MUSIC_MAGMA},
{TRAINER_CLASS_LASS, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_BUG_CATCHER, TRAINER_ENCOUNTER_MUSIC_MALE},
{TRAINER_CLASS_NINJA_BOY, TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS},
{TRAINER_CLASS_RICH_BOY, TRAINER_ENCOUNTER_MUSIC_RICH},
{TRAINER_CLASS_HEX_MANIAC, TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS},
{TRAINER_CLASS_BEAUTY, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_LADY, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_PARASOL_LADY, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_PICNICKER, TRAINER_ENCOUNTER_MUSIC_GIRL},
{TRAINER_CLASS_PKMN_BREEDER, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_COLLECTOR, TRAINER_ENCOUNTER_MUSIC_SUSPICIOUS},
{TRAINER_CLASS_PKMN_RANGER, TRAINER_ENCOUNTER_MUSIC_COOL},
{TRAINER_CLASS_RIVAL, TRAINER_ENCOUNTER_MUSIC_MALE},
2019-02-07 02:01:29 +00:00
{TRAINER_CLASS_YOUNG_COUPLE, TRAINER_ENCOUNTER_MUSIC_GIRL},
{TRAINER_CLASS_PSYCHIC, TRAINER_ENCOUNTER_MUSIC_INTENSE},
{TRAINER_CLASS_SR_AND_JR, TRAINER_ENCOUNTER_MUSIC_TWINS},
{TRAINER_CLASS_ELITE_FOUR, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_YOUNGSTER, TRAINER_ENCOUNTER_MUSIC_MALE},
{TRAINER_CLASS_EXPERT, TRAINER_ENCOUNTER_MUSIC_INTENSE},
{TRAINER_CLASS_TRIATHLETE, TRAINER_ENCOUNTER_MUSIC_MALE},
{TRAINER_CLASS_BIRD_KEEPER, TRAINER_ENCOUNTER_MUSIC_COOL},
{TRAINER_CLASS_FISHERMAN, TRAINER_ENCOUNTER_MUSIC_HIKER},
{TRAINER_CLASS_CHAMPION, TRAINER_ENCOUNTER_MUSIC_MALE},
{TRAINER_CLASS_TUBER_M, TRAINER_ENCOUNTER_MUSIC_MALE},
{TRAINER_CLASS_TUBER_F, TRAINER_ENCOUNTER_MUSIC_GIRL},
{TRAINER_CLASS_SIS_AND_BRO, TRAINER_ENCOUNTER_MUSIC_SWIMMER},
{TRAINER_CLASS_HIKER, TRAINER_ENCOUNTER_MUSIC_HIKER},
{TRAINER_CLASS_LEADER, TRAINER_ENCOUNTER_MUSIC_FEMALE},
{TRAINER_CLASS_SCHOOL_KID, TRAINER_ENCOUNTER_MUSIC_MALE},
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 sTrainerTextGroups[50][2] =
{
{FACILITY_CLASS_AROMA_LADY, 3},
{FACILITY_CLASS_RUIN_MANIAC, 4},
{FACILITY_CLASS_TUBER_F, 1},
{FACILITY_CLASS_TUBER_M, 0},
{FACILITY_CLASS_COOLTRAINER_M, 2},
{FACILITY_CLASS_COOLTRAINER_F, 3},
{FACILITY_CLASS_HEX_MANIAC, 3},
{FACILITY_CLASS_LADY, 3},
{FACILITY_CLASS_BEAUTY, 3},
{FACILITY_CLASS_RICH_BOY, 2},
{FACILITY_CLASS_POKEMANIAC, 2},
{FACILITY_CLASS_SWIMMER_M, 2},
{FACILITY_CLASS_BLACK_BELT, 4},
{FACILITY_CLASS_GUITARIST, 2},
{FACILITY_CLASS_KINDLER, 2},
{FACILITY_CLASS_CAMPER, 0},
{FACILITY_CLASS_BUG_MANIAC, 2},
{FACILITY_CLASS_PSYCHIC_M, 2},
{FACILITY_CLASS_PSYCHIC_F, 3},
{FACILITY_CLASS_GENTLEMAN, 4},
{FACILITY_CLASS_SCHOOL_KID_M, 0},
{FACILITY_CLASS_SCHOOL_KID_F, 1},
{FACILITY_CLASS_POKEFAN_M, 4},
{FACILITY_CLASS_POKEFAN_F, 5},
{FACILITY_CLASS_EXPERT_M, 4},
{FACILITY_CLASS_EXPERT_F, 5},
{FACILITY_CLASS_YOUNGSTER, 0},
{FACILITY_CLASS_FISHERMAN, 4},
{FACILITY_CLASS_CYCLING_TRIATHLETE_M, 2},
{FACILITY_CLASS_RUNNING_TRIATHLETE_M, 2},
{FACILITY_CLASS_SWIMMING_TRIATHLETE_M, 2},
{FACILITY_CLASS_RUNNING_TRIATHLETE_F, 3},
{FACILITY_CLASS_CYCLING_TRIATHLETE_F, 3},
{FACILITY_CLASS_SWIMMING_TRIATHLETE_F, 3},
{FACILITY_CLASS_DRAGON_TAMER, 2},
{FACILITY_CLASS_BIRD_KEEPER, 2},
{FACILITY_CLASS_NINJA_BOY, 0},
{FACILITY_CLASS_BATTLE_GIRL, 3},
{FACILITY_CLASS_PARASOL_LADY, 3},
{FACILITY_CLASS_SWIMMER_F, 3},
{FACILITY_CLASS_PICNICKER, 1},
{FACILITY_CLASS_SAILOR, 2},
{FACILITY_CLASS_COLLECTOR, 2},
{FACILITY_CLASS_PKMN_BREEDER_M, 2},
2019-11-24 21:58:40 +00:00
{FACILITY_CLASS_PKMN_BREEDER_F, 3},
2019-02-07 02:01:29 +00:00
{FACILITY_CLASS_PKMN_RANGER_M, 2},
{FACILITY_CLASS_PKMN_RANGER_F, 3},
{FACILITY_CLASS_LASS, 3},
{FACILITY_CLASS_BUG_CATCHER, 0},
{FACILITY_CLASS_HIKER, 4},
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sExitDirectionHintTexts1[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ExitHintUp1,
BattlePyramid_Text_ExitHintLeft1,
BattlePyramid_Text_ExitHintRight1,
BattlePyramid_Text_ExitHintDown1,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingItemsHintTexts1[] =
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroItemsRemaining1,
BattlePyramid_Text_OneItemRemaining1,
BattlePyramid_Text_TwoItemsRemaining1,
BattlePyramid_Text_ThreeItemsRemaining1,
BattlePyramid_Text_FourItemsRemaining1,
BattlePyramid_Text_FiveItemsRemaining1,
BattlePyramid_Text_SixItemsRemaining1,
BattlePyramid_Text_SevenItemsRemaining1,
BattlePyramid_Text_EightItemsRemaining1,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingTrainersHintTexts1[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroTrainersRemaining1,
BattlePyramid_Text_OneTrainersRemaining1,
BattlePyramid_Text_TwoTrainersRemaining1,
BattlePyramid_Text_ThreeTrainersRemaining1,
BattlePyramid_Text_FourTrainersRemaining1,
BattlePyramid_Text_FiveTrainersRemaining1,
BattlePyramid_Text_SixTrainersRemaining1,
BattlePyramid_Text_SevenTrainersRemaining1,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sExitDirectionHintTexts2[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ExitHintUp2,
BattlePyramid_Text_ExitHintLeft2,
BattlePyramid_Text_ExitHintRight2,
BattlePyramid_Text_ExitHintDown2,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingItemsHintTexts2[] =
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroItemsRemaining2,
BattlePyramid_Text_OneItemRemaining2,
BattlePyramid_Text_TwoItemsRemaining2,
BattlePyramid_Text_ThreeItemsRemaining2,
BattlePyramid_Text_FourItemsRemaining2,
BattlePyramid_Text_FiveItemsRemaining2,
BattlePyramid_Text_SixItemsRemaining2,
BattlePyramid_Text_SevenItemsRemaining2,
BattlePyramid_Text_EightItemsRemaining2,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingTrainersHintTexts2[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroTrainersRemaining2,
BattlePyramid_Text_OneTrainersRemaining2,
BattlePyramid_Text_TwoTrainersRemaining2,
BattlePyramid_Text_ThreeTrainersRemaining2,
BattlePyramid_Text_FourTrainersRemaining2,
BattlePyramid_Text_FiveTrainersRemaining2,
BattlePyramid_Text_SixTrainersRemaining2,
BattlePyramid_Text_SevenTrainersRemaining2,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sExitDirectionHintTexts3[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ExitHintUp3,
BattlePyramid_Text_ExitHintLeft3,
BattlePyramid_Text_ExitHintRight3,
BattlePyramid_Text_ExitHintDown3,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingItemsHintTexts3[] =
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroItemsRemaining3,
BattlePyramid_Text_OneItemRemaining3,
BattlePyramid_Text_TwoItemsRemaining3,
BattlePyramid_Text_ThreeItemsRemaining3,
BattlePyramid_Text_FourItemsRemaining3,
BattlePyramid_Text_FiveItemsRemaining3,
BattlePyramid_Text_SixItemsRemaining3,
BattlePyramid_Text_SevenItemsRemaining3,
BattlePyramid_Text_EightItemsRemaining3,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingTrainersHintTexts3[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroTrainersRemaining3,
BattlePyramid_Text_OneTrainersRemaining3,
BattlePyramid_Text_TwoTrainersRemaining3,
BattlePyramid_Text_ThreeTrainersRemaining3,
BattlePyramid_Text_FourTrainersRemaining3,
BattlePyramid_Text_FiveTrainersRemaining3,
BattlePyramid_Text_SixTrainersRemaining3,
BattlePyramid_Text_SevenTrainersRemaining3,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sExitDirectionHintTexts4[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ExitHintUp4,
BattlePyramid_Text_ExitHintLeft4,
BattlePyramid_Text_ExitHintRight4,
BattlePyramid_Text_ExitHintDown4,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingItemsHintTexts4[] =
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroItemsRemaining4,
BattlePyramid_Text_OneItemRemaining4,
BattlePyramid_Text_TwoItemsRemaining4,
BattlePyramid_Text_ThreeItemsRemaining4,
BattlePyramid_Text_FourItemsRemaining4,
BattlePyramid_Text_FiveItemsRemaining4,
BattlePyramid_Text_SixItemsRemaining4,
BattlePyramid_Text_SevenItemsRemaining4,
BattlePyramid_Text_EightItemsRemaining4,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingTrainersHintTexts4[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroTrainersRemaining4,
BattlePyramid_Text_OneTrainersRemaining4,
BattlePyramid_Text_TwoTrainersRemaining4,
BattlePyramid_Text_ThreeTrainersRemaining4,
BattlePyramid_Text_FourTrainersRemaining4,
BattlePyramid_Text_FiveTrainersRemaining4,
BattlePyramid_Text_SixTrainersRemaining4,
BattlePyramid_Text_SevenTrainersRemaining4,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sExitDirectionHintTexts5[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ExitHintUp5,
BattlePyramid_Text_ExitHintLeft5,
BattlePyramid_Text_ExitHintRight5,
BattlePyramid_Text_ExitHintDown5,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingItemsHintTexts5[] =
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroItemsRemaining5,
BattlePyramid_Text_OneItemRemaining5,
BattlePyramid_Text_TwoItemsRemaining5,
BattlePyramid_Text_ThreeItemsRemaining5,
BattlePyramid_Text_FourItemsRemaining5,
BattlePyramid_Text_FiveItemsRemaining5,
BattlePyramid_Text_SixItemsRemaining5,
BattlePyramid_Text_SevenItemsRemaining5,
BattlePyramid_Text_EightItemsRemaining5,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingTrainersHintTexts5[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroTrainersRemaining5,
BattlePyramid_Text_OneTrainersRemaining5,
BattlePyramid_Text_TwoTrainersRemaining5,
BattlePyramid_Text_ThreeTrainersRemaining5,
BattlePyramid_Text_FourTrainersRemaining5,
BattlePyramid_Text_FiveTrainersRemaining5,
BattlePyramid_Text_SixTrainersRemaining5,
BattlePyramid_Text_SevenTrainersRemaining5,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sExitDirectionHintTexts6[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ExitHintUp6,
BattlePyramid_Text_ExitHintLeft6,
BattlePyramid_Text_ExitHintRight6,
BattlePyramid_Text_ExitHintDown6,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingItemsHintTexts6[] =
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroItemsRemaining6,
BattlePyramid_Text_OneItemRemaining6,
BattlePyramid_Text_TwoItemsRemaining6,
BattlePyramid_Text_ThreeItemsRemaining6,
BattlePyramid_Text_FourItemsRemaining6,
BattlePyramid_Text_FiveItemsRemaining6,
BattlePyramid_Text_SixItemsRemaining6,
BattlePyramid_Text_SevenItemsRemaining6,
BattlePyramid_Text_EightItemsRemaining6,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const sRemainingTrainersHintTexts6[] =
2018-11-27 21:45:50 +00:00
{
2019-12-11 08:28:55 +00:00
BattlePyramid_Text_ZeroTrainersRemaining6,
BattlePyramid_Text_OneTrainersRemaining6,
BattlePyramid_Text_TwoTrainersRemaining6,
BattlePyramid_Text_ThreeTrainersRemaining6,
BattlePyramid_Text_FourTrainersRemaining6,
BattlePyramid_Text_FiveTrainersRemaining6,
BattlePyramid_Text_SixTrainersRemaining6,
BattlePyramid_Text_SevenTrainersRemaining6,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const *const sPostBattleHintTexts1[] =
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
sExitDirectionHintTexts1,
sRemainingItemsHintTexts1,
sRemainingTrainersHintTexts1,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const *const sPostBattleHintTexts2[] =
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
sExitDirectionHintTexts2,
sRemainingItemsHintTexts2,
sRemainingTrainersHintTexts2,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const *const sPostBattleHintTexts3[] =
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
sExitDirectionHintTexts3,
sRemainingItemsHintTexts3,
sRemainingTrainersHintTexts3,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const *const sPostBattleHintTexts4[] =
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
sExitDirectionHintTexts4,
sRemainingItemsHintTexts4,
sRemainingTrainersHintTexts4,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const *const sPostBattleHintTexts5[] =
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
sExitDirectionHintTexts5,
sRemainingItemsHintTexts5,
sRemainingTrainersHintTexts5,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const *const sPostBattleHintTexts6[] =
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
sExitDirectionHintTexts6,
sRemainingItemsHintTexts6,
sRemainingTrainersHintTexts6,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 *const *const *const sPostBattleTexts[] =
2018-11-27 21:45:50 +00:00
{
2019-02-07 02:01:29 +00:00
sPostBattleHintTexts1,
sPostBattleHintTexts2,
sPostBattleHintTexts3,
sPostBattleHintTexts4,
sPostBattleHintTexts5,
sPostBattleHintTexts6,
2018-11-27 21:45:50 +00:00
};
2019-02-07 02:01:29 +00:00
static const u8 sHintTextTypes[] =
{
HINT_EXIT_SHORT_REMAINING_TRAINERS,
HINT_EXIT_SHORT_REMAINING_ITEMS,
HINT_EXIT_MEDIUM_REMAINING_TRAINERS,
HINT_EXIT_MEDIUM_REMAINING_ITEMS,
HINT_EXIT_FAR_REMAINING_TRAINERS,
HINT_EXIT_FAR_REMAINING_ITEMS,
HINT_EXIT_SHORT_REMAINING_TRAINERS,
HINT_EXIT_SHORT_REMAINING_ITEMS,
};
2018-11-18 16:52:22 +00:00
static void (* const sBattlePyramidFunctions[])(void) =
{
2019-12-11 08:28:55 +00:00
[BATTLE_PYRAMID_FUNC_INIT] = InitPyramidChallenge,
[BATTLE_PYRAMID_FUNC_GET_DATA] = GetBattlePyramidData,
[BATTLE_PYRAMID_FUNC_SET_DATA] = SetBattlePyramidData,
[BATTLE_PYRAMID_FUNC_SAVE] = SavePyramidChallenge,
[BATTLE_PYRAMID_FUNC_SET_PRIZE] = SetBattlePyramidPrize,
[BATTLE_PYRAMID_FUNC_GIVE_PRIZE] = GiveBattlePyramidPrize,
[BATTLE_PYRAMID_FUNC_SEED_FLOOR] = SeedPyramidFloor,
[BATTLE_PYRAMID_FUNC_SET_ITEM] = SetPickupItem,
[BATTLE_PYRAMID_FUNC_HIDE_ITEM] = HidePyramidItem,
[BATTLE_PYRAMID_FUNC_SET_TRAINERS] = SetPyramidFacilityTrainers,
[BATTLE_PYRAMID_FUNC_SHOW_HINT_TEXT] = ShowPostBattleHintText,
[BATTLE_PYRAMID_FUNC_UPDATE_STREAK] = UpdatePyramidWinStreak,
[BATTLE_PYRAMID_FUNC_IS_IN] = GetInBattlePyramid,
[BATTLE_PYRAMID_FUNC_UPDATE_LIGHT] = UpdatePyramidLightRadius,
[BATTLE_PYRAMID_FUNC_CLEAR_HELD_ITEMS] = ClearPyramidPartyHeldItems,
2019-12-02 14:52:16 +00:00
[BATTLE_PYRAMID_FUNC_SET_FLOOR_PALETTE] = SetPyramidFloorPalette,
2019-12-11 08:28:55 +00:00
[BATTLE_PYRAMID_FUNC_START_MENU] = BattlePyramidStartMenu,
[BATTLE_PYRAMID_FUNC_RESTORE_PARTY] = RestorePyramidPlayerParty,
2018-11-18 16:52:22 +00:00
};
2019-02-07 02:01:29 +00:00
static const u16 sShortStreakRewardItems[] = {ITEM_HP_UP, ITEM_PROTEIN, ITEM_IRON, ITEM_CALCIUM, ITEM_CARBOS, ITEM_ZINC};
static const u16 sLongStreakRewardItems[] = {ITEM_BRIGHT_POWDER, ITEM_WHITE_HERB, ITEM_QUICK_CLAW, ITEM_LEFTOVERS, ITEM_MENTAL_HERB, ITEM_KINGS_ROCK, ITEM_FOCUS_BAND, ITEM_SCOPE_LENS, ITEM_CHOICE_BAND};
static const u8 sBorderedSquareIds[][4] =
{
{1, 4, -1, -1},
{0, 2, 5, -1},
{1, 3, 6, -1},
{2, 7, -1, -1},
{0, 5, 8, -1},
{1, 4, 6, 9},
{2, 5, 7, 10},
{3, 6, 11, -1},
{4, 9, 12, -1},
{5, 8, 10, 13},
{6, 9, 11, 14},
{7, 10, 15, -1},
{8, 13, -1, -1},
{9, 12, 14, -1},
{10, 13, 15, -1},
{11, 14, -1, -1},
2018-11-18 16:52:22 +00:00
};
static const u8 sPickupPercentages[PICKUP_ITEMS_PER_ROUND] = {30, 40, 50, 60, 70, 80, 85, 90, 95, 100};
2018-11-17 14:30:34 +00:00
// code
2018-11-18 16:52:22 +00:00
void CallBattlePyramidFunction(void)
2018-11-17 14:30:34 +00:00
{
2018-11-18 16:52:22 +00:00
sBattlePyramidFunctions[gSpecialVar_0x8004]();
2018-11-17 14:30:34 +00:00
}
2019-02-07 23:37:41 +00:00
static void InitPyramidChallenge(void)
2018-11-17 14:30:34 +00:00
{
bool32 isCurrent;
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.challengeStatus = 0;
2018-11-17 14:30:34 +00:00
gSaveBlock2Ptr->frontier.curChallengeBattleNum = 0;
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.challengePaused = FALSE;
2018-11-17 14:30:34 +00:00
if (lvlMode != FRONTIER_LVL_50)
2019-11-24 21:58:40 +00:00
isCurrent = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_PYRAMID_OPEN;
2018-11-17 14:30:34 +00:00
else
2019-11-24 21:58:40 +00:00
isCurrent = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_PYRAMID_50;
2018-11-17 14:30:34 +00:00
if (!isCurrent)
{
gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] = 0;
2019-02-07 02:01:29 +00:00
InitPyramidBagItems(lvlMode);
2018-11-17 14:30:34 +00:00
}
2019-02-07 02:01:29 +00:00
InitBattlePyramidBagCursorPosition();
2018-11-17 14:30:34 +00:00
gTrainerBattleOpponent_A = 0;
gBattleOutcome = 0;
}
2019-02-07 02:01:29 +00:00
static void GetBattlePyramidData(void)
2018-11-17 14:30:34 +00:00
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
switch (gSpecialVar_0x8005)
{
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_PRIZE:
gSpecialVar_Result = gSaveBlock2Ptr->frontier.pyramidPrize;
2018-11-17 14:30:34 +00:00
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_WIN_STREAK:
2018-11-17 14:30:34 +00:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode];
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_WIN_STREAK_ACTIVE:
2018-11-17 14:30:34 +00:00
if (lvlMode != FRONTIER_LVL_50)
2019-11-24 21:58:40 +00:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_PYRAMID_OPEN;
2018-11-17 14:30:34 +00:00
else
2019-11-24 21:58:40 +00:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_PYRAMID_50;
2018-11-17 14:30:34 +00:00
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_WIN_STREAK_50:
2018-11-17 14:30:34 +00:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.pyramidWinStreaks[FRONTIER_LVL_50];
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_WIN_STREAK_OPEN:
2018-11-17 14:30:34 +00:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.pyramidWinStreaks[FRONTIER_LVL_OPEN];
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_WIN_STREAK_ACTIVE_50:
2019-11-24 21:58:40 +00:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_PYRAMID_50;
2018-11-17 14:30:34 +00:00
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_WIN_STREAK_ACTIVE_OPEN:
2019-11-24 21:58:40 +00:00
gSpecialVar_Result = gSaveBlock2Ptr->frontier.winStreakActiveFlags & STREAK_PYRAMID_OPEN;
2018-11-17 14:30:34 +00:00
break;
}
}
2019-02-07 02:01:29 +00:00
static void SetBattlePyramidData(void)
2018-11-17 14:30:34 +00:00
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
switch (gSpecialVar_0x8005)
{
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_PRIZE:
gSaveBlock2Ptr->frontier.pyramidPrize = gSpecialVar_0x8006;
2018-11-17 14:30:34 +00:00
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_WIN_STREAK:
2018-11-17 14:30:34 +00:00
gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] = gSpecialVar_0x8006;
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_WIN_STREAK_ACTIVE:
2018-11-17 14:30:34 +00:00
if (lvlMode != FRONTIER_LVL_50)
{
if (gSpecialVar_0x8006)
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.winStreakActiveFlags |= STREAK_PYRAMID_OPEN;
2018-11-17 14:30:34 +00:00
else
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.winStreakActiveFlags &= ~(STREAK_PYRAMID_OPEN);
2018-11-17 14:30:34 +00:00
}
else
{
if (gSpecialVar_0x8006)
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.winStreakActiveFlags |= STREAK_PYRAMID_50;
2018-11-17 14:30:34 +00:00
else
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.winStreakActiveFlags &= ~(STREAK_PYRAMID_50);
2018-11-17 14:30:34 +00:00
}
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_DATA_TRAINER_FLAGS:
2019-02-07 02:01:29 +00:00
gSaveBlock2Ptr->frontier.pyramidTrainerFlags = gSpecialVar_0x8006;
2018-11-17 14:30:34 +00:00
break;
}
}
static void SavePyramidChallenge(void)
2018-11-17 14:30:34 +00:00
{
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.challengeStatus = gSpecialVar_0x8005;
2023-08-04 19:17:28 +01:00
VarSet(VAR_TEMP_CHALLENGE_STATUS, 0);
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.challengePaused = TRUE;
2021-04-06 21:05:43 +01:00
SaveMapView();
2018-11-17 14:30:34 +00:00
TrySavingData(SAVE_LINK);
}
static void SetBattlePyramidPrize(void)
2018-11-17 14:30:34 +00:00
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
if (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] > 41)
gSaveBlock2Ptr->frontier.pyramidPrize = sLongStreakRewardItems[Random() % ARRAY_COUNT(sLongStreakRewardItems)];
2018-11-17 14:30:34 +00:00
else
gSaveBlock2Ptr->frontier.pyramidPrize = sShortStreakRewardItems[Random() % ARRAY_COUNT(sShortStreakRewardItems)];
2018-11-17 14:30:34 +00:00
}
static void GiveBattlePyramidPrize(void)
2018-11-17 14:30:34 +00:00
{
if (AddBagItem(gSaveBlock2Ptr->frontier.pyramidPrize, 1) == TRUE)
2018-11-17 14:30:34 +00:00
{
CopyItemName(gSaveBlock2Ptr->frontier.pyramidPrize, gStringVar1);
gSaveBlock2Ptr->frontier.pyramidPrize = 0;
2018-11-17 14:30:34 +00:00
gSpecialVar_Result = TRUE;
}
else
{
gSpecialVar_Result = FALSE;
}
}
2019-02-07 02:01:29 +00:00
static void SeedPyramidFloor(void)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
2018-11-17 14:30:34 +00:00
for (i = 0; i < (int)ARRAY_COUNT(gSaveBlock2Ptr->frontier.pyramidRandoms); i++)
2019-02-07 02:01:29 +00:00
gSaveBlock2Ptr->frontier.pyramidRandoms[i] = Random();
2018-11-17 14:30:34 +00:00
2019-02-07 02:01:29 +00:00
gSaveBlock2Ptr->frontier.pyramidTrainerFlags = 0;
2018-11-17 14:30:34 +00:00
}
2019-02-07 02:01:29 +00:00
static void SetPickupItem(void)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
int itemIndex;
int rand;
2018-11-17 14:30:34 +00:00
u8 id;
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
u32 floor = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
2023-02-01 16:43:21 +00:00
u32 round = (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] / FRONTIER_STAGES_PER_CHALLENGE) % TOTAL_PYRAMID_ROUNDS;
2018-11-17 14:30:34 +00:00
2023-02-01 16:43:21 +00:00
if (round >= TOTAL_PYRAMID_ROUNDS)
round = TOTAL_PYRAMID_ROUNDS - 1;
2018-11-17 14:30:34 +00:00
2019-02-07 02:01:29 +00:00
id = GetPyramidFloorTemplateId();
itemIndex = (gSpecialVar_LastTalked - sPyramidFloorTemplates[id].numTrainers) - 1;
rand = gSaveBlock2Ptr->frontier.pyramidRandoms[itemIndex / 2];
2018-11-17 14:30:34 +00:00
SeedRng2(rand);
2019-02-07 02:01:29 +00:00
for (i = 0; i < itemIndex + 1; i++)
2018-11-17 14:30:34 +00:00
rand = Random2() % 100;
2019-02-07 02:01:29 +00:00
for (i = sPickupItemOffsets[floor]; i < ARRAY_COUNT(sPickupItemSlots); i++)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
if (rand < sPickupItemSlots[i][0])
2018-11-17 14:30:34 +00:00
break;
}
if (lvlMode != FRONTIER_LVL_50)
2019-02-07 02:01:29 +00:00
gSpecialVar_0x8000 = sPickupItemsLvlOpen[round][sPickupItemSlots[i][1]];
2018-11-17 14:30:34 +00:00
else
2019-02-07 02:01:29 +00:00
gSpecialVar_0x8000 = sPickupItemsLvl50[round][sPickupItemSlots[i][1]];
2018-11-17 14:30:34 +00:00
2019-12-02 14:52:16 +00:00
// Quantity of item to give
2018-11-17 14:30:34 +00:00
gSpecialVar_0x8001 = 1;
}
2019-02-07 02:01:29 +00:00
static void HidePyramidItem(void)
2018-11-17 14:30:34 +00:00
{
struct ObjectEventTemplate *events = gSaveBlock1Ptr->objectEventTemplates;
2019-02-07 02:01:29 +00:00
int i = 0;
2018-11-17 14:30:34 +00:00
for (;;)
{
if (events[i].localId == gSpecialVar_LastTalked)
{
// Rather than using event flags to hide the item object event,
2019-02-07 02:01:29 +00:00
// it moves them far off the map bounds.
events[i].x = SHRT_MAX;
events[i].y = SHRT_MAX;
2018-11-17 14:30:34 +00:00
break;
}
i++;
if (events[i].localId == 0)
break;
}
}
2019-12-11 08:28:55 +00:00
static void SetPyramidFacilityTrainers(void)
2018-11-17 14:30:34 +00:00
{
gFacilityTrainers = gBattleFrontierTrainers;
}
2019-02-07 02:01:29 +00:00
static void ShowPostBattleHintText(void)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
int hintType;
2018-11-17 14:30:34 +00:00
u8 id;
2019-02-07 02:01:29 +00:00
int textGroup = 0;
int textIndex = 0;
struct ObjectEventTemplate *events = gSaveBlock1Ptr->objectEventTemplates;
u16 trainerId = LocalIdToPyramidTrainerId(gObjectEvents[gSelectedObjectEvent].localId);
2018-11-17 14:30:34 +00:00
2019-02-07 02:01:29 +00:00
for (i = 0; i < ARRAY_COUNT(sTrainerTextGroups); i++)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
if (sTrainerTextGroups[i][0] == gFacilityTrainers[trainerId].facilityClass)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
textGroup = sTrainerTextGroups[i][1];
2018-11-17 14:30:34 +00:00
break;
}
}
hintType = sHintTextTypes[gObjectEvents[gSelectedObjectEvent].localId - 1];
2018-11-17 14:30:34 +00:00
i = 0;
while (!i)
{
2019-02-07 02:01:29 +00:00
switch (hintType)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
case HINT_EXIT_DIRECTION:
textIndex = GetPostBattleDirectionHintTextIndex(&hintType, 8, HINT_EXIT_DIRECTION);
2018-11-17 14:30:34 +00:00
i = 1;
break;
2019-02-07 02:01:29 +00:00
case HINT_REMAINING_ITEMS:
for (i = 0; i < GetNumBattlePyramidObjectEvents(); i++)
2018-11-17 14:30:34 +00:00
{
if (events[i].graphicsId == OBJ_EVENT_GFX_ITEM_BALL && events[i].x != SHRT_MAX && events[i].y != SHRT_MAX)
2019-02-07 02:01:29 +00:00
textIndex++;
2018-11-17 14:30:34 +00:00
}
i = 1;
break;
2019-02-07 02:01:29 +00:00
case HINT_REMAINING_TRAINERS:
id = GetPyramidFloorTemplateId();
textIndex = sPyramidFloorTemplates[id].numTrainers;
for (i = 0; i < MAX_PYRAMID_TRAINERS; i++)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
if (gBitTable[i] & gSaveBlock2Ptr->frontier.pyramidTrainerFlags)
textIndex--;
2018-11-17 14:30:34 +00:00
}
i = 1;
break;
2019-02-07 02:01:29 +00:00
case HINT_EXIT_SHORT_REMAINING_TRAINERS:
GetPostBattleDirectionHintTextIndex(&hintType, 8, HINT_REMAINING_TRAINERS);
2018-11-17 14:30:34 +00:00
break;
2019-02-07 02:01:29 +00:00
case HINT_EXIT_SHORT_REMAINING_ITEMS:
GetPostBattleDirectionHintTextIndex(&hintType, 8, HINT_REMAINING_ITEMS);
2018-11-17 14:30:34 +00:00
break;
2019-02-07 02:01:29 +00:00
case HINT_EXIT_MEDIUM_REMAINING_TRAINERS:
GetPostBattleDirectionHintTextIndex(&hintType, 16, HINT_REMAINING_TRAINERS);
2018-11-17 14:30:34 +00:00
break;
2019-02-07 02:01:29 +00:00
case HINT_EXIT_MEDIUM_REMAINING_ITEMS:
GetPostBattleDirectionHintTextIndex(&hintType, 16, HINT_REMAINING_ITEMS);
2018-11-17 14:30:34 +00:00
break;
2019-02-07 02:01:29 +00:00
case HINT_EXIT_FAR_REMAINING_TRAINERS:
GetPostBattleDirectionHintTextIndex(&hintType, 24, HINT_REMAINING_TRAINERS);
2018-11-17 14:30:34 +00:00
break;
2019-02-07 02:01:29 +00:00
case HINT_EXIT_FAR_REMAINING_ITEMS:
GetPostBattleDirectionHintTextIndex(&hintType, 24, HINT_REMAINING_ITEMS);
2018-11-17 14:30:34 +00:00
break;
}
}
2019-02-07 02:01:29 +00:00
ShowFieldMessage(sPostBattleTexts[textGroup][hintType][textIndex]);
2018-11-17 14:30:34 +00:00
}
2019-02-07 02:01:29 +00:00
static void UpdatePyramidWinStreak(void)
2018-11-17 14:30:34 +00:00
{
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
if (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] < 999)
gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode]++;
if (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] > gSaveBlock2Ptr->frontier.pyramidRecordStreaks[lvlMode])
gSaveBlock2Ptr->frontier.pyramidRecordStreaks[lvlMode] = gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode];
}
2019-02-07 02:01:29 +00:00
static void GetInBattlePyramid(void)
2018-11-17 14:30:34 +00:00
{
gSpecialVar_Result = InBattlePyramid();
}
2019-02-07 02:01:29 +00:00
static void UpdatePyramidLightRadius(void)
2018-11-17 14:30:34 +00:00
{
switch (gSpecialVar_0x8006)
{
2019-12-02 14:52:16 +00:00
case PYRAMID_LIGHT_SET_RADIUS:
2019-02-07 02:01:29 +00:00
gSaveBlock2Ptr->frontier.pyramidLightRadius = gSpecialVar_0x8005;
2018-11-17 14:30:34 +00:00
break;
2019-12-02 14:52:16 +00:00
case PYRAMID_LIGHT_INCR_RADIUS:
2018-11-17 14:30:34 +00:00
switch (gSpecialVar_Result)
{
case 0:
if (!gPaletteFade.active)
{
2019-02-07 02:01:29 +00:00
if (gSaveBlock2Ptr->frontier.pyramidLightRadius >= 120)
gSaveBlock2Ptr->frontier.pyramidLightRadius = 120;
2018-11-17 14:30:34 +00:00
else
PlaySE(gSpecialVar_0x8007);
gSpecialVar_Result++;
}
break;
case 1:
if (gSpecialVar_0x8005 != 0)
{
gSpecialVar_0x8005--;
2019-02-07 02:01:29 +00:00
gSaveBlock2Ptr->frontier.pyramidLightRadius++;
if (gSaveBlock2Ptr->frontier.pyramidLightRadius > 120)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
gSaveBlock2Ptr->frontier.pyramidLightRadius = 120;
2018-11-17 14:30:34 +00:00
gSpecialVar_Result++;
}
2019-02-07 02:01:29 +00:00
WriteBattlePyramidViewScanlineEffectBuffer();
2018-11-17 14:30:34 +00:00
}
else
{
gSpecialVar_Result = 2;
}
break;
case 2:
default:
break;
}
break;
}
}
2019-02-07 02:01:29 +00:00
static void ClearPyramidPartyHeldItems(void)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
int i, j;
2018-11-17 14:30:34 +00:00
u16 item = 0;
for (i = 0; i < PARTY_SIZE; i++)
{
2019-11-24 21:58:40 +00:00
for (j = 0; j < MAX_FRONTIER_PARTY_SIZE; j++)
2018-11-17 14:30:34 +00:00
{
if (gSaveBlock2Ptr->frontier.selectedPartyMons[j] != 0 && gSaveBlock2Ptr->frontier.selectedPartyMons[j] - 1 == i)
SetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM, &item);
}
}
}
2019-02-07 02:01:29 +00:00
static void SetPyramidFloorPalette(void)
2018-11-17 14:30:34 +00:00
{
2019-02-07 02:01:29 +00:00
CreateTask(Task_SetPyramidFloorPalette, 0);
2018-11-17 14:30:34 +00:00
}
2019-02-07 02:01:29 +00:00
static void Task_SetPyramidFloorPalette(u8 taskId)
2018-11-17 14:30:34 +00:00
{
if (gPaletteFade.active)
{
2023-05-23 18:16:18 +01:00
CpuCopy16(gBattlePyramidFloor_Pal[gSaveBlock2Ptr->frontier.curChallengeBattleNum], &gPlttBufferUnfaded[BG_PLTT_ID(6)], PLTT_SIZE_4BPP);
2018-11-17 14:30:34 +00:00
DestroyTask(taskId);
}
}
2019-12-11 08:28:55 +00:00
// Unused. Handled by BuildStartMenuActions
static void BattlePyramidStartMenu(void)
2018-11-17 14:30:34 +00:00
{
2019-12-11 08:28:55 +00:00
ShowBattlePyramidStartMenu();
2018-11-17 14:30:34 +00:00
}
2018-11-17 21:55:39 +00:00
2019-02-07 17:37:28 +00:00
static void RestorePyramidPlayerParty(void)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
int i, j, k, l;
2018-11-17 21:55:39 +00:00
2019-11-24 21:58:40 +00:00
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
int partyIndex = gSaveBlock2Ptr->frontier.selectedPartyMons[i] - 1;
2019-11-24 21:58:40 +00:00
for (j = 0; j < FRONTIER_PARTY_SIZE; j++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (GetMonData(&gSaveBlock1Ptr->playerParty[partyIndex], MON_DATA_SPECIES, NULL) == GetMonData(&gPlayerParty[j], MON_DATA_SPECIES, NULL))
2018-11-17 21:55:39 +00:00
{
for (k = 0; k < MAX_MON_MOVES; k++)
2018-11-17 21:55:39 +00:00
{
for (l = 0; l < MAX_MON_MOVES; l++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (GetMonData(&gSaveBlock1Ptr->playerParty[partyIndex], MON_DATA_MOVE1 + l, NULL) == GetMonData(&gPlayerParty[j], MON_DATA_MOVE1 + k, NULL))
2018-11-17 21:55:39 +00:00
break;
}
if (l == MAX_MON_MOVES)
2018-11-17 21:55:39 +00:00
SetMonMoveSlot(&gPlayerParty[j], MOVE_SKETCH, k);
}
2019-02-07 02:01:29 +00:00
gSaveBlock1Ptr->playerParty[partyIndex] = gPlayerParty[j];
gSelectedOrderFromParty[j] = partyIndex + 1;
2018-11-17 21:55:39 +00:00
break;
}
}
}
2019-11-24 21:58:40 +00:00
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
2018-11-25 21:50:54 +00:00
gSaveBlock2Ptr->frontier.selectedPartyMons[i] = gSelectedOrderFromParty[i];
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
static u8 GetPostBattleDirectionHintTextIndex(int *hintType, u8 minDistanceForExitHint, u8 defaultHintType)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
int x, y;
u8 textIndex = 0;
2018-12-28 17:18:23 +00:00
u16 *map = gBackupMapLayout.map;
2021-10-09 17:12:18 +01:00
map += gBackupMapLayout.width * 7 + MAP_OFFSET;
2018-11-17 21:55:39 +00:00
2019-02-07 02:01:29 +00:00
for (y = 0; y < 32; map += 47, y++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
for (x = 0; x < 32; x++)
2018-11-17 21:55:39 +00:00
{
if ((map[x] & MAPGRID_METATILE_ID_MASK) == METATILE_BattlePyramid_Exit)
2018-11-17 21:55:39 +00:00
{
2021-10-09 17:12:18 +01:00
x += MAP_OFFSET - gObjectEvents[gSelectedObjectEvent].initialCoords.x;
y += MAP_OFFSET - gObjectEvents[gSelectedObjectEvent].initialCoords.y;
2019-02-07 02:01:29 +00:00
if (x >= minDistanceForExitHint
|| x <= -minDistanceForExitHint
|| y >= minDistanceForExitHint
|| y <= -minDistanceForExitHint
|| defaultHintType == HINT_EXIT_DIRECTION)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (x > 0 && y > 0)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (x >= y)
textIndex = 2;
2018-11-17 21:55:39 +00:00
else
2019-02-07 02:01:29 +00:00
textIndex = 3;
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
else if (x < 0 && y < 0)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (x > y)
textIndex = 0;
2018-11-17 21:55:39 +00:00
else
2019-02-07 02:01:29 +00:00
textIndex = 1;
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
else if (x == 0)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (y > 0)
textIndex = 3;
2018-11-17 21:55:39 +00:00
else
2019-02-07 02:01:29 +00:00
textIndex = 0;
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
else if (y == 0)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (x > 0)
textIndex = 2;
2018-11-17 21:55:39 +00:00
else
2019-02-07 02:01:29 +00:00
textIndex = 1;
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
else if (x < 0)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (x + y > 0)
textIndex = 3;
2018-11-17 21:55:39 +00:00
else
2019-02-07 02:01:29 +00:00
textIndex = 1;
2018-11-17 21:55:39 +00:00
}
else
{
2019-02-07 02:01:29 +00:00
textIndex = (~(x + y) >= 0) ? 0 : 2;
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
*hintType = HINT_EXIT_DIRECTION;
2018-11-17 21:55:39 +00:00
}
else
{
2019-02-07 02:01:29 +00:00
*hintType = defaultHintType;
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
return textIndex;
2018-11-17 21:55:39 +00:00
}
}
}
2019-02-07 02:01:29 +00:00
return textIndex;
2018-11-17 21:55:39 +00:00
}
2018-11-18 16:52:22 +00:00
u16 LocalIdToPyramidTrainerId(u8 localId)
2018-11-17 21:55:39 +00:00
{
2019-02-07 17:37:28 +00:00
return gSaveBlock2Ptr->frontier.trainerIds[localId - 1];
2018-11-17 21:55:39 +00:00
}
bool8 GetBattlePyramidTrainerFlag(u8 eventId)
{
return gSaveBlock2Ptr->frontier.pyramidTrainerFlags & gBitTable[gObjectEvents[eventId].localId - 1];
2018-11-17 21:55:39 +00:00
}
2019-02-07 17:37:28 +00:00
void MarkApproachingPyramidTrainersAsBattled(void)
2018-11-17 21:55:39 +00:00
{
2019-02-07 17:37:28 +00:00
MarkPyramidTrainerAsBattled(gTrainerBattleOpponent_A);
2018-11-17 21:55:39 +00:00
if (gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS)
{
gSelectedObjectEvent = GetChosenApproachingTrainerObjectEventId(1);
2019-02-07 17:37:28 +00:00
MarkPyramidTrainerAsBattled(gTrainerBattleOpponent_B);
2018-11-17 21:55:39 +00:00
}
}
2019-02-07 17:37:28 +00:00
static void MarkPyramidTrainerAsBattled(u16 trainerId)
2018-11-17 21:55:39 +00:00
{
2019-02-07 17:37:28 +00:00
int i;
2018-11-17 21:55:39 +00:00
for (i = 0; i < MAX_PYRAMID_TRAINERS; i++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 17:37:28 +00:00
if (gSaveBlock2Ptr->frontier.trainerIds[i] == trainerId)
2019-02-07 02:01:29 +00:00
gSaveBlock2Ptr->frontier.pyramidTrainerFlags |= gBitTable[i];
2018-11-17 21:55:39 +00:00
}
gObjectEvents[gSelectedObjectEvent].movementType = MOVEMENT_TYPE_WANDER_AROUND;
gSaveBlock1Ptr->objectEventTemplates[gSpecialVar_LastTalked - 1].movementType = MOVEMENT_TYPE_WANDER_AROUND;
gObjectEvents[gSelectedObjectEvent].initialCoords.x = gObjectEvents[gSelectedObjectEvent].currentCoords.x;
gObjectEvents[gSelectedObjectEvent].initialCoords.y = gObjectEvents[gSelectedObjectEvent].currentCoords.y;
2018-11-17 21:55:39 +00:00
}
#if BATTLE_PYRAMID_RANDOM_ENCOUNTERS == TRUE
// check if given species evolved from a specific evolutionary stone
// if nItems is passed as 0, it will check for any EVO_ITEM case
static bool32 CheckBattlePyramidEvoRequirement(u16 species, const u16 *evoItems, u8 nItems)
{
u32 i, j, k;
for (i = 0; i < NUM_SPECIES; i++)
{
Species Simplifier™ - Part 3 (#3562) * Added SpeciesInfo fields # Conflicts: # include/pokemon.h * Added missing comments * Renamed gigantamax to isGigantamax * Converted species flags to agbcc bit flags * Added padding after flags * Pikachu form config * Dex text * Reordered Paradox flag * Missing Pikachu ifdef comments * Moved P_GEN_x_POKEMON settings to the species_families file * Gen 1 Dex entries * Renamed file to species_enabled.h * Prevent Pokémon from evolving if their evolution is disabled * Prevent Pokémon from being affected by Eviolite if their evolution is disabled * Prevent Pokémon offspring if they're disabled * Corrected imprementation of evolution prevention It could potentially overwrite items by accident * Cross-evo configs * Gen 2 dex entries * Changed cry table to use assignable IDs # Conflicts: # include/pokemon.h * Form table pointers * Beginning support for moving data to gSpeciesInfo * Pokédexes reads text from gSpeciesInfo * Reading species names from gSpeciesInfo * Fixed erroneous copy-paste * Moved Bulbasaur to Raichu Family data do gSpeciesinfo * Added female pic sizes * Macros for Front, Back, Palette and Learnsets * Sandshrew to Dugtrio Families * Obtains Height/Weight from gSpeciesInfo * Read category from gSpeciesInfo * Removed unused data from pokedex_entries.h * Moved Gen 1 data to gSpeciesInfo * Moved Gen 2 data to gSpeciesInfo + fixed Ursaluna Bloodmoon not producing Teddiursa eggs * Moved Gen 3 data to gSpeciesInfo * Moved Gen 4 data to gSpeciesInfo * HGSS dex properly shows form sprites * Fixed data type for GetSpeciesHeight/Weight * Reading Pokédex Size data from gSpeciesInfo * Cleaned up mon graphic decompression function * Reading Front Pics gSpeciesInfo * Reading Back Pics gSpeciesInfo * Updated uses of GetMonSpritePalStruct to allow loading the data directly instead of reading the struct * Reading palettes from gSpeciesInfo * Reading animation delay from gSpeciesInfo * Fixed Pokémon Debug Menu not reading animation delay * Reading front anim Id from gSpeciesInfo * Reading back anim Id from gSpeciesInfo * Reading Animation Frames from gSpeciesInfo * Reading Icon Sprites from gSpeciesInfo * Reading Icon Palette IDs from gSpeciesInfo * Reading Footprints from gSpeciesInfo * Reading Mon Pic sizes from gSpeciesInfo * Separate mon pic sizes for female mon * Reading Level Up Learnsets from gSpeciesInfo * Reading Teachable Learnsets from gSpeciesInfo * Reading National Dex Number from gSpeciesInfo * Reading Enemy Mon Elevation from gSpeciesInfo * Reading Evolutions from gSpeciesInfo * Reading form table from gSpeciesInfo * Fixed button label inconsistency in pokémon debug menu * Reading form change table from gSpeciesInfo * Removed need to define mon graphics in include/graphics.h * Reordered mon graphics by family * Fixed National dex number offset * gFrontierBannedSpecies now checks IsSpeciesEnabled * Added 3 more toggles for Fusions, Primal Reversions and Ultra Burst * Gen 3 & 4 family toggles for dex entries * Fixed missing Mr. Rime data * Gen 1 dex descriptions as compound strings * Gen 2 dex descriptions as compound strings * Gen 3 dex descriptions as compound strings * Gen 4 dex descriptions as compound strings * Fixed compile in agbcc * Moved Gen 5 data to gSpeciesInfo * Using PLACEHOLDER_ANIM_SINGLE_FRAME when needed (same hash) * Renamed PLACEHOLDER_TWO_FRAME_ANIMATION to PLACEHOLDER_ANIM_TWO_FRAMES * Fixed capitalization for front pic anims * Fixed `CanEvolve` * Moved Gen 6 data to gSpeciesInfo * Gen 7 without macros * Gen 8 without macros * Gen 9 without macros * Fixed Gen 9 sound data * Finished moving Gen 7 data in macros (by Alex) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Ultra Necrozma is now included in the fusion forms define * Cries are now properly excluded from the rom when disabling species * Removed P_GEN_x_POKEMON from form_change_tables.h * Fixed Yanmega's cry ignoring the P_GEN_4_CROSS_EVOS setting * Added P_NEW_EVOS_IN_REGIONAL_DEX setting * Automatic ASSUMPTION_FAIL when used species are disabled * Finished moving Gen 8 data in macros (by Alex) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Expanded Alcremie macro * Finished moving Gen 9 data in macros (by Alex) * Fixed missing data for Komala and Marshadow * Form species id tables use family toggles + added missing Ursaluna form species id table * Fixed Genesect palettes * Fixed Flabébé family graphics * Fixed Minior Graphics * Fixed missing Calyrex data * Family toggles in mon graphcis (By Jasper/Bassoonian) Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed missing Ogerpon data * Ordered Level Up Learnsets (missing toggles) Also added White Basculin learnset * Added more Minior synonyms * Fixed enamorus order * Reordered teachable learnsets * Removed sSpeciesXXX level up learnsets + reordered * Removed unneeded assumes * Removed unused extra animations * Family toggles in mon level up learnsets (By Jasper/Bassoonian) Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed Phione graphics inclusion * Family toggles for Teachable Learnsets Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Ordered Front Pic Anims * Family toggles for front pic animations Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed HGSS dex incorrectly showing the wrong mon when catching it * Family toggles for Egg Moves + reodered Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed HGSS not checking for null footprints * Review changes * Fixed Female difference mon not using their macros * Fixed Alcremie Macro * Fixed compile error when disabling the Bulbasaur family * Fixed Turtwig and Chimchar family + Houndour and Mareep cries not being excluded properly * Re-added missing Egg graphical data * Fixed crash during the Birch Intro when Lotad is disabled * Renamed PALLETE to PALETTES * Removed extra spacing for YOffsets * Fixed compile when only disabling cross-gen evolutions * Added Tera Forms define (Ogerpon and Terapagos) * Fixed Necrozma macro * Removed .noFlip = FALSE * Fixed dex number in summary screen for forms when nat dex is disabled * Fixed Paldean form paths --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
2023-12-08 14:05:10 +00:00
const struct Evolution *evolutions = GetSpeciesEvolutions(i);
if (evolutions == NULL)
continue;
for (j = 0; evolutions[j].method != EVOLUTIONS_END; j++)
{
Species Simplifier™ - Part 3 (#3562) * Added SpeciesInfo fields # Conflicts: # include/pokemon.h * Added missing comments * Renamed gigantamax to isGigantamax * Converted species flags to agbcc bit flags * Added padding after flags * Pikachu form config * Dex text * Reordered Paradox flag * Missing Pikachu ifdef comments * Moved P_GEN_x_POKEMON settings to the species_families file * Gen 1 Dex entries * Renamed file to species_enabled.h * Prevent Pokémon from evolving if their evolution is disabled * Prevent Pokémon from being affected by Eviolite if their evolution is disabled * Prevent Pokémon offspring if they're disabled * Corrected imprementation of evolution prevention It could potentially overwrite items by accident * Cross-evo configs * Gen 2 dex entries * Changed cry table to use assignable IDs # Conflicts: # include/pokemon.h * Form table pointers * Beginning support for moving data to gSpeciesInfo * Pokédexes reads text from gSpeciesInfo * Reading species names from gSpeciesInfo * Fixed erroneous copy-paste * Moved Bulbasaur to Raichu Family data do gSpeciesinfo * Added female pic sizes * Macros for Front, Back, Palette and Learnsets * Sandshrew to Dugtrio Families * Obtains Height/Weight from gSpeciesInfo * Read category from gSpeciesInfo * Removed unused data from pokedex_entries.h * Moved Gen 1 data to gSpeciesInfo * Moved Gen 2 data to gSpeciesInfo + fixed Ursaluna Bloodmoon not producing Teddiursa eggs * Moved Gen 3 data to gSpeciesInfo * Moved Gen 4 data to gSpeciesInfo * HGSS dex properly shows form sprites * Fixed data type for GetSpeciesHeight/Weight * Reading Pokédex Size data from gSpeciesInfo * Cleaned up mon graphic decompression function * Reading Front Pics gSpeciesInfo * Reading Back Pics gSpeciesInfo * Updated uses of GetMonSpritePalStruct to allow loading the data directly instead of reading the struct * Reading palettes from gSpeciesInfo * Reading animation delay from gSpeciesInfo * Fixed Pokémon Debug Menu not reading animation delay * Reading front anim Id from gSpeciesInfo * Reading back anim Id from gSpeciesInfo * Reading Animation Frames from gSpeciesInfo * Reading Icon Sprites from gSpeciesInfo * Reading Icon Palette IDs from gSpeciesInfo * Reading Footprints from gSpeciesInfo * Reading Mon Pic sizes from gSpeciesInfo * Separate mon pic sizes for female mon * Reading Level Up Learnsets from gSpeciesInfo * Reading Teachable Learnsets from gSpeciesInfo * Reading National Dex Number from gSpeciesInfo * Reading Enemy Mon Elevation from gSpeciesInfo * Reading Evolutions from gSpeciesInfo * Reading form table from gSpeciesInfo * Fixed button label inconsistency in pokémon debug menu * Reading form change table from gSpeciesInfo * Removed need to define mon graphics in include/graphics.h * Reordered mon graphics by family * Fixed National dex number offset * gFrontierBannedSpecies now checks IsSpeciesEnabled * Added 3 more toggles for Fusions, Primal Reversions and Ultra Burst * Gen 3 & 4 family toggles for dex entries * Fixed missing Mr. Rime data * Gen 1 dex descriptions as compound strings * Gen 2 dex descriptions as compound strings * Gen 3 dex descriptions as compound strings * Gen 4 dex descriptions as compound strings * Fixed compile in agbcc * Moved Gen 5 data to gSpeciesInfo * Using PLACEHOLDER_ANIM_SINGLE_FRAME when needed (same hash) * Renamed PLACEHOLDER_TWO_FRAME_ANIMATION to PLACEHOLDER_ANIM_TWO_FRAMES * Fixed capitalization for front pic anims * Fixed `CanEvolve` * Moved Gen 6 data to gSpeciesInfo * Gen 7 without macros * Gen 8 without macros * Gen 9 without macros * Fixed Gen 9 sound data * Finished moving Gen 7 data in macros (by Alex) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Ultra Necrozma is now included in the fusion forms define * Cries are now properly excluded from the rom when disabling species * Removed P_GEN_x_POKEMON from form_change_tables.h * Fixed Yanmega's cry ignoring the P_GEN_4_CROSS_EVOS setting * Added P_NEW_EVOS_IN_REGIONAL_DEX setting * Automatic ASSUMPTION_FAIL when used species are disabled * Finished moving Gen 8 data in macros (by Alex) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Expanded Alcremie macro * Finished moving Gen 9 data in macros (by Alex) * Fixed missing data for Komala and Marshadow * Form species id tables use family toggles + added missing Ursaluna form species id table * Fixed Genesect palettes * Fixed Flabébé family graphics * Fixed Minior Graphics * Fixed missing Calyrex data * Family toggles in mon graphcis (By Jasper/Bassoonian) Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed missing Ogerpon data * Ordered Level Up Learnsets (missing toggles) Also added White Basculin learnset * Added more Minior synonyms * Fixed enamorus order * Reordered teachable learnsets * Removed sSpeciesXXX level up learnsets + reordered * Removed unneeded assumes * Removed unused extra animations * Family toggles in mon level up learnsets (By Jasper/Bassoonian) Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed Phione graphics inclusion * Family toggles for Teachable Learnsets Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Ordered Front Pic Anims * Family toggles for front pic animations Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed HGSS dex incorrectly showing the wrong mon when catching it * Family toggles for Egg Moves + reodered Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed HGSS not checking for null footprints * Review changes * Fixed Female difference mon not using their macros * Fixed Alcremie Macro * Fixed compile error when disabling the Bulbasaur family * Fixed Turtwig and Chimchar family + Houndour and Mareep cries not being excluded properly * Re-added missing Egg graphical data * Fixed crash during the Birch Intro when Lotad is disabled * Renamed PALLETE to PALETTES * Removed extra spacing for YOffsets * Fixed compile when only disabling cross-gen evolutions * Added Tera Forms define (Ogerpon and Terapagos) * Fixed Necrozma macro * Removed .noFlip = FALSE * Fixed dex number in summary screen for forms when nat dex is disabled * Fixed Paldean form paths --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
2023-12-08 14:05:10 +00:00
if (evolutions[j].targetSpecies == species
&& (evolutions[j].method == EVO_ITEM
|| evolutions[j].method == EVO_ITEM_MALE
|| evolutions[j].method == EVO_ITEM_FEMALE))
{
if (nItems == 0)
{
// Any EVO_ITEM case will do
return TRUE;
}
else
{
// Otherwise, need to match specific set provided
Species Simplifier™ - Part 3 (#3562) * Added SpeciesInfo fields # Conflicts: # include/pokemon.h * Added missing comments * Renamed gigantamax to isGigantamax * Converted species flags to agbcc bit flags * Added padding after flags * Pikachu form config * Dex text * Reordered Paradox flag * Missing Pikachu ifdef comments * Moved P_GEN_x_POKEMON settings to the species_families file * Gen 1 Dex entries * Renamed file to species_enabled.h * Prevent Pokémon from evolving if their evolution is disabled * Prevent Pokémon from being affected by Eviolite if their evolution is disabled * Prevent Pokémon offspring if they're disabled * Corrected imprementation of evolution prevention It could potentially overwrite items by accident * Cross-evo configs * Gen 2 dex entries * Changed cry table to use assignable IDs # Conflicts: # include/pokemon.h * Form table pointers * Beginning support for moving data to gSpeciesInfo * Pokédexes reads text from gSpeciesInfo * Reading species names from gSpeciesInfo * Fixed erroneous copy-paste * Moved Bulbasaur to Raichu Family data do gSpeciesinfo * Added female pic sizes * Macros for Front, Back, Palette and Learnsets * Sandshrew to Dugtrio Families * Obtains Height/Weight from gSpeciesInfo * Read category from gSpeciesInfo * Removed unused data from pokedex_entries.h * Moved Gen 1 data to gSpeciesInfo * Moved Gen 2 data to gSpeciesInfo + fixed Ursaluna Bloodmoon not producing Teddiursa eggs * Moved Gen 3 data to gSpeciesInfo * Moved Gen 4 data to gSpeciesInfo * HGSS dex properly shows form sprites * Fixed data type for GetSpeciesHeight/Weight * Reading Pokédex Size data from gSpeciesInfo * Cleaned up mon graphic decompression function * Reading Front Pics gSpeciesInfo * Reading Back Pics gSpeciesInfo * Updated uses of GetMonSpritePalStruct to allow loading the data directly instead of reading the struct * Reading palettes from gSpeciesInfo * Reading animation delay from gSpeciesInfo * Fixed Pokémon Debug Menu not reading animation delay * Reading front anim Id from gSpeciesInfo * Reading back anim Id from gSpeciesInfo * Reading Animation Frames from gSpeciesInfo * Reading Icon Sprites from gSpeciesInfo * Reading Icon Palette IDs from gSpeciesInfo * Reading Footprints from gSpeciesInfo * Reading Mon Pic sizes from gSpeciesInfo * Separate mon pic sizes for female mon * Reading Level Up Learnsets from gSpeciesInfo * Reading Teachable Learnsets from gSpeciesInfo * Reading National Dex Number from gSpeciesInfo * Reading Enemy Mon Elevation from gSpeciesInfo * Reading Evolutions from gSpeciesInfo * Reading form table from gSpeciesInfo * Fixed button label inconsistency in pokémon debug menu * Reading form change table from gSpeciesInfo * Removed need to define mon graphics in include/graphics.h * Reordered mon graphics by family * Fixed National dex number offset * gFrontierBannedSpecies now checks IsSpeciesEnabled * Added 3 more toggles for Fusions, Primal Reversions and Ultra Burst * Gen 3 & 4 family toggles for dex entries * Fixed missing Mr. Rime data * Gen 1 dex descriptions as compound strings * Gen 2 dex descriptions as compound strings * Gen 3 dex descriptions as compound strings * Gen 4 dex descriptions as compound strings * Fixed compile in agbcc * Moved Gen 5 data to gSpeciesInfo * Using PLACEHOLDER_ANIM_SINGLE_FRAME when needed (same hash) * Renamed PLACEHOLDER_TWO_FRAME_ANIMATION to PLACEHOLDER_ANIM_TWO_FRAMES * Fixed capitalization for front pic anims * Fixed `CanEvolve` * Moved Gen 6 data to gSpeciesInfo * Gen 7 without macros * Gen 8 without macros * Gen 9 without macros * Fixed Gen 9 sound data * Finished moving Gen 7 data in macros (by Alex) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Ultra Necrozma is now included in the fusion forms define * Cries are now properly excluded from the rom when disabling species * Removed P_GEN_x_POKEMON from form_change_tables.h * Fixed Yanmega's cry ignoring the P_GEN_4_CROSS_EVOS setting * Added P_NEW_EVOS_IN_REGIONAL_DEX setting * Automatic ASSUMPTION_FAIL when used species are disabled * Finished moving Gen 8 data in macros (by Alex) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Expanded Alcremie macro * Finished moving Gen 9 data in macros (by Alex) * Fixed missing data for Komala and Marshadow * Form species id tables use family toggles + added missing Ursaluna form species id table * Fixed Genesect palettes * Fixed Flabébé family graphics * Fixed Minior Graphics * Fixed missing Calyrex data * Family toggles in mon graphcis (By Jasper/Bassoonian) Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed missing Ogerpon data * Ordered Level Up Learnsets (missing toggles) Also added White Basculin learnset * Added more Minior synonyms * Fixed enamorus order * Reordered teachable learnsets * Removed sSpeciesXXX level up learnsets + reordered * Removed unneeded assumes * Removed unused extra animations * Family toggles in mon level up learnsets (By Jasper/Bassoonian) Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed Phione graphics inclusion * Family toggles for Teachable Learnsets Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Ordered Front Pic Anims * Family toggles for front pic animations Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed HGSS dex incorrectly showing the wrong mon when catching it * Family toggles for Egg Moves + reodered Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed HGSS not checking for null footprints * Review changes * Fixed Female difference mon not using their macros * Fixed Alcremie Macro * Fixed compile error when disabling the Bulbasaur family * Fixed Turtwig and Chimchar family + Houndour and Mareep cries not being excluded properly * Re-added missing Egg graphical data * Fixed crash during the Birch Intro when Lotad is disabled * Renamed PALLETE to PALETTES * Removed extra spacing for YOffsets * Fixed compile when only disabling cross-gen evolutions * Added Tera Forms define (Ogerpon and Terapagos) * Fixed Necrozma macro * Removed .noFlip = FALSE * Fixed dex number in summary screen for forms when nat dex is disabled * Fixed Paldean form paths --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
2023-12-08 14:05:10 +00:00
for (k = 0; k < nItems; k++)
{
if (evolutions[j].param == evoItems[k])
return TRUE;
}
}
}
}
}
return FALSE;
}
extern u32 GetTotalBaseStat(u32 species);
void GenerateBattlePyramidWildMon(void)
{
u8 name[POKEMON_NAME_LENGTH + 1];
int i, j;
u32 id;
u32 lvl = gSaveBlock2Ptr->frontier.lvlMode;
u16 round = (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvl] / 7) % TOTAL_PYRAMID_ROUNDS;
const struct BattlePyramidRequirement *reqs = &sBattlePyramidRequirementsByRound[round];
u16 species;
u32 bstLim;
u16 *moves = NULL;
u16 *abilities = NULL;
int moveCount = 0, abilityCount = 0;
if (reqs->nMoves != 0)
moves = AllocZeroed(sizeof(u16) * reqs->nMoves);
2024-04-01 19:31:01 +01:00
if (reqs->nAbilities != 0)
abilities = AllocZeroed(sizeof(u16) * reqs->nAbilities);
if (round >= TOTAL_PYRAMID_ROUNDS)
round = TOTAL_PYRAMID_ROUNDS - 1;
2024-04-01 19:31:01 +01:00
id = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL) - 1; // index in table (0-11) -> higher index is lower probability
bstLim = 450 + (25*round) + (5*id); // higher BST limit for 'rarer' wild mon rolls
while (1)
{
2024-04-01 19:31:01 +01:00
species = Random() % NUM_SPECIES;
// check if base species
2024-04-01 19:38:58 +01:00
if (GET_BASE_SPECIES_ID(species) != species)
2024-04-01 19:31:01 +01:00
continue;
// check type
if (reqs->type != TYPE_MYSTERY && gSpeciesInfo[species].types[0] != reqs->type && gSpeciesInfo[species].types[1] != reqs->type)
continue;
2024-04-01 19:31:01 +01:00
// check base stat total
if (GetTotalBaseStat(species) > bstLim)
continue;
2024-04-01 19:31:01 +01:00
// check moves
if (reqs->nMoves != 0)
{
moveCount = 0;
// get list of moves that can be learned
for (i = 0; i < reqs->nMoves; i++)
{
if (CanLearnTeachableMove(species, reqs->moves[i]))
{
moves[moveCount] = reqs->moves[i];
moveCount++;
}
}
if (moveCount == 0)
continue;
}
2024-04-01 19:31:01 +01:00
// check abilities
if (reqs->nAbilities != 0)
{
abilityCount = 0;
// get list of moves that can be learned
for (i = 0; i < reqs->nAbilities; i++)
{
for (j = 0; j < NUM_ABILITY_SLOTS; j++)
{
if (gSpeciesInfo[species].abilities[j] == reqs->abilities[i])
{
abilities[abilityCount] = reqs->abilities[i];
abilityCount++;
break;
}
}
}
if (abilityCount == 0)
continue;
}
// check evos
2024-04-01 19:31:01 +01:00
if (reqs->evoItems != NULL && !CheckBattlePyramidEvoRequirement(species, reqs->evoItems, reqs->nEvoItems))
continue;
2024-04-01 19:31:01 +01:00
// we found a species we can use!
break;
}
// Set species, name
SetMonData(&gEnemyParty[0], MON_DATA_SPECIES, &species);
Species Simplifier™ - Part 3 (#3562) * Added SpeciesInfo fields # Conflicts: # include/pokemon.h * Added missing comments * Renamed gigantamax to isGigantamax * Converted species flags to agbcc bit flags * Added padding after flags * Pikachu form config * Dex text * Reordered Paradox flag * Missing Pikachu ifdef comments * Moved P_GEN_x_POKEMON settings to the species_families file * Gen 1 Dex entries * Renamed file to species_enabled.h * Prevent Pokémon from evolving if their evolution is disabled * Prevent Pokémon from being affected by Eviolite if their evolution is disabled * Prevent Pokémon offspring if they're disabled * Corrected imprementation of evolution prevention It could potentially overwrite items by accident * Cross-evo configs * Gen 2 dex entries * Changed cry table to use assignable IDs # Conflicts: # include/pokemon.h * Form table pointers * Beginning support for moving data to gSpeciesInfo * Pokédexes reads text from gSpeciesInfo * Reading species names from gSpeciesInfo * Fixed erroneous copy-paste * Moved Bulbasaur to Raichu Family data do gSpeciesinfo * Added female pic sizes * Macros for Front, Back, Palette and Learnsets * Sandshrew to Dugtrio Families * Obtains Height/Weight from gSpeciesInfo * Read category from gSpeciesInfo * Removed unused data from pokedex_entries.h * Moved Gen 1 data to gSpeciesInfo * Moved Gen 2 data to gSpeciesInfo + fixed Ursaluna Bloodmoon not producing Teddiursa eggs * Moved Gen 3 data to gSpeciesInfo * Moved Gen 4 data to gSpeciesInfo * HGSS dex properly shows form sprites * Fixed data type for GetSpeciesHeight/Weight * Reading Pokédex Size data from gSpeciesInfo * Cleaned up mon graphic decompression function * Reading Front Pics gSpeciesInfo * Reading Back Pics gSpeciesInfo * Updated uses of GetMonSpritePalStruct to allow loading the data directly instead of reading the struct * Reading palettes from gSpeciesInfo * Reading animation delay from gSpeciesInfo * Fixed Pokémon Debug Menu not reading animation delay * Reading front anim Id from gSpeciesInfo * Reading back anim Id from gSpeciesInfo * Reading Animation Frames from gSpeciesInfo * Reading Icon Sprites from gSpeciesInfo * Reading Icon Palette IDs from gSpeciesInfo * Reading Footprints from gSpeciesInfo * Reading Mon Pic sizes from gSpeciesInfo * Separate mon pic sizes for female mon * Reading Level Up Learnsets from gSpeciesInfo * Reading Teachable Learnsets from gSpeciesInfo * Reading National Dex Number from gSpeciesInfo * Reading Enemy Mon Elevation from gSpeciesInfo * Reading Evolutions from gSpeciesInfo * Reading form table from gSpeciesInfo * Fixed button label inconsistency in pokémon debug menu * Reading form change table from gSpeciesInfo * Removed need to define mon graphics in include/graphics.h * Reordered mon graphics by family * Fixed National dex number offset * gFrontierBannedSpecies now checks IsSpeciesEnabled * Added 3 more toggles for Fusions, Primal Reversions and Ultra Burst * Gen 3 & 4 family toggles for dex entries * Fixed missing Mr. Rime data * Gen 1 dex descriptions as compound strings * Gen 2 dex descriptions as compound strings * Gen 3 dex descriptions as compound strings * Gen 4 dex descriptions as compound strings * Fixed compile in agbcc * Moved Gen 5 data to gSpeciesInfo * Using PLACEHOLDER_ANIM_SINGLE_FRAME when needed (same hash) * Renamed PLACEHOLDER_TWO_FRAME_ANIMATION to PLACEHOLDER_ANIM_TWO_FRAMES * Fixed capitalization for front pic anims * Fixed `CanEvolve` * Moved Gen 6 data to gSpeciesInfo * Gen 7 without macros * Gen 8 without macros * Gen 9 without macros * Fixed Gen 9 sound data * Finished moving Gen 7 data in macros (by Alex) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Ultra Necrozma is now included in the fusion forms define * Cries are now properly excluded from the rom when disabling species * Removed P_GEN_x_POKEMON from form_change_tables.h * Fixed Yanmega's cry ignoring the P_GEN_4_CROSS_EVOS setting * Added P_NEW_EVOS_IN_REGIONAL_DEX setting * Automatic ASSUMPTION_FAIL when used species are disabled * Finished moving Gen 8 data in macros (by Alex) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> * Expanded Alcremie macro * Finished moving Gen 9 data in macros (by Alex) * Fixed missing data for Komala and Marshadow * Form species id tables use family toggles + added missing Ursaluna form species id table * Fixed Genesect palettes * Fixed Flabébé family graphics * Fixed Minior Graphics * Fixed missing Calyrex data * Family toggles in mon graphcis (By Jasper/Bassoonian) Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed missing Ogerpon data * Ordered Level Up Learnsets (missing toggles) Also added White Basculin learnset * Added more Minior synonyms * Fixed enamorus order * Reordered teachable learnsets * Removed sSpeciesXXX level up learnsets + reordered * Removed unneeded assumes * Removed unused extra animations * Family toggles in mon level up learnsets (By Jasper/Bassoonian) Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed Phione graphics inclusion * Family toggles for Teachable Learnsets Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Ordered Front Pic Anims * Family toggles for front pic animations Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed HGSS dex incorrectly showing the wrong mon when catching it * Family toggles for Egg Moves + reodered Co-authored-by: Bassoonian <iasperbassoonian@gmail.com> * Fixed HGSS not checking for null footprints * Review changes * Fixed Female difference mon not using their macros * Fixed Alcremie Macro * Fixed compile error when disabling the Bulbasaur family * Fixed Turtwig and Chimchar family + Houndour and Mareep cries not being excluded properly * Re-added missing Egg graphical data * Fixed crash during the Birch Intro when Lotad is disabled * Renamed PALLETE to PALETTES * Removed extra spacing for YOffsets * Fixed compile when only disabling cross-gen evolutions * Added Tera Forms define (Ogerpon and Terapagos) * Fixed Necrozma macro * Removed .noFlip = FALSE * Fixed dex number in summary screen for forms when nat dex is disabled * Fixed Paldean form paths --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
2023-12-08 14:05:10 +00:00
StringCopy(name, GetSpeciesName(species));
SetMonData(&gEnemyParty[0], MON_DATA_NICKNAME, &name);
2024-04-01 19:31:01 +01:00
// set level
if (lvl != FRONTIER_LVL_50)
{
lvl = SetFacilityPtrsGetLevel();
lvl -= (5 + (Random() % (TOTAL_PYRAMID_ROUNDS - round)/2));
}
else
{
lvl = 50 - (5 + (Random() % (TOTAL_PYRAMID_ROUNDS - round)/4));
}
SetMonData(&gEnemyParty[0],
MON_DATA_EXP,
&gExperienceTables[gSpeciesInfo[species].growthRate][lvl]);
// Give initial moves and replace one with desired move
GiveBoxMonInitialMoveset(&gEnemyParty[0].box);
if (moves != NULL)
{
// get a random move to give
i = 0;
while (1)
{
id = moves[Random() % moveCount];
if (!MonKnowsMove(&gEnemyParty[0], id))
{
// replace random move
SetMonData(&gEnemyParty[0], MON_DATA_MOVE1 + Random() % MAX_MON_MOVES, &id);
break;
}
i++;
if (i == 20)
break;
}
Free(moves);
}
2024-04-01 19:31:01 +01:00
// Initialize a random ability num
if (gSpeciesInfo[species].abilities[1])
{
i = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY, NULL) % 2;
SetMonData(&gEnemyParty[0], MON_DATA_ABILITY_NUM, &i);
}
else
{
i = 0;
SetMonData(&gEnemyParty[0], MON_DATA_ABILITY_NUM, &i);
}
2024-04-01 19:31:01 +01:00
// Try to replace with desired ability
if (abilities != NULL)
{
i = 0;
while (1)
{
id = abilities[Random() % abilityCount];
for (j = 0; j < NUM_ABILITY_SLOTS; j++)
{
if (id == gSpeciesInfo[species].abilities[j])
{
// Set this ability num
SetMonData(&gEnemyParty[0], MON_DATA_ABILITY_NUM, &id);
2024-04-01 19:31:01 +01:00
break;
}
}
2024-04-01 19:31:01 +01:00
if (id >= NUM_ABILITY_SLOTS - 1)
break;
}
Free(abilities);
}
2024-04-01 19:31:01 +01:00
if (gSaveBlock2Ptr->frontier.pyramidWinStreaks[gSaveBlock2Ptr->frontier.lvlMode] >= 140)
{
id = (Random() % 17) + 15;
for (i = 0; i < NUM_STATS; i++)
SetMonData(&gEnemyParty[0], MON_DATA_HP_IV + i, &id);
}
CalculateMonStats(&gEnemyParty[0]);
}
#else
2018-11-17 21:55:39 +00:00
void GenerateBattlePyramidWildMon(void)
{
u8 name[POKEMON_NAME_LENGTH + 1];
2019-02-07 17:37:28 +00:00
int i;
2018-11-17 21:55:39 +00:00
const struct PyramidWildMon *wildMons;
u32 id;
u32 lvl = gSaveBlock2Ptr->frontier.lvlMode;
2023-02-01 16:43:21 +00:00
u16 round = (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvl] / FRONTIER_STAGES_PER_CHALLENGE) % TOTAL_PYRAMID_ROUNDS;
2018-11-17 21:55:39 +00:00
2023-02-01 16:43:21 +00:00
if (round >= TOTAL_PYRAMID_ROUNDS)
round = TOTAL_PYRAMID_ROUNDS - 1;
2018-11-17 21:55:39 +00:00
if (lvl != FRONTIER_LVL_50)
2018-11-27 21:45:50 +00:00
wildMons = sOpenLevelWildMonPointers[round];
2018-11-17 21:55:39 +00:00
else
2018-11-27 21:45:50 +00:00
wildMons = sLevel50WildMonPointers[round];
2018-11-17 21:55:39 +00:00
id = GetMonData(&gEnemyParty[0], MON_DATA_SPECIES, NULL) - 1;
SetMonData(&gEnemyParty[0], MON_DATA_SPECIES, &wildMons[id].species);
StringCopy(name, GetSpeciesName(wildMons[id].species));
2018-11-17 21:55:39 +00:00
SetMonData(&gEnemyParty[0], MON_DATA_NICKNAME, &name);
if (lvl != FRONTIER_LVL_50)
{
lvl = SetFacilityPtrsGetLevel();
lvl -= wildMons[id].lvl;
lvl = lvl - 5 + (Random() % 11);
}
else
{
lvl = wildMons[id].lvl - 5 + ((Random() % 11));
}
SetMonData(&gEnemyParty[0],
MON_DATA_EXP,
2022-10-24 21:01:48 +01:00
&gExperienceTables[gSpeciesInfo[wildMons[id].species].growthRate][lvl]);
2018-11-17 21:55:39 +00:00
2019-05-14 14:22:16 +01:00
switch (wildMons[id].abilityNum)
2018-11-17 21:55:39 +00:00
{
case 0:
case 1:
2019-05-14 14:22:16 +01:00
SetMonData(&gEnemyParty[0], MON_DATA_ABILITY_NUM, &wildMons[id].abilityNum);
2018-11-17 21:55:39 +00:00
break;
case ABILITY_RANDOM:
2018-11-17 21:55:39 +00:00
default:
2022-10-24 21:01:48 +01:00
if (gSpeciesInfo[wildMons[id].species].abilities[1])
2018-11-17 21:55:39 +00:00
{
i = GetMonData(&gEnemyParty[0], MON_DATA_PERSONALITY, NULL) % 2;
2019-05-14 14:22:16 +01:00
SetMonData(&gEnemyParty[0], MON_DATA_ABILITY_NUM, &i);
2018-11-17 21:55:39 +00:00
}
else
{
i = 0;
2019-05-14 14:22:16 +01:00
SetMonData(&gEnemyParty[0], MON_DATA_ABILITY_NUM, &i);
2018-11-17 21:55:39 +00:00
}
break;
}
for (i = 0; i < MAX_MON_MOVES; i++)
2018-11-17 21:55:39 +00:00
SetMonMoveSlot(&gEnemyParty[0], wildMons[id].moves[i], i);
2021-05-15 21:56:17 +01:00
// UB: Reading outside the array as lvl was used for mon level instead of frontier lvl mode.
#ifndef UBFIX
2019-02-07 17:37:28 +00:00
if (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvl] >= 140)
2021-05-15 21:56:17 +01:00
#else
2021-05-15 21:59:54 +01:00
if (gSaveBlock2Ptr->frontier.pyramidWinStreaks[gSaveBlock2Ptr->frontier.lvlMode] >= 140)
2021-05-15 21:56:17 +01:00
#endif
2018-11-17 21:55:39 +00:00
{
id = (Random() % 17) + 15;
for (i = 0; i < NUM_STATS; i++)
SetMonData(&gEnemyParty[0], MON_DATA_HP_IV + i, &id);
}
CalculateMonStats(&gEnemyParty[0]);
}
#endif
2018-11-17 21:55:39 +00:00
2018-11-18 16:52:22 +00:00
u8 GetPyramidRunMultiplier(void)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
u8 id = GetPyramidFloorTemplateId();
return sPyramidFloorTemplates[id].runMultiplier;
2018-11-17 21:55:39 +00:00
}
u8 InBattlePyramid(void)
{
2019-12-11 08:28:55 +00:00
if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR)
2018-11-17 21:55:39 +00:00
return 1;
2019-01-31 21:51:20 +00:00
else if (gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_TOP)
2018-11-17 21:55:39 +00:00
return 2;
else
return FALSE;
}
bool8 InBattlePyramid_(void)
{
2019-12-11 08:28:55 +00:00
return gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR
2019-01-31 21:51:20 +00:00
|| gMapHeader.mapLayoutId == LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_TOP;
2018-11-17 21:55:39 +00:00
}
2019-12-11 08:28:55 +00:00
void PausePyramidChallenge(void)
2018-11-17 21:55:39 +00:00
{
if (InBattlePyramid())
{
2019-02-07 17:37:28 +00:00
RestorePyramidPlayerParty();
2019-11-24 21:58:40 +00:00
gSaveBlock2Ptr->frontier.challengeStatus = CHALLENGE_STATUS_PAUSED;
2023-08-04 19:17:28 +01:00
VarSet(VAR_TEMP_PLAYING_PYRAMID_MUSIC, 0);
2018-11-17 21:55:39 +00:00
LoadPlayerParty();
}
}
2019-02-07 17:37:28 +00:00
void SoftResetInBattlePyramid(void)
2018-11-17 21:55:39 +00:00
{
if (InBattlePyramid())
DoSoftReset();
}
2018-11-18 16:52:22 +00:00
void CopyPyramidTrainerSpeechBefore(u16 trainerId)
2018-11-17 21:55:39 +00:00
{
FrontierSpeechToString(gFacilityTrainers[trainerId].speechBefore);
}
2018-11-18 16:52:22 +00:00
void CopyPyramidTrainerWinSpeech(u16 trainerId)
2018-11-17 21:55:39 +00:00
{
FrontierSpeechToString(gFacilityTrainers[trainerId].speechWin);
}
2018-11-18 16:52:22 +00:00
void CopyPyramidTrainerLoseSpeech(u16 trainerId)
2018-11-17 21:55:39 +00:00
{
FrontierSpeechToString(gFacilityTrainers[trainerId].speechLose);
}
u8 GetTrainerEncounterMusicIdInBattlePyramid(u16 trainerId)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
2018-11-17 21:55:39 +00:00
2019-02-07 02:01:29 +00:00
for (i = 0; i < ARRAY_COUNT(sTrainerClassEncounterMusic); i++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (sTrainerClassEncounterMusic[i].trainerClass == gFacilityClassToTrainerClass[gFacilityTrainers[trainerId].facilityClass])
return sTrainerClassEncounterMusic[i].trainerEncounterMusic;
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
return TRAINER_ENCOUNTER_MUSIC_MALE;
2018-11-17 21:55:39 +00:00
}
static void UNUSED BattlePyramidRetireChallenge(void)
2018-11-17 21:55:39 +00:00
{
ScriptContext_SetupScript(BattlePyramid_Retire);
2018-11-17 21:55:39 +00:00
}
static u16 GetUniqueTrainerId(u8 objectEventId)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
2018-11-17 21:55:39 +00:00
u16 trainerId;
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
u32 challengeNum = gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] / FRONTIER_STAGES_PER_CHALLENGE;
u32 floor = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
if (floor == FRONTIER_STAGES_PER_CHALLENGE)
2018-11-17 21:55:39 +00:00
{
do
{
trainerId = GetRandomScaledFrontierTrainerId(challengeNum + 1, floor);
for (i = 0; i < objectEventId; i++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 17:37:28 +00:00
if (gSaveBlock2Ptr->frontier.trainerIds[i] == trainerId)
2018-11-17 21:55:39 +00:00
break;
}
} while (i != objectEventId);
2018-11-17 21:55:39 +00:00
}
else
{
do
{
trainerId = GetRandomScaledFrontierTrainerId(challengeNum, floor);
for (i = 0; i < objectEventId; i++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 17:37:28 +00:00
if (gSaveBlock2Ptr->frontier.trainerIds[i] == trainerId)
2018-11-17 21:55:39 +00:00
break;
}
} while (i != objectEventId);
2018-11-17 21:55:39 +00:00
}
return trainerId;
}
2019-02-07 02:01:29 +00:00
void GenerateBattlePyramidFloorLayout(u16 *backupMapData, bool8 setPlayerPosition)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
int y, x;
int i;
u8 entranceSquareId, exitSquareId;
u8 *floorLayoutOffsets = AllocZeroed(NUM_PYRAMID_FLOOR_SQUARES);
2018-11-17 21:55:39 +00:00
2019-02-07 17:37:28 +00:00
GetPyramidFloorLayoutOffsets(floorLayoutOffsets);
GetPyramidEntranceAndExitSquareIds(&entranceSquareId, &exitSquareId);
for (i = 0; i < NUM_PYRAMID_FLOOR_SQUARES; i++)
2018-11-17 21:55:39 +00:00
{
u16 *map;
2019-02-07 02:01:29 +00:00
int yOffset, xOffset;
2019-12-11 08:28:55 +00:00
const struct MapLayout *mapLayout = gMapLayouts[floorLayoutOffsets[i] + LAYOUT_BATTLE_FRONTIER_BATTLE_PYRAMID_FLOOR];
2018-11-17 21:55:39 +00:00
const u16 *layoutMap = mapLayout->map;
2019-02-07 02:01:29 +00:00
gBackupMapLayout.map = backupMapData;
gBackupMapLayout.width = mapLayout->width * PYRAMID_FLOOR_SQUARES_WIDE + MAP_OFFSET_W;
gBackupMapLayout.height = mapLayout->height * PYRAMID_FLOOR_SQUARES_HIGH + MAP_OFFSET_H;
2019-02-07 02:01:29 +00:00
map = backupMapData;
yOffset = ((i / PYRAMID_FLOOR_SQUARES_WIDE * mapLayout->height) + MAP_OFFSET) * gBackupMapLayout.width;
xOffset = (i % PYRAMID_FLOOR_SQUARES_WIDE * mapLayout->width) + MAP_OFFSET;
2019-02-07 02:01:29 +00:00
map += yOffset + xOffset;
for (y = 0; y < mapLayout->height; y++)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
for (x = 0; x < mapLayout->width; x++)
2018-11-17 21:55:39 +00:00
{
if ((layoutMap[x] & MAPGRID_METATILE_ID_MASK) != METATILE_BattlePyramid_Exit)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
map[x] = layoutMap[x];
2018-11-17 21:55:39 +00:00
}
2019-02-07 02:01:29 +00:00
else if (i != exitSquareId)
2018-11-17 21:55:39 +00:00
{
2019-02-07 02:01:29 +00:00
if (i == entranceSquareId && setPlayerPosition == FALSE)
2018-11-17 21:55:39 +00:00
{
gSaveBlock1Ptr->pos.x = (mapLayout->width * (i % PYRAMID_FLOOR_SQUARES_WIDE)) + x;
gSaveBlock1Ptr->pos.y = (mapLayout->height * (i / PYRAMID_FLOOR_SQUARES_WIDE)) + y;
2018-11-17 21:55:39 +00:00
}
map[x] = (layoutMap[x] & (MAPGRID_ELEVATION_MASK | MAPGRID_COLLISION_MASK)) | METATILE_BattlePyramid_Floor;
2018-11-17 21:55:39 +00:00
}
else
{
2019-02-07 02:01:29 +00:00
map[x] = layoutMap[x];
2018-11-17 21:55:39 +00:00
}
}
map += MAP_OFFSET_W + (mapLayout->width * PYRAMID_FLOOR_SQUARES_WIDE);
2018-11-17 21:55:39 +00:00
layoutMap += mapLayout->width;
}
}
RunOnLoadMapScript();
2022-09-17 00:36:44 +01:00
Free(floorLayoutOffsets);
2018-11-17 21:55:39 +00:00
}
2018-11-18 16:52:22 +00:00
void LoadBattlePyramidObjectEventTemplates(void)
2018-11-18 16:52:22 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
2018-11-18 16:52:22 +00:00
u8 id;
2019-02-07 02:01:29 +00:00
u8 entranceSquareId, exitSquareId;
2018-11-18 16:52:22 +00:00
for (i = 0; i < MAX_PYRAMID_TRAINERS; i++)
2019-02-07 17:37:28 +00:00
gSaveBlock2Ptr->frontier.trainerIds[i] = 0xFFFF;
2018-11-18 16:52:22 +00:00
2019-02-07 02:01:29 +00:00
id = GetPyramidFloorTemplateId();
2019-02-07 17:37:28 +00:00
GetPyramidEntranceAndExitSquareIds(&entranceSquareId, &exitSquareId);
CpuFill32(0, gSaveBlock1Ptr->objectEventTemplates, sizeof(gSaveBlock1Ptr->objectEventTemplates));
2018-11-18 16:52:22 +00:00
for (i = 0; i < 2; i++)
{
2019-02-07 17:37:28 +00:00
u8 objectPositionsType;
2018-11-18 16:52:22 +00:00
2019-02-07 17:37:28 +00:00
if (i == OBJ_TRAINERS)
objectPositionsType = sPyramidFloorTemplates[id].trainerPositions;
else // OBJ_ITEMS
objectPositionsType = sPyramidFloorTemplates[id].itemPositions;
2018-11-18 16:52:22 +00:00
2019-02-07 17:37:28 +00:00
switch (objectPositionsType)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
case OBJ_POSITIONS_UNIFORM:
SetPyramidObjectPositionsUniformly(i);
2018-11-18 16:52:22 +00:00
break;
2019-02-07 17:37:28 +00:00
case OBJ_POSITIONS_IN_AND_NEAR_ENTRANCE:
if (SetPyramidObjectPositionsInAndNearSquare(i, entranceSquareId))
SetPyramidObjectPositionsUniformly(i);
2018-11-18 16:52:22 +00:00
break;
2019-02-07 17:37:28 +00:00
case OBJ_POSITIONS_IN_AND_NEAR_EXIT:
if (SetPyramidObjectPositionsInAndNearSquare(i, exitSquareId))
SetPyramidObjectPositionsUniformly(i);
2018-11-18 16:52:22 +00:00
break;
2019-02-07 17:54:51 +00:00
case OBJ_POSITIONS_NEAR_ENTRANCE:
2019-02-07 17:37:28 +00:00
if (SetPyramidObjectPositionsNearSquare(i, entranceSquareId))
SetPyramidObjectPositionsUniformly(i);
2018-11-18 16:52:22 +00:00
break;
2019-02-07 17:54:51 +00:00
case OBJ_POSITIONS_NEAR_EXIT:
2019-02-07 17:37:28 +00:00
if (SetPyramidObjectPositionsNearSquare(i, exitSquareId))
SetPyramidObjectPositionsUniformly(i);
2018-11-18 16:52:22 +00:00
break;
}
}
}
void LoadBattlePyramidFloorObjectEventScripts(void)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
int i;
struct ObjectEventTemplate *events = gSaveBlock1Ptr->objectEventTemplates;
2018-11-18 16:52:22 +00:00
for (i = 0; i < OBJECT_EVENT_TEMPLATES_COUNT; i++)
2018-11-18 16:52:22 +00:00
{
if (events[i].graphicsId != OBJ_EVENT_GFX_ITEM_BALL)
2019-02-07 17:37:28 +00:00
events[i].script = BattlePyramid_TrainerBattle;
2018-11-18 16:52:22 +00:00
else
2019-02-07 17:37:28 +00:00
events[i].script = BattlePyramid_FindItemBall;
2018-11-18 16:52:22 +00:00
}
}
2019-02-07 17:37:28 +00:00
static void GetPyramidEntranceAndExitSquareIds(u8 *entranceSquareId, u8 *exitSquareId)
2018-11-18 16:52:22 +00:00
{
*entranceSquareId = gSaveBlock2Ptr->frontier.pyramidRandoms[3] % NUM_PYRAMID_FLOOR_SQUARES;
*exitSquareId = gSaveBlock2Ptr->frontier.pyramidRandoms[0] % NUM_PYRAMID_FLOOR_SQUARES;
2018-11-18 16:52:22 +00:00
2019-02-07 02:01:29 +00:00
if (*entranceSquareId == *exitSquareId)
2018-11-18 16:52:22 +00:00
{
*entranceSquareId = (gSaveBlock2Ptr->frontier.pyramidRandoms[3] + 1 ) % NUM_PYRAMID_FLOOR_SQUARES;
*exitSquareId = (gSaveBlock2Ptr->frontier.pyramidRandoms[0] + NUM_PYRAMID_FLOOR_SQUARES - 1) % NUM_PYRAMID_FLOOR_SQUARES;
2018-11-18 16:52:22 +00:00
}
}
2019-02-07 17:37:28 +00:00
static void SetPyramidObjectPositionsUniformly(u8 objType)
2018-11-18 16:52:22 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
2019-02-07 17:37:28 +00:00
int numObjects;
int objectStartIndex;
2019-02-07 02:01:29 +00:00
int squareId;
2018-11-18 16:52:22 +00:00
u32 bits = 0;
2019-02-07 02:01:29 +00:00
u8 id = GetPyramidFloorTemplateId();
u8 *floorLayoutOffsets = AllocZeroed(NUM_PYRAMID_FLOOR_SQUARES);
2018-11-18 16:52:22 +00:00
2019-02-07 17:37:28 +00:00
GetPyramidFloorLayoutOffsets(floorLayoutOffsets);
squareId = gSaveBlock2Ptr->frontier.pyramidRandoms[2] % NUM_PYRAMID_FLOOR_SQUARES;
2019-02-07 17:37:28 +00:00
if (objType == OBJ_TRAINERS)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
numObjects = sPyramidFloorTemplates[id].numTrainers;
objectStartIndex = 0;
2018-11-18 16:52:22 +00:00
}
2019-02-07 17:37:28 +00:00
else // OBJ_ITEMS
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
numObjects = sPyramidFloorTemplates[id].numItems;
objectStartIndex = sPyramidFloorTemplates[id].numTrainers;
2018-11-18 16:52:22 +00:00
}
2019-02-07 17:37:28 +00:00
for (i = 0; i < numObjects; i++)
2018-11-18 16:52:22 +00:00
{
do
{
do
{
if (bits & 1)
{
2019-02-07 02:01:29 +00:00
if (!(gBitTable[squareId] & gSaveBlock2Ptr->frontier.pyramidRandoms[3]))
2018-11-18 16:52:22 +00:00
bits |= 2;
}
else
{
2019-02-07 02:01:29 +00:00
if (gBitTable[squareId] & gSaveBlock2Ptr->frontier.pyramidRandoms[3])
2018-11-18 16:52:22 +00:00
bits |= 2;
}
if (++squareId >= NUM_PYRAMID_FLOOR_SQUARES)
2019-02-07 02:01:29 +00:00
squareId = 0;
2018-11-18 16:52:22 +00:00
if (squareId == gSaveBlock2Ptr->frontier.pyramidRandoms[2] % NUM_PYRAMID_FLOOR_SQUARES)
2018-11-18 16:52:22 +00:00
{
if (bits & 1)
bits |= 6;
else
bits |= 1;
}
} while (!(bits & 2));
} while (!(bits & 4) && TrySetPyramidObjectEventPositionInSquare(objType, floorLayoutOffsets, squareId, objectStartIndex + i));
2018-11-18 16:52:22 +00:00
bits &= 1;
}
2022-09-17 00:36:44 +01:00
Free(floorLayoutOffsets);
2018-11-18 16:52:22 +00:00
}
2019-02-07 17:37:28 +00:00
static bool8 SetPyramidObjectPositionsInAndNearSquare(u8 objType, u8 squareId)
2018-11-18 16:52:22 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
2019-02-07 17:37:28 +00:00
int objectStartIndex;
2019-02-07 02:01:29 +00:00
int borderedIndex = 0;
int r7 = 0;
2019-02-07 17:37:28 +00:00
int numPlacedObjects = 0;
int numObjects;
2019-02-07 02:01:29 +00:00
u8 id = GetPyramidFloorTemplateId();
u8 *floorLayoutOffsets = AllocZeroed(NUM_PYRAMID_FLOOR_SQUARES);
2019-02-07 02:01:29 +00:00
2019-02-07 17:37:28 +00:00
GetPyramidFloorLayoutOffsets(floorLayoutOffsets);
if (objType == OBJ_TRAINERS)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
numObjects = sPyramidFloorTemplates[id].numTrainers;
objectStartIndex = 0;
2018-11-18 16:52:22 +00:00
}
2019-02-07 17:37:28 +00:00
else // OBJ_ITEMS
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
numObjects = sPyramidFloorTemplates[id].numItems;
objectStartIndex = sPyramidFloorTemplates[id].numTrainers;
2018-11-18 16:52:22 +00:00
}
2019-02-07 17:37:28 +00:00
for (i = 0; i < numObjects; i++)
2018-11-18 16:52:22 +00:00
{
if (r7 == 0)
{
if (TrySetPyramidObjectEventPositionInSquare(objType, floorLayoutOffsets, squareId, objectStartIndex + i))
2018-11-18 16:52:22 +00:00
r7 = 1;
else
2019-02-07 17:37:28 +00:00
numPlacedObjects++;
2018-11-18 16:52:22 +00:00
}
if (r7 & 1)
{
if (TrySetPyramidObjectEventPositionInSquare(objType, floorLayoutOffsets, sBorderedSquareIds[squareId][borderedIndex], objectStartIndex + i))
2018-11-18 16:52:22 +00:00
{
do
{
2019-02-07 02:01:29 +00:00
borderedIndex++;
if (sBorderedSquareIds[squareId][borderedIndex] == 0xFF || borderedIndex >= 4)
borderedIndex = 0;
2018-11-18 16:52:22 +00:00
r7 += 2;
} while (r7 >> 1 != 4 && TrySetPyramidObjectEventPositionInSquare(objType, floorLayoutOffsets, sBorderedSquareIds[squareId][borderedIndex], objectStartIndex + i));
2019-02-07 17:37:28 +00:00
numPlacedObjects++;
2018-11-18 16:52:22 +00:00
}
else
{
2019-02-07 02:01:29 +00:00
borderedIndex++;
if (sBorderedSquareIds[squareId][borderedIndex] == 0xFF || borderedIndex >= 4)
borderedIndex = 0;
2019-02-07 17:37:28 +00:00
numPlacedObjects++;
2018-11-18 16:52:22 +00:00
}
}
if (r7 >> 1 == 4)
break;
r7 &= 1;
}
2020-12-13 04:28:01 +00:00
#ifdef BUGFIX
2022-09-17 00:36:44 +01:00
Free(floorLayoutOffsets);
2020-12-13 04:28:01 +00:00
#endif
2018-11-18 16:52:22 +00:00
2019-02-07 17:37:28 +00:00
return (numObjects / 2) > numPlacedObjects;
2018-11-18 16:52:22 +00:00
}
2019-02-07 17:37:28 +00:00
static bool8 SetPyramidObjectPositionsNearSquare(u8 objType, u8 squareId)
2018-11-18 16:52:22 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
2019-02-07 17:37:28 +00:00
int objectStartIndex;
int borderOffset = 0;
int numPlacedObjects = 0;
2019-02-07 02:01:29 +00:00
int r8 = 0;
2019-02-07 17:37:28 +00:00
int numObjects;
2019-02-07 02:01:29 +00:00
u8 id = GetPyramidFloorTemplateId();
u8 *floorLayoutOffsets = AllocZeroed(NUM_PYRAMID_FLOOR_SQUARES);
2019-02-07 02:01:29 +00:00
2019-02-07 17:37:28 +00:00
GetPyramidFloorLayoutOffsets(floorLayoutOffsets);
if (objType == OBJ_TRAINERS)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
numObjects = sPyramidFloorTemplates[id].numTrainers;
objectStartIndex = 0;
2018-11-18 16:52:22 +00:00
}
2019-02-07 17:37:28 +00:00
else // OBJ_ITEMS
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
numObjects = sPyramidFloorTemplates[id].numItems;
objectStartIndex = sPyramidFloorTemplates[id].numTrainers;
2018-11-18 16:52:22 +00:00
}
2019-02-07 17:37:28 +00:00
for (i = 0; i < numObjects; i++)
2018-11-18 16:52:22 +00:00
{
if (TrySetPyramidObjectEventPositionInSquare(objType, floorLayoutOffsets, sBorderedSquareIds[squareId][borderOffset], objectStartIndex + i))
2018-11-18 16:52:22 +00:00
{
do
{
2019-02-07 17:37:28 +00:00
borderOffset++;
if (sBorderedSquareIds[squareId][borderOffset] == 0xFF || borderOffset >= 4)
borderOffset = 0;
2018-11-18 16:52:22 +00:00
r8++;
} while (r8 != 4 && TrySetPyramidObjectEventPositionInSquare(objType, floorLayoutOffsets, sBorderedSquareIds[squareId][borderOffset], objectStartIndex + i));
2019-02-07 17:37:28 +00:00
numPlacedObjects++;
2018-11-18 16:52:22 +00:00
}
else
{
2019-02-07 17:37:28 +00:00
borderOffset++;
if (sBorderedSquareIds[squareId][borderOffset] == 0xFF || borderOffset >= 4)
borderOffset = 0;
numPlacedObjects++;
2018-11-18 16:52:22 +00:00
}
if (r8 == 4)
break;
}
2020-12-13 04:28:01 +00:00
#ifdef BUGFIX
2022-09-17 00:36:44 +01:00
Free(floorLayoutOffsets);
2020-12-13 04:28:01 +00:00
#endif
2018-11-18 16:52:22 +00:00
2019-02-07 17:37:28 +00:00
return (numObjects / 2) > numPlacedObjects;
2018-11-18 16:52:22 +00:00
}
static bool8 TrySetPyramidObjectEventPositionInSquare(u8 objType, u8 *floorLayoutOffsets, u8 squareId, u8 objectEventId)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
int x, y;
2018-11-18 16:52:22 +00:00
2019-02-07 02:01:29 +00:00
if (gSaveBlock2Ptr->frontier.pyramidRandoms[0] & 1)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
for (y = 7; y > -1; y--)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
for (x = 7; x > -1; x--)
2018-11-18 16:52:22 +00:00
{
if (!TrySetPyramidObjectEventPositionAtCoords(objType, x, y, floorLayoutOffsets, squareId, objectEventId))
2018-11-18 16:52:22 +00:00
return FALSE;
}
}
}
else
{
2019-02-07 17:37:28 +00:00
for (y = 0; y < 8; y++)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
for (x = 0; x < 8; x++)
2018-11-18 16:52:22 +00:00
{
if (!TrySetPyramidObjectEventPositionAtCoords(objType, x, y, floorLayoutOffsets, squareId, objectEventId))
2018-11-18 16:52:22 +00:00
return FALSE;
}
}
}
return TRUE;
}
static bool8 TrySetPyramidObjectEventPositionAtCoords(u8 objType, u8 x, u8 y, u8 *floorLayoutOffsets, u8 squareId, u8 objectEventId)
2018-11-18 16:52:22 +00:00
{
2019-02-07 02:01:29 +00:00
int i, j;
2018-11-18 16:52:22 +00:00
const struct MapHeader *mapHeader;
struct ObjectEventTemplate *floorEvents = gSaveBlock1Ptr->objectEventTemplates;
2018-11-18 16:52:22 +00:00
2019-02-07 02:01:29 +00:00
mapHeader = Overworld_GetMapHeaderByGroupAndId(MAP_GROUP(BATTLE_PYRAMID_SQUARE01), floorLayoutOffsets[squareId] + MAP_NUM(BATTLE_PYRAMID_SQUARE01));
for (i = 0; i < mapHeader->events->objectEventCount; i++)
2018-11-18 16:52:22 +00:00
{
if (mapHeader->events->objectEvents[i].x != x || mapHeader->events->objectEvents[i].y != y)
2018-11-18 16:52:22 +00:00
continue;
if (objType != OBJ_TRAINERS || mapHeader->events->objectEvents[i].graphicsId == OBJ_EVENT_GFX_ITEM_BALL)
2018-11-18 16:52:22 +00:00
{
if (objType != OBJ_ITEMS || mapHeader->events->objectEvents[i].graphicsId != OBJ_EVENT_GFX_ITEM_BALL)
2018-11-18 16:52:22 +00:00
continue;
}
2019-02-07 17:37:28 +00:00
// Ensure an object wasn't previously placed in the exact same position.
for (j = 0; j < objectEventId; j++)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
if (floorEvents[j].x == x + ((squareId % 4) * 8) && floorEvents[j].y == y + ((squareId / 4) * 8))
2018-11-18 16:52:22 +00:00
break;
}
if (j == objectEventId)
2018-11-18 16:52:22 +00:00
{
floorEvents[objectEventId] = mapHeader->events->objectEvents[i];
floorEvents[objectEventId].x += (squareId % 4) * 8;
floorEvents[objectEventId].y += (squareId / 4) * 8;
floorEvents[objectEventId].localId = objectEventId + 1;
if (floorEvents[objectEventId].graphicsId != OBJ_EVENT_GFX_ITEM_BALL)
2019-02-07 17:37:28 +00:00
{
i = GetUniqueTrainerId(objectEventId);
floorEvents[objectEventId].graphicsId = GetBattleFacilityTrainerGfxId(i);
gSaveBlock2Ptr->frontier.trainerIds[objectEventId] = i;
2019-02-07 17:37:28 +00:00
}
return FALSE;
2018-11-18 16:52:22 +00:00
}
}
return TRUE;
}
2019-02-07 17:37:28 +00:00
static void GetPyramidFloorLayoutOffsets(u8 *layoutOffsets)
2018-11-18 16:52:22 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
int rand = (gSaveBlock2Ptr->frontier.pyramidRandoms[0]) | (gSaveBlock2Ptr->frontier.pyramidRandoms[1] << 16);
u8 id = GetPyramidFloorTemplateId();
2018-11-18 16:52:22 +00:00
for (i = 0; i < NUM_PYRAMID_FLOOR_SQUARES; i++)
2018-11-18 16:52:22 +00:00
{
2023-08-16 21:44:45 +01:00
layoutOffsets[i] = sPyramidFloorTemplates[id].layoutOffsets[MOD(rand, NUM_LAYOUT_OFFSETS)];
2019-02-07 02:01:29 +00:00
rand >>= 3;
2018-11-18 16:52:22 +00:00
if (i == 7)
{
2019-02-07 02:01:29 +00:00
rand = (gSaveBlock2Ptr->frontier.pyramidRandoms[2]) | (gSaveBlock2Ptr->frontier.pyramidRandoms[3] << 16);
rand >>= 8;
2018-11-18 16:52:22 +00:00
}
}
}
2019-02-07 02:01:29 +00:00
static u8 GetPyramidFloorTemplateId(void)
2018-11-18 16:52:22 +00:00
{
2019-02-07 02:01:29 +00:00
int i;
int rand = gSaveBlock2Ptr->frontier.pyramidRandoms[3] % 100;
int floor = gSaveBlock2Ptr->frontier.curChallengeBattleNum;
2018-11-18 16:52:22 +00:00
2019-02-07 02:01:29 +00:00
for (i = sFloorTemplateOffsets[floor]; i < ARRAY_COUNT(sPyramidFloorTemplateOptions); i++)
2018-11-18 16:52:22 +00:00
{
2019-02-07 02:01:29 +00:00
if (rand < sPyramidFloorTemplateOptions[i][0])
return sPyramidFloorTemplateOptions[i][1];
2018-11-18 16:52:22 +00:00
}
return 0;
}
u8 GetNumBattlePyramidObjectEvents(void)
2018-11-18 16:52:22 +00:00
{
u8 i;
struct ObjectEventTemplate *events = gSaveBlock1Ptr->objectEventTemplates;
2018-11-18 16:52:22 +00:00
for (i = 0; i < OBJECT_EVENTS_COUNT; i++)
2018-11-18 16:52:22 +00:00
{
if (events[i].localId == 0)
break;
}
return i;
}
2019-02-07 02:01:29 +00:00
static void InitPyramidBagItems(u8 lvlMode)
2018-11-18 16:52:22 +00:00
{
2019-02-07 17:37:28 +00:00
int i;
2018-11-18 16:52:22 +00:00
for (i = 0; i < PYRAMID_BAG_ITEMS_COUNT; i++)
{
2019-02-07 02:01:29 +00:00
gSaveBlock2Ptr->frontier.pyramidBag.itemId[lvlMode][i] = ITEM_NONE;
gSaveBlock2Ptr->frontier.pyramidBag.quantity[lvlMode][i] = ITEM_NONE;
2018-11-18 16:52:22 +00:00
}
AddPyramidBagItem(ITEM_HYPER_POTION, 1);
AddPyramidBagItem(ITEM_ETHER, 1);
}
u16 GetBattlePyramidPickupItemId(void)
{
2019-02-07 02:01:29 +00:00
int rand;
2018-11-18 16:52:22 +00:00
u32 i;
u32 lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
int round = (gSaveBlock2Ptr->frontier.pyramidWinStreaks[lvlMode] / FRONTIER_STAGES_PER_CHALLENGE);
2018-11-18 16:52:22 +00:00
2023-02-01 16:43:21 +00:00
if (round >= TOTAL_PYRAMID_ROUNDS)
round = TOTAL_PYRAMID_ROUNDS - 1;
2018-11-18 16:52:22 +00:00
rand = Random() % 100;
for (i = 0; i < ARRAY_COUNT(sPickupPercentages); i++)
{
if (sPickupPercentages[i] > rand)
break;
}
if (i >= PICKUP_ITEMS_PER_ROUND)
i = PICKUP_ITEMS_PER_ROUND - 1;
if (lvlMode != FRONTIER_LVL_50)
return sPickupItemsLvlOpen[round][i];
else
return sPickupItemsLvl50[round][i];
}