pokeemmo/src/battle_debug.c
2025-06-02 14:17:22 +08:00

2584 lines
94 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "global.h"
#include "battle.h"
#include "battle_anim.h"
#include "battle_message.h"
#include "main.h"
#include "menu.h"
#include "menu_helpers.h"
#include "scanline_effect.h"
#include "palette.h"
#include "party_menu.h"
#include "pokemon_icon.h"
#include "sprite.h"
#include "item.h"
#include "task.h"
#include "bg.h"
#include "gpu_regs.h"
#include "window.h"
#include "text.h"
#include "text_window.h"
#include "international_string_util.h"
#include "strings.h"
#include "battle_ai_main.h"
#include "battle_ai_util.h"
#include "list_menu.h"
#include "decompress.h"
#include "trainer_pokemon_sprites.h"
#include "malloc.h"
#include "string_util.h"
#include "util.h"
#include "data.h"
#include "reset_rtc_screen.h"
#include "reshow_battle_screen.h"
#include "constants/abilities.h"
#include "constants/party_menu.h"
#include "constants/moves.h"
#include "constants/items.h"
#include "constants/rgb.h"
#include "constants/hold_effects.h"
#define MAX_MODIFY_DIGITS 4
struct BattleDebugModifyArrows
{
u8 arrowSpriteId[2];
u16 minValue;
u16 maxValue;
int currValue;
u8 currentDigit:4;
u8 maxDigits:4;
u8 charDigits[MAX_MODIFY_DIGITS];
void *modifiedValPtr;
u8 typeOfVal;
};
struct BattleDebugMenu
{
u8 battlerId:2;
u8 aiBattlerId:2;
u8 battlerWindowId;
u8 mainListWindowId;
u8 mainListTaskId;
u8 currentMainListItemId;
u8 secondaryListWindowId;
u8 secondaryListTaskId;
u8 currentSecondaryListItemId;
u8 secondaryListItemCount;
u8 modifyWindowId;
u8 activeWindow;
struct BattleDebugModifyArrows modifyArrows;
const struct BitfieldInfo *bitfield;
bool8 battlerWasChanged[MAX_BATTLERS_COUNT];
u8 aiViewState;
u8 aiMonSpriteId;
u8 aiMovesWindowId;
union
{
u8 aiIconSpriteIds[MAX_BATTLERS_COUNT];
u8 aiPartyIcons[PARTY_SIZE];
} spriteIds;
};
struct __attribute__((__packed__)) BitfieldInfo
{
u8 bitsCount;
u8 currBit;
};
enum
{
LIST_ITEM_MOVES,
LIST_ITEM_ABILITY,
LIST_ITEM_HELD_ITEM,
LIST_ITEM_PP,
LIST_ITEM_TYPES,
LIST_ITEM_STATS,
LIST_ITEM_STAT_STAGES,
LIST_ITEM_STATUS1,
LIST_ITEM_STATUS2,
LIST_ITEM_STATUS3,
LIST_ITEM_STATUS4,
LIST_ITEM_SIDE_STATUS,
LIST_ITEM_AI,
LIST_ITEM_AI_MOVES_PTS,
LIST_ITEM_AI_INFO,
LIST_ITEM_AI_PARTY,
LIST_ITEM_VARIOUS,
LIST_ITEM_COUNT
};
enum
{
LIST_STAT_HP_CURRENT,
LIST_STAT_HP_MAX,
LIST_STAT_ATTACK,
LIST_STAT_DEFENSE,
LIST_STAT_SPEED,
LIST_STAT_SP_ATK,
LIST_STAT_SP_DEF,
};
enum
{
LIST_STATUS1_SLEEP,
LIST_STATUS1_POISON,
LIST_STATUS1_BURN,
LIST_STATUS1_FREEZE,
LIST_STATUS1_PARALYSIS,
LIST_STATUS1_TOXIC_POISON,
LIST_STATUS1_TOXIC_COUNTER,
LIST_STATUS1_FROSTBITE,
};
enum
{
LIST_STATUS2_CONFUSION,
LIST_STATUS2_FLINCHED,
LIST_STATUS2_TORMENT,
LIST_STATUS2_POWDER,
LIST_STATUS2_DEFENSE_CURL,
LIST_STATUS2_RECHARGE,
LIST_STATUS2_RAGE,
LIST_STATUS2_DESTINY_BOND,
LIST_STATUS2_ESCAPE_PREVENTION,
LIST_STATUS2_CURSED,
LIST_STATUS2_FORESIGHT,
LIST_STATUS2_DRAGON_CHEER,
LIST_STATUS2_FOCUS_ENERGY
};
enum
{
LIST_STATUS3_LEECH_SEED_HEALER,
LIST_STATUS3_LEECH_SEEDED,
LIST_STATUS3_ALWAYS_HITS,
LIST_STATUS3_PERISH_SONG,
LIST_STATUS3_ON_AIR,
LIST_STATUS3_UNDERGROUND,
LIST_STATUS3_MINIMIZED,
LIST_STATUS3_CHARGED_UP,
LIST_STATUS3_ROOTED,
LIST_STATUS3_YAWN,
LIST_STATUS3_IMPRISONED_OTHERS,
LIST_STATUS3_GRUDGE,
LIST_STATUS3_GASTRO_ACID,
LIST_STATUS3_EMBARGO,
LIST_STATUS3_UNDERWATER,
LIST_STATUS3_SMACKED_DOWN,
LIST_STATUS3_TELEKINESIS,
LIST_STATUS3_MIRACLE_EYED,
LIST_STATUS3_MAGNET_RISE,
LIST_STATUS3_HEAL_BLOCK,
LIST_STATUS3_AQUA_RING,
LIST_STATUS3_LASER_FOCUS,
LIST_STATUS3_POWER_TRICK,
};
enum
{
LIST_STATUS4_ELECTRIFIED,
LIST_STATUS4_MUD_SPORT,
LIST_STATUS4_WATER_SPORT,
LIST_STATUS4_SALT_CURE,
LIST_STATUS4_SYRUP_BOMB,
LIST_STATUS4_GLAIVE_RUSH,
};
enum
{
LIST_SIDE_REFLECT,
LIST_SIDE_LIGHTSCREEN,
LIST_SIDE_STICKY_WEB,
LIST_SIDE_SPIKES,
LIST_SIDE_SAFEGUARD,
LIST_SIDE_MIST,
LIST_SIDE_TAILWIND,
LIST_SIDE_AURORA_VEIL,
LIST_SIDE_LUCKY_CHANT,
LIST_SIDE_TOXIC_SPIKES,
LIST_SIDE_STEALTH_ROCK,
LIST_SIDE_STEELSURGE,
LIST_SIDE_DAMAGE_NON_TYPES,
LIST_SIDE_RAINBOW,
LIST_SIDE_SEA_OF_FIRE,
LIST_SIDE_SWAMP,
};
enum
{
LIST_AI_CHECK_BAD_MOVE,
LIST_AI_TRY_TO_FAINT,
LIST_AI_CHECK_VIABILITY,
LIST_AI_FORCE_SETUP_FIRST_TURN,
LIST_AI_RISKY,
LIST_AI_TRY_TO_2HKO,
LIST_AI_PREFER_BATON_PASS,
LIST_AI_DOUBLE_BATTLE,
LIST_AI_HP_AWARE,
LIST_AI_POWERFUL_STATUS,
LIST_AI_NEGATE_UNAWARE,
LIST_AI_WILL_SUICIDE,
LIST_AI_PREFER_STATUS_MOVES,
LIST_AI_STALL,
LIST_AI_SMART_SWITCHING,
LIST_AI_ACE_POKEMON,
LIST_AI_OMNISCIENT,
LIST_AI_SMART_MON_CHOICES,
LIST_AI_CONSERVATIVE,
LIST_AI_SEQUENCE_SWITCHING,
LIST_AI_DOUBLE_ACE_POKEMON,
LIST_AI_WEIGH_ABILITY_PREDICTION,
LIST_AI_PREFER_HIGHEST_DAMAGE_MOVE,
LIST_AI_PREDICT_SWITCH,
LIST_AI_PREDICT_INCOMING_MON,
LIST_AI_DYNAMIC_FUNC,
LIST_AI_ROAMING,
LIST_AI_SAFARI,
LIST_AI_FIRST_BATTLE,
};
enum
{
VARIOUS_SHOW_HP,
VARIOUS_SUBSTITUTE_HP,
VARIOUS_IN_LOVE,
};
enum
{
ACTIVE_WIN_MAIN,
ACTIVE_WIN_SECONDARY,
ACTIVE_WIN_MODIFY
};
enum
{
VAL_U8,
VAL_U16,
VAL_U32,
VAL_BITFIELD_8,
VAL_BITFIELD_16,
VAL_BITFIELD_32,
VAR_SIDE_STATUS,
VAR_SHOW_HP,
VAR_SUBSTITUTE,
VAR_IN_LOVE,
VAR_U16_4_ENTRIES,
VAL_S8,
VAL_ALL_STAT_STAGES,
};
// Static Declarations
static const u8 *GetHoldEffectName(enum ItemHoldEffect holdEffect);
// const rom data
static const u8 sText_Moves[] = _("招式");
static const u8 sText_Ability[] = _("特性");
static const u8 sText_HeldItem[] = _("持有物");
static const u8 sText_HoldEffect[] = _("携带效果");
static const u8 sText_PP[] = _("PP");
static const u8 sText_Types[] = _("属性");
static const u8 sText_Stats[] = _("能力");
static const u8 sText_StatStages[] = _("能力阶级");
static const u8 sText_Status1[] = _("状态1");
static const u8 sText_Status2[] = _("状态2");
static const u8 sText_Status3[] = _("状态3");
static const u8 sText_Status4[] = _("状态4");
static const u8 sText_SideStatus[] = _("场地状态");
static const u8 sText_AI[] = _("AI");
static const u8 sText_AIMovePts[] = _("AI点数/伤害");
static const u8 sText_AiKnowledge[] = _("AI信息");
static const u8 sText_AiParty[] = _("AI队伍");
static const u8 sText_Various[] = _("杂项");
static const u8 sText_CurrHp[] = _("当前HP");
static const u8 sText_MaxHp[] = _("最大HP");
static const u8 sText_Attack[] = _("攻击");
static const u8 sText_Defense[] = _("防御");
static const u8 sText_Speed[] = _("速度");
static const u8 sText_SpAtk[] = _("特攻");
static const u8 sText_SpDef[] = _("特防");
static const u8 sText_Sleep[] = _("睡眠");
static const u8 sText_Poison[] = _("中毒");
static const u8 sText_Burn[] = _("灼伤");
static const u8 sText_Freeze[] = _("冰冻");
static const u8 sText_Paralysis[] = _("麻痹");
static const u8 sText_ToxicPoison[] = _("剧毒");
static const u8 sText_ToxicCounter[] = _("剧毒经过回合");
static const u8 sText_Frostbite[] = _("冻伤");
static const u8 sText_Confusion[] = _("念力");
static const u8 sText_Flinched[] = _("畏缩");
static const u8 sText_Uproar[] = _("吵闹");
static const u8 sText_Torment[] = _("无理取闹");
static const u8 sText_Bide[] = _("忍耐");
static const u8 sText_LockConfuse[] = _("锁定混乱?");
static const u8 sText_MultipleTurns[] = _("多回合");
static const u8 sText_Wrapped[] = _("束缚");
static const u8 sText_Powder[] = _("粉尘");
static const u8 sText_Infatuation[] = _("着迷");
static const u8 sText_DefenseCurl[] = _("变圆");
static const u8 sText_Transformed[] = _("变身");
static const u8 sText_Recharge[] = _("无法动弹");
static const u8 sText_Rage[] = _("愤怒");
static const u8 sText_Substitute[] = _("替身");
static const u8 sText_DestinyBond[] = _("同命");
static const u8 sText_EscapePrevention[] = _("无法逃走");
static const u8 sText_Nightmare[] = _("恶梦");
static const u8 sText_Cursed[] = _("诅咒");
static const u8 sText_Foresight[] = _("识破");
static const u8 sText_DragonCheer[] = _("龙声鼓舞");
static const u8 sText_FocusEnergy[] = _("聚气");
static const u8 sText_LeechSeedHealer[] = _("因寄生种子回复");
static const u8 sText_LeechSeeded[] = _("被寄生种子寄生");
static const u8 sText_AlwaysHits[] = _("锁定");
static const u8 sText_PerishSong[] = _("终焉之歌");
static const u8 sText_OnAir[] = _("飞翔");
static const u8 sText_Underground[] = _("挖洞");
static const u8 sText_Minimized[] = _("变小");
static const u8 sText_ChargedUp[] = _("充电");
static const u8 sText_Rooted[] = _("扎根");
static const u8 sText_Yawn[] = _("哈欠");
static const u8 sText_ImprisonedOthers[] = _("封印其他宝可梦");
static const u8 sText_Grudge[] = _("怨念");
static const u8 sText_GastroAcid[] = _("胃液");
static const u8 sText_Embargo[] = _("查封");
static const u8 sText_Underwater[] = _("潜水");
static const u8 sText_Trace[] = _("复制");
static const u8 sText_SmackedDown[] = _("被击落");
static const u8 sText_MeFirst[] = _("抢先一步");
static const u8 sText_Telekinesis[] = _("意念移物");
static const u8 sText_PhantomForce[] = _("潜灵奇袭");
static const u8 sText_MiracleEyed[] = _("奇迹之眼");
static const u8 sText_MagnetRise[] = _("电磁飘浮");
static const u8 sText_HealBlock[] = _("回复封锁");
static const u8 sText_AquaRing[] = _("水流环");
static const u8 sText_LaserFocus[] = _("磨砺");
static const u8 sText_PowerTrick[] = _("力量戏法");
static const u8 sText_SkyDropped[] = _("自由落体中");
static const u8 sText_Electrified[] = _("输电");
static const u8 sText_MudSport[] = _("玩泥巴");
static const u8 sText_WaterSport[] = _("玩水");
static const u8 sText_InfiniteConfusion[] = _("无限混乱");
static const u8 sText_SaltCure[] = _("盐腌");
static const u8 sText_SyrupBomb[] = _("满身糖");
static const u8 sText_GlaiveRush[] = _("巨剑突击");
static const u8 sText_Reflect[] = _("反射壁");
static const u8 sText_LightScreen[] = _("光墙");
static const u8 sText_StickyWeb[] = _("黏黏网");
static const u8 sText_Spikes[] = _("撒菱");
static const u8 sText_Safeguard[] = _("神秘守护");
static const u8 sText_FutureAttack[] = _("未来攻击");
static const u8 sText_Mist[] = _("白雾");
static const u8 sText_Tailwind[] = _("顺风");
static const u8 sText_AuroraVeil[] = _("极光幕");
static const u8 sText_LuckyChant[] = _("幸运咒语");
static const u8 sText_ToxicSpikes[] = _("毒菱");
static const u8 sText_StealthRock[] = _("隐形岩");
static const u8 sText_Steelsurge[] = _("超极巨钢铁阵法");
static const u8 sText_DamageNonTypes[] = _("无属性攻击?");
static const u8 sText_Rainbow[] = _("彩虹");
static const u8 sText_SeaOfFire[] = _("火海");
static const u8 sText_Swamp[] = _("湿地");
static const u8 sText_CheckBadMove[] = _("检查效果不好的招式");
static const u8 sText_TryToFaint[] = _("尝试击晕");
static const u8 sText_CheckViability[] = _("检查可行性");
static const u8 sText_ForceSetupFirstTurn[] = _("遵循第一回合设置");
static const u8 sText_Risky[] = _("危险大胆");
static const u8 sText_TryTo2HKO[] = _("尝试两招击倒");
static const u8 sText_PreferBatonPass[] = _("偏好接力棒");
static const u8 sText_DoubleBattle[] = _("双打对战");
static const u8 sText_HpAware[] = _("注意HP");
static const u8 sText_PowerfulStatus[] = _("异常状态干扰?");
static const u8 sText_NegateUnaware[] = _("纯朴无效?");
static const u8 sText_WillSuicide[] = _("愿意自杀");
static const u8 sText_PreferStatusMoves[] = _("偏好状态变化招式");
static const u8 sText_Stall[] = _("拖延消耗");
static const u8 sText_SmartSwitching[] = _("聪明替换");
static const u8 sText_AcePokemon[] = _("主力宝可梦");
static const u8 sText_Omniscient[] = _("全知");
static const u8 sText_SmartMonChoices[] = _("聪明的宝可梦选择");
static const u8 sText_Conservative[] = _("保守");
static const u8 sText_SequenceSwitching[] = _("按顺序替换");
static const u8 sText_DoubleAcePokemon[] = _("双主力宝可梦");
static const u8 sText_WeighAbilityPrediction[] = _("权衡特性预测");
static const u8 sText_PreferHighestDamageMove[] = _("偏好最高伤害招式");
static const u8 sText_PredictSwitch[] = _("预测替换");
static const u8 sText_PredictIncomingMon[] = _("预测上场宝可梦");
static const u8 sText_DynamicFunc[] = _("动态功能");
static const u8 sText_Roaming[] = _("四处游走");
static const u8 sText_Safari[] = _("狩猎地带");
static const u8 sText_FirstBattle[] = _("第一战");
static const u8 sText_ShowHP[] = _("显示HP");
static const u8 sText_SubstituteHp[] = _("替换HP");
static const u8 sText_InLove[] = _("着迷");
static const u8 sText_Unknown[] = _("未知");
static const u8 sText_EmptyString[] = _("");
static const u8 sText_IsSwitching[] = _("替换为");
static const struct BitfieldInfo sStatus1Bitfield[] =
{
{/*Sleep*/ 3, 0},
{/*Poison*/ 1, 3},
{/*Burn*/ 1, 4},
{/*Freeze*/ 1, 5},
{/*Paralysis*/1, 6},
{/*Toxic Poison*/ 1, 7},
{/*Toxic Counter*/ 4, 8},
{/*Frostbite*/ 1, 12},
};
static const struct BitfieldInfo sStatus2Bitfield[] =
{
{/*Confusion*/ 3, 0},
{/*Flinched*/ 1, 3},
{/*Torment*/ 1, 7},
{/*Powder*/ 1, 14},
{/*Defense Curl*/ 1, 20},
{/*Recharge*/ 1, 22},
{/*Rage*/ 1, 23},
{/*Destiny Bond*/ 1, 25},
{/*Escape Prevention*/ 1, 26},
{/*Cursed*/ 1, 28},
{/*Foresight*/ 1, 29},
{/*Dragon Cheer*/ 1, 30},
{/*Focus Energy*/ 1, 31},
};
static const struct BitfieldInfo sStatus3Bitfield[] =
{
{/*Leech Seed Battler*/ 2, 0},
{/*Leech Seed*/ 1, 2},
{/*Always Hits*/ 2, 3},
{/*Perish Song*/ 1, 5},
{/*On Air*/ 1, 6},
{/*Underground*/ 1, 7},
{/*Minimized*/ 1, 8},
{/*Charged Up*/ 1, 9},
{/*Rooted*/ 1, 10},
{/*Yawn*/ 2, 11},
{/*Imprisoned Others*/ 1, 13},
{/*Grudge*/ 1, 14},
{/*Gastro Acid*/ 1, 16},
{/*Embargo*/ 1, 17},
{/*Underwater*/ 1, 18},
{/*Smacked Down*/ 1, 21},
{/*Telekinesis*/ 1, 23},
{/*Miracle Eyed*/ 1, 25},
{/*Magnet Rise*/ 1, 26},
{/*Heal Blocked*/ 1, 27},
{/*Aqua Ring*/ 1, 28},
{/*Laser Focus*/ 1, 29},
{/*Power Trick*/ 1, 30},
};
static const struct BitfieldInfo sStatus4Bitfield[] =
{
{/*Electrified*/ 1, 0},
{/*Mud Sport*/ 1, 1},
{/*Water Sport*/ 1, 2},
{/*Salt Cure*/ 1, 4},
{/*Syrup Bomb*/ 1, 5},
{/*Glaive Rush*/ 1, 6},
};
static const struct BitfieldInfo sAIBitfield[] =
{
{/*Check Bad Move*/ 1, 0},
{/*Try to Faint*/ 1, 1},
{/*Check Viability*/ 1, 2},
{/*Force Setup First Turn*/ 1, 3},
{/*Risky*/ 1, 4},
{/*Prefer Strongest Move*/ 1, 5},
{/*Prefer Baton Pass*/ 1, 6},
{/*Double Battle*/ 1, 7},
{/*HP Aware*/ 1, 8},
{/*Powerful Status*/ 1, 9},
{/*Negate Unaware*/ 1, 10},
{/*Will Suicide*/ 1, 11},
{/*Prefer Status Moves*/ 1, 12},
{/*Stall*/ 1, 13},
{/*Smart Switching*/ 1, 14},
{/*Ace Pokemon*/ 1, 15},
{/*Omniscient*/ 1, 16},
{/*Smart Mon Choices*/ 1, 17},
{/*Conservative*/ 1, 18},
{/*Sequence Switching*/ 1, 19},
{/*Double Ace Pokemon*/ 1, 20},
{/*Weigh Ability Prediction*/ 1, 21},
{/*Prefer Highest Damage Move*/ 1, 22},
{/*Predict Switch*/ 1, 23},
{/*Predict Incoming Mon*/ 1, 24},
{/*Dynamic Func*/ 1, 28},
{/*Roaming*/ 1, 29},
{/*Safari*/ 1, 30},
{/*First Battle*/ 1, 31},
};
static const struct ListMenuItem sMainListItems[] =
{
{sText_Moves, LIST_ITEM_MOVES},
{sText_Ability, LIST_ITEM_ABILITY},
{sText_HeldItem, LIST_ITEM_HELD_ITEM},
{sText_PP, LIST_ITEM_PP},
{sText_Types, LIST_ITEM_TYPES},
{sText_Stats, LIST_ITEM_STATS},
{sText_StatStages, LIST_ITEM_STAT_STAGES},
{sText_Status1, LIST_ITEM_STATUS1},
{sText_Status2, LIST_ITEM_STATUS2},
{sText_Status3, LIST_ITEM_STATUS3},
{sText_Status4, LIST_ITEM_STATUS4},
{sText_SideStatus, LIST_ITEM_SIDE_STATUS},
{sText_AI, LIST_ITEM_AI},
{sText_AIMovePts, LIST_ITEM_AI_MOVES_PTS},
{sText_AiKnowledge, LIST_ITEM_AI_INFO},
{sText_AiParty, LIST_ITEM_AI_PARTY},
{sText_Various, LIST_ITEM_VARIOUS},
};
static const struct ListMenuItem sStatsListItems[] =
{
{sText_CurrHp, LIST_STAT_HP_CURRENT},
{sText_MaxHp, LIST_STAT_HP_MAX},
{sText_Attack, LIST_STAT_ATTACK},
{sText_Defense, LIST_STAT_DEFENSE},
{sText_Speed, LIST_STAT_SPEED},
{sText_SpAtk, LIST_STAT_SP_ATK},
{sText_SpDef, LIST_STAT_SP_DEF},
};
static const struct ListMenuItem sStatus1ListItems[] =
{
{sText_Sleep, LIST_STATUS1_SLEEP},
{sText_Poison, LIST_STATUS1_POISON},
{sText_Burn, LIST_STATUS1_BURN},
{sText_Freeze, LIST_STATUS1_FREEZE},
{sText_Paralysis, LIST_STATUS1_PARALYSIS},
{sText_ToxicPoison, LIST_STATUS1_TOXIC_POISON},
{sText_ToxicCounter, LIST_STATUS1_TOXIC_COUNTER},
{sText_Frostbite, LIST_STATUS1_FROSTBITE},
};
static const struct ListMenuItem sStatus2ListItems[] =
{
{sText_Confusion, LIST_STATUS2_CONFUSION},
{sText_Flinched, LIST_STATUS2_FLINCHED},
{sText_Torment, LIST_STATUS2_TORMENT},
{sText_Powder, LIST_STATUS2_POWDER},
{sText_DefenseCurl, LIST_STATUS2_DEFENSE_CURL},
{sText_Recharge, LIST_STATUS2_RECHARGE},
{sText_Rage, LIST_STATUS2_RAGE},
{sText_DestinyBond, LIST_STATUS2_DESTINY_BOND},
{sText_EscapePrevention, LIST_STATUS2_ESCAPE_PREVENTION},
{sText_Cursed, LIST_STATUS2_CURSED},
{sText_Foresight, LIST_STATUS2_FORESIGHT},
{sText_DragonCheer, LIST_STATUS2_DRAGON_CHEER},
{sText_FocusEnergy, LIST_STATUS2_FOCUS_ENERGY},
};
static const struct ListMenuItem sStatus3ListItems[] =
{
{sText_LeechSeedHealer, LIST_STATUS3_LEECH_SEED_HEALER},
{sText_LeechSeeded, LIST_STATUS3_LEECH_SEEDED},
{sText_AlwaysHits, LIST_STATUS3_ALWAYS_HITS},
{sText_PerishSong, LIST_STATUS3_PERISH_SONG},
{sText_OnAir, LIST_STATUS3_ON_AIR},
{sText_Underground, LIST_STATUS3_UNDERGROUND},
{sText_Minimized, LIST_STATUS3_MINIMIZED},
{sText_ChargedUp, LIST_STATUS3_CHARGED_UP},
{sText_Rooted, LIST_STATUS3_ROOTED},
{sText_Yawn, LIST_STATUS3_YAWN},
{sText_ImprisonedOthers, LIST_STATUS3_IMPRISONED_OTHERS},
{sText_Grudge, LIST_STATUS3_GRUDGE},
{sText_GastroAcid, LIST_STATUS3_GASTRO_ACID},
{sText_Embargo, LIST_STATUS3_EMBARGO},
{sText_Underwater, LIST_STATUS3_UNDERWATER},
{sText_SmackedDown, LIST_STATUS3_SMACKED_DOWN},
{sText_Telekinesis, LIST_STATUS3_TELEKINESIS},
{sText_MiracleEyed, LIST_STATUS3_MIRACLE_EYED},
{sText_MagnetRise, LIST_STATUS3_MAGNET_RISE},
{sText_HealBlock, LIST_STATUS3_HEAL_BLOCK},
{sText_AquaRing, LIST_STATUS3_AQUA_RING},
{sText_LaserFocus, LIST_STATUS3_LASER_FOCUS},
{sText_PowerTrick, LIST_STATUS3_POWER_TRICK},
};
static const struct ListMenuItem sStatus4ListItems[] =
{
{sText_Electrified, LIST_STATUS4_ELECTRIFIED},
{sText_MudSport, LIST_STATUS4_MUD_SPORT},
{sText_WaterSport, LIST_STATUS4_WATER_SPORT},
{sText_SaltCure, LIST_STATUS4_SALT_CURE},
{sText_SyrupBomb, LIST_STATUS4_SYRUP_BOMB},
{sText_GlaiveRush, LIST_STATUS4_GLAIVE_RUSH},
};
static const struct ListMenuItem sSideStatusListItems[] =
{
{sText_Reflect, LIST_SIDE_REFLECT},
{sText_LightScreen, LIST_SIDE_LIGHTSCREEN},
{sText_StickyWeb, LIST_SIDE_STICKY_WEB},
{sText_Spikes, LIST_SIDE_SPIKES},
{sText_Safeguard, LIST_SIDE_SAFEGUARD},
{sText_Mist, LIST_SIDE_MIST},
{sText_Tailwind, LIST_SIDE_TAILWIND},
{sText_AuroraVeil, LIST_SIDE_AURORA_VEIL},
{sText_LuckyChant, LIST_SIDE_LUCKY_CHANT},
{sText_ToxicSpikes, LIST_SIDE_TOXIC_SPIKES},
{sText_StealthRock, LIST_SIDE_STEALTH_ROCK},
{sText_Steelsurge, LIST_SIDE_STEELSURGE},
{sText_DamageNonTypes, LIST_SIDE_DAMAGE_NON_TYPES},
{sText_Rainbow, LIST_SIDE_RAINBOW},
{sText_SeaOfFire, LIST_SIDE_SEA_OF_FIRE},
{sText_Swamp, LIST_SIDE_SWAMP},
};
static const struct ListMenuItem sAIListItems[] =
{
{sText_CheckBadMove, LIST_AI_CHECK_BAD_MOVE},
{sText_TryToFaint, LIST_AI_TRY_TO_FAINT},
{sText_CheckViability, LIST_AI_CHECK_VIABILITY},
{sText_ForceSetupFirstTurn, LIST_AI_FORCE_SETUP_FIRST_TURN},
{sText_Risky, LIST_AI_RISKY},
{sText_TryTo2HKO, LIST_AI_TRY_TO_2HKO},
{sText_PreferBatonPass, LIST_AI_PREFER_BATON_PASS},
{sText_DoubleBattle, LIST_AI_DOUBLE_BATTLE},
{sText_HpAware, LIST_AI_HP_AWARE},
{sText_PowerfulStatus, LIST_AI_POWERFUL_STATUS},
{sText_NegateUnaware, LIST_AI_NEGATE_UNAWARE},
{sText_WillSuicide, LIST_AI_WILL_SUICIDE},
{sText_PreferStatusMoves, LIST_AI_PREFER_STATUS_MOVES},
{sText_Stall, LIST_AI_STALL},
{sText_SmartSwitching, LIST_AI_SMART_SWITCHING},
{sText_AcePokemon, LIST_AI_ACE_POKEMON},
{sText_Omniscient, LIST_AI_OMNISCIENT},
{sText_SmartMonChoices, LIST_AI_SMART_MON_CHOICES},
{sText_Conservative, LIST_AI_CONSERVATIVE},
{sText_SequenceSwitching, LIST_AI_SEQUENCE_SWITCHING},
{sText_DoubleAcePokemon, LIST_AI_DOUBLE_ACE_POKEMON},
{sText_WeighAbilityPrediction, LIST_AI_WEIGH_ABILITY_PREDICTION},
{sText_PreferHighestDamageMove, LIST_AI_PREFER_HIGHEST_DAMAGE_MOVE},
{sText_PredictSwitch, LIST_AI_PREDICT_SWITCH},
{sText_PredictIncomingMon, LIST_AI_PREDICT_INCOMING_MON},
{sText_DynamicFunc, LIST_AI_DYNAMIC_FUNC},
{sText_Roaming, LIST_AI_ROAMING},
{sText_Safari, LIST_AI_SAFARI},
{sText_FirstBattle, LIST_AI_FIRST_BATTLE},
};
static const struct ListMenuItem sVariousListItems[] =
{
{sText_ShowHP, VARIOUS_SHOW_HP},
{sText_SubstituteHp, VARIOUS_SUBSTITUTE_HP},
{sText_InLove, VARIOUS_IN_LOVE},
};
static const struct ListMenuItem sSecondaryListItems[] =
{
{sText_EmptyString, 0},
{sText_EmptyString, 1},
{sText_EmptyString, 2},
{sText_EmptyString, 3},
{sText_EmptyString, 4},
{sText_EmptyString, 5},
{sText_EmptyString, 6},
{sText_EmptyString, 7},
{sText_EmptyString, 8},
};
static const struct ListMenuTemplate sMainListTemplate =
{
.items = sMainListItems,
.moveCursorFunc = NULL,
.itemPrintFunc = NULL,
.totalItems = ARRAY_COUNT(sMainListItems),
.maxShowed = 6,
.windowId = 0,
.header_X = 0,
.item_X = 8,
.cursor_X = 0,
.upText_Y = 1,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = 1,
.itemVerticalPadding = 0,
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
.fontId = 1,
.cursorKind = 0
};
static const struct ListMenuTemplate sSecondaryListTemplate =
{
.items = sSecondaryListItems,
.moveCursorFunc = NULL,
.itemPrintFunc = NULL,
.totalItems = 0,
.maxShowed = 0,
.windowId = 0,
.header_X = 0,
.item_X = 8,
.cursor_X = 0,
.upText_Y = 1,
.cursorPal = 2,
.fillValue = 1,
.cursorShadowPal = 3,
.lettersSpacing = 1,
.itemVerticalPadding = 0,
.scrollMultiple = LIST_NO_MULTIPLE_SCROLL,
.fontId = 1,
.cursorKind = 0
};
static const struct WindowTemplate sMainListWindowTemplate =
{
.bg = 0,
.tilemapLeft = 1,
.tilemapTop = 3,
.width = 9,
.height = 12,
.paletteNum = 0xF,
.baseBlock = 0x1
};
static const struct WindowTemplate sSecondaryListWindowTemplate =
{
.bg = 0,
.tilemapLeft = 12,
.tilemapTop = 3,
.width = 20,
.height = 16,
.paletteNum = 0xF,
.baseBlock = 0x6D
};
static const struct WindowTemplate sModifyWindowTemplate =
{
.bg = 0,
.tilemapLeft = 25,
.tilemapTop = 2,
.width = 4,
.height = 2,
.paletteNum = 0xF,
.baseBlock = 0x1AD
};
static const struct WindowTemplate sBattlerWindowTemplate =
{
.bg = 0,
.tilemapLeft = 10,
.tilemapTop = 0,
.width = 14,
.height = 2,
.paletteNum = 0xF,
.baseBlock = 0x1B5
};
static const struct BgTemplate sBgTemplates[] =
{
{
.bg = 0,
.charBaseIndex = 0,
.mapBaseIndex = 31,
.screenSize = 0,
.paletteMode = 0,
.priority = 1,
.baseTile = 0
},
{
.bg = 1,
.charBaseIndex = 2,
.mapBaseIndex = 20,
.screenSize = 0,
.paletteMode = 0,
.priority = 0,
.baseTile = 0
}
};
static const u8 sBitsToMaxDigit[] =
{
[0] = 0,
[1] = 1, // max 1
[2] = 1, // max 3
[3] = 1, // max 7
[4] = 2, // max 15
[5] = 2, // max 31
[6] = 2, // max 63
[7] = 3, // max 127
[8] = 3, // max 255
};
static const bool8 sHasChangeableEntries[LIST_ITEM_COUNT] =
{
[LIST_ITEM_MOVES] = TRUE,
[LIST_ITEM_AI_MOVES_PTS] = TRUE,
[LIST_ITEM_PP] = TRUE,
[LIST_ITEM_ABILITY] = TRUE,
[LIST_ITEM_TYPES] = TRUE,
[LIST_ITEM_HELD_ITEM] = TRUE,
[LIST_ITEM_STAT_STAGES] = TRUE,
};
static const u16 sBgColor[] = {RGB_WHITE};
// this file's functions
static void Task_DebugMenuFadeOut(u8 taskId);
static void Task_DebugMenuProcessInput(u8 taskId);
static void Task_DebugMenuFadeIn(u8 taskId);
static void PrintOnBattlerWindow(u8 windowId, u8 battlerId);
static void UpdateWindowsOnChangedBattler(struct BattleDebugMenu *data);
static void CreateSecondaryListMenu(struct BattleDebugMenu *data);
static void PrintSecondaryEntries(struct BattleDebugMenu *data);
static void DestroyModifyArrows(struct BattleDebugMenu *data);
static void PrintDigitChars(struct BattleDebugMenu *data);
static void SetUpModifyArrows(struct BattleDebugMenu *data);
static void UpdateBattlerValue(struct BattleDebugMenu *data);
static void UpdateMonData(struct BattleDebugMenu *data);
static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue);
static bool32 TryMoveDigit(struct BattleDebugModifyArrows *modArrows, bool32 moveUp);
static void SwitchToDebugView(u8 taskId);
static void SwitchToDebugViewFromAiParty(u8 taskId);
// code
static struct BattleDebugMenu *GetStructPtr(u8 taskId)
{
u8 *taskDataPtr = (u8 *)(&gTasks[taskId].data[0]);
return (struct BattleDebugMenu*)(T1_READ_PTR(taskDataPtr));
}
static void SetStructPtr(u8 taskId, void *ptr)
{
u32 structPtr = (u32)(ptr);
u8 *taskDataPtr = (u8 *)(&gTasks[taskId].data[0]);
taskDataPtr[0] = structPtr >> 0;
taskDataPtr[1] = structPtr >> 8;
taskDataPtr[2] = structPtr >> 16;
taskDataPtr[3] = structPtr >> 24;
}
static void MainCB2(void)
{
RunTasks();
AnimateSprites();
BuildOamBuffer();
UpdatePaletteFade();
}
static void VBlankCB(void)
{
LoadOam();
ProcessSpriteCopyRequests();
TransferPlttBuffer();
}
void CB2_BattleDebugMenu(void)
{
u8 taskId;
struct BattleDebugMenu *data;
switch (gMain.state)
{
default:
case 0:
SetVBlankCallback(NULL);
gMain.state++;
break;
case 1:
ResetVramOamAndBgCntRegs();
SetGpuReg(REG_OFFSET_DISPCNT, 0);
ResetBgsAndClearDma3BusyFlags(0);
InitBgsFromTemplates(0, sBgTemplates, ARRAY_COUNT(sBgTemplates));
ResetAllBgsCoordinates();
FreeAllWindowBuffers();
DeactivateAllTextPrinters();
SetGpuReg(REG_OFFSET_DISPCNT, DISPCNT_OBJ_ON | DISPCNT_OBJ_1D_MAP);
ShowBg(0);
ShowBg(1);
gMain.state++;
break;
case 2:
ResetPaletteFade();
ScanlineEffect_Stop();
ResetTasks();
ResetSpriteData();
gMain.state++;
break;
case 3:
LoadPalette(sBgColor, 0, 2);
LoadPalette(GetOverworldTextboxPalettePtr(), 0xf0, 16);
gMain.state++;
break;
case 4:
taskId = CreateTask(Task_DebugMenuFadeIn, 0);
data = AllocZeroed(sizeof(struct BattleDebugMenu));
SetStructPtr(taskId, data);
data->battlerId = gBattleStruct->debugBattler;
data->battlerWindowId = AddWindow(&sBattlerWindowTemplate);
PutWindowTilemap(data->battlerWindowId);
PrintOnBattlerWindow(data->battlerWindowId, data->battlerId);
data->mainListWindowId = AddWindow(&sMainListWindowTemplate);
gMultiuseListMenuTemplate = sMainListTemplate;
gMultiuseListMenuTemplate.windowId = data->mainListWindowId;
data->mainListTaskId = ListMenuInit(&gMultiuseListMenuTemplate, 0, 0);
data->currentMainListItemId = 0;
data->activeWindow = ACTIVE_WIN_MAIN;
data->secondaryListTaskId = 0xFF;
CopyWindowToVram(data->mainListWindowId, COPYWIN_FULL);
gMain.state++;
break;
case 5:
BeginNormalPaletteFade(-1, 0, 0x10, 0, 0);
SetVBlankCallback(VBlankCB);
SetMainCallback2(MainCB2);
return;
}
}
static void PutMovesPointsText(struct BattleDebugMenu *data)
{
u32 i, j, count, battlerDef;
u8 *text = Alloc(0x50);
FillWindowPixelBuffer(data->aiMovesWindowId, 0x11);
for (i = 0; i < MAX_MON_MOVES; i++)
{
text[0] = CHAR_SPACE;
StringCopy(text + 1, GetMoveName(gBattleMons[data->aiBattlerId].moves[i]));
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 0, i * 15, 0, NULL);
for (count = 0, j = 0; j < MAX_BATTLERS_COUNT; j++)
{
if (data->spriteIds.aiIconSpriteIds[j] == 0xFF)
continue;
battlerDef = gSprites[data->spriteIds.aiIconSpriteIds[j]].data[0];
ConvertIntToDecimalStringN(text,
gAiBattleData->finalScore[data->aiBattlerId][battlerDef][i],
STR_CONV_MODE_RIGHT_ALIGN, 3);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 83 + count * 54, i * 15, 0, NULL);
ConvertIntToDecimalStringN(text,
AI_GetDamage(data->aiBattlerId, battlerDef, i, AI_ATTACKING, gAiLogicData),
STR_CONV_MODE_RIGHT_ALIGN, 3);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, text, 110 + count * 54, i * 15, 0, NULL);
count++;
}
}
if (gAiLogicData->shouldSwitch & (1u << data->aiBattlerId))
{
u32 switchMon = GetMonData(&gEnemyParty[gAiLogicData->mostSuitableMonId[data->aiBattlerId]], MON_DATA_SPECIES);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, sText_IsSwitching, 74, 64, 0, NULL);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, gSpeciesInfo[switchMon].speciesName, 74 + 68, 64, 0, NULL);
}
CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL);
Free(text);
}
static void CleanUpAiInfoWindow(u8 taskId)
{
u32 i;
struct BattleDebugMenu *data = GetStructPtr(taskId);
FreeMonIconPalettes();
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (data->spriteIds.aiIconSpriteIds[i] != 0xFF)
FreeAndDestroyMonIconSprite(&gSprites[data->spriteIds.aiIconSpriteIds[i]]);
}
FreeAndDestroyMonPicSprite(data->aiMonSpriteId);
ClearWindowTilemap(data->aiMovesWindowId);
RemoveWindow(data->aiMovesWindowId);
}
static void Task_ShowAiPoints(u8 taskId)
{
u32 i, count;
struct WindowTemplate winTemplate;
struct BattleDebugMenu *data = GetStructPtr(taskId);
struct Pokemon *mon;
switch (data->aiViewState)
{
case 0:
HideBg(0);
ShowBg(1);
// Swap battler if it's player mon
data->aiBattlerId = data->battlerId;
while (!BattlerHasAi(data->aiBattlerId))
{
if (++data->aiBattlerId >= gBattlersCount)
data->aiBattlerId = 0;
}
data->battlerId = data->aiBattlerId;
LoadMonIconPalettes();
for (count = 0, i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (i != data->aiBattlerId && IsBattlerAlive(i))
{
data->spriteIds.aiIconSpriteIds[i] = CreateMonIcon(gBattleMons[i].species,
SpriteCallbackDummy,
95 + (count * 60), 17, 0, 0);
gSprites[data->spriteIds.aiIconSpriteIds[i]].data[0] = i; // battler id
count++;
}
else
{
data->spriteIds.aiIconSpriteIds[i] = 0xFF;
}
}
mon = GetBattlerMon(data->aiBattlerId);
data->aiMonSpriteId = CreateMonPicSprite(gBattleMons[data->aiBattlerId].species,
GetMonData(mon, MON_DATA_IS_SHINY),
gBattleMons[data->aiBattlerId].personality,
TRUE,
39, 130, 15, TAG_NONE);
data->aiViewState++;
break;
// Put text
case 1:
winTemplate = CreateWindowTemplate(1, 0, 4, 30, 14, 15, 0x200);
data->aiMovesWindowId = AddWindow(&winTemplate);
PutWindowTilemap(data->aiMovesWindowId);
PutMovesPointsText(data);
data->aiViewState++;
break;
// Input
case 2:
if (JOY_NEW(R_BUTTON) && IsDoubleBattle())
{
CleanUpAiInfoWindow(taskId);
do {
data->battlerId++;
data->battlerId %= gBattlersCount;
} while (!IsBattlerAlive(data->battlerId));
data->aiViewState = 0;
}
else if (JOY_NEW(L_BUTTON) && IsDoubleBattle())
{
CleanUpAiInfoWindow(taskId);
do {
if (data->battlerId == 0)
data->battlerId = gBattlersCount - 1;
else
data->battlerId--;
} while (!IsBattlerAlive(data->battlerId) || !BattlerHasAi(data->battlerId));
data->aiViewState = 0;
}
else if (JOY_NEW(SELECT_BUTTON | B_BUTTON))
{
SwitchToDebugView(taskId);
HideBg(1);
ShowBg(0);
return;
}
break;
}
}
static void SwitchToAiPointsView(u8 taskId)
{
gTasks[taskId].func = Task_ShowAiPoints;
GetStructPtr(taskId)->aiViewState = 0;
}
static const u8 *const sAiInfoItemNames[] =
{
sText_Ability,
sText_HeldItem,
sText_HoldEffect,
};
static void PutAiInfoText(struct BattleDebugMenu *data)
{
u32 i;
u8 *text = Alloc(0x50);
FillWindowPixelBuffer(data->aiMovesWindowId, 0x11);
// item names
for (i = 0; i < ARRAY_COUNT(sAiInfoItemNames); i++)
{
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_NORMAL, sAiInfoItemNames[i], 3, i * 15, 0, NULL);
}
// items info
for (i = 0; i < gBattlersCount; i++)
{
if (IsOnPlayerSide(i) && IsBattlerAlive(i))
{
u16 ability = gAiLogicData->abilities[i];
enum ItemHoldEffect holdEffect = gAiLogicData->holdEffects[i];
u16 item = gAiLogicData->items[i];
u8 x = (i == B_POSITION_PLAYER_LEFT) ? 83 + (i) * 75 : 83 + (i-1) * 75;
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, gAbilitiesInfo[ability].name, x, 0, 0, NULL);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, GetItemName(item), x, 15, 0, NULL);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, GetHoldEffectName(holdEffect), x, 30, 0, NULL);
}
}
CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL);
Free(text);
}
static void PutAiPartyText(struct BattleDebugMenu *data)
{
u32 i, j, count;
u8 *text = Alloc(0x50), *txtPtr;
struct AiPartyMon *aiMons = gAiPartyData->mons[GetBattlerSide(data->aiBattlerId)];
FillWindowPixelBuffer(data->aiMovesWindowId, 0x11);
count = gAiPartyData->count[GetBattlerSide(data->aiBattlerId)];
for (i = 0; i < count; i++)
{
if (aiMons[i].wasSentInBattle)
{
text[0] = CHAR_LV;
txtPtr = ConvertIntToDecimalStringN(text + 1, aiMons[i].level, STR_CONV_MODE_LEFT_ALIGN, 3);
*txtPtr++ = CHAR_SPACE;
if (aiMons[i].gender == MON_MALE)
*txtPtr++ = CHAR_MALE;
else if (aiMons[i].gender == MON_FEMALE)
*txtPtr++ = CHAR_FEMALE;
*txtPtr = EOS;
AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL_NARROW, text, i * 41, 0, 0, NULL, 0, 0);
}
txtPtr = StringCopyN(text, gAbilitiesInfo[aiMons[i].ability].name, 7); // The screen is too small to fit the whole string, so we need to drop the last letters.
*txtPtr = EOS;
AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL_NARROW, text, i * 41, 15, 0, NULL, 0, 0);
for (j = 0; j < MAX_MON_MOVES; j++)
{
txtPtr = StringCopyN(text, GetMoveName(aiMons[i].moves[j]), 8);
*txtPtr = EOS;
AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL_NARROW, text, i * 41, 35 + j * 15, 0, NULL, 0, 0);
}
txtPtr = StringCopyN(text, GetHoldEffectName(aiMons[i].heldEffect), 7);
*txtPtr = EOS;
AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL_NARROW, text, i * 41, 35 + j * 15, 0, NULL, 0, 0);
txtPtr = ConvertIntToDecimalStringN(text, aiMons[i].switchInCount, STR_CONV_MODE_LEFT_ALIGN, 2);
*txtPtr = EOS;
AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL_NARROW, text, i * 41, 35 + (j + 1) * 15, 0, NULL, 0, 0);
}
CopyWindowToVram(data->aiMovesWindowId, COPYWIN_FULL);
Free(text);
}
static void Task_ShowAiKnowledge(u8 taskId)
{
u32 i, count;
struct WindowTemplate winTemplate;
struct BattleDebugMenu *data = GetStructPtr(taskId);
struct Pokemon *mon;
switch (data->aiViewState)
{
case 0:
HideBg(0);
ShowBg(1);
// Swap battler if it's player mon
data->aiBattlerId = data->battlerId;
while (!BattlerHasAi(data->aiBattlerId))
{
if (++data->aiBattlerId >= gBattlersCount)
data->aiBattlerId = 0;
}
LoadMonIconPalettes();
for (count = 0, i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (IsOnPlayerSide(i) && IsBattlerAlive(i))
{
data->spriteIds.aiIconSpriteIds[i] = CreateMonIcon(gBattleMons[i].species,
SpriteCallbackDummy,
95 + (count * 80), 17, 0, 0);
gSprites[data->spriteIds.aiIconSpriteIds[i]].data[0] = i; // battler id
count++;
}
else
{
data->spriteIds.aiIconSpriteIds[i] = 0xFF;
}
}
mon = GetBattlerMon(data->aiBattlerId);
data->aiMonSpriteId = CreateMonPicSprite(gBattleMons[data->aiBattlerId].species,
GetMonData(mon, MON_DATA_IS_SHINY),
gBattleMons[data->aiBattlerId].personality,
TRUE,
39, 130, 15, TAG_NONE);
data->aiViewState++;
break;
// Put text
case 1:
winTemplate = CreateWindowTemplate(1, 0, 4, 27, 14, 15, 0x200);
data->aiMovesWindowId = AddWindow(&winTemplate);
PutWindowTilemap(data->aiMovesWindowId);
PutAiInfoText(data);
data->aiViewState++;
break;
// Input
case 2:
if (JOY_NEW(SELECT_BUTTON | B_BUTTON))
{
SwitchToDebugView(taskId);
HideBg(1);
ShowBg(0);
return;
}
break;
}
}
#define sConditionSpriteId data[1]
static void Task_ShowAiParty(u8 taskId)
{
u32 i, ailment;
struct WindowTemplate winTemplate;
struct AiPartyMon *aiMons;
struct BattleDebugMenu *data = GetStructPtr(taskId);
switch (data->aiViewState)
{
case 0:
HideBg(0);
ShowBg(1);
LoadMonIconPalettes();
LoadPartyMenuAilmentGfx();
data->aiBattlerId = data->battlerId;
aiMons = gAiPartyData->mons[GetBattlerSide(data->aiBattlerId)];
for (i = 0; i < gAiPartyData->count[GetBattlerSide(data->aiBattlerId)]; i++)
{
u16 species = SPECIES_NONE; // Question mark
if (aiMons[i].wasSentInBattle && aiMons[i].species)
species = aiMons[i].species;
data->spriteIds.aiPartyIcons[i] = CreateMonIcon(species, SpriteCallbackDummy, (i * 41) + 15, 7, 1, 0);
gSprites[data->spriteIds.aiPartyIcons[i]].oam.priority = 0;
gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId = CreateSprite(&gSpriteTemplate_StatusIcons, (i * 41) + 15, 7, 0);
gSprites[gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId].oam.priority = 0;
if (aiMons[i].isFainted)
ailment = AILMENT_FNT;
else
ailment = GetAilmentFromStatus(aiMons[i].status);
if (ailment != AILMENT_NONE)
StartSpriteAnim(&gSprites[gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId], ailment - 1);
else
gSprites[gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId].invisible = TRUE;
}
for (; i < PARTY_SIZE; i++)
data->spriteIds.aiPartyIcons[i] = 0xFF;
data->aiViewState++;
break;
// Put text
case 1:
winTemplate = CreateWindowTemplate(1, 0, 3, 29, 16, 15, 0x150);
data->aiMovesWindowId = AddWindow(&winTemplate);
PutWindowTilemap(data->aiMovesWindowId);
PutAiPartyText(data);
data->aiViewState++;
break;
// Input
case 2:
if (JOY_NEW(SELECT_BUTTON | B_BUTTON))
{
SwitchToDebugViewFromAiParty(taskId);
HideBg(1);
ShowBg(0);
return;
}
break;
}
}
static void SwitchToAiInfoView(u8 taskId)
{
gTasks[taskId].func = Task_ShowAiKnowledge;
GetStructPtr(taskId)->aiViewState = 0;
}
static void SwitchToAiPartyView(u8 taskId)
{
gTasks[taskId].func = Task_ShowAiParty;
GetStructPtr(taskId)->aiViewState = 0;
}
static void SwitchToDebugViewFromAiParty(u8 taskId)
{
u32 i;
struct BattleDebugMenu *data = GetStructPtr(taskId);
FreeMonIconPalettes();
for (i = 0; i < PARTY_SIZE; i++)
{
if (data->spriteIds.aiPartyIcons[i] != 0xFF)
{
DestroySpriteAndFreeResources(&gSprites[gSprites[data->spriteIds.aiPartyIcons[i]].sConditionSpriteId]);
FreeAndDestroyMonIconSprite(&gSprites[data->spriteIds.aiPartyIcons[i]]);
}
}
ClearWindowTilemap(data->aiMovesWindowId);
RemoveWindow(data->aiMovesWindowId);
gTasks[taskId].func = Task_DebugMenuProcessInput;
}
#undef sConditionSpriteId
static void SwitchToDebugView(u8 taskId)
{
CleanUpAiInfoWindow(taskId);
gTasks[taskId].func = Task_DebugMenuProcessInput;
}
static void Task_DebugMenuFadeIn(u8 taskId)
{
if (!gPaletteFade.active)
gTasks[taskId].func = Task_DebugMenuProcessInput;
}
static void Task_DebugMenuProcessInput(u8 taskId)
{
s32 listItemId = 0;
struct BattleDebugMenu *data = GetStructPtr(taskId);
// Exit the menu.
if (JOY_NEW(SELECT_BUTTON) || ((JOY_NEW(B_BUTTON)) && data->activeWindow == ACTIVE_WIN_MAIN))
{
BeginNormalPaletteFade(-1, 0, 0, 0x10, 0);
gTasks[taskId].func = Task_DebugMenuFadeOut;
return;
}
// Try changing active battler.
if (JOY_NEW(R_BUTTON))
{
if (data->battlerId++ == gBattlersCount - 1)
data->battlerId = 0;
UpdateWindowsOnChangedBattler(data);
}
else if (JOY_NEW(L_BUTTON))
{
if (data->battlerId-- == 0)
data->battlerId = gBattlersCount - 1;
UpdateWindowsOnChangedBattler(data);
}
// A main list item is active, handle input.
if (data->activeWindow == ACTIVE_WIN_MAIN)
{
listItemId = ListMenu_ProcessInput(data->mainListTaskId);
if (listItemId != LIST_CANCEL && listItemId != LIST_NOTHING_CHOSEN && listItemId < LIST_ITEM_COUNT)
{
if (listItemId == LIST_ITEM_AI_MOVES_PTS && JOY_NEW(A_BUTTON))
{
SwitchToAiPointsView(taskId);
return;
}
else if (listItemId == LIST_ITEM_AI_INFO && JOY_NEW(A_BUTTON))
{
SwitchToAiInfoView(taskId);
return;
}
else if (listItemId == LIST_ITEM_AI_PARTY && JOY_NEW(A_BUTTON))
{
SwitchToAiPartyView(taskId);
return;
}
data->currentMainListItemId = listItemId;
// Create the secondary menu list.
CreateSecondaryListMenu(data);
PrintSecondaryEntries(data);
data->activeWindow = ACTIVE_WIN_SECONDARY;
}
}
// Secondary list is active, handle input.
else if (data->activeWindow == ACTIVE_WIN_SECONDARY)
{
listItemId = ListMenu_ProcessInput(data->secondaryListTaskId);
if (listItemId == LIST_CANCEL)
{
DestroyListMenuTask(data->secondaryListTaskId, NULL, NULL);
ClearStdWindowAndFrameToTransparent(data->secondaryListWindowId, TRUE);
RemoveWindow(data->secondaryListWindowId);
data->activeWindow = ACTIVE_WIN_MAIN;
data->secondaryListTaskId = 0xFF;
}
else if (listItemId != LIST_NOTHING_CHOSEN)
{
data->currentSecondaryListItemId = listItemId;
data->modifyWindowId = AddWindow(&sModifyWindowTemplate);
PutWindowTilemap(data->modifyWindowId);
CopyWindowToVram(data->modifyWindowId, COPYWIN_FULL);
SetUpModifyArrows(data);
PrintDigitChars(data);
data->activeWindow = ACTIVE_WIN_MODIFY;
}
}
// Handle value modifying.
else if (data->activeWindow == ACTIVE_WIN_MODIFY)
{
if (JOY_NEW(B_BUTTON | A_BUTTON))
{
ClearStdWindowAndFrameToTransparent(data->modifyWindowId, TRUE);
RemoveWindow(data->modifyWindowId);
DestroyModifyArrows(data);
data->activeWindow = ACTIVE_WIN_SECONDARY;
}
else if (JOY_NEW(DPAD_RIGHT))
{
if (data->modifyArrows.currentDigit != (data->modifyArrows.maxDigits - 1))
{
data->modifyArrows.currentDigit++;
gSprites[data->modifyArrows.arrowSpriteId[0]].x2 += 6;
gSprites[data->modifyArrows.arrowSpriteId[1]].x2 += 6;
}
}
else if (JOY_NEW(DPAD_LEFT))
{
if (data->modifyArrows.currentDigit != 0)
{
data->modifyArrows.currentDigit--;
gSprites[data->modifyArrows.arrowSpriteId[0]].x2 -= 6;
gSprites[data->modifyArrows.arrowSpriteId[1]].x2 -= 6;
}
}
else if (JOY_NEW(DPAD_UP))
{
if (TryMoveDigit(&data->modifyArrows, TRUE))
{
PrintDigitChars(data);
UpdateBattlerValue(data);
PrintSecondaryEntries(data);
}
}
else if (JOY_NEW(DPAD_DOWN))
{
if (TryMoveDigit(&data->modifyArrows, FALSE))
{
PrintDigitChars(data);
UpdateBattlerValue(data);
PrintSecondaryEntries(data);
}
}
}
}
static void Task_DebugMenuFadeOut(u8 taskId)
{
if (!gPaletteFade.active)
{
struct BattleDebugMenu *data = GetStructPtr(taskId);
DestroyListMenuTask(data->mainListTaskId, 0, 0);
if (data->secondaryListTaskId != 0xFF)
DestroyListMenuTask(data->secondaryListTaskId, 0, 0);
FreeAllWindowBuffers();
UpdateMonData(data);
gBattleStruct->debugBattler = data->battlerId;
Free(data);
DestroyTask(taskId);
SetMainCallback2(ReshowBattleScreenAfterMenu);
}
}
static void PrintOnBattlerWindow(u8 windowId, u8 battlerId)
{
u8 text[POKEMON_NAME_LENGTH + 10];
text[0] = CHAR_0 + battlerId;
text[1] = CHAR_SPACE;
text[2] = CHAR_HYPHEN;
text[3] = CHAR_SPACE;
StringCopy(&text[4], gBattleMons[battlerId].nickname);
FillWindowPixelBuffer(windowId, 0x11);
AddTextPrinterParameterized(windowId, FONT_NORMAL, text, 0, 0, 0, NULL);
CopyWindowToVram(windowId, COPYWIN_FULL);
}
static void UpdateWindowsOnChangedBattler(struct BattleDebugMenu *data)
{
PrintOnBattlerWindow(data->battlerWindowId, data->battlerId);
if (data->secondaryListTaskId != 0xFF)
{
DestroyListMenuTask(data->secondaryListTaskId, 0, 0);
RemoveWindow(data->secondaryListWindowId);
CreateSecondaryListMenu(data);
data->currentSecondaryListItemId = 0;
PrintSecondaryEntries(data);
}
if (data->activeWindow == ACTIVE_WIN_MODIFY)
{
DestroyModifyArrows(data);
SetUpModifyArrows(data);
PrintDigitChars(data);
}
}
static void CreateSecondaryListMenu(struct BattleDebugMenu *data)
{
struct WindowTemplate winTemplate;
struct ListMenuTemplate listTemplate;
u8 itemsCount = 1;
winTemplate = sSecondaryListWindowTemplate;
listTemplate = sSecondaryListTemplate;
switch (data->currentMainListItemId)
{
case LIST_ITEM_ABILITY:
itemsCount = 1;
break;
case LIST_ITEM_HELD_ITEM:
itemsCount = 1;
break;
case LIST_ITEM_TYPES:
itemsCount = 3;
break;
case LIST_ITEM_MOVES:
itemsCount = 5;
break;
case LIST_ITEM_PP:
itemsCount = 4;
break;
case LIST_ITEM_STATS:
listTemplate.items = sStatsListItems;
itemsCount = ARRAY_COUNT(sStatsListItems);
break;
case LIST_ITEM_STAT_STAGES:
itemsCount = 8;
break;
case LIST_ITEM_STATUS1:
listTemplate.items = sStatus1ListItems;
itemsCount = ARRAY_COUNT(sStatus1ListItems);
data->bitfield = sStatus1Bitfield;
break;
case LIST_ITEM_STATUS2:
listTemplate.items = sStatus2ListItems;
itemsCount = ARRAY_COUNT(sStatus2ListItems);
data->bitfield = sStatus2Bitfield;
break;
case LIST_ITEM_STATUS3:
listTemplate.items = sStatus3ListItems;
itemsCount = ARRAY_COUNT(sStatus3ListItems);
data->bitfield = sStatus3Bitfield;
break;
case LIST_ITEM_STATUS4:
listTemplate.items = sStatus4ListItems;
itemsCount = ARRAY_COUNT(sStatus4ListItems);
data->bitfield = sStatus4Bitfield;
break;
case LIST_ITEM_AI:
listTemplate.items = sAIListItems;
itemsCount = ARRAY_COUNT(sAIListItems);
data->bitfield = sAIBitfield;
break;
case LIST_ITEM_VARIOUS:
listTemplate.items = sVariousListItems;
itemsCount = ARRAY_COUNT(sVariousListItems);
break;
case LIST_ITEM_SIDE_STATUS:
listTemplate.items = sSideStatusListItems;
itemsCount = ARRAY_COUNT(sSideStatusListItems);
break;
case LIST_ITEM_AI_MOVES_PTS:
case LIST_ITEM_AI_INFO:
return;
}
data->secondaryListItemCount = itemsCount;
data->secondaryListWindowId = AddWindow(&winTemplate);
listTemplate.totalItems = itemsCount;
listTemplate.maxShowed = itemsCount;
if (listTemplate.maxShowed > 7 && !sHasChangeableEntries[data->currentMainListItemId])
listTemplate.maxShowed = 7;
listTemplate.windowId = data->secondaryListWindowId;
data->secondaryListTaskId = ListMenuInit(&listTemplate, 0, 0);
CopyWindowToVram(data->secondaryListWindowId, COPYWIN_FULL);
}
static void PadString(const u8 *src, u8 *dst)
{
u32 i;
for (i = 0; i < 19 && src[i] != EOS; i++)
dst[i] = src[i];
for (; i < 19; i++)
dst[i] = CHAR_SPACE;
dst[i] = EOS;
}
static const u8 sTextAll[] = _("全部");
static void PrintSecondaryEntries(struct BattleDebugMenu *data)
{
u8 text[20];
s32 i;
struct TextPrinterTemplate printer;
u8 yMultiplier;
// Do not print entries if they are not changing.
if (!sHasChangeableEntries[data->currentMainListItemId])
return;
yMultiplier = (GetFontAttribute(sSecondaryListTemplate.fontId, 1) + sSecondaryListTemplate.itemVerticalPadding);
printer.windowId = data->secondaryListWindowId;
printer.fontId = 1;
printer.unk = 0;
printer.letterSpacing = 0;
printer.lineSpacing = 1;
printer.fgColor = 2;
printer.bgColor = 1;
printer.shadowColor = 3;
printer.x = sSecondaryListTemplate.item_X;
printer.currentX = sSecondaryListTemplate.item_X;
printer.currentChar = text;
switch (data->currentMainListItemId)
{
case LIST_ITEM_MOVES:
case LIST_ITEM_PP:
for (i = 0; i < 4; i++)
{
PadString(GetMoveName(gBattleMons[data->battlerId].moves[i]), text);
printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y;
AddTextPrinter(&printer, 0, NULL);
}
// Allow changing all moves at once. Useful for testing in wild doubles.
if (data->currentMainListItemId == LIST_ITEM_MOVES)
{
PadString(sTextAll, text);
printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y;
AddTextPrinter(&printer, 0, NULL);
}
break;
case LIST_ITEM_ABILITY:
PadString(gAbilitiesInfo[gBattleMons[data->battlerId].ability].name, text);
printer.currentY = printer.y = sSecondaryListTemplate.upText_Y;
AddTextPrinter(&printer, 0, NULL);
break;
case LIST_ITEM_HELD_ITEM:
PadString(GetItemName(gBattleMons[data->battlerId].item), text);
printer.currentY = printer.y = sSecondaryListTemplate.upText_Y;
AddTextPrinter(&printer, 0, NULL);
break;
case LIST_ITEM_TYPES:
for (i = 0; i < 3; i++)
{
u8 *types = &gBattleMons[data->battlerId].types[0];
PadString(gTypesInfo[types[i]].name, text);
printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y;
AddTextPrinter(&printer, 0, NULL);
}
break;
case LIST_ITEM_STAT_STAGES:
for (i = 0; i < NUM_BATTLE_STATS - 1; i++)
{
u8 *txtPtr = StringCopy(text, gStatNamesTable[STAT_ATK + i]);
txtPtr[0] = CHAR_SPACE;
if (gBattleMons[data->battlerId].statStages[STAT_ATK + i] >= DEFAULT_STAT_STAGE)
{
txtPtr[1] = CHAR_PLUS;
txtPtr[2] = CHAR_0 + (gBattleMons[data->battlerId].statStages[STAT_ATK + i] - DEFAULT_STAT_STAGE);
}
else
{
txtPtr[1] = CHAR_HYPHEN;
txtPtr[2] = CHAR_6 - (gBattleMons[data->battlerId].statStages[STAT_ATK + i]);
}
txtPtr[3] = EOS;
PadString(text, text);
printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y;
AddTextPrinter(&printer, 0, NULL);
}
// Allow changing all stat stages at once.
PadString(sTextAll, text);
printer.currentY = printer.y = (i * yMultiplier) + sSecondaryListTemplate.upText_Y;
AddTextPrinter(&printer, 0, NULL);
break;
}
}
static void DestroyModifyArrows(struct BattleDebugMenu *data)
{
if (data->modifyArrows.arrowSpriteId[0] != 0xFF)
DestroySpriteAndFreeResources(&gSprites[data->modifyArrows.arrowSpriteId[0]]);
if (data->modifyArrows.arrowSpriteId[1] != 0xFF)
DestroySpriteAndFreeResources(&gSprites[data->modifyArrows.arrowSpriteId[1]]);
}
static void PrintDigitChars(struct BattleDebugMenu *data)
{
s32 i;
u8 text[MAX_MODIFY_DIGITS + 1];
for (i = 0; i < data->modifyArrows.maxDigits; i++)
text[i] = data->modifyArrows.charDigits[i];
text[i] = EOS;
FillWindowPixelBuffer(data->modifyWindowId, 0x11);
AddTextPrinterParameterized(data->modifyWindowId, FONT_NORMAL, text, 3, 0, 0, NULL);
}
static const u32 GetBitfieldToAndValue(u32 currBit, u32 bitsCount)
{
u32 i;
u32 toAnd = 0;
for (i = 0; i < bitsCount; i++)
toAnd |= (1 << (currBit + i));
return toAnd;
}
static const u32 GetBitfieldValue(u32 value, u32 currBit, u32 bitsCount)
{
return (value & (GetBitfieldToAndValue(currBit, bitsCount))) >> currBit;
}
static void UpdateBattlerValue(struct BattleDebugMenu *data)
{
u32 i;
switch (data->modifyArrows.typeOfVal)
{
case VAL_U8:
*(u8 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue;
break;
case VAL_S8:
*(s8 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue;
break;
case VAL_U16:
*(u16 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue;
break;
case VAR_U16_4_ENTRIES:
((u16 *)(data->modifyArrows.modifiedValPtr))[0] = data->modifyArrows.currValue;
((u16 *)(data->modifyArrows.modifiedValPtr))[1] = data->modifyArrows.currValue;
((u16 *)(data->modifyArrows.modifiedValPtr))[2] = data->modifyArrows.currValue;
((u16 *)(data->modifyArrows.modifiedValPtr))[3] = data->modifyArrows.currValue;
break;
case VAL_ALL_STAT_STAGES:
for (i = 0; i < NUM_BATTLE_STATS; i++)
gBattleMons[data->battlerId].statStages[i] = data->modifyArrows.currValue;
break;
case VAL_U32:
*(u32 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue;
break;
case VAL_BITFIELD_32:
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~(GetBitfieldToAndValue(data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount));
*(u32 *)(data->modifyArrows.modifiedValPtr) |= (data->modifyArrows.currValue << data->bitfield[data->currentSecondaryListItemId].currBit);
break;
case VAR_SIDE_STATUS:
*GetSideStatusValue(data, TRUE, data->modifyArrows.currValue != 0) = data->modifyArrows.currValue;
break;
case VAR_SHOW_HP:
(*(struct BattleSpriteInfo*)(data->modifyArrows.modifiedValPtr)).hpNumbersNoBars = data->modifyArrows.currValue;
break;
case VAR_SUBSTITUTE:
*(u8 *)(data->modifyArrows.modifiedValPtr) = data->modifyArrows.currValue;
if (*(u8 *)(data->modifyArrows.modifiedValPtr) == 0)
{
gBattleMons[data->battlerId].status2 &= ~STATUS2_SUBSTITUTE;
gBattleSpritesDataPtr->battlerData[data->battlerId].behindSubstitute = 0;
}
else
{
gBattleMons[data->battlerId].status2 |= STATUS2_SUBSTITUTE;
gBattleSpritesDataPtr->battlerData[data->battlerId].behindSubstitute = 1;
}
break;
case VAR_IN_LOVE:
if (data->modifyArrows.currValue)
{
if (IsBattlerAlive(BATTLE_OPPOSITE(data->battlerId)))
gBattleMons[data->battlerId].status2 |= STATUS2_INFATUATED_WITH(BATTLE_OPPOSITE(data->battlerId));
else
gBattleMons[data->battlerId].status2 |= STATUS2_INFATUATED_WITH(BATTLE_PARTNER(BATTLE_OPPOSITE(data->battlerId)));
}
else
{
gBattleMons[data->battlerId].status2 &= ~STATUS2_INFATUATION;
}
break;
}
data->battlerWasChanged[data->battlerId] = TRUE;
}
static u32 CharDigitsToValue(u8 *charDigits, u8 maxDigits)
{
s32 i;
u8 id = 0;
u32 newValue = 0;
u8 valueDigits[MAX_MODIFY_DIGITS];
for (i = 0; i < MAX_MODIFY_DIGITS; i++)
valueDigits[i] = charDigits[i] - CHAR_0;
if (maxDigits >= MAX_MODIFY_DIGITS)
newValue += valueDigits[id++] * 1000;
if (maxDigits >= MAX_MODIFY_DIGITS - 1)
newValue += valueDigits[id++] * 100;
if (maxDigits >= MAX_MODIFY_DIGITS - 2)
newValue += valueDigits[id++] * 10;
if (maxDigits >= MAX_MODIFY_DIGITS - 3)
newValue += valueDigits[id++];
return newValue;
}
static void ValueToCharDigits(u8 *charDigits, u32 newValue, u8 maxDigits)
{
s32 i;
u8 valueDigits[MAX_MODIFY_DIGITS];
u8 id = 0;
if (maxDigits >= MAX_MODIFY_DIGITS)
valueDigits[id++] = newValue / 1000;
if (maxDigits >= MAX_MODIFY_DIGITS - 1)
valueDigits[id++] = (newValue % 1000) / 100;
if (maxDigits >= MAX_MODIFY_DIGITS - 2)
valueDigits[id++] = (newValue % 100) / 10;
if (maxDigits >= MAX_MODIFY_DIGITS - 3)
valueDigits[id++] = newValue % 10;
for (i = 0; i < MAX_MODIFY_DIGITS; i++)
charDigits[i] = valueDigits[i] + CHAR_0;
}
static u16 *GetSideStatusValue(struct BattleDebugMenu *data, bool32 changeStatus, bool32 statusTrue)
{
struct SideTimer *sideTimer = &gSideTimers[GetBattlerSide(data->battlerId)];
switch (data->currentSecondaryListItemId)
{
case LIST_SIDE_REFLECT:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_REFLECT;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_REFLECT;
}
return &sideTimer->reflectTimer;
case LIST_SIDE_LIGHTSCREEN:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_LIGHTSCREEN;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_LIGHTSCREEN;
}
return &sideTimer->lightscreenTimer;
case LIST_SIDE_STICKY_WEB:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STICKY_WEB;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STICKY_WEB;
sideTimer->stickyWebBattlerId = data->battlerId;
sideTimer->stickyWebBattlerSide = GetBattlerSide(data->battlerId);
}
return &sideTimer->stickyWebAmount;
case LIST_SIDE_SPIKES:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_SPIKES;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_SPIKES;
}
return &sideTimer->spikesAmount;
case LIST_SIDE_SAFEGUARD:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_SAFEGUARD;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_SAFEGUARD;
}
return &sideTimer->safeguardTimer;
case LIST_SIDE_MIST:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_MIST;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_MIST;
}
return &sideTimer->mistTimer;
case LIST_SIDE_TAILWIND:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_TAILWIND;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_TAILWIND;
}
return &sideTimer->tailwindTimer;
case LIST_SIDE_AURORA_VEIL:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_AURORA_VEIL;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_AURORA_VEIL;
}
return &sideTimer->auroraVeilTimer;
case LIST_SIDE_LUCKY_CHANT:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_LUCKY_CHANT;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_LUCKY_CHANT;
}
return &sideTimer->luckyChantTimer;
case LIST_SIDE_TOXIC_SPIKES:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_TOXIC_SPIKES;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_TOXIC_SPIKES;
}
return &sideTimer->toxicSpikesAmount;
case LIST_SIDE_STEALTH_ROCK:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEALTH_ROCK;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STEALTH_ROCK;
}
return &sideTimer->stealthRockAmount;
case LIST_SIDE_STEELSURGE:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_STEELSURGE;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_STEELSURGE;
}
return &sideTimer->steelsurgeAmount;
case LIST_SIDE_DAMAGE_NON_TYPES:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_DAMAGE_NON_TYPES;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_DAMAGE_NON_TYPES;
sideTimer->damageNonTypesType = GetMoveType(gCurrentMove);
}
return &sideTimer->damageNonTypesTimer;
case LIST_SIDE_RAINBOW:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_RAINBOW;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_RAINBOW;
}
return &sideTimer->rainbowTimer;
case LIST_SIDE_SEA_OF_FIRE:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_SEA_OF_FIRE;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_SEA_OF_FIRE;
}
return &sideTimer->seaOfFireTimer;
case LIST_SIDE_SWAMP:
if (changeStatus)
{
if (statusTrue)
*(u32 *)(data->modifyArrows.modifiedValPtr) |= SIDE_STATUS_SWAMP;
else
*(u32 *)(data->modifyArrows.modifiedValPtr) &= ~SIDE_STATUS_SWAMP;
}
return &sideTimer->swampTimer;
default:
return NULL;
}
}
static void SetUpModifyArrows(struct BattleDebugMenu *data)
{
LoadSpritePalette(&gSpritePalette_Arrow);
data->modifyArrows.arrowSpriteId[0] = CreateSprite(&gSpriteTemplate_Arrow, 207, 12, 0);
data->modifyArrows.arrowSpriteId[1] = CreateSprite(&gSpriteTemplate_Arrow, 207, 36, 0);
gSprites[data->modifyArrows.arrowSpriteId[1]].animNum = 1;
switch (data->currentMainListItemId)
{
case LIST_ITEM_ABILITY:
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = ABILITIES_COUNT - 1;
data->modifyArrows.maxDigits = 3;
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].ability;
data->modifyArrows.typeOfVal = VAL_U16;
data->modifyArrows.currValue = gBattleMons[data->battlerId].ability;
break;
case LIST_ITEM_MOVES:
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = MOVES_COUNT - 1;
data->modifyArrows.maxDigits = 3;
if (data->currentSecondaryListItemId == 4)
{
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].moves[0];
data->modifyArrows.currValue = gBattleMons[data->battlerId].moves[0];
data->modifyArrows.typeOfVal = VAR_U16_4_ENTRIES;
}
else
{
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].moves[data->currentSecondaryListItemId];
data->modifyArrows.currValue = gBattleMons[data->battlerId].moves[data->currentSecondaryListItemId];
data->modifyArrows.typeOfVal = VAL_U16;
}
break;
case LIST_ITEM_PP:
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = CalculatePPWithBonus(gBattleMons[data->battlerId].moves[data->currentSecondaryListItemId], gBattleMons[data->battlerId].ppBonuses, data->currentSecondaryListItemId);
data->modifyArrows.maxDigits = 2;
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].pp[data->currentSecondaryListItemId];
data->modifyArrows.typeOfVal = VAL_U8;
data->modifyArrows.currValue = gBattleMons[data->battlerId].pp[data->currentSecondaryListItemId];
break;
case LIST_ITEM_HELD_ITEM:
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = ITEMS_COUNT - 1;
data->modifyArrows.maxDigits = 3;
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].item;
data->modifyArrows.typeOfVal = VAL_U16;
data->modifyArrows.currValue = gBattleMons[data->battlerId].item;
break;
case LIST_ITEM_TYPES:
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = NUMBER_OF_MON_TYPES - 1;
data->modifyArrows.maxDigits = 2;
data->modifyArrows.modifiedValPtr = (u8 *)((&gBattleMons[data->battlerId].types[0]) + data->currentSecondaryListItemId);
data->modifyArrows.typeOfVal = VAL_U8;
data->modifyArrows.currValue = *(u8 *)((&gBattleMons[data->battlerId].types[0]) + data->currentSecondaryListItemId);
break;
case LIST_ITEM_STATS:
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = 9999;
data->modifyArrows.maxDigits = 4;
data->modifyArrows.typeOfVal = VAL_U16;
if (data->currentSecondaryListItemId == LIST_STAT_HP_CURRENT)
{
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].hp;
data->modifyArrows.currValue = gBattleMons[data->battlerId].hp;
data->modifyArrows.minValue = 1;
data->modifyArrows.maxValue = gBattleMons[data->battlerId].maxHP;
}
else if (data->currentSecondaryListItemId == LIST_STAT_HP_MAX)
{
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].maxHP;
data->modifyArrows.minValue = gBattleMons[data->battlerId].hp;
data->modifyArrows.currValue = gBattleMons[data->battlerId].maxHP;
}
else
{
data->modifyArrows.modifiedValPtr = (u16 *)((&gBattleMons[data->battlerId].attack) + (data->currentSecondaryListItemId - 2));
data->modifyArrows.currValue = *(u16 *)((&gBattleMons[data->battlerId].attack) + (data->currentSecondaryListItemId - 2));
}
break;
case LIST_ITEM_STAT_STAGES:
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = 12;
data->modifyArrows.maxDigits = 2;
if (data->currentSecondaryListItemId == NUM_BATTLE_STATS - 1) // Change all stats
{
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].statStages[STAT_ATK];
data->modifyArrows.currValue = gBattleMons[data->battlerId].statStages[STAT_ATK];
data->modifyArrows.typeOfVal = VAL_ALL_STAT_STAGES;
}
else
{
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].statStages[data->currentSecondaryListItemId + STAT_ATK];
data->modifyArrows.typeOfVal = VAL_U8;
data->modifyArrows.currValue = gBattleMons[data->battlerId].statStages[data->currentSecondaryListItemId + STAT_ATK];
}
break;
case LIST_ITEM_VARIOUS:
if (data->currentSecondaryListItemId == VARIOUS_SHOW_HP)
{
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = 1;
data->modifyArrows.maxDigits = 1;
data->modifyArrows.modifiedValPtr = &gBattleSpritesDataPtr->battlerData[data->battlerId];
data->modifyArrows.typeOfVal = VAR_SHOW_HP;
data->modifyArrows.currValue = gBattleSpritesDataPtr->battlerData[data->battlerId].hpNumbersNoBars;
}
else if (data->currentSecondaryListItemId == VARIOUS_SUBSTITUTE_HP)
{
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = 255;
data->modifyArrows.maxDigits = 3;
data->modifyArrows.modifiedValPtr = &gDisableStructs[data->battlerId].substituteHP;
data->modifyArrows.typeOfVal = VAR_SUBSTITUTE;
data->modifyArrows.currValue = gDisableStructs[data->battlerId].substituteHP;
}
else if (data->currentSecondaryListItemId == VARIOUS_IN_LOVE)
{
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = 1;
data->modifyArrows.maxDigits = 1;
data->modifyArrows.modifiedValPtr = NULL;
data->modifyArrows.typeOfVal = VAR_IN_LOVE;
data->modifyArrows.currValue = (gBattleMons[data->battlerId].status2 & STATUS2_INFATUATION) != 0;
}
break;
case LIST_ITEM_STATUS1:
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].status1;
data->modifyArrows.currValue = GetBitfieldValue(gBattleMons[data->battlerId].status1, data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount);
data->modifyArrows.typeOfVal = VAL_BITFIELD_32;
goto CASE_ITEM_STATUS;
case LIST_ITEM_STATUS2:
data->modifyArrows.modifiedValPtr = &gBattleMons[data->battlerId].status2;
data->modifyArrows.currValue = GetBitfieldValue(gBattleMons[data->battlerId].status2, data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount);
data->modifyArrows.typeOfVal = VAL_BITFIELD_32;
goto CASE_ITEM_STATUS;
case LIST_ITEM_STATUS3:
data->modifyArrows.modifiedValPtr = &gStatuses3[data->battlerId];
data->modifyArrows.currValue = GetBitfieldValue(gStatuses3[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount);
data->modifyArrows.typeOfVal = VAL_BITFIELD_32;
goto CASE_ITEM_STATUS;
case LIST_ITEM_STATUS4:
data->modifyArrows.modifiedValPtr = &gStatuses4[data->battlerId];
data->modifyArrows.currValue = GetBitfieldValue(gStatuses4[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount);
data->modifyArrows.typeOfVal = VAL_BITFIELD_32;
goto CASE_ITEM_STATUS;
case LIST_ITEM_AI:
data->modifyArrows.modifiedValPtr = &gAiThinkingStruct->aiFlags[data->battlerId];
data->modifyArrows.currValue = GetBitfieldValue(gAiThinkingStruct->aiFlags[data->battlerId], data->bitfield[data->currentSecondaryListItemId].currBit, data->bitfield[data->currentSecondaryListItemId].bitsCount);
data->modifyArrows.typeOfVal = VAL_BITFIELD_32;
goto CASE_ITEM_STATUS;
CASE_ITEM_STATUS:
data->modifyArrows.minValue = 0;
data->modifyArrows.maxValue = (1 << data->bitfield[data->currentSecondaryListItemId].bitsCount) - 1;
data->modifyArrows.maxDigits = sBitsToMaxDigit[data->bitfield[data->currentSecondaryListItemId].bitsCount];
break;
case LIST_ITEM_SIDE_STATUS:
data->modifyArrows.minValue = 0;
if (data->currentSecondaryListItemId == LIST_SIDE_SPIKES)
data->modifyArrows.maxValue = 3;
else if (data->currentSecondaryListItemId == LIST_SIDE_STEALTH_ROCK || data->currentSecondaryListItemId == LIST_SIDE_STICKY_WEB)
data->modifyArrows.maxValue = 1;
else
data->modifyArrows.maxValue = 9;
data->modifyArrows.maxDigits = 2;
data->modifyArrows.modifiedValPtr = &gSideStatuses[GetBattlerSide(data->battlerId)];
data->modifyArrows.typeOfVal = VAR_SIDE_STATUS;
data->modifyArrows.currValue = *GetSideStatusValue(data, FALSE, FALSE);
break;
}
data->modifyArrows.currentDigit = 0;
ValueToCharDigits(data->modifyArrows.charDigits, data->modifyArrows.currValue, data->modifyArrows.maxDigits);
}
static bool32 TryMoveDigit(struct BattleDebugModifyArrows *modArrows, bool32 moveUp)
{
s32 i;
u8 charDigits[MAX_MODIFY_DIGITS];
u32 newValue;
for (i = 0; i < MAX_MODIFY_DIGITS; i++)
charDigits[i] = modArrows->charDigits[i];
if (moveUp)
{
if (charDigits[modArrows->currentDigit] == CHAR_9)
{
charDigits[modArrows->currentDigit] = CHAR_0;
for (i = modArrows->currentDigit - 1; i >= 0; i--)
{
if (charDigits[i] == CHAR_9)
{
charDigits[i] = CHAR_0;
}
else
{
charDigits[i]++;
break;
}
}
}
else
charDigits[modArrows->currentDigit]++;
}
else
{
if (charDigits[modArrows->currentDigit] == CHAR_0)
{
charDigits[modArrows->currentDigit] = CHAR_9;
for (i = modArrows->currentDigit - 1; i >= 0; i--)
{
if (charDigits[i] == CHAR_0)
{
charDigits[i] = CHAR_9;
}
else
{
charDigits[i]--;
break;
}
}
}
else
charDigits[modArrows->currentDigit]--;
}
newValue = CharDigitsToValue(charDigits, modArrows->maxDigits);
if (newValue > modArrows->maxValue || newValue < modArrows->minValue)
{
return FALSE;
}
else
{
modArrows->currValue = newValue;
for (i = 0; i < MAX_MODIFY_DIGITS; i++)
modArrows->charDigits[i] = charDigits[i];
return TRUE;
}
}
static void UpdateMonData(struct BattleDebugMenu *data)
{
s32 i, j;
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (data->battlerWasChanged[i])
{
struct Pokemon *mon = GetBattlerMon(i);
struct BattlePokemon *battleMon = &gBattleMons[i];
SetMonData(mon, MON_DATA_HELD_ITEM, &battleMon->item);
SetMonData(mon, MON_DATA_STATUS, &battleMon->status1);
SetMonData(mon, MON_DATA_HP, &battleMon->hp);
SetMonData(mon, MON_DATA_MAX_HP, &battleMon->maxHP);
for (j = 0; j < 4; j++)
SetMonData(mon, MON_DATA_MOVE1 + j, &battleMon->moves[j]);
}
}
}
static const u8 sText_HoldEffectNone[] = _("");
static const u8 sText_HoldEffectRestoreHp[] = _("回复HP");
static const u8 sText_HoldEffectCurePar[] = _("麻痹解除");
static const u8 sText_HoldEffectCureSlp[] = _("睡眠解除");
static const u8 sText_HoldEffectCurePsn[] = _("中毒解除");
static const u8 sText_HoldEffectCureBrn[] = _("灼伤解除");
static const u8 sText_HoldEffectCureFrz[] = _("冰冻解除");
static const u8 sText_HoldEffectRestorePp[] = _("回复PP");
static const u8 sText_HoldEffectCureConfusion[] = _("混乱解除");
static const u8 sText_HoldEffectCureStatus[] = _("异常状态解除");
static const u8 sText_HoldEffectConfuseSpicy[] = _("因树果太辣混乱");
static const u8 sText_HoldEffectConfuseDry[] = _("因树果太涩混乱");
static const u8 sText_HoldEffectConfuseSweet[] = _("因树果太甜混乱");
static const u8 sText_HoldEffectConfuseBitter[] = _("因树果太苦混乱");
static const u8 sText_HoldEffectConfuseSour[] = _("因树果太酸混乱");
static const u8 sText_HoldEffectAttackUp[] = _("攻击提升");
static const u8 sText_HoldEffectDefenseUp[] = _("防御提升");
static const u8 sText_HoldEffectSpeedUp[] = _("速度提升");
static const u8 sText_HoldEffectSpAttackUp[] = _("特攻提升");
static const u8 sText_HoldEffectSpDefenseUp[] = _("特防提升");
static const u8 sText_HoldEffectCriticalUp[] = _("击中要害率提升");
static const u8 sText_HoldEffectRandomStatUp[] = _("随机能力提升");
static const u8 sText_HoldEffectEvasionUp[] = _("闪避率提升");
static const u8 sText_HoldEffectRestoreStats[] = _("能力恢复");
static const u8 sText_HoldEffectMachoBrace[] = _("强制锻炼器");
static const u8 sText_HoldEffectExpShare[] = _("学习装置");
static const u8 sText_HoldEffectQuickClaw[] = _("先制之爪");
static const u8 sText_HoldEffectFriendshipUp[] = _("亲密度上升");
static const u8 sText_HoldEffectMentalHerb[] = _("心灵香草");
static const u8 sText_HoldEffectChoiceBand[] = _("讲究头带");
static const u8 sText_HoldEffectFlinch[] = _("畏缩");
static const u8 sText_HoldEffectDoublePrize[] = _("零花钱翻倍");
static const u8 sText_HoldEffectRepel[] = _("除虫喷雾");
static const u8 sText_HoldEffectSoulDew[] = _("心之水滴");
static const u8 sText_HoldEffectDeepSeaTooth[] = _("深海之牙");
static const u8 sText_HoldEffectDeepSeaScale[] = _("深海鳞片");
static const u8 sText_HoldEffectCanAlwaysRun[] = _("必定能逃走");
static const u8 sText_HoldEffectPreventEvolve[] = _("不会进化");
static const u8 sText_HoldEffectFocusBand[] = _("气势头带");
static const u8 sText_HoldEffectLuckyEgg[] = _("幸运蛋");
static const u8 sText_HoldEffectScopeLens[] = _("焦点镜");
static const u8 sText_HoldEffectLeftovers[] = _("吃剩的东西");
static const u8 sText_HoldEffectDragonScale[] = _("龙之鳞片");
static const u8 sText_HoldEffectLightBall[] = _("电气球");
static const u8 sText_HoldEffectTypePower[] = _("属性威力");
static const u8 sText_HoldEffectUpgrade[] = _("升级数据");
static const u8 sText_HoldEffectShellBell[] = _("贝壳之铃");
static const u8 sText_HoldEffectLuckyPunch[] = _("吉利拳");
static const u8 sText_HoldEffectMetalPowder[] = _("金属粉");
static const u8 sText_HoldEffectThickClub[] = _("粗骨头");
static const u8 sText_HoldEffectLeek[] = _("大葱");
static const u8 sText_HoldEffectChoiceScarf[] = _("讲究围巾");
static const u8 sText_HoldEffectChoiceSpecs[] = _("讲究眼镜");
static const u8 sText_HoldEffectDampRock[] = _("潮湿岩石");
static const u8 sText_HoldEffectGripClaw[] = _("紧缠钩爪");
static const u8 sText_HoldEffectHeatRock[] = _("炽热岩石");
static const u8 sText_HoldEffectIcyRock[] = _("冰冷岩石");
static const u8 sText_HoldEffectLightClay[] = _("光之黏土");
static const u8 sText_HoldEffectSmoothRock[] = _("沙沙岩石");
static const u8 sText_HoldEffectPowerHerb[] = _("强力香草");
static const u8 sText_HoldEffectBigRoot[] = _("大根茎");
static const u8 sText_HoldEffectExpertBelt[] = _("达人带");
static const u8 sText_HoldEffectLifeOrb[] = _("生命宝珠");
static const u8 sText_HoldEffectMetronome[] = _("挥指");
static const u8 sText_HoldEffectMuscleBand[] = _("力量头带");
static const u8 sText_HoldEffectWideLens[] = _("广角镜");
static const u8 sText_HoldEffectWiseGlasses[] = _("博识眼镜");
static const u8 sText_HoldEffectZoomLens[] = _("对焦镜");
static const u8 sText_HoldEffectLaggingTail[] = _("后攻之尾");
static const u8 sText_HoldEffectFocusSash[] = _("气势披带");
static const u8 sText_HoldEffectFlameOrb[] = _("火焰宝珠");
static const u8 sText_HoldEffectToxicOrb[] = _("剧毒宝珠");
static const u8 sText_HoldEffectStickyBarb[] = _("附着针");
static const u8 sText_HoldEffectIronBall[] = _("黑色铁球");
static const u8 sText_HoldEffectBlackSludge[] = _("黑色污泥");
static const u8 sText_HoldEffectDestinyKnot[] = _("红线");
static const u8 sText_HoldEffectShedShell[] = _("美丽空壳");
static const u8 sText_HoldEffectQuickPowder[] = _("速度粉");
static const u8 sText_HoldEffectAdamantOrb[] = _("金刚宝珠");
static const u8 sText_HoldEffectLustrousOrb[] = _("白玉宝珠");
static const u8 sText_HoldEffectGriseousOrb[] = _("白金宝珠");
static const u8 sText_HoldEffectEnigmaBerry[] = _("谜芝果");
static const u8 sText_HoldEffectResistBerry[] = _("属性抵抗类树果");
static const u8 sText_HoldEffectPowerItem[] = _("属性增强类道具");
static const u8 sText_HoldEffectRestorePctHp[] = _("一定比例HP回复");
static const u8 sText_HoldEffectMicleBerry[] = _("奇秘果");
static const u8 sText_HoldEffectCustapBerry[] = _("释陀果");
static const u8 sText_HoldEffectJabocaBerry[] = _("嘉珍果");
static const u8 sText_HoldEffectRowapBerry[] = _("雾莲果");
static const u8 sText_HoldEffectKeeBerry[] = _("亚开果");
static const u8 sText_HoldEffectMarangaBerry[] = _("香罗果");
static const u8 sText_HoldEffectFloatStone[] = _("轻石");
static const u8 sText_HoldEffectEviolite[] = _("进化奇石");
static const u8 sText_HoldEffectAssaultVest[] = _("突击背心");
static const u8 sText_HoldEffectDrive[] = _("属性卡带");
static const u8 sText_HoldEffectGems[] = _("属性宝石");
static const u8 sText_HoldEffectRockyHelmet[] = _("凸凸头盔");
static const u8 sText_HoldEffectAirBalloon[] = _("气球");
static const u8 sText_HoldEffectRedCard[] = _("红牌");
static const u8 sText_HoldEffectRingTarget[] = _("标靶");
static const u8 sText_HoldEffectBindingBand[] = _("紧绑束带");
static const u8 sText_HoldEffectEjectButton[] = _("逃脱按键");
static const u8 sText_HoldEffectAbsorbBulb[] = _("球根");
static const u8 sText_HoldEffectCellBattery[] = _("充电电池");
static const u8 sText_HoldEffectMegaStone[] = _("超级进化石");
static const u8 sText_HoldEffectSafetyGoggles[] = _("防尘护目镜");
static const u8 sText_HoldEffectLuminousMoss[] = _("光苔");
static const u8 sText_HoldEffectSnowball[] = _("雪丸");
static const u8 sText_HoldEffectWeaknessPolicy[] = _("弱点保险");
static const u8 sText_HoldEffectPrimalOrb[] = _("原始回归宝珠");
static const u8 sText_HoldEffectProtectivePads[] = _("部位护具");
static const u8 sText_HoldEffectTerrainExtender[] = _("大地膜");
static const u8 sText_HoldEffectSeeds[] = _("场地种子");
static const u8 sText_HoldEffectAdrenalineOrb[] = _("胆怯球");
static const u8 sText_HoldEffectMemory[] = _("属性存储碟");
static const u8 sText_HoldEffectZCrystal[] = _("Z纯晶");
static const u8 sText_HoldEffectPlate[] = _("属性石板");
static const u8 sText_HoldEffectUtilityUmbrella[] = _("万能伞");
static const u8 sText_HoldEffectEjectPack[] = _("避难背包");
static const u8 sText_HoldEffectRoomService[] = _("客房服务");
static const u8 sText_HoldEffectBlunderPolicy[] = _("打空保险");
static const u8 sText_HoldEffectHeavyDutyBoots[] = _("厚底靴");
static const u8 sText_HoldEffectThroatSpray[] = _("爽喉喷雾");
static const u8 sText_HoldEffectAbilityShield[] = _("特性护具");
static const u8 sText_HoldEffectClearAmulet[] = _("清净坠饰");
static const u8 sText_HoldEffectMirrorHerb[] = _("模仿香草");
static const u8 sText_HoldEffectPunchingGlove[] = _("拳击手套");
static const u8 sText_HoldEffectCovertCloak[] = _("密探斗篷");
static const u8 sText_HoldEffectLoadedDice[] = _("机变骰子");
static const u8 sText_HoldEffectBoosterEnergy[] = _("驱劲能量");
static const u8 sText_HoldEffectBerserkGene[] = _("破坏基因");
static const u8 sText_HoldEffectOgerponMask[] = _("厄诡椪面具");
static const u8 *const sHoldEffectNames[] =
{
[HOLD_EFFECT_NONE] = sText_HoldEffectNone,
[HOLD_EFFECT_RESTORE_HP] = sText_HoldEffectRestoreHp,
[HOLD_EFFECT_CURE_PAR] = sText_HoldEffectCurePar,
[HOLD_EFFECT_CURE_SLP] = sText_HoldEffectCureSlp,
[HOLD_EFFECT_CURE_PSN] = sText_HoldEffectCurePsn,
[HOLD_EFFECT_CURE_BRN] = sText_HoldEffectCureBrn,
[HOLD_EFFECT_CURE_FRZ] = sText_HoldEffectCureFrz,
[HOLD_EFFECT_RESTORE_PP] = sText_HoldEffectRestorePp,
[HOLD_EFFECT_CURE_CONFUSION] = sText_HoldEffectCureConfusion,
[HOLD_EFFECT_CURE_STATUS] = sText_HoldEffectCureStatus,
[HOLD_EFFECT_CONFUSE_SPICY] = sText_HoldEffectConfuseSpicy,
[HOLD_EFFECT_CONFUSE_DRY] = sText_HoldEffectConfuseDry,
[HOLD_EFFECT_CONFUSE_SWEET] = sText_HoldEffectConfuseSweet,
[HOLD_EFFECT_CONFUSE_BITTER] = sText_HoldEffectConfuseBitter,
[HOLD_EFFECT_CONFUSE_SOUR] = sText_HoldEffectConfuseSour,
[HOLD_EFFECT_ATTACK_UP] = sText_HoldEffectAttackUp,
[HOLD_EFFECT_DEFENSE_UP] = sText_HoldEffectDefenseUp,
[HOLD_EFFECT_SPEED_UP] = sText_HoldEffectSpeedUp,
[HOLD_EFFECT_SP_ATTACK_UP] = sText_HoldEffectSpAttackUp,
[HOLD_EFFECT_SP_DEFENSE_UP] = sText_HoldEffectSpDefenseUp,
[HOLD_EFFECT_CRITICAL_UP] = sText_HoldEffectCriticalUp,
[HOLD_EFFECT_RANDOM_STAT_UP] = sText_HoldEffectRandomStatUp,
[HOLD_EFFECT_EVASION_UP] = sText_HoldEffectEvasionUp,
[HOLD_EFFECT_WHITE_HERB] = sText_HoldEffectRestoreStats,
[HOLD_EFFECT_MACHO_BRACE] = sText_HoldEffectMachoBrace,
[HOLD_EFFECT_EXP_SHARE] = sText_HoldEffectExpShare,
[HOLD_EFFECT_QUICK_CLAW] = sText_HoldEffectQuickClaw,
[HOLD_EFFECT_FRIENDSHIP_UP] = sText_HoldEffectFriendshipUp,
[HOLD_EFFECT_MENTAL_HERB] = sText_HoldEffectMentalHerb,
[HOLD_EFFECT_CHOICE_BAND] = sText_HoldEffectChoiceBand,
[HOLD_EFFECT_FLINCH] = sText_HoldEffectFlinch,
[HOLD_EFFECT_DOUBLE_PRIZE] = sText_HoldEffectDoublePrize,
[HOLD_EFFECT_REPEL] = sText_HoldEffectRepel,
[HOLD_EFFECT_SOUL_DEW] = sText_HoldEffectSoulDew,
[HOLD_EFFECT_DEEP_SEA_TOOTH] = sText_HoldEffectDeepSeaTooth,
[HOLD_EFFECT_DEEP_SEA_SCALE] = sText_HoldEffectDeepSeaScale,
[HOLD_EFFECT_CAN_ALWAYS_RUN] = sText_HoldEffectCanAlwaysRun,
[HOLD_EFFECT_PREVENT_EVOLVE] = sText_HoldEffectPreventEvolve,
[HOLD_EFFECT_FOCUS_BAND] = sText_HoldEffectFocusBand,
[HOLD_EFFECT_LUCKY_EGG] = sText_HoldEffectLuckyEgg,
[HOLD_EFFECT_SCOPE_LENS] = sText_HoldEffectScopeLens,
[HOLD_EFFECT_LEFTOVERS] = sText_HoldEffectLeftovers,
[HOLD_EFFECT_DRAGON_SCALE] = sText_HoldEffectDragonScale,
[HOLD_EFFECT_LIGHT_BALL] = sText_HoldEffectLightBall,
[HOLD_EFFECT_TYPE_POWER] = sText_HoldEffectTypePower,
[HOLD_EFFECT_UPGRADE] = sText_HoldEffectUpgrade,
[HOLD_EFFECT_SHELL_BELL] = sText_HoldEffectShellBell,
[HOLD_EFFECT_LUCKY_PUNCH] = sText_HoldEffectLuckyPunch,
[HOLD_EFFECT_METAL_POWDER] = sText_HoldEffectMetalPowder,
[HOLD_EFFECT_THICK_CLUB] = sText_HoldEffectThickClub,
[HOLD_EFFECT_LEEK] = sText_HoldEffectLeek,
[HOLD_EFFECT_CHOICE_SCARF] = sText_HoldEffectChoiceScarf,
[HOLD_EFFECT_CHOICE_SPECS] = sText_HoldEffectChoiceSpecs,
[HOLD_EFFECT_DAMP_ROCK] = sText_HoldEffectDampRock,
[HOLD_EFFECT_GRIP_CLAW] = sText_HoldEffectGripClaw,
[HOLD_EFFECT_HEAT_ROCK] = sText_HoldEffectHeatRock,
[HOLD_EFFECT_ICY_ROCK] = sText_HoldEffectIcyRock,
[HOLD_EFFECT_LIGHT_CLAY] = sText_HoldEffectLightClay,
[HOLD_EFFECT_SMOOTH_ROCK] = sText_HoldEffectSmoothRock,
[HOLD_EFFECT_POWER_HERB] = sText_HoldEffectPowerHerb,
[HOLD_EFFECT_BIG_ROOT] = sText_HoldEffectBigRoot,
[HOLD_EFFECT_EXPERT_BELT] = sText_HoldEffectExpertBelt,
[HOLD_EFFECT_LIFE_ORB] = sText_HoldEffectLifeOrb,
[HOLD_EFFECT_METRONOME] = sText_HoldEffectMetronome,
[HOLD_EFFECT_MUSCLE_BAND] = sText_HoldEffectMuscleBand,
[HOLD_EFFECT_WIDE_LENS] = sText_HoldEffectWideLens,
[HOLD_EFFECT_WISE_GLASSES] = sText_HoldEffectWiseGlasses,
[HOLD_EFFECT_ZOOM_LENS] = sText_HoldEffectZoomLens,
[HOLD_EFFECT_LAGGING_TAIL] = sText_HoldEffectLaggingTail,
[HOLD_EFFECT_FOCUS_SASH] = sText_HoldEffectFocusSash,
[HOLD_EFFECT_FLAME_ORB] = sText_HoldEffectFlameOrb,
[HOLD_EFFECT_TOXIC_ORB] = sText_HoldEffectToxicOrb,
[HOLD_EFFECT_STICKY_BARB] = sText_HoldEffectStickyBarb,
[HOLD_EFFECT_IRON_BALL] = sText_HoldEffectIronBall,
[HOLD_EFFECT_BLACK_SLUDGE] = sText_HoldEffectBlackSludge,
[HOLD_EFFECT_DESTINY_KNOT] = sText_HoldEffectDestinyKnot,
[HOLD_EFFECT_SHED_SHELL] = sText_HoldEffectShedShell,
[HOLD_EFFECT_QUICK_POWDER] = sText_HoldEffectQuickPowder,
[HOLD_EFFECT_ADAMANT_ORB] = sText_HoldEffectAdamantOrb,
[HOLD_EFFECT_LUSTROUS_ORB] = sText_HoldEffectLustrousOrb,
[HOLD_EFFECT_GRISEOUS_ORB] = sText_HoldEffectGriseousOrb,
[HOLD_EFFECT_ENIGMA_BERRY] = sText_HoldEffectEnigmaBerry,
[HOLD_EFFECT_RESIST_BERRY] = sText_HoldEffectResistBerry,
[HOLD_EFFECT_POWER_ITEM] = sText_HoldEffectPowerItem,
[HOLD_EFFECT_RESTORE_PCT_HP] = sText_HoldEffectRestorePctHp,
[HOLD_EFFECT_MICLE_BERRY] = sText_HoldEffectMicleBerry,
[HOLD_EFFECT_CUSTAP_BERRY] = sText_HoldEffectCustapBerry,
[HOLD_EFFECT_JABOCA_BERRY] = sText_HoldEffectJabocaBerry,
[HOLD_EFFECT_ROWAP_BERRY] = sText_HoldEffectRowapBerry,
[HOLD_EFFECT_KEE_BERRY] = sText_HoldEffectKeeBerry,
[HOLD_EFFECT_MARANGA_BERRY] = sText_HoldEffectMarangaBerry,
[HOLD_EFFECT_PLATE] = sText_HoldEffectPlate,
[HOLD_EFFECT_FLOAT_STONE] = sText_HoldEffectFloatStone,
[HOLD_EFFECT_EVIOLITE] = sText_HoldEffectEviolite,
[HOLD_EFFECT_ASSAULT_VEST] = sText_HoldEffectAssaultVest,
[HOLD_EFFECT_DRIVE] = sText_HoldEffectDrive,
[HOLD_EFFECT_GEMS] = sText_HoldEffectGems,
[HOLD_EFFECT_ROCKY_HELMET] = sText_HoldEffectRockyHelmet,
[HOLD_EFFECT_AIR_BALLOON] = sText_HoldEffectAirBalloon,
[HOLD_EFFECT_RED_CARD] = sText_HoldEffectRedCard,
[HOLD_EFFECT_RING_TARGET] = sText_HoldEffectRingTarget,
[HOLD_EFFECT_BINDING_BAND] = sText_HoldEffectBindingBand,
[HOLD_EFFECT_EJECT_BUTTON] = sText_HoldEffectEjectButton,
[HOLD_EFFECT_ABSORB_BULB] = sText_HoldEffectAbsorbBulb,
[HOLD_EFFECT_CELL_BATTERY] = sText_HoldEffectCellBattery,
[HOLD_EFFECT_MEGA_STONE] = sText_HoldEffectMegaStone,
[HOLD_EFFECT_SAFETY_GOGGLES] = sText_HoldEffectSafetyGoggles,
[HOLD_EFFECT_LUMINOUS_MOSS] = sText_HoldEffectLuminousMoss,
[HOLD_EFFECT_SNOWBALL] = sText_HoldEffectSnowball,
[HOLD_EFFECT_WEAKNESS_POLICY] = sText_HoldEffectWeaknessPolicy,
[HOLD_EFFECT_PRIMAL_ORB] = sText_HoldEffectPrimalOrb,
[HOLD_EFFECT_PROTECTIVE_PADS] = sText_HoldEffectProtectivePads,
[HOLD_EFFECT_TERRAIN_EXTENDER] = sText_HoldEffectTerrainExtender,
[HOLD_EFFECT_SEEDS] = sText_HoldEffectSeeds,
[HOLD_EFFECT_ADRENALINE_ORB] = sText_HoldEffectAdrenalineOrb,
[HOLD_EFFECT_MEMORY] = sText_HoldEffectMemory,
[HOLD_EFFECT_Z_CRYSTAL] = sText_HoldEffectZCrystal,
[HOLD_EFFECT_UTILITY_UMBRELLA] = sText_HoldEffectUtilityUmbrella,
[HOLD_EFFECT_EJECT_PACK] = sText_HoldEffectEjectPack,
[HOLD_EFFECT_ROOM_SERVICE] = sText_HoldEffectRoomService,
[HOLD_EFFECT_BLUNDER_POLICY] = sText_HoldEffectBlunderPolicy,
[HOLD_EFFECT_HEAVY_DUTY_BOOTS] = sText_HoldEffectHeavyDutyBoots,
[HOLD_EFFECT_THROAT_SPRAY] = sText_HoldEffectThroatSpray,
[HOLD_EFFECT_ABILITY_SHIELD] = sText_HoldEffectAbilityShield,
[HOLD_EFFECT_CLEAR_AMULET] = sText_HoldEffectClearAmulet,
[HOLD_EFFECT_MIRROR_HERB] = sText_HoldEffectMirrorHerb,
[HOLD_EFFECT_PUNCHING_GLOVE] = sText_HoldEffectPunchingGlove,
[HOLD_EFFECT_COVERT_CLOAK] = sText_HoldEffectCovertCloak,
[HOLD_EFFECT_LOADED_DICE] = sText_HoldEffectLoadedDice,
[HOLD_EFFECT_BOOSTER_ENERGY] = sText_HoldEffectBoosterEnergy,
[HOLD_EFFECT_OGERPON_MASK] = sText_HoldEffectOgerponMask,
[HOLD_EFFECT_BERSERK_GENE] = sText_HoldEffectBerserkGene,
};
static const u8 *GetHoldEffectName(enum ItemHoldEffect holdEffect)
{
if (holdEffect > ARRAY_COUNT(sHoldEffectNames))
return sHoldEffectNames[0];
return sHoldEffectNames[holdEffect];
}