From 3ad66028e9291ab3dc91340ea40758c32a9df949 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 27 Dec 2023 16:48:17 +0000 Subject: [PATCH 01/13] =?UTF-8?q?Backwards-compatible=20BoxPok=C3=A9mon=20?= =?UTF-8?q?Refactor=20(#3438)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Check progress in non-battle PARAMETRIZEd tests * Overworld Script Tests * Backward-compatible BoxPokemon Refactor Reuses space that contains zeros to provide space for: - HP/status in the box - 12-character nicknames - Up to 63 PokéBalls - Shininess separate from PID - Hidden Nature - Hyper Training - Dynamax Level - Gigantamax Factor - Terastallization Types - Shadow Implements: - OW_PC_HEAL to switch between Gen7- and Gen8+ behavior - Nature Mints - Dynamax Candy - Hyper Training commands (canhypertrain/hypertrain) - Gigantamax Factor commands (hasgigantamaxfactor/togglegigantamaxfactor) - Terastallization Type on the summary screen - Prevents Gigantamax Factor Pokémon from evolving into a species without a Gigantamax form * fixup! Backward-compatible BoxPokemon Refactor * displaydexinfo fix from Jasper --- asm/macros/event.inc | 30 ++ include/battle.h | 4 +- include/battle_anim.h | 2 +- include/config/overworld.h | 1 + include/config/pokemon.h | 1 + include/constants/battle.h | 5 +- include/constants/global.h | 2 + include/constants/moves.h | 2 + include/constants/pokemon.h | 2 + include/contest.h | 6 +- include/data.h | 2 + include/global.h | 7 +- include/item_use.h | 2 + include/party_menu.h | 2 + include/pokedex.h | 2 +- include/pokemon.h | 195 ++++++----- include/test/battle.h | 8 + include/test/overworld_script.h | 48 +++ include/test/test.h | 5 +- include/trainer_pokemon_sprites.h | 4 +- src/battle_anim_effects_1.c | 2 +- src/battle_anim_effects_3.c | 22 +- src/battle_anim_mons.c | 6 +- src/battle_anim_throw.c | 11 +- src/battle_controllers.c | 2 +- src/battle_debug.c | 4 +- src/battle_dynamax.c | 10 +- src/battle_factory_screen.c | 33 +- src/battle_gfx_sfx_util.c | 26 +- src/battle_main.c | 17 +- src/battle_script_commands.c | 7 +- src/battle_tower.c | 10 +- src/battle_util.c | 5 +- src/contest.c | 11 +- src/contest_painting.c | 2 +- src/contest_util.c | 13 +- src/data/items.h | 109 ++++--- src/daycare.c | 1 - src/debug.c | 24 +- src/evolution_scene.c | 31 +- src/field_effect.c | 16 +- src/frontier_util.c | 7 +- src/hall_of_fame.c | 10 +- src/item_use.c | 12 + src/load_save.c | 10 + src/main_menu.c | 2 +- src/menu_specialized.c | 4 +- src/party_menu.c | 162 +++++++++ src/pokeblock_feed.c | 7 +- src/pokedex.c | 18 +- src/pokemon.c | 523 +++++++++++++++++++++++------- src/pokemon_jump.c | 11 +- src/pokemon_storage_system.c | 18 +- src/pokemon_summary_screen.c | 13 +- src/pokenav_conditions.c | 7 +- src/pokenav_ribbons_summary.c | 18 +- src/script_pokemon_util.c | 109 +++++-- src/starter_choose.c | 2 +- src/trade.c | 2 +- src/trainer_pokemon_sprites.c | 44 +-- test/battle/trainer_control.c | 6 +- test/dynamax.c | 51 +-- test/pokemon.c | 182 +++++++++++ test/species.c | 2 + test/test_runner.c | 10 + test/test_runner_battle.c | 29 +- 66 files changed, 1437 insertions(+), 514 deletions(-) create mode 100644 include/test/overworld_script.h create mode 100644 test/pokemon.c diff --git a/asm/macros/event.inc b/asm/macros/event.inc index d2d8f8ca6f..62743b6f7c 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -2025,3 +2025,33 @@ callnative CreateTrainerPartyForPlayer trainerbattle_no_intro \trainer2, NULL .endm + + @ Sets VAR_RESULT to TRUE if stat can be hyper trained, or to + @ FALSE otherwise. + .macro canhypertrain stat:req, slot:req + callnative CanHyperTrain + .byte \stat + .2byte \slot + .endm + + @ Hyper Trains a stat. + .macro hypertrain stat:req, slot:req + callnative HyperTrain + .byte \stat + .2byte \slot + .endm + + @ Sets VAR_RESULT to TRUE if the Pokemon has the Gigantamax Factor, + @ or to FALSE otherwise. + .macro hasgigantamaxfactor slot:req + callnative HasGigantamaxFactor + .2byte \slot + .endm + + @ Toggles the Gigantamax Factor for a Pokemon. + @ Fails for Melmetal (vanilla behavior). + @ Sets VAR_RESULT to TRUE if it succeeds, and FALSE otherwise. + .macro togglegigantamaxfactor slot:req + callnative ToggleGigantamaxFactor + .2byte \slot + .endm diff --git a/include/battle.h b/include/battle.h index 3fe22a4377..ecf8250774 100644 --- a/include/battle.h +++ b/include/battle.h @@ -65,7 +65,7 @@ struct ResourceFlags struct DisableStruct { u32 transformedMonPersonality; - u32 transformedMonOtId; + bool8 transformedMonShininess; u16 disabledMove; u16 encoredMove; u8 protectUses:4; @@ -1066,7 +1066,7 @@ extern u8 gBattlerStatusSummaryTaskId[MAX_BATTLERS_COUNT]; extern u8 gBattlerInMenuId; extern bool8 gDoingBattleAnim; extern u32 gTransformedPersonalities[MAX_BATTLERS_COUNT]; -extern u32 gTransformedOtIds[MAX_BATTLERS_COUNT]; +extern bool8 gTransformedShininess[MAX_BATTLERS_COUNT]; extern u8 gPlayerDpadHoldFrames; extern struct BattleSpriteData *gBattleSpritesDataPtr; extern struct MonSpritesGfx *gMonSpritesGfxPtr; diff --git a/include/battle_anim.h b/include/battle_anim.h index 672b640cc9..c41d94eb09 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -159,7 +159,7 @@ void PrepareAffineAnimInTaskData(struct Task *task, u8 spriteId, const union Aff bool8 RunAffineAnimFromTaskData(struct Task *task); void AnimThrowProjectile(struct Sprite *sprite); void GetBgDataForTransform(struct BattleAnimBgData *dest, u8 battlerId); -u8 CreateAdditionalMonSpriteForMoveAnim(u16 species, bool8 isBackpic, u8 id, s16 x, s16 y, u8 subpriority, u32 personality, u32 trainerId, u32 battlerId); +u8 CreateAdditionalMonSpriteForMoveAnim(u16 species, bool8 isBackpic, u8 id, s16 x, s16 y, u8 subpriority, u32 personality, bool8 isShiny, u32 battlerId); void ResetSpriteRotScale_PreserveAffine(struct Sprite *sprite); void Trade_MoveSelectedMonToTarget(struct Sprite *sprite); void DestroyAnimVisualTaskAndDisableBlend(u8 taskId); diff --git a/include/config/overworld.h b/include/config/overworld.h index 3488064421..513eb36723 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -11,6 +11,7 @@ // PC settings #define OW_PC_PRESS_B GEN_LATEST // In Gen4, pressing B when holding a Pokémon is equivalent to placing it. In Gen3, it gives the "You're holding a Pokémon!" error. #define OW_PC_JAPAN_WALDA_ICONS TRUE // In the US release of Emerald, the Cross, Bolt, and Plusle icons for Walda's wallpapers were left blank from the Japan release. Setting this to TRUE will restore them. +#define OW_PC_HEAL GEN_LATEST // In Gen8+, Pokémon are not healed when deposited in the PC. // Out-of-battle Ability effects #define OW_SYNCHRONIZE_NATURE GEN_LATEST // In Gen8, if a Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same Nature, as opposed to 50% previously. Stationary Pokémon are excluded in Gen3. In Gen6, all No Eggs Discovered gift Pokémon will have the same Nature, while in Gen7 all gift Pokémon will, regardless of Egg Group - In Gen 8, no gift Pokémon are affected. In Gen9, this ability has no out-of-battle effect. diff --git a/include/config/pokemon.h b/include/config/pokemon.h index abdb728ac1..58c740f079 100644 --- a/include/config/pokemon.h +++ b/include/config/pokemon.h @@ -32,6 +32,7 @@ #define P_LEGENDARY_PERFECT_IVS GEN_LATEST // Since Gen 6, Legendaries, Mythicals and Ultra Beasts found in the wild or given through gifts have at least 3 perfect IVs. #define P_EV_CAP GEN_LATEST // Since Gen 6, the max EVs per stat is 252 instead of 255. #define P_CATCH_CURVE GEN_LATEST // Since Gen 6, the capture rate curve was changed to make pokeballs more effective on lower level pokemon +#define P_SHOW_TERA_TYPE GEN_LATEST // Since Gen 9, the Tera Type is shown on the summary screen. // Flag settings // To use the following features in scripting, replace the 0s with the flag ID you're assigning it to. diff --git a/include/constants/battle.h b/include/constants/battle.h index 35addb937b..92688026f8 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -104,7 +104,10 @@ #define B_OUTCOME_LINK_BATTLE_RAN (1 << 7) // 128 // Non-volatile status conditions -// These persist remain outside of battle and after switching out +// These remain outside of battle and after switching out. +// If a new STATUS1 is added here, it should also be added to +// sCompressedStatuses in src/pokemon.c or else it will be lost outside +// of battle. #define STATUS1_NONE 0 #define STATUS1_SLEEP (1 << 0 | 1 << 1 | 1 << 2) // First 3 bits (Number of turns to sleep) #define STATUS1_SLEEP_TURN(num) ((num) << 0) // Just for readability (or if rearranging statuses) diff --git a/include/constants/global.h b/include/constants/global.h index 7f4d8ccd3a..f9b7241ef6 100644 --- a/include/constants/global.h +++ b/include/constants/global.h @@ -24,6 +24,8 @@ #define VERSION_PLATINUM 12 #define VERSION_GAMECUBE 15 +#define NUM_VERSIONS 15 + #define LANGUAGE_JAPANESE 1 #define LANGUAGE_ENGLISH 2 #define LANGUAGE_FRENCH 3 diff --git a/include/constants/moves.h b/include/constants/moves.h index a8fcb01654..54b366e18b 100644 --- a/include/constants/moves.h +++ b/include/constants/moves.h @@ -1014,6 +1014,8 @@ #define MOVES_COUNT_DYNAMAX (LAST_MAX_MOVE + 1) +#define MOVES_COUNT_ALL MOVES_COUNT_DYNAMAX + // Used for checks for moves affected by Disable, Mimic, etc. #define MOVE_UNAVAILABLE 0xFFFF diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 67053a2819..06da4a179e 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -146,6 +146,8 @@ #define MIN_LEVEL 1 #define MAX_LEVEL 100 +#define MAX_DYNAMAX_LEVEL 10 + #define OT_ID_PLAYER_ID 0 #define OT_ID_PRESET 1 #define OT_ID_RANDOM_NO_SHINY 2 diff --git a/include/contest.h b/include/contest.h index 7a67fecd55..9f2fafaf25 100644 --- a/include/contest.h +++ b/include/contest.h @@ -107,7 +107,9 @@ struct ContestPokemon u8 sheen; u8 highestRank; bool8 gameCleared; - u8 unused[10]; + u8 isShiny:1; + u8 unused1:7; + u8 unused2[9]; u32 personality; u32 otId; }; @@ -125,6 +127,8 @@ struct ContestMoveAnimData u16 species; u16 targetSpecies; bool8 hasTargetAnim:1; + u8 isShiny:1; + u8 targetIsShiny:1; u8 contestant; u32 personality; u32 otId; diff --git a/include/data.h b/include/data.h index a5918fcb98..6351b6eb16 100644 --- a/include/data.h +++ b/include/data.h @@ -66,6 +66,8 @@ struct TrainerMon u8 nature : 5; bool8 gender : 2; bool8 isShiny : 1; + u8 dynamaxLevel : 4; + bool8 gigantamaxFactor : 1; }; #define TRAINER_PARTY(partyArray) partyArray, .partySize = ARRAY_COUNT(partyArray) diff --git a/include/global.h b/include/global.h index 60abf094af..84d5cafa7c 100644 --- a/include/global.h +++ b/include/global.h @@ -129,8 +129,8 @@ #define CAT(a, b) CAT_(a, b) #define CAT_(a, b) a ## b -#define STR(a) STR_(a) -#define STR_(a) #a +#define STR(...) STR_(__VA_ARGS__) +#define STR_(...) #__VA_ARGS__ // Converts a string to a compound literal, essentially making it a pointer to const u8 #define COMPOUND_STRING(str) (const u8[]) _(str) @@ -738,7 +738,8 @@ struct ContestWinner u8 contestCategory; u8 monName[POKEMON_NAME_LENGTH + 1]; u8 trainerName[PLAYER_NAME_LENGTH + 1]; - u8 contestRank; + u8 contestRank:7; + bool8 isShiny:1; //u8 padding; }; diff --git a/include/item_use.h b/include/item_use.h index 3117e603d5..d073e9d3ea 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -13,12 +13,14 @@ void ItemUseOutOfBattle_WailmerPail(u8); void ItemUseOutOfBattle_Medicine(u8); void ItemUseOutOfBattle_AbilityCapsule(u8); void ItemUseOutOfBattle_AbilityPatch(u8); +void ItemUseOutOfBattle_Mint(u8); void ItemUseOutOfBattle_ResetEVs(u8); void ItemUseOutOfBattle_ReduceEV(u8); void ItemUseOutOfBattle_SacredAsh(u8); void ItemUseOutOfBattle_PPRecovery(u8); void ItemUseOutOfBattle_PPUp(u8); void ItemUseOutOfBattle_RareCandy(u8); +void ItemUseOutOfBattle_DynamaxCandy(u8); void ItemUseOutOfBattle_TMHM(u8); void ItemUseOutOfBattle_Repel(u8); void ItemUseOutOfBattle_Lure(u8); diff --git a/include/party_menu.h b/include/party_menu.h index c50abc276a..1352f54a43 100644 --- a/include/party_menu.h +++ b/include/party_menu.h @@ -53,6 +53,7 @@ void ItemUseCB_BattleChooseMove(u8 taskId, TaskFunc task); void ItemUseCB_Medicine(u8 taskId, TaskFunc task); void ItemUseCB_AbilityCapsule(u8 taskId, TaskFunc task); void ItemUseCB_AbilityPatch(u8 taskId, TaskFunc task); +void ItemUseCB_Mint(u8 taskId, TaskFunc task); void ItemUseCB_ResetEVs(u8 taskId, TaskFunc task); void ItemUseCB_ReduceEV(u8 taskId, TaskFunc task); void ItemUseCB_PPRecovery(u8 taskId, TaskFunc task); @@ -62,6 +63,7 @@ bool8 MonKnowsMove(struct Pokemon *mon, u16 move); bool8 BoxMonKnowsMove(struct BoxPokemon *boxMon, u16 move); void ItemUseCB_TMHM(u8 taskId, TaskFunc task); void ItemUseCB_RareCandy(u8 taskId, TaskFunc task); +void ItemUseCB_DynamaxCandy(u8 taskId, TaskFunc task); void ItemUseCB_SacredAsh(u8 taskId, TaskFunc task); void ItemUseCB_EvolutionStone(u8 taskId, TaskFunc task); void ItemUseCB_FormChange(u8 taskId, TaskFunc task); diff --git a/include/pokedex.h b/include/pokedex.h index 39b45fc5ff..c2169c6994 100644 --- a/include/pokedex.h +++ b/include/pokedex.h @@ -21,7 +21,7 @@ enum void ResetPokedex(void); u16 GetNationalPokedexCount(u8); u16 GetHoennPokedexCount(u8); -u8 DisplayCaughtMonDexPage(u16 species, u32 otId, u32 personality); +u8 DisplayCaughtMonDexPage(u16 species, bool32 isShiny, u32 personality); s8 GetSetPokedexFlag(u16 nationalNum, u8 caseId); u16 CreateMonSpriteFromNationalDexNumber(u16, s16, s16, u16); bool16 HasAllHoennMons(void); diff --git a/include/pokemon.h b/include/pokemon.h index b081a86fef..dda784629a 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -12,8 +12,8 @@ // Property labels for Get(Box)MonData / Set(Box)MonData enum { MON_DATA_PERSONALITY, + MON_DATA_STATUS, MON_DATA_OT_ID, - MON_DATA_NICKNAME, MON_DATA_LANGUAGE, MON_DATA_SANITY_IS_BAD_EGG, MON_DATA_SANITY_HAS_SPECIES, @@ -21,7 +21,12 @@ enum { MON_DATA_OT_NAME, MON_DATA_MARKINGS, MON_DATA_CHECKSUM, + MON_DATA_HP, + MON_DATA_IS_SHINY, + MON_DATA_HIDDEN_NATURE, + MON_DATA_HP_LOST, MON_DATA_ENCRYPT_SEPARATOR, + MON_DATA_NICKNAME, MON_DATA_SPECIES, MON_DATA_HELD_ITEM, MON_DATA_MOVE1, @@ -66,9 +71,7 @@ enum { MON_DATA_CUTE_RIBBON, MON_DATA_SMART_RIBBON, MON_DATA_TOUGH_RIBBON, - MON_DATA_STATUS, MON_DATA_LEVEL, - MON_DATA_HP, MON_DATA_MAX_HP, MON_DATA_ATK, MON_DATA_DEF, @@ -90,7 +93,6 @@ enum { MON_DATA_NATIONAL_RIBBON, MON_DATA_EARTH_RIBBON, MON_DATA_WORLD_RIBBON, - MON_DATA_UNUSED_RIBBONS, MON_DATA_MODERN_FATEFUL_ENCOUNTER, MON_DATA_KNOWN_MOVES, MON_DATA_RIBBON_COUNT, @@ -100,87 +102,116 @@ enum { MON_DATA_SPEED2, MON_DATA_SPATK2, MON_DATA_SPDEF2, + MON_DATA_HYPER_TRAINED_HP, + MON_DATA_HYPER_TRAINED_ATK, + MON_DATA_HYPER_TRAINED_DEF, + MON_DATA_HYPER_TRAINED_SPEED, + MON_DATA_HYPER_TRAINED_SPATK, + MON_DATA_HYPER_TRAINED_SPDEF, + MON_DATA_IS_SHADOW, + MON_DATA_DYNAMAX_LEVEL, + MON_DATA_GIGANTAMAX_FACTOR, + MON_DATA_TERA_TYPE, }; struct PokemonSubstruct0 { - /*0x00*/ u16 species; - /*0x02*/ u16 heldItem; - /*0x04*/ u32 experience; - /*0x08*/ u8 ppBonuses; - /*0x09*/ u8 friendship; - /*0x0A*/ u16 pokeball:5; //31 balls - u16 filler:11; -}; /* size = 12 */ + u16 species:11; // 2047 species. + u16 teraType:5; // 30 types. + u16 heldItem:10; // 1023 items. + u16 unused_02:6; + u32 experience:21; + u32 nickname11:8; // 11th character of nickname. + u32 unused_04:3; + u8 ppBonuses; + u8 friendship; + u16 pokeball:6; // 63 balls. + u16 nickname12:8; // 12th character of nickname. + u16 unused_0A:2; +}; struct PokemonSubstruct1 { - /*0x00*/ u16 moves[MAX_MON_MOVES]; - /*0x08*/ u8 pp[MAX_MON_MOVES]; -}; /* size = 12 */ + u16 move1:11; // 2047 moves. + u16 unused_00:5; + u16 move2:11; // 2047 moves. + u16 unused_02:5; + u16 move3:11; // 2047 moves. + u16 unused_04:5; + u16 move4:11; // 2047 moves. + u16 unused_06:3; + u16 hyperTrainedHP:1; + u16 hyperTrainedAttack:1; + u8 pp1:7; // 127 PP. + u8 hyperTrainedDefense:1; + u8 pp2:7; // 127 PP. + u8 hyperTrainedSpeed:1; + u8 pp3:7; // 127 PP. + u8 hyperTrainedSpAttack:1; + u8 pp4:7; // 127 PP. + u8 hyperTrainedSpDefense:1; +}; struct PokemonSubstruct2 { - /*0x00*/ u8 hpEV; - /*0x01*/ u8 attackEV; - /*0x02*/ u8 defenseEV; - /*0x03*/ u8 speedEV; - /*0x04*/ u8 spAttackEV; - /*0x05*/ u8 spDefenseEV; - /*0x06*/ u8 cool; - /*0x07*/ u8 beauty; - /*0x08*/ u8 cute; - /*0x09*/ u8 smart; - /*0x0A*/ u8 tough; - /*0x0B*/ u8 sheen; -}; /* size = 12 */ + u8 hpEV; + u8 attackEV; + u8 defenseEV; + u8 speedEV; + u8 spAttackEV; + u8 spDefenseEV; + u8 cool; + u8 beauty; + u8 cute; + u8 smart; + u8 tough; + u8 sheen; +}; struct PokemonSubstruct3 { - /* 0x00 */ u8 pokerus; - /* 0x01 */ u8 metLocation; + u8 pokerus; + u8 metLocation; + u16 metLevel:7; + u16 metGame:4; + u16 dynamaxLevel:4; + u16 otGender:1; + u32 hpIV:5; + u32 attackIV:5; + u32 defenseIV:5; + u32 speedIV:5; + u32 spAttackIV:5; + u32 spDefenseIV:5; + u32 isEgg:1; + u32 gigantamaxFactor:1; + u32 coolRibbon:3; // Stores the highest contest rank achieved in the Cool category. + u32 beautyRibbon:3; // Stores the highest contest rank achieved in the Beauty category. + u32 cuteRibbon:3; // Stores the highest contest rank achieved in the Cute category. + u32 smartRibbon:3; // Stores the highest contest rank achieved in the Smart category. + u32 toughRibbon:3; // Stores the highest contest rank achieved in the Tough category. + u32 championRibbon:1; // Given when defeating the Champion. Because both RSE and FRLG use it, later generations don't specify from which region it comes from. + u32 winningRibbon:1; // Given at the Battle Tower's Level 50 challenge by winning a set of seven battles that extends the current streak to 56 or more. + u32 victoryRibbon:1; // Given at the Battle Tower's Level 100 challenge by winning a set of seven battles that extends the current streak to 56 or more. + u32 artistRibbon:1; // Given at the Contest Hall by winning a Master Rank contest with at least 800 points, and agreeing to have the Pokémon's portrait placed in the museum after being offered. + u32 effortRibbon:1; // Given at Slateport's market to Pokémon with maximum EVs. + u32 marineRibbon:1; // Never distributed. + u32 landRibbon:1; // Never distributed. + u32 skyRibbon:1; // Never distributed. + u32 countryRibbon:1; // Distributed during Pokémon Festa '04 and '05 to tournament winners. + u32 nationalRibbon:1; // Given to purified Shadow Pokémon in Colosseum/XD. + u32 earthRibbon:1; // Given to teams that have beaten Mt. Battle's 100-battle challenge in Colosseum/XD. + u32 worldRibbon:1; // Distributed during Pokémon Festa '04 and '05 to tournament winners. + u32 isShadow:1; + u32 unused_0B:1; + u32 abilityNum:2; - /* 0x02 */ u16 metLevel:7; - /* 0x02 */ u16 metGame:4; - /* 0x03 */ u16 unused1:4; - /* 0x03 */ u16 otGender:1; - - /* 0x04 */ u32 hpIV:5; - /* 0x04 */ u32 attackIV:5; - /* 0x05 */ u32 defenseIV:5; - /* 0x05 */ u32 speedIV:5; - /* 0x05 */ u32 spAttackIV:5; - /* 0x06 */ u32 spDefenseIV:5; - /* 0x07 */ u32 isEgg:1; - /* 0x07 */ u32 unused2:1; - - /* 0x08 */ u32 coolRibbon:3; // Stores the highest contest rank achieved in the Cool category. - /* 0x08 */ u32 beautyRibbon:3; // Stores the highest contest rank achieved in the Beauty category. - /* 0x08 */ u32 cuteRibbon:3; // Stores the highest contest rank achieved in the Cute category. - /* 0x09 */ u32 smartRibbon:3; // Stores the highest contest rank achieved in the Smart category. - /* 0x09 */ u32 toughRibbon:3; // Stores the highest contest rank achieved in the Tough category. - /* 0x09 */ u32 championRibbon:1; // Given when defeating the Champion. Because both RSE and FRLG use it, later generations don't specify from which region it comes from. - /* 0x0A */ u32 winningRibbon:1; // Given at the Battle Tower's Level 50 challenge by winning a set of seven battles that extends the current streak to 56 or more. - /* 0x0A */ u32 victoryRibbon:1; // Given at the Battle Tower's Level 100 challenge by winning a set of seven battles that extends the current streak to 56 or more. - /* 0x0A */ u32 artistRibbon:1; // Given at the Contest Hall by winning a Master Rank contest with at least 800 points, and agreeing to have the Pokémon's portrait placed in the museum after being offered. - /* 0x0A */ u32 effortRibbon:1; // Given at Slateport's market to Pokémon with maximum EVs. - /* 0x0A */ u32 marineRibbon:1; // Never distributed. - /* 0x0A */ u32 landRibbon:1; // Never distributed. - /* 0x0A */ u32 skyRibbon:1; // Never distributed. - /* 0x0A */ u32 countryRibbon:1; // Distributed during Pokémon Festa '04 and '05 to tournament winners. - /* 0x0B */ u32 nationalRibbon:1; // Given to purified Shadow Pokémon in Colosseum/XD. - /* 0x0B */ u32 earthRibbon:1; // Given to teams that have beaten Mt. Battle's 100-battle challenge in Colosseum/XD. - /* 0x0B */ u32 worldRibbon:1; // Distributed during Pokémon Festa '04 and '05 to tournament winners. - /* 0x0B */ u32 unusedRibbons:2; // Discarded in Gen 4. - /* 0x0B */ u32 abilityNum:2; - - // The functionality of this bit changed in FRLG: - // In RS, this bit does nothing, is never set, & is accidentally unset when hatching Eggs. - // In FRLG & Emerald, this controls Mew & Deoxys obedience and whether they can be traded. - // If set, a Pokémon is a fateful encounter in FRLG's summary screen if hatched & for all Pokémon in Gen 4+ summary screens. - // Set for in-game event island legendaries, events distributed after a certain date, & Pokémon from XD: Gale of Darkness. - // Not to be confused with METLOC_FATEFUL_ENCOUNTER. - /* 0x0B */ u32 modernFatefulEncounter:1; + // The functionality of this bit changed in FRLG: + // In RS, this bit does nothing, is never set, & is accidentally unset when hatching Eggs. + // In FRLG & Emerald, this controls Mew & Deoxys obedience and whether they can be traded. + // If set, a Pokémon is a fateful encounter in FRLG's summary screen if hatched & for all Pokémon in Gen 4+ summary screens. + // Set for in-game event island legendaries, events distributed after a certain date, & Pokémon from XD: Gale of Darkness. + // Not to be confused with METLOC_FATEFUL_ENCOUNTER. + u32 modernFatefulEncounter:1; }; // Number of bytes in the largest Pokémon substruct. @@ -205,17 +236,21 @@ struct BoxPokemon { u32 personality; u32 otId; - u8 nickname[POKEMON_NAME_LENGTH]; - u8 language; + u8 nickname[min(10, POKEMON_NAME_LENGTH)]; + u8 language:3; + u8 hiddenNatureModifier:5; // 31 natures. u8 isBadEgg:1; u8 hasSpecies:1; u8 isEgg:1; - u8 blockBoxRS:1; // Unused, but Pokémon Box Ruby & Sapphire will refuse to deposit a Pokémon with this flag set - u8 unused:4; + u8 blockBoxRS:1; // Unused, but Pokémon Box Ruby & Sapphire will refuse to deposit a Pokémon with this flag set. + u8 unused_13:4; u8 otName[PLAYER_NAME_LENGTH]; - u8 markings; + u8 markings:4; + u8 compressedStatus:4; u16 checksum; - u16 unknown; + u16 hpLost:14; // 16383 HP. + u16 shinyModifier:1; + u16 unused_1E:1; union { @@ -301,6 +336,7 @@ struct BattlePokemon /*0x51*/ u32 status2; /*0x55*/ u32 otId; /*0x59*/ u8 metLevel; + /*0x5A*/ bool8 isShiny; }; struct Evolution @@ -673,7 +709,7 @@ void PlayBattleBGM(void); void PlayMapChosenOrBattleBGM(u16 songId); void CreateTask_PlayMapChosenOrBattleBGM(u16 songId); const u32 *GetMonFrontSpritePal(struct Pokemon *mon); -const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality); +const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, bool32 isShiny, u32 personality); bool8 IsMoveHM(u16 move); bool8 IsMonSpriteNotFlipped(u16 species); s8 GetMonFlavorRelation(struct Pokemon *mon, u8 flavor); @@ -685,7 +721,6 @@ void BoxMonRestorePP(struct BoxPokemon *boxMon); void SetMonPreventsSwitchingString(void); void SetWildMonHeldItem(void); bool8 IsMonShiny(struct Pokemon *mon); -bool8 IsShinyOtIdPersonality(u32 otId, u32 personality); const u8 *GetTrainerPartnerName(void); void BattleAnimateFrontSprite(struct Sprite *sprite, u16 species, bool8 noCry, u8 panMode); void DoMonFrontSpriteAnimation(struct Sprite *sprite, u16 species, bool8 noCry, u8 panModeAnimFlag); @@ -719,5 +754,7 @@ u16 SanitizeSpeciesId(u16 species); bool32 IsSpeciesEnabled(u16 species); u16 GetCryIdBySpecies(u16 species); u16 GetSpeciesPreEvolution(u16 species); +void HealPokemon(struct Pokemon *mon); +void HealBoxPokemon(struct BoxPokemon *boxMon); #endif // GUARD_POKEMON_H diff --git a/include/test/battle.h b/include/test/battle.h index ee41032102..581546f87b 100644 --- a/include/test/battle.h +++ b/include/test/battle.h @@ -849,6 +849,10 @@ struct moveWithPP { #define Friendship(friendship) Friendship_(__LINE__, friendship) #define Status1(status1) Status1_(__LINE__, status1) #define OTName(otName) do {static const u8 otName_[] = _(otName); OTName_(__LINE__, otName_);} while (0) +#define DynamaxLevel(dynamaxLevel) DynamaxLevel_(__LINE__, dynamaxLevel) +#define GigantamaxFactor(gigantamaxFactor) GigantamaxFactor_(__LINE__, gigantamaxFactor) +#define TeraType(teraType) TeraType_(__LINE__, teraType) +#define Shadow(isShadow) Shadow_(__LINE__, shadow) void SetFlagForTest(u32 sourceLine, u16 flagId); void ClearFlagAfterTest(void); @@ -875,6 +879,10 @@ void MovesWithPP_(u32 sourceLine, struct moveWithPP moveWithPP[MAX_MON_MOVES]); void Friendship_(u32 sourceLine, u32 friendship); void Status1_(u32 sourceLine, u32 status1); void OTName_(u32 sourceLine, const u8 *otName); +void DynamaxLevel_(u32 sourceLine, u32 dynamaxLevel); +void GigantamaxFactor_(u32 sourceLine, bool32 gigantamaxFactor); +void TeraType_(u32 sourceLine, u32 teraType); +void Shadow_(u32 sourceLine, bool32 isShadow); // Created for easy use of EXPECT_MOVES, so the user can provide 1, 2, 3 or 4 moves for AI which can pass the test. struct FourMoves diff --git a/include/test/overworld_script.h b/include/test/overworld_script.h new file mode 100644 index 0000000000..e2f65930f5 --- /dev/null +++ b/include/test/overworld_script.h @@ -0,0 +1,48 @@ +/* Embedded DSL for testing overworld scripts in isolation. + * The overworld is not available, so it is only possible to test + * commands which don't affect the overworld itself, e.g. givemon can + * be tested because it only alters gPlayerParty, but addobject cannot + * because it affects object events (which aren't loaded). + * + * OVERWORLD_SCRIPT(instructions...) + * Returns a pointer to a compiled overworld script. Cannot be used to + * initialize global const data, although the pointer IS to const data. + * Note that each script command must be followed by a ;, e.g.: + * const u8 *myScript = OVERWORLD_SCRIPT( + * random 2; + * addvar VAR_RESULT, 1; + * ); + * + * RUN_OVERWORLD_SCRIPT(instructions...) + * Runs an overworld script in the immediate script context, which means + * that commands like waitstate are not supported. + * RUN_OVERWORLD_SCRIPT( + * setvar VAR_RESULT, 3; + * ); + * EXPECT_EQ(GetVar(VAR_RESULT), 3); */ +#ifndef GUARD_TEST_OVERWORLD_SCRIPT +#define GUARD_TEST_OVERWORLD_SCRIPT + +#include "script.h" +#include "test/test.h" + +#define OVERWORLD_SCRIPT(...) \ + ({ \ + const u8 *_script; \ + asm("mov %0, pc\n" \ + "b .Lend" STR(__LINE__) "\n" \ + STR(__VA_ARGS__) \ + "\n" \ + "end\n" \ + ".balign 2\n" \ + ".Lend" STR(__LINE__) ":\n" \ + : "=r" (_script)); \ + _script; \ + }) + +#define RUN_OVERWORLD_SCRIPT(...) RunScriptImmediately(OVERWORLD_SCRIPT(__VA_ARGS__)) + +// Make overworld script macros available. +asm(".include \"asm/macros/event.inc\"\n"); + +#endif diff --git a/include/test/test.h b/include/test/test.h index e9c920bd0b..74e10ec691 100644 --- a/include/test/test.h +++ b/include/test/test.h @@ -59,8 +59,9 @@ extern const struct TestRunner gAssumptionsRunner; struct FunctionTestRunnerState { - u8 parameters; - u8 runParameter; + u16 parameters; + u16 runParameter; + u16 checkProgressParameter; }; extern const struct TestRunner gFunctionTestRunner; diff --git a/include/trainer_pokemon_sprites.h b/include/trainer_pokemon_sprites.h index e56ed0ffa5..7c83ca62ee 100644 --- a/include/trainer_pokemon_sprites.h +++ b/include/trainer_pokemon_sprites.h @@ -8,8 +8,8 @@ #define F_MON_PIC_NO_AFFINE (1 << 7) bool16 ResetAllPicSprites(void); -u16 CreateMonPicSprite_Affine(u16 species, u32 otId, u32 personality, u8 flags, s16 x, s16 y, u8 paletteSlot, u16 paletteTag); -u16 CreateMonPicSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag); +u16 CreateMonPicSprite_Affine(u16 species, bool8 isShiny, u32 personality, u8 flags, s16 x, s16 y, u8 paletteSlot, u16 paletteTag); +u16 CreateMonPicSprite(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag); u16 FreeAndDestroyMonPicSprite(u16 spriteId); u16 CreateTrainerPicSprite(u16 species, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag); u16 FreeAndDestroyTrainerPicSprite(u16 spriteId); diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 188ec915d6..d14005b1ae 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6576,7 +6576,7 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) SwapStructData(&gBattleSpritesDataPtr->battlerData[battlerAtk], &gBattleSpritesDataPtr->battlerData[battlerPartner], data, sizeof(struct BattleSpriteInfo)); SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp); - SWAP(gTransformedOtIds[battlerAtk], gTransformedOtIds[battlerPartner], temp); + SWAP(gTransformedShininess[battlerAtk], gTransformedShininess[battlerPartner], temp); SWAP(gStatuses3[battlerAtk], gStatuses3[battlerPartner], temp); SWAP(gStatuses4[battlerAtk], gStatuses4[battlerPartner], temp); SWAP(gBattleStruct->chosenMovePositions[battlerAtk], gBattleStruct->chosenMovePositions[battlerPartner], temp); diff --git a/src/battle_anim_effects_3.c b/src/battle_anim_effects_3.c index 2c8572cc8c..26fb3ef2ec 100644 --- a/src/battle_anim_effects_3.c +++ b/src/battle_anim_effects_3.c @@ -3255,9 +3255,8 @@ static void AnimReversalOrb_Step(struct Sprite *sprite) // Copies the target mon's sprite, and makes a white silhouette that shrinks away. void AnimTask_RolePlaySilhouette(u8 taskId) { - bool8 isBackPic; + bool8 isBackPic, isShiny; u32 personality; - u32 otId; u16 species; s16 xOffset; u32 priority; @@ -3269,7 +3268,7 @@ void AnimTask_RolePlaySilhouette(u8 taskId) { isBackPic = TRUE; personality = gContestResources->moveAnim->targetPersonality; - otId = gContestResources->moveAnim->otId; + isShiny = gContestResources->moveAnim->targetIsShiny; species = gContestResources->moveAnim->targetSpecies; xOffset = 20; priority = GetBattlerSpriteBGPriority(gBattleAnimAttacker); @@ -3280,7 +3279,7 @@ void AnimTask_RolePlaySilhouette(u8 taskId) { isBackPic = FALSE; personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_PERSONALITY); - otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_OT_ID); + isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_IS_SHINY); if (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies == SPECIES_NONE) { if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) @@ -3300,7 +3299,7 @@ void AnimTask_RolePlaySilhouette(u8 taskId) { isBackPic = TRUE; personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_PERSONALITY); - otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_OT_ID); + isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimTarget]], MON_DATA_IS_SHINY); if (gBattleSpritesDataPtr->battlerData[gBattleAnimTarget].transformSpecies == SPECIES_NONE) { if (GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER) @@ -3320,7 +3319,7 @@ void AnimTask_RolePlaySilhouette(u8 taskId) coord1 = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X); coord2 = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y); - spriteId = CreateAdditionalMonSpriteForMoveAnim(species, isBackPic, 0, coord1 + xOffset, coord2, 5, personality, otId, gBattleAnimTarget); + spriteId = CreateAdditionalMonSpriteForMoveAnim(species, isBackPic, 0, coord1 + xOffset, coord2, 5, personality, isShiny, gBattleAnimTarget); gSprites[spriteId].oam.priority = priority; gSprites[spriteId].oam.objMode = ST_OAM_OBJ_BLEND; @@ -5162,10 +5161,9 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId) { u8 spriteId, spriteId2; int personality; - int otId; u16 species; u8 subpriority; - bool8 isBackPic; + bool8 isBackPic, isShiny; s16 x; switch (gTasks[taskId].data[0]) @@ -5190,7 +5188,7 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId) if (IsContest()) { personality = gContestResources->moveAnim->personality; - otId = gContestResources->moveAnim->otId; + isShiny = gContestResources->moveAnim->isShiny; species = gContestResources->moveAnim->species; subpriority = GetBattlerSpriteSubpriority(gBattleAnimAttacker); isBackPic = FALSE; @@ -5201,7 +5199,7 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId) if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_PLAYER) { personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_PERSONALITY); - otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_OT_ID); + isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_IS_SHINY); if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies == SPECIES_NONE) species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES); else @@ -5214,7 +5212,7 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId) else { personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_PERSONALITY); - otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_OT_ID); + isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_IS_SHINY); if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies == SPECIES_NONE) species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattleAnimAttacker]], MON_DATA_SPECIES); else @@ -5226,7 +5224,7 @@ void AnimTask_SnatchOpposingMonMove(u8 taskId) } } - spriteId2 = CreateAdditionalMonSpriteForMoveAnim(species, isBackPic, 0, x, GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y), subpriority, personality, otId, gBattleAnimAttacker); + spriteId2 = CreateAdditionalMonSpriteForMoveAnim(species, isBackPic, 0, x, GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y), subpriority, personality, isShiny, gBattleAnimAttacker); if (gBattleSpritesDataPtr->battlerData[gBattleAnimAttacker].transformSpecies != SPECIES_NONE) BlendPalette(OBJ_PLTT_ID(gSprites[spriteId2].oam.paletteNum), 16, 6, RGB_WHITE); diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index 78e1a0a445..891fa402f5 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -2053,7 +2053,7 @@ u8 GetBattlerSpriteBGPriorityRank(u8 battlerId) } // Create pokemon sprite to be used for a move animation effect (e.g. Role Play / Snatch) -u8 CreateAdditionalMonSpriteForMoveAnim(u16 species, bool8 isBackpic, u8 id, s16 x, s16 y, u8 subpriority, u32 personality, u32 trainerId, u32 battlerId) +u8 CreateAdditionalMonSpriteForMoveAnim(u16 species, bool8 isBackpic, u8 id, s16 x, s16 y, u8 subpriority, u32 personality, bool8 isShiny, u32 battlerId) { u8 spriteId; u16 sheet = LoadSpriteSheet(&sSpriteSheets_MoveEffectMons[id]); @@ -2063,7 +2063,7 @@ u8 CreateAdditionalMonSpriteForMoveAnim(u16 species, bool8 isBackpic, u8 id, s16 gMonSpritesGfxPtr->buffer = AllocZeroed(MON_PIC_SIZE * MAX_MON_PIC_FRAMES); if (!isBackpic) { - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, trainerId, personality), OBJ_PLTT_ID(palette), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), OBJ_PLTT_ID(palette), PLTT_SIZE_4BPP); LoadSpecialPokePic(gMonSpritesGfxPtr->buffer, species, personality, @@ -2071,7 +2071,7 @@ u8 CreateAdditionalMonSpriteForMoveAnim(u16 species, bool8 isBackpic, u8 id, s16 } else { - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, trainerId, personality), OBJ_PLTT_ID(palette), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), OBJ_PLTT_ID(palette), PLTT_SIZE_4BPP); LoadSpecialPokePic(gMonSpritesGfxPtr->buffer, species, personality, diff --git a/src/battle_anim_throw.c b/src/battle_anim_throw.c index 4d2873a92a..6a23807a13 100644 --- a/src/battle_anim_throw.c +++ b/src/battle_anim_throw.c @@ -2481,26 +2481,17 @@ void AnimTask_SetTargetToEffectBattler(u8 taskId) void TryShinyAnimation(u8 battler, struct Pokemon *mon) { bool8 isShiny; - u32 otId, personality; - u32 shinyValue; u8 taskCirc, taskDgnl; struct Pokemon* illusionMon; - isShiny = FALSE; + isShiny = GetMonData(mon, MON_DATA_IS_SHINY); gBattleSpritesDataPtr->healthBoxesData[battler].triedShinyMonAnim = TRUE; illusionMon = GetIllusionMonPtr(battler); if (illusionMon != NULL) mon = illusionMon; - otId = GetMonData(mon, MON_DATA_OT_ID); - personality = GetMonData(mon, MON_DATA_PERSONALITY); - if (IsBattlerSpriteVisible(battler) && IsValidForBattle(mon)) { - shinyValue = GET_SHINY_VALUE(otId, personality); - if (shinyValue < SHINY_ODDS) - isShiny = TRUE; - if (isShiny) { if (GetSpriteTileStartByTag(ANIM_TAG_GOLD_STARS) == 0xFFFF) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index 632d7e50d8..d6389f02cc 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -2649,7 +2649,7 @@ void BtlController_HandleMoveAnimation(u32 battler, bool32 updateTvData) gWeatherMoveAnim = gBattleResources->bufferA[battler][12] | (gBattleResources->bufferA[battler][13] << 8); gAnimDisableStructPtr = (struct DisableStruct *)&gBattleResources->bufferA[battler][16]; gTransformedPersonalities[battler] = gAnimDisableStructPtr->transformedMonPersonality; - gTransformedOtIds[battler] = gAnimDisableStructPtr->transformedMonOtId; + gTransformedShininess[battler] = gAnimDisableStructPtr->transformedMonShininess; gBattleSpritesDataPtr->healthBoxesData[battler].animationState = 0; gBattlerControllerFuncs[battler] = Controller_DoMoveAnimation; if (updateTvData) diff --git a/src/battle_debug.c b/src/battle_debug.c index 1b172046ba..24ec2d13cd 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -801,7 +801,7 @@ static void Task_ShowAiPoints(u8 taskId) } } data->aiMonSpriteId = CreateMonPicSprite(gBattleMons[data->aiBattlerId].species, - gBattleMons[data->aiBattlerId].otId, + gBattleMons[data->aiBattlerId].isShiny, gBattleMons[data->aiBattlerId].personality, TRUE, 39, 130, 15, TAG_NONE); @@ -958,7 +958,7 @@ static void Task_ShowAiKnowledge(u8 taskId) } } data->aiMonSpriteId = CreateMonPicSprite(gBattleMons[data->aiBattlerId].species, - gBattleMons[data->aiBattlerId].otId, + gBattleMons[data->aiBattlerId].isShiny, gBattleMons[data->aiBattlerId].personality, TRUE, 39, 130, 15, TAG_NONE); diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index a44bb3aeb9..bf223e5002 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -149,8 +149,8 @@ bool32 CanDynamax(u16 battlerId) // Returns whether a battler is transformed into a Gigantamax form. bool32 IsGigantamaxed(u16 battlerId) { - // TODO: Incorporate Gigantamax factor. - if ((gSpeciesInfo[gBattleMons[battlerId].species].isGigantamax)) + struct Pokemon *mon = &GetSideParty(GetBattlerSide(battlerId))[gBattlerPartyIndexes[battlerId]]; + if ((gSpeciesInfo[gBattleMons[battlerId].species].isGigantamax) && GetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR)) return TRUE; return FALSE; } @@ -162,9 +162,9 @@ void ApplyDynamaxHPMultiplier(u32 battler, struct Pokemon* mon) return; else { - u16 mult = UQ_4_12(1.5); // placeholder - u16 hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP) * mult) + UQ_4_12_ROUND); - u16 maxHP = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_MAX_HP) * mult) + UQ_4_12_ROUND); + u32 scale = 150 + 5 * GetMonData(mon, MON_DATA_DYNAMAX_LEVEL); + u32 hp = (GetMonData(mon, MON_DATA_HP) * scale + 99) / 100; + u32 maxHP = (GetMonData(mon, MON_DATA_MAX_HP) * scale + 99) / 100; SetMonData(mon, MON_DATA_HP, &hp); SetMonData(mon, MON_DATA_MAX_HP, &maxHP); } diff --git a/src/battle_factory_screen.c b/src/battle_factory_screen.c index 66ff6bcb03..d010ec53c8 100644 --- a/src/battle_factory_screen.c +++ b/src/battle_factory_screen.c @@ -2017,9 +2017,9 @@ static void Select_CreateMonSprite(void) struct Pokemon *mon = &sFactorySelectScreen->mons[monId].monData; u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); - u32 otId = GetMonData(mon, MON_DATA_OT_ID, NULL); + bool8 isShiny = GetMonData(mon, MON_DATA_IS_SHINY, NULL); - sFactorySelectScreen->monPics[1].monSpriteId = CreateMonPicSprite(species, otId, personality, TRUE, 88, 32, 15, TAG_NONE); + sFactorySelectScreen->monPics[1].monSpriteId = CreateMonPicSprite(species, isShiny, personality, TRUE, 88, 32, 15, TAG_NONE); gSprites[sFactorySelectScreen->monPics[1].monSpriteId].centerToCornerVecX = 0; gSprites[sFactorySelectScreen->monPics[1].monSpriteId].centerToCornerVecY = 0; @@ -2035,7 +2035,8 @@ static void Select_ReshowMonSprite(void) { struct Pokemon *mon; u16 species; - u32 personality, otId; + u32 personality; + bool8 isShiny; sFactorySelectScreen->monPics[1].bgSpriteId = CreateSprite(&sSpriteTemplate_Select_MonPicBgAnim, 120, 64, 1); StartSpriteAffineAnim(&gSprites[sFactorySelectScreen->monPics[1].bgSpriteId], 2); @@ -2043,9 +2044,9 @@ static void Select_ReshowMonSprite(void) mon = &sFactorySelectScreen->mons[sFactorySelectScreen->cursorPos].monData; species = GetMonData(mon, MON_DATA_SPECIES, NULL); personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); - otId = GetMonData(mon, MON_DATA_OT_ID, NULL); + isShiny = GetMonData(mon, MON_DATA_IS_SHINY, NULL); - sFactorySelectScreen->monPics[1].monSpriteId = CreateMonPicSprite(species, otId, personality, TRUE, 88, 32, 15, TAG_NONE); + sFactorySelectScreen->monPics[1].monSpriteId = CreateMonPicSprite(species, isShiny, personality, TRUE, 88, 32, 15, TAG_NONE); gSprites[sFactorySelectScreen->monPics[1].monSpriteId].centerToCornerVecX = 0; gSprites[sFactorySelectScreen->monPics[1].monSpriteId].centerToCornerVecY = 0; @@ -2065,9 +2066,9 @@ static void Select_CreateChosenMonsSprites(void) struct Pokemon *mon = &sFactorySelectScreen->mons[j].monData; u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); - u32 otId = GetMonData(mon, MON_DATA_OT_ID, NULL); + bool8 isShiny = GetMonData(mon, MON_DATA_IS_SHINY, NULL); - sFactorySelectScreen->monPics[i].monSpriteId = CreateMonPicSprite(species, otId, personality, TRUE, (i * 72) + 16, 32, i + 13, TAG_NONE); + sFactorySelectScreen->monPics[i].monSpriteId = CreateMonPicSprite(species, isShiny, personality, TRUE, (i * 72) + 16, 32, i + 13, TAG_NONE); gSprites[sFactorySelectScreen->monPics[i].monSpriteId].centerToCornerVecX = 0; gSprites[sFactorySelectScreen->monPics[i].monSpriteId].centerToCornerVecY = 0; break; @@ -4076,7 +4077,8 @@ static void Swap_ShowSummaryMonSprite(void) { struct Pokemon *mon; u16 species; - u32 personality, otId; + u32 personality; + bool8 isShiny; sFactorySwapScreen->monPic.bgSpriteId = CreateSprite(&sSpriteTemplate_Swap_MonPicBgAnim, 120, 64, 1); StartSpriteAffineAnim(&gSprites[sFactorySwapScreen->monPic.bgSpriteId], 2); @@ -4084,13 +4086,9 @@ static void Swap_ShowSummaryMonSprite(void) mon = &gPlayerParty[sFactorySwapScreen->cursorPos]; species = GetMonData(mon, MON_DATA_SPECIES, NULL); personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); - otId = GetMonData(mon, MON_DATA_OT_ID, NULL); + isShiny = GetMonData(mon, MON_DATA_IS_SHINY, NULL); -#ifdef BUGFIX - sFactorySwapScreen->monPic.monSpriteId = CreateMonPicSprite(species, otId, personality, TRUE, 88, 32, 15, TAG_NONE); -#else - sFactorySwapScreen->monPic.monSpriteId = CreateMonPicSprite(species, personality, otId, TRUE, 88, 32, 15, TAG_NONE); -#endif + sFactorySwapScreen->monPic.monSpriteId = CreateMonPicSprite(species, isShiny, personality, TRUE, 88, 32, 15, TAG_NONE); gSprites[sFactorySwapScreen->monPic.monSpriteId].centerToCornerVecX = 0; gSprites[sFactorySwapScreen->monPic.monSpriteId].centerToCornerVecY = 0; @@ -4295,7 +4293,8 @@ static void Swap_CreateMonSprite(void) { struct Pokemon *mon; u16 species; - u32 personality, otId; + u32 personality; + bool8 isShiny; if (!sFactorySwapScreen->inEnemyScreen) mon = &gPlayerParty[sFactorySwapScreen->cursorPos]; @@ -4304,9 +4303,9 @@ static void Swap_CreateMonSprite(void) species = GetMonData(mon, MON_DATA_SPECIES, NULL); personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); - otId = GetMonData(mon, MON_DATA_OT_ID, NULL); + isShiny = GetMonData(mon, MON_DATA_IS_SHINY, NULL); - sFactorySwapScreen->monPic.monSpriteId = CreateMonPicSprite(species, otId, personality, TRUE, 88, 32, 15, TAG_NONE); + sFactorySwapScreen->monPic.monSpriteId = CreateMonPicSprite(species, isShiny, personality, TRUE, 88, 32, 15, TAG_NONE); gSprites[sFactorySwapScreen->monPic.monSpriteId].centerToCornerVecX = 0; gSprites[sFactorySwapScreen->monPic.monSpriteId].centerToCornerVecY = 0; diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index b38ccf495b..06deedaaa5 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -570,7 +570,7 @@ bool8 IsBattleSEPlaying(u8 battler) void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) { - u32 monsPersonality, currentPersonality, otId, currentOtId, species, paletteOffset, position; + u32 monsPersonality, currentPersonality, isShiny, species, paletteOffset, position; const void *lzPaletteData; struct Pokemon *illusionMon = GetIllusionMonPtr(battler); if (illusionMon != NULL) @@ -580,13 +580,12 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) return; monsPersonality = GetMonData(mon, MON_DATA_PERSONALITY); - otId = GetMonData(mon, MON_DATA_OT_ID); + isShiny = GetMonData(mon, MON_DATA_IS_SHINY); if (gBattleSpritesDataPtr->battlerData[battler].transformSpecies == SPECIES_NONE) { species = GetMonData(mon, MON_DATA_SPECIES); currentPersonality = monsPersonality; - currentOtId = otId; } else { @@ -594,12 +593,10 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) if (B_TRANSFORM_SHINY >= GEN_4) { currentPersonality = gTransformedPersonalities[battler]; - currentOtId = gTransformedOtIds[battler]; } else { currentPersonality = monsPersonality; - currentOtId = otId; } } @@ -622,7 +619,7 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) if (gBattleSpritesDataPtr->battlerData[battler].transformSpecies == SPECIES_NONE) lzPaletteData = GetMonFrontSpritePal(mon); else - lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, currentOtId, currentPersonality); + lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, currentPersonality); LZDecompressWram(lzPaletteData, gDecompressionBuffer); LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); @@ -867,7 +864,8 @@ void CopyBattleSpriteInvisibility(u8 battler) void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bool8 trackEnemyPersonality) { - u32 personalityValue, otId, position, paletteOffset, targetSpecies; + u32 personalityValue, position, paletteOffset, targetSpecies; + bool8 isShiny; const void *lzPaletteData, *src; void *dst; @@ -876,7 +874,7 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo position = B_POSITION_PLAYER_LEFT; targetSpecies = gContestResources->moveAnim->targetSpecies; personalityValue = gContestResources->moveAnim->personality; - otId = gContestResources->moveAnim->otId; + isShiny = gContestResources->moveAnim->isShiny; HandleLoadSpecialPokePic(FALSE, gMonSpritesGfxPtr->sprites.ptr[position], @@ -897,14 +895,13 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo if (B_TRANSFORM_SHINY >= GEN_4 && trackEnemyPersonality) { personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_IS_SHINY); } else { personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_IS_SHINY); } - otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); HandleLoadSpecialPokePic(FALSE, gMonSpritesGfxPtr->sprites.ptr[position], @@ -916,13 +913,12 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo if (B_TRANSFORM_SHINY >= GEN_4 && trackEnemyPersonality) { personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - otId = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); - + isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_IS_SHINY); } else { personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - otId = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_OT_ID); + isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_IS_SHINY); } HandleLoadSpecialPokePic(TRUE, @@ -935,7 +931,7 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo dst = (void *)(OBJ_VRAM0 + gSprites[gBattlerSpriteIds[battlerAtk]].oam.tileNum * 32); DmaCopy32(3, src, dst, MON_PIC_SIZE); paletteOffset = OBJ_PLTT_ID(battlerAtk); - lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(targetSpecies, otId, personalityValue); + lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(targetSpecies, isShiny, personalityValue); LZDecompressWram(lzPaletteData, gDecompressionBuffer); LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); diff --git a/src/battle_main.c b/src/battle_main.c index 6a1d6eb6ab..d5186b7ef2 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -214,7 +214,7 @@ EWRAM_DATA u8 gBattlerStatusSummaryTaskId[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gBattlerInMenuId = 0; EWRAM_DATA bool8 gDoingBattleAnim = FALSE; EWRAM_DATA u32 gTransformedPersonalities[MAX_BATTLERS_COUNT] = {0}; -EWRAM_DATA u32 gTransformedOtIds[MAX_BATTLERS_COUNT] = {0}; +EWRAM_DATA bool8 gTransformedShininess[MAX_BATTLERS_COUNT] = {0}; EWRAM_DATA u8 gPlayerDpadHoldFrames = 0; EWRAM_DATA struct BattleSpriteData *gBattleSpritesDataPtr = NULL; EWRAM_DATA struct MonSpritesGfx *gMonSpritesGfxPtr = NULL; @@ -2018,6 +2018,21 @@ u8 CreateNPCTrainerPartyFromTrainer(struct Pokemon *party, const struct Trainer { SetMonData(&party[i], MON_DATA_NICKNAME, partyData[i].nickname); } + if (partyData[i].isShiny) + { + u32 data = TRUE; + SetMonData(&party[i], MON_DATA_IS_SHINY, &data); + } + if (partyData[i].dynamaxLevel > 0) + { + u32 data = partyData[i].dynamaxLevel; + SetMonData(&party[i], MON_DATA_DYNAMAX_LEVEL, &data); + } + if (partyData[i].gigantamaxFactor) + { + u32 data = partyData[i].gigantamaxFactor; + SetMonData(&party[i], MON_DATA_GIGANTAMAX_FACTOR, &data); + } CalculateMonStats(&party[i]); #if B_TRAINER_CLASS_POKE_BALLS >= GEN_7 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0272aa4108..290895a80b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12308,7 +12308,7 @@ static void Cmd_transformdataexecution(void) gDisableStructs[gBattlerAttacker].disabledMove = MOVE_NONE; gDisableStructs[gBattlerAttacker].disableTimer = 0; gDisableStructs[gBattlerAttacker].transformedMonPersonality = gBattleMons[gBattlerTarget].personality; - gDisableStructs[gBattlerAttacker].transformedMonOtId = gBattleMons[gBattlerTarget].otId; + gDisableStructs[gBattlerAttacker].transformedMonShininess = gBattleMons[gBattlerTarget].isShiny; gDisableStructs[gBattlerAttacker].mimickedMoves = 0; gDisableStructs[gBattlerAttacker].usedMoves = 0; @@ -15171,10 +15171,11 @@ static void Cmd_displaydexinfo(void) case 1: if (!gPaletteFade.active) { + struct Pokemon *mon = &gEnemyParty[gBattlerPartyIndexes[GetCatchingBattler()]]; FreeAllWindowBuffers(); gBattleCommunication[TASK_ID] = DisplayCaughtMonDexPage(species, - gBattleMons[GetCatchingBattler()].otId, - gBattleMons[GetCatchingBattler()].personality); + GetMonData(mon, MON_DATA_IS_SHINY), + GetMonData(mon, MON_DATA_PERSONALITY)); gBattleCommunication[0]++; } break; diff --git a/src/battle_tower.c b/src/battle_tower.c index 6dba9a63ed..53ed39f236 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -2990,21 +2990,17 @@ static void FillPartnerParty(u16 trainerId) else otID = ((firstIdPart % 72) * 1000) + ((secondIdPart % 23) * 10) + (thirdIdPart % 37) % 65536; - do - { - personality = Random32(); - } while (IsShinyOtIdPersonality(otID, personality)); - + personality = Random32(); if (partyData[i].gender == TRAINER_MON_MALE) personality = (personality & 0xFFFFFF00) | GeneratePersonalityForGender(MON_MALE, partyData[i].species); else if (partyData[i].gender == TRAINER_MON_FEMALE) personality = (personality & 0xFFFFFF00) | GeneratePersonalityForGender(MON_FEMALE, partyData[i].species); if (partyData[i].nature != 0) ModifyPersonalityForNature(&personality, partyData[i].nature - 1); - if (partyData[i].isShiny) - otID ^= GET_SHINY_VALUE(otID, personality) << 16; CreateMon(&gPlayerParty[i + 3], partyData[i].species, partyData[i].lvl, 0, TRUE, personality, OT_ID_PRESET, otID); + j = partyData[i].isShiny; + SetMonData(&gPlayerParty[i + 3], MON_DATA_IS_SHINY, &j); SetMonData(&gPlayerParty[i + 3], MON_DATA_HELD_ITEM, &partyData[i].heldItem); CustomTrainerPartyAssignMoves(&gPlayerParty[i + 3], &partyData[i]); diff --git a/src/battle_util.c b/src/battle_util.c index da42b40010..fa34fc7460 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10555,6 +10555,7 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method) u16 targetSpecies = SPECIES_NONE; u16 species = gBattleMons[battler].species; const struct FormChange *formChanges = GetSpeciesFormChanges(species); + struct Pokemon *mon = &GetBattlerParty(battler)[gBattlerPartyIndexes[battler]]; u16 heldItem; if (formChanges != NULL) @@ -10602,8 +10603,8 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method) } break; case FORM_CHANGE_BATTLE_GIGANTAMAX: - // TODO: check Gigantamax factor - targetSpecies = formChanges[i].targetSpecies; + if (GetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR)) + targetSpecies = formChanges[i].targetSpecies; break; case FORM_CHANGE_BATTLE_WEATHER: // Check if there is a required ability and if the battler's ability does not match it diff --git a/src/contest.c b/src/contest.c index d4cc73677c..6b7322335c 100644 --- a/src/contest.c +++ b/src/contest.c @@ -98,7 +98,7 @@ static void PrintContestantMonName(u8); static void PrintContestantMonNameWithColor(u8, u8); static u8 CreateJudgeSprite(void); static u8 CreateJudgeSpeechBubbleSprite(void); -static u8 CreateContestantSprite(u16, u32, u32, u32); +static u8 CreateContestantSprite(u16, bool8, u32, u32); static void PrintContestMoveDescription(u16); static u16 SanitizeSpecies(u16); static void ContestClearGeneralTextWindow(void); @@ -1781,7 +1781,7 @@ static void Task_DoAppeals(u8 taskId) SetMoveAnimAttackerData(eContest.currentContestant); spriteId = CreateContestantSprite( gContestMons[eContest.currentContestant].species, - gContestMons[eContest.currentContestant].otId, + gContestMons[eContest.currentContestant].isShiny, gContestMons[eContest.currentContestant].personality, eContest.currentContestant); gSprites[spriteId].x2 = 120; @@ -2811,6 +2811,7 @@ void CreateContestMonFromParty(u8 partyIndex) gContestMons[gContestPlayerMonIndex].moves[3] = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MOVE4); gContestMons[gContestPlayerMonIndex].personality = GetMonData(&gPlayerParty[partyIndex], MON_DATA_PERSONALITY); gContestMons[gContestPlayerMonIndex].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID); + gContestMons[gContestPlayerMonIndex].isShiny = GetMonData(&gPlayerParty[partyIndex], MON_DATA_IS_SHINY); heldItem = GetMonData(&gPlayerParty[partyIndex], MON_DATA_HELD_ITEM); cool = gContestMons[gContestPlayerMonIndex].cool; @@ -3114,14 +3115,14 @@ static u8 CreateJudgeSpeechBubbleSprite(void) return spriteId; } -static u8 CreateContestantSprite(u16 species, u32 otId, u32 personality, u32 index) +static u8 CreateContestantSprite(u16 species, bool8 isShiny, u32 personality, u32 index) { u8 spriteId; species = SanitizeSpecies(species); HandleLoadSpecialPokePic(FALSE, gMonSpritesGfxPtr->sprites.ptr[B_POSITION_PLAYER_LEFT], species, personality); - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); SetMultiuseSpriteTemplateToPokemon(species, B_POSITION_PLAYER_LEFT); spriteId = CreateSprite(&gMultiuseSpriteTemplate, 0x70, GetBattlerSpriteFinal_Y(2, species, FALSE), 30); @@ -5354,6 +5355,7 @@ static void SetMoveAnimAttackerData(u8 contestant) gContestResources->moveAnim->species = SanitizeSpecies(gContestMons[contestant].species); gContestResources->moveAnim->personality = gContestMons[contestant].personality; gContestResources->moveAnim->otId = gContestMons[contestant].otId; + gContestResources->moveAnim->isShiny = gContestMons[contestant].isShiny; } static void CreateInvisibleBattleTargetSprite(void) @@ -5565,6 +5567,7 @@ bool8 SaveContestWinner(u8 rank) { // Set the most recent winner so the artist can show the player their painting gCurContestWinner.personality = gContestMons[i].personality; + gCurContestWinner.isShiny = gContestMons[i].isShiny; gCurContestWinner.trainerId = gContestMons[i].otId; gCurContestWinner.species = gContestMons[i].species; StringCopy(gCurContestWinner.monName, gContestMons[i].nickname); diff --git a/src/contest_painting.c b/src/contest_painting.c index 00bacb5f48..529330a522 100644 --- a/src/contest_painting.c +++ b/src/contest_painting.c @@ -363,7 +363,7 @@ static void VBlankCB_ContestPainting(void) static void InitContestMonPixels(u16 species, bool8 backPic) { - const void *pal = GetMonSpritePalFromSpeciesAndPersonality(species, gContestPaintingWinner->trainerId, gContestPaintingWinner->personality); + const void *pal = GetMonSpritePalFromSpeciesAndPersonality(species, gContestPaintingWinner->isShiny, gContestPaintingWinner->personality); LZDecompressVram(pal, gContestPaintingMonPalette); if (!backPic) { diff --git a/src/contest_util.c b/src/contest_util.c index 32588a8c00..7de4923037 100644 --- a/src/contest_util.c +++ b/src/contest_util.c @@ -879,7 +879,7 @@ static void Task_ShowWinnerMonBanner(u8 taskId) int i; u8 spriteId; u16 species; - u32 otId; + bool8 isShiny; u32 personality; switch (gTasks[taskId].tState) @@ -891,13 +891,13 @@ static void Task_ShowWinnerMonBanner(u8 taskId) GET_CONTEST_WINNER_ID(i); species = gContestMons[i].species; personality = gContestMons[i].personality; - otId = gContestMons[i].otId; + isShiny = gContestMons[i].isShiny; HandleLoadSpecialPokePic(TRUE, gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, personality); - LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), species); + LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), species); SetMultiuseSpriteTemplateToPokemon(species, B_POSITION_OPPONENT_LEFT); gMultiuseSpriteTemplate.paletteTag = species; spriteId = CreateSprite(&gMultiuseSpriteTemplate, DISPLAY_WIDTH + 32, DISPLAY_HEIGHT / 2, 10); @@ -2552,11 +2552,12 @@ bool8 IsContestDebugActive(void) void ShowContestEntryMonPic(void) { - u32 personality, otId; + u32 personality; u16 species; u8 spriteId; u8 taskId; u8 left, top; + bool32 isShiny; if (FindTaskIdByFunc(Task_ShowContestEntryMonPic) == TASK_NONE) { @@ -2565,13 +2566,13 @@ void ShowContestEntryMonPic(void) top = 3; species = gContestMons[gSpecialVar_0x8006].species; personality = gContestMons[gSpecialVar_0x8006].personality; - otId = gContestMons[gSpecialVar_0x8006].otId; + isShiny = gContestMons[gSpecialVar_0x8006].isShiny; taskId = CreateTask(Task_ShowContestEntryMonPic, 0x50); gTasks[taskId].data[0] = 0; gTasks[taskId].data[1] = species; HandleLoadSpecialPokePic(TRUE, gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], species, personality); - LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), species); + LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), species); SetMultiuseSpriteTemplateToPokemon(species, B_POSITION_OPPONENT_LEFT); gMultiuseSpriteTemplate.paletteTag = species; spriteId = CreateSprite(&gMultiuseSpriteTemplate, (left + 1) * 8 + 32, (top * 8) + 40, 0); diff --git a/src/data/items.h b/src/data/items.h index 2114d1a4bd..7c1f3e2472 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -1272,8 +1272,9 @@ const struct Item gItems[] = "ups Attack, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_LONELY, .flingPower = 10, }, @@ -1285,8 +1286,9 @@ const struct Item gItems[] = "ups Attack, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_ADAMANT, .flingPower = 10, }, @@ -1298,8 +1300,9 @@ const struct Item gItems[] = "ups Attack, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_NAUGHTY, .flingPower = 10, }, @@ -1311,8 +1314,9 @@ const struct Item gItems[] = "ups Attack, but\n" "reduces Speed."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_BRAVE, .flingPower = 10, }, @@ -1324,8 +1328,9 @@ const struct Item gItems[] = "ups Defense, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_BOLD, .flingPower = 10, }, @@ -1337,8 +1342,9 @@ const struct Item gItems[] = "ups Defense, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_IMPISH, .flingPower = 10, }, @@ -1350,8 +1356,9 @@ const struct Item gItems[] = "ups Defense, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_LAX, .flingPower = 10, }, @@ -1363,8 +1370,9 @@ const struct Item gItems[] = "ups Defense, but\n" "reduces Speed."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_RELAXED, .flingPower = 10, }, @@ -1376,8 +1384,9 @@ const struct Item gItems[] = "ups Sp. Atk, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_MODEST, .flingPower = 10, }, @@ -1389,8 +1398,9 @@ const struct Item gItems[] = "ups Sp. Atk, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_MILD, .flingPower = 10, }, @@ -1402,8 +1412,9 @@ const struct Item gItems[] = "ups Sp. Atk, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_RASH, .flingPower = 10, }, @@ -1415,8 +1426,9 @@ const struct Item gItems[] = "ups Sp. Atk, but\n" "reduces Speed."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_QUIET, .flingPower = 10, }, @@ -1428,8 +1440,9 @@ const struct Item gItems[] = "ups Sp. Def, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_CALM, .flingPower = 10, }, @@ -1441,8 +1454,9 @@ const struct Item gItems[] = "ups Sp. Def, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_GENTLE, .flingPower = 10, }, @@ -1454,8 +1468,9 @@ const struct Item gItems[] = "ups Sp. Def, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_CAREFUL, .flingPower = 10, }, @@ -1467,8 +1482,9 @@ const struct Item gItems[] = "ups Sp. Def, but\n" "reduces Speed."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_SASSY, .flingPower = 10, }, @@ -1480,8 +1496,9 @@ const struct Item gItems[] = "ups Speed, but\n" "reduces Attack."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_TIMID, .flingPower = 10, }, @@ -1493,8 +1510,9 @@ const struct Item gItems[] = "ups Speed, but\n" "reduces Defense."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_HASTY, .flingPower = 10, }, @@ -1506,8 +1524,9 @@ const struct Item gItems[] = "ups Speed, but\n" "reduces Sp. Atk."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_JOLLY, .flingPower = 10, }, @@ -1519,8 +1538,9 @@ const struct Item gItems[] = "ups Speed, but\n" "reduces Sp. Def."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_NAIVE, .flingPower = 10, }, @@ -1532,8 +1552,9 @@ const struct Item gItems[] = "makes each stat\n" "grow equally."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_Mint, + .secondaryId = NATURE_SERIOUS, .flingPower = 10, }, @@ -1630,8 +1651,8 @@ const struct Item gItems[] = "Level of a single\n" "Pokémon by one."), .pocket = POCKET_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_DynamaxCandy, .flingPower = 30, }, diff --git a/src/daycare.c b/src/daycare.c index 33b3d8ac1b..31d2abe62e 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -229,7 +229,6 @@ static void StorePokemonInDaycare(struct Pokemon *mon, struct DaycareMon *daycar } daycareMon->mon = mon->box; - BoxMonRestorePP(&daycareMon->mon); daycareMon->steps = 0; ZeroMonData(mon); CompactPartySlots(); diff --git a/src/debug.c b/src/debug.c index c1853af4cf..e68d65cbd6 100644 --- a/src/debug.c +++ b/src/debug.c @@ -2938,7 +2938,7 @@ static void ResetMonDataStruct(struct DebugMonData *sDebugMonData) { sDebugMonData->species = 1; sDebugMonData->level = MIN_LEVEL; - sDebugMonData->isShiny = 0; + sDebugMonData->isShiny = FALSE; sDebugMonData->nature = 0; sDebugMonData->abilityNum = 0; sDebugMonData->mon_iv_hp = 0; @@ -3608,7 +3608,7 @@ static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://githu u8 iv_val; u16 species = sDebugMonData->species; u8 level = sDebugMonData->level; - u8 isShiny = sDebugMonData->isShiny; //Shiny: no 0, yes 1 + bool8 isShiny = sDebugMonData->isShiny; u8 nature = sDebugMonData->nature; u8 abilityNum = sDebugMonData->abilityNum; moves[0] = sDebugMonData->mon_move_0; @@ -3625,26 +3625,10 @@ static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://githu //Nature if (nature == NUM_NATURES || nature == 0xFF) nature = Random() % NUM_NATURES; + CreateMonWithNature(&mon, species, level, 32, nature); //Shininess - if (isShiny == 1) - { - u32 personality; - u32 otid = gSaveBlock2Ptr->playerTrainerId[0] - | (gSaveBlock2Ptr->playerTrainerId[1] << 8) - | (gSaveBlock2Ptr->playerTrainerId[2] << 16) - | (gSaveBlock2Ptr->playerTrainerId[3] << 24); - - do - { - personality = Random32(); - personality = ((((Random() % 8) ^ (HIHALF(otid) ^ LOHALF(otid))) ^ LOHALF(personality)) << 16) | LOHALF(personality); - } while (nature != GetNatureFromPersonality(personality)); - - CreateMon(&mon, species, level, 32, 1, personality, OT_ID_PRESET, otid); - } - else - CreateMonWithNature(&mon, species, level, 32, nature); + SetMonData(&mon, MON_DATA_IS_SHINY, &isShiny); //IVs for (i = 0; i < NUM_STATS; i++) diff --git a/src/evolution_scene.c b/src/evolution_scene.c index 1bd0e26561..b254dab42a 100644 --- a/src/evolution_scene.c +++ b/src/evolution_scene.c @@ -209,7 +209,8 @@ void EvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, bool8 canStopEvo, u { u8 name[POKEMON_NAME_BUFFER_SIZE]; u16 currSpecies; - u32 trainerId, personality; + u32 personality; + bool32 isShiny; u8 id; SetHBlankCallback(NULL); @@ -255,13 +256,13 @@ void EvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, bool8 canStopEvo, u // preEvo sprite currSpecies = GetMonData(mon, MON_DATA_SPECIES); - trainerId = GetMonData(mon, MON_DATA_OT_ID); + isShiny = GetMonData(mon, MON_DATA_IS_SHINY); personality = GetMonData(mon, MON_DATA_PERSONALITY); LoadSpecialPokePic(gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_LEFT], currSpecies, personality, TRUE); - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(currSpecies, trainerId, personality), OBJ_PLTT_ID(1), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(currSpecies, isShiny, personality), OBJ_PLTT_ID(1), PLTT_SIZE_4BPP); SetMultiuseSpriteTemplateToPokemon(currSpecies, B_POSITION_OPPONENT_LEFT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; @@ -276,7 +277,7 @@ void EvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, bool8 canStopEvo, u postEvoSpecies, personality, TRUE); - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(postEvoSpecies, trainerId, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(postEvoSpecies, isShiny, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, B_POSITION_OPPONENT_RIGHT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; @@ -310,11 +311,12 @@ static void CB2_EvolutionSceneLoadGraphics(void) { u8 id; u16 postEvoSpecies; - u32 trainerId, personality; + u32 personality; struct Pokemon *mon = &gPlayerParty[gTasks[sEvoStructPtr->evoTaskId].tPartyId]; + bool8 isShiny; postEvoSpecies = gTasks[sEvoStructPtr->evoTaskId].tPostEvoSpecies; - trainerId = GetMonData(mon, MON_DATA_OT_ID); + isShiny = GetMonData(mon, MON_DATA_IS_SHINY); personality = GetMonData(mon, MON_DATA_PERSONALITY); SetHBlankCallback(NULL); @@ -352,7 +354,7 @@ static void CB2_EvolutionSceneLoadGraphics(void) postEvoSpecies, personality, TRUE); - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(postEvoSpecies, trainerId, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(postEvoSpecies, isShiny, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, B_POSITION_OPPONENT_RIGHT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; @@ -416,13 +418,13 @@ static void CB2_TradeEvolutionSceneLoadGraphics(void) break; case 4: { - u32 trainerId = GetMonData(mon, MON_DATA_OT_ID); + bool8 isShiny = GetMonData(mon, MON_DATA_IS_SHINY); u32 personality = GetMonData(mon, MON_DATA_PERSONALITY); LoadSpecialPokePic(gMonSpritesGfxPtr->sprites.ptr[B_POSITION_OPPONENT_RIGHT], postEvoSpecies, personality, TRUE); - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(postEvoSpecies, trainerId, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(postEvoSpecies, isShiny, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); gMain.state++; } break; @@ -464,8 +466,9 @@ void TradeEvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, u8 preEvoSprit { u8 name[POKEMON_NAME_BUFFER_SIZE]; u16 currSpecies; - u32 trainerId, personality; + u32 personality; u8 id; + bool8 isShiny; GetMonData(mon, MON_DATA_NICKNAME, name); StringCopy_Nickname(gStringVar1, name); @@ -476,7 +479,7 @@ void TradeEvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, u8 preEvoSprit // preEvo sprite currSpecies = GetMonData(mon, MON_DATA_SPECIES); personality = GetMonData(mon, MON_DATA_PERSONALITY); - trainerId = GetMonData(mon, MON_DATA_OT_ID); + isShiny = GetMonData(mon, MON_DATA_IS_SHINY); sEvoStructPtr = AllocZeroed(sizeof(struct EvoInfo)); sEvoStructPtr->preEvoSpriteId = preEvoSpriteId; @@ -486,7 +489,7 @@ void TradeEvolutionScene(struct Pokemon *mon, u16 postEvoSpecies, u8 preEvoSprit personality, TRUE); - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(postEvoSpecies, trainerId, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(postEvoSpecies, isShiny, personality), OBJ_PLTT_ID(2), PLTT_SIZE_4BPP); SetMultiuseSpriteTemplateToPokemon(postEvoSpecies, B_POSITION_OPPONENT_LEFT); gMultiuseSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; @@ -564,8 +567,6 @@ static void CreateShedinja(u16 preEvoSpecies, struct Pokemon *mon) SetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_NICKNAME, GetSpeciesName(evolutions[1].targetSpecies)); SetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_HELD_ITEM, &data); SetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_MARKINGS, &data); - SetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_ENCRYPT_SEPARATOR, &data); - #if P_SHEDINJA_BALL >= GEN_4 SetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_POKEBALL, &ball); RemoveBagItem(ball, 1); @@ -573,7 +574,7 @@ static void CreateShedinja(u16 preEvoSpecies, struct Pokemon *mon) for (i = MON_DATA_COOL_RIBBON; i < MON_DATA_COOL_RIBBON + CONTEST_CATEGORIES_COUNT; i++) SetMonData(&gPlayerParty[gPlayerPartyCount], i, &data); - for (i = MON_DATA_CHAMPION_RIBBON; i <= MON_DATA_UNUSED_RIBBONS; i++) + for (i = MON_DATA_CHAMPION_RIBBON; i <= MON_DATA_WORLD_RIBBON; i++) SetMonData(&gPlayerParty[gPlayerPartyCount], i, &data); SetMonData(&gPlayerParty[gPlayerPartyCount], MON_DATA_STATUS, &data); diff --git a/src/field_effect.c b/src/field_effect.c index 5d0ba3a50d..294d13b01c 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -183,7 +183,7 @@ static void AnimateIndoorShowMonBg(struct Task *); static bool8 SlideIndoorBannerOnscreen(struct Task *); static bool8 SlideIndoorBannerOffscreen(struct Task *); -static u8 InitFieldMoveMonSprite(u32, u32, u32); +static u8 InitFieldMoveMonSprite(u32, bool8, u32); static void SpriteCB_FieldMoveMonSlideOnscreen(struct Sprite *); static void SpriteCB_FieldMoveMonWaitAfterCry(struct Sprite *); static void SpriteCB_FieldMoveMonSlideOffscreen(struct Sprite *); @@ -919,7 +919,7 @@ u8 AddNewGameBirchObject(s16 x, s16 y, u8 subpriority) u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y, u8 subpriority) { - s32 spriteId = CreateMonPicSprite(species, 0, 0x8000, TRUE, x, y, 0, species); + s32 spriteId = CreateMonPicSprite(species, FALSE, 0x8000, TRUE, x, y, 0, species); PreservePaletteInWeather(IndexOfSpritePaletteTag(species) + 0x10); if (spriteId == 0xFFFF) return MAX_SPRITES; @@ -927,10 +927,10 @@ u8 CreateMonSprite_PicBox(u16 species, s16 x, s16 y, u8 subpriority) return spriteId; } -u8 CreateMonSprite_FieldMove(u16 species, u32 otId, u32 personality, s16 x, s16 y, u8 subpriority) +u8 CreateMonSprite_FieldMove(u16 species, bool8 isShiny, u32 personality, s16 x, s16 y, u8 subpriority) { - u16 spriteId = CreateMonPicSprite(species, otId, personality, TRUE, x, y, 0, species); - PreservePaletteInWeather(IndexOfSpritePaletteTag(species) + 0x10); + u16 spriteId = CreateMonPicSprite(species, isShiny, personality, TRUE, x, y, 0, species); + PreservePaletteInWeather(gSprites[spriteId].oam.paletteNum + 0x10); if (spriteId == 0xFFFF) return MAX_SPRITES; else @@ -2586,7 +2586,7 @@ bool8 FldEff_FieldMoveShowMonInit(void) bool32 noDucking = gFieldEffectArguments[0] & SHOW_MON_CRY_NO_DUCKING; pokemon = &gPlayerParty[(u8)gFieldEffectArguments[0]]; gFieldEffectArguments[0] = GetMonData(pokemon, MON_DATA_SPECIES); - gFieldEffectArguments[1] = GetMonData(pokemon, MON_DATA_OT_ID); + gFieldEffectArguments[1] = GetMonData(pokemon, MON_DATA_IS_SHINY); gFieldEffectArguments[2] = GetMonData(pokemon, MON_DATA_PERSONALITY); gFieldEffectArguments[0] |= noDucking; FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON); @@ -2926,14 +2926,14 @@ static bool8 SlideIndoorBannerOffscreen(struct Task *task) #undef tBgOffset #undef tMonSpriteId -static u8 InitFieldMoveMonSprite(u32 species, u32 otId, u32 personality) +static u8 InitFieldMoveMonSprite(u32 species, bool8 isShiny, u32 personality) { bool16 noDucking; u8 monSprite; struct Sprite *sprite; noDucking = (species & SHOW_MON_CRY_NO_DUCKING) >> 16; species &= ~SHOW_MON_CRY_NO_DUCKING; - monSprite = CreateMonSprite_FieldMove(species, otId, personality, 320, 80, 0); + monSprite = CreateMonSprite_FieldMove(species, isShiny, personality, 320, 80, 0); sprite = &gSprites[monSprite]; sprite->callback = SpriteCallbackDummy; sprite->oam.priority = 0; diff --git a/src/frontier_util.c b/src/frontier_util.c index 40bc24c741..15f5385e83 100644 --- a/src/frontier_util.c +++ b/src/frontier_util.c @@ -2462,10 +2462,7 @@ void CreateFrontierBrainPokemon(void) do { - do - { - j = Random32(); //should just be one while loop, but that doesn't match - } while (IsShinyOtIdPersonality(FRONTIER_BRAIN_OTID, j)); + j = Random32(); //should just be one while loop, but that doesn't match } while (sFrontierBrainsMons[facility][symbol][i].nature != GetNatureFromPersonality(j)); CreateMon(&gEnemyParty[monPartyId], sFrontierBrainsMons[facility][symbol][i].species, @@ -2484,6 +2481,8 @@ void CreateFrontierBrainPokemon(void) friendship = 0; } SetMonData(&gEnemyParty[monPartyId], MON_DATA_FRIENDSHIP, &friendship); + j = FALSE; + SetMonData(&gPlayerParty[MULTI_PARTY_SIZE + i], MON_DATA_IS_SHINY, &j); CalculateMonStats(&gEnemyParty[monPartyId]); monPartyId++; } diff --git a/src/hall_of_fame.c b/src/hall_of_fame.c index caa497e395..cdb1edb461 100644 --- a/src/hall_of_fame.c +++ b/src/hall_of_fame.c @@ -42,7 +42,8 @@ struct HallofFameMon { u32 tid; u32 personality; - u16 species; + u16 isShiny:1; + u16 species:15; u8 lvl; u8 nickname[POKEMON_NAME_LENGTH]; }; @@ -336,6 +337,7 @@ static const struct HallofFameMon sDummyFameMon = { .tid = 0x3EA03EA, .personality = 0, + .isShiny = FALSE, .species = SPECIES_NONE, .lvl = 0, .nickname = {0} @@ -447,6 +449,7 @@ static void Task_Hof_InitMonData(u8 taskId) { sHofMonPtr->mon[i].species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES_OR_EGG); sHofMonPtr->mon[i].tid = GetMonData(&gPlayerParty[i], MON_DATA_OT_ID); + sHofMonPtr->mon[i].isShiny = GetMonData(&gPlayerParty[i], MON_DATA_IS_SHINY); sHofMonPtr->mon[i].personality = GetMonData(&gPlayerParty[i], MON_DATA_PERSONALITY); sHofMonPtr->mon[i].lvl = GetMonData(&gPlayerParty[i], MON_DATA_LEVEL); GetMonData(&gPlayerParty[i], MON_DATA_NICKNAME, nickname); @@ -458,6 +461,7 @@ static void Task_Hof_InitMonData(u8 taskId) { sHofMonPtr->mon[i].species = SPECIES_NONE; sHofMonPtr->mon[i].tid = 0; + sHofMonPtr->mon[i].isShiny = FALSE; sHofMonPtr->mon[i].personality = 0; sHofMonPtr->mon[i].lvl = 0; sHofMonPtr->mon[i].nickname[0] = EOS; @@ -583,7 +587,7 @@ static void Task_Hof_DisplayMon(u8 taskId) if (currMon->species == SPECIES_EGG) destY += 10; - spriteId = CreateMonPicSprite_Affine(currMon->species, currMon->tid, currMon->personality, MON_PIC_AFFINE_FRONT, startX, startY, currMonId, TAG_NONE); + spriteId = CreateMonPicSprite_Affine(currMon->species, currMon->isShiny, currMon->personality, MON_PIC_AFFINE_FRONT, startX, startY, currMonId, TAG_NONE); gSprites[spriteId].tDestinationX = destX; gSprites[spriteId].tDestinationY = destY; gSprites[spriteId].data[0] = 0; @@ -929,7 +933,7 @@ static void Task_HofPC_DrawSpritesPrintText(u8 taskId) if (currMon->species == SPECIES_EGG) posY += 10; - spriteId = CreateMonPicSprite(currMon->species, currMon->tid, currMon->personality, TRUE, posX, posY, i, TAG_NONE); + spriteId = CreateMonPicSprite(currMon->species, currMon->isShiny, currMon->personality, TRUE, posX, posY, i, TAG_NONE); gSprites[spriteId].oam.priority = 1; gTasks[taskId].tMonSpriteId(i) = spriteId; } diff --git a/src/item_use.c b/src/item_use.c index bce5d83ed6..344122e8b3 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -797,6 +797,12 @@ void ItemUseOutOfBattle_AbilityPatch(u8 taskId) SetUpItemUseCallback(taskId); } +void ItemUseOutOfBattle_Mint(u8 taskId) +{ + gItemUseCB = ItemUseCB_Mint; + SetUpItemUseCallback(taskId); +} + void ItemUseOutOfBattle_ResetEVs(u8 taskId) { gItemUseCB = ItemUseCB_ResetEVs; @@ -833,6 +839,12 @@ void ItemUseOutOfBattle_RareCandy(u8 taskId) SetUpItemUseCallback(taskId); } +void ItemUseOutOfBattle_DynamaxCandy(u8 taskId) +{ + gItemUseCB = ItemUseCB_DynamaxCandy; + SetUpItemUseCallback(taskId); +} + void ItemUseOutOfBattle_TMHM(u8 taskId) { if (gSpecialVar_ItemId >= ITEM_HM01) diff --git a/src/load_save.c b/src/load_save.c index d42b71a4a9..667f9e1c3c 100644 --- a/src/load_save.c +++ b/src/load_save.c @@ -175,7 +175,17 @@ void LoadPlayerParty(void) gPlayerPartyCount = gSaveBlock1Ptr->playerPartyCount; for (i = 0; i < PARTY_SIZE; i++) + { + u32 data; gPlayerParty[i] = gSaveBlock1Ptr->playerParty[i]; + + // TODO: Turn this into a save migration once those are available. + // At which point we can remove hp and status from Pokemon entirely. + data = gPlayerParty[i].maxHP - gPlayerParty[i].hp; + SetBoxMonData(&gPlayerParty[i].box, MON_DATA_HP_LOST, &data); + data = gPlayerParty[i].status; + SetBoxMonData(&gPlayerParty[i].box, MON_DATA_STATUS, &data); + } } void SaveObjectEvents(void) diff --git a/src/main_menu.c b/src/main_menu.c index c7295bd863..c1f092b2ca 100644 --- a/src/main_menu.c +++ b/src/main_menu.c @@ -1876,7 +1876,7 @@ static void SpriteCB_MovePlayerDownWhileShrinking(struct Sprite *sprite) static u8 NewGameBirchSpeech_CreateLotadSprite(u8 x, u8 y) { - return CreateMonPicSprite_Affine(SPECIES_LOTAD, SHINY_ODDS, 0, MON_PIC_AFFINE_FRONT, x, y, 14, TAG_NONE); + return CreateMonPicSprite_Affine(SPECIES_LOTAD, FALSE, 0, MON_PIC_AFFINE_FRONT, x, y, 14, TAG_NONE); } static void AddBirchSpeechObjects(u8 taskId) diff --git a/src/menu_specialized.c b/src/menu_specialized.c index c99c71e4b5..125a935666 100644 --- a/src/menu_specialized.c +++ b/src/menu_specialized.c @@ -1075,11 +1075,11 @@ void GetConditionMenuMonGfx(void *tilesDst, void *palDst, u16 boxId, u16 monId, if (partyId != numMons) { u16 species = GetBoxOrPartyMonData(boxId, monId, MON_DATA_SPECIES_OR_EGG, NULL); - u32 trainerId = GetBoxOrPartyMonData(boxId, monId, MON_DATA_OT_ID, NULL); + bool8 isShiny = GetBoxOrPartyMonData(boxId, monId, MON_DATA_IS_SHINY, NULL); u32 personality = GetBoxOrPartyMonData(boxId, monId, MON_DATA_PERSONALITY, NULL); LoadSpecialPokePic(tilesDst, species, personality, TRUE); - LZ77UnCompWram(GetMonSpritePalFromSpeciesAndPersonality(species, trainerId, personality), palDst); + LZ77UnCompWram(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), palDst); } } diff --git a/src/party_menu.c b/src/party_menu.c index e973100586..eb276b30c6 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4851,6 +4851,104 @@ void ItemUseCB_AbilityPatch(u8 taskId, TaskFunc task) #undef tMonId #undef tOldFunc +#define tState data[0] +#define tMonId data[1] +#define tOldNature data[2] +#define tNewNature data[3] +#define tOldFunc 4 + +void Task_Mint(u8 taskId) +{ + static const u8 askText[] = _("It might affect {STR_VAR_1}'s stats.\nAre you sure you want to use it?"); + static const u8 doneText[] = _("{STR_VAR_1}'s stats may have changed due\nto the effects of the {STR_VAR_2}!{PAUSE_UNTIL_PRESS}"); + s16 *data = gTasks[taskId].data; + + switch (tState) + { + case 0: + // Can't use. + if (tOldNature == tNewNature) + { + gPartyMenuUseExitCallback = FALSE; + PlaySE(SE_SELECT); + DisplayPartyMenuMessage(gText_WontHaveEffect, 1); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = Task_ClosePartyMenuAfterText; + return; + } + gPartyMenuUseExitCallback = TRUE; + GetMonNickname(&gPlayerParty[tMonId], gStringVar1); + CopyItemName(gSpecialVar_ItemId, gStringVar2); + StringExpandPlaceholders(gStringVar4, askText); + PlaySE(SE_SELECT); + DisplayPartyMenuMessage(gStringVar4, 1); + ScheduleBgCopyTilemapToVram(2); + tState++; + break; + case 1: + if (!IsPartyMenuTextPrinterActive()) + { + PartyMenuDisplayYesNoMenu(); + tState++; + } + break; + case 2: + switch (Menu_ProcessInputNoWrapClearOnChoose()) + { + case 0: + tState++; + break; + case 1: + case MENU_B_PRESSED: + gPartyMenuUseExitCallback = FALSE; + PlaySE(SE_SELECT); + ScheduleBgCopyTilemapToVram(2); + // Don't exit party selections screen, return to choosing a mon. + ClearStdWindowAndFrameToTransparent(6, 0); + ClearWindowTilemap(6); + DisplayPartyMenuStdMessage(5); + gTasks[taskId].func = (void *)GetWordTaskArg(taskId, tOldFunc); + return; + } + break; + case 3: + PlaySE(SE_USE_ITEM); + StringExpandPlaceholders(gStringVar4, doneText); + DisplayPartyMenuMessage(gStringVar4, 1); + ScheduleBgCopyTilemapToVram(2); + tState++; + break; + case 4: + if (!IsPartyMenuTextPrinterActive()) + tState++; + break; + case 5: + SetMonData(&gPlayerParty[tMonId], MON_DATA_HIDDEN_NATURE, &tNewNature); + CalculateMonStats(&gPlayerParty[tMonId]); + RemoveBagItem(gSpecialVar_ItemId, 1); + gTasks[taskId].func = Task_ClosePartyMenu; + break; + } +} + +void ItemUseCB_Mint(u8 taskId, TaskFunc task) +{ + s16 *data = gTasks[taskId].data; + + tState = 0; + tMonId = gPartyMenu.slotId; + tOldNature = GetMonData(&gPlayerParty[tMonId], MON_DATA_HIDDEN_NATURE); + tNewNature = ItemId_GetSecondaryId(gSpecialVar_ItemId); + SetWordTaskArg(taskId, tOldFunc, (uintptr_t)(gTasks[taskId].func)); + gTasks[taskId].func = Task_Mint; +} + +#undef tState +#undef tMonId +#undef tOldNature +#undef tNewNature +#undef tOldFunc + static void Task_DisplayHPRestoredMessage(u8 taskId) { GetMonNickname(&gPlayerParty[gPartyMenu.slotId], gStringVar1); @@ -5672,6 +5770,70 @@ static void BufferMonStatsToTaskData(struct Pokemon *mon, s16 *data) data[3] = GetMonData(mon, MON_DATA_SPEED); } +#define tState data[0] +#define tMonId data[1] +#define tDynamaxLevel data[2] +#define tOldFunc 4 + +void Task_DynamaxCandy(u8 taskId) +{ + static const u8 doneText[] = _("{STR_VAR_1}'s Dynamax Level\nincreased by 1!{PAUSE_UNTIL_PRESS}"); + s16 *data = gTasks[taskId].data; + + switch (tState) + { + case 0: + // Can't use. + if (tDynamaxLevel == MAX_DYNAMAX_LEVEL) + { + gPartyMenuUseExitCallback = FALSE; + PlaySE(SE_SELECT); + DisplayPartyMenuMessage(gText_WontHaveEffect, 1); + ScheduleBgCopyTilemapToVram(2); + gTasks[taskId].func = Task_ClosePartyMenuAfterText; + return; + } + gPartyMenuUseExitCallback = TRUE; + GetMonNickname(&gPlayerParty[tMonId], gStringVar1); + CopyItemName(gSpecialVar_ItemId, gStringVar2); + tState++; + break; + case 1: + PlaySE(SE_USE_ITEM); + StringExpandPlaceholders(gStringVar4, doneText); + DisplayPartyMenuMessage(gStringVar4, 1); + ScheduleBgCopyTilemapToVram(2); + tState++; + break; + case 2: + if (!IsPartyMenuTextPrinterActive()) + tState++; + break; + case 3: + tDynamaxLevel++; + SetMonData(&gPlayerParty[tMonId], MON_DATA_DYNAMAX_LEVEL, &tDynamaxLevel); + RemoveBagItem(gSpecialVar_ItemId, 1); + gTasks[taskId].func = Task_ClosePartyMenu; + break; + } +} + +void ItemUseCB_DynamaxCandy(u8 taskId, TaskFunc task) +{ + s16 *data = gTasks[taskId].data; + + tState = 0; + tMonId = gPartyMenu.slotId; + tDynamaxLevel = GetMonData(&gPlayerParty[tMonId], MON_DATA_DYNAMAX_LEVEL); + SetWordTaskArg(taskId, tOldFunc, (uintptr_t)(gTasks[taskId].func)); + gTasks[taskId].func = Task_DynamaxCandy; +} + +#undef tState +#undef tMonId +#undef tDynamaxLevel +#undef tOldFunc + #define tUsedOnSlot data[0] #define tHadEffect data[1] #define tLastSlotUsed data[2] diff --git a/src/pokeblock_feed.c b/src/pokeblock_feed.c index c7ef8c9e90..61e1b7a6b3 100644 --- a/src/pokeblock_feed.c +++ b/src/pokeblock_feed.c @@ -718,7 +718,8 @@ static void HandleInitBackgrounds(void) static bool8 LoadMonAndSceneGfx(struct Pokemon *mon) { u16 species; - u32 personality, trainerId; + u32 personality; + bool32 isShiny; switch (sPokeblockFeed->loadGfxState) { @@ -733,8 +734,8 @@ static bool8 LoadMonAndSceneGfx(struct Pokemon *mon) // Load mon palette species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG); personality = GetMonData(mon, MON_DATA_PERSONALITY); - trainerId = GetMonData(mon, MON_DATA_OT_ID); - LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, trainerId, personality), species); + isShiny = GetMonData(mon, MON_DATA_IS_SHINY); + LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), species); SetMultiuseSpriteTemplateToPokemon(species, B_POSITION_OPPONENT_LEFT); sPokeblockFeed->loadGfxState++; break; diff --git a/src/pokedex.c b/src/pokedex.c index 33b7dd02dd..ee3656da68 100644 --- a/src/pokedex.c +++ b/src/pokedex.c @@ -3971,12 +3971,11 @@ static void HighlightSubmenuScreenSelectBarItem(u8 a, u16 b) #define tSpecies data[1] #define tPalTimer data[2] #define tMonSpriteId data[3] -#define tOtIdLo data[12] -#define tOtIdHi data[13] +#define tIsShiny data[13] #define tPersonalityLo data[14] #define tPersonalityHi data[15] -u8 DisplayCaughtMonDexPage(u16 species, u32 otId, u32 personality) +u8 DisplayCaughtMonDexPage(u16 species, bool32 isShiny, u32 personality) { u8 taskId = 0; if (POKEDEX_PLUS_HGSS) @@ -3986,8 +3985,7 @@ u8 DisplayCaughtMonDexPage(u16 species, u32 otId, u32 personality) gTasks[taskId].tState = 0; gTasks[taskId].tSpecies = species; - gTasks[taskId].tOtIdLo = otId; - gTasks[taskId].tOtIdHi = otId >> 16; + gTasks[taskId].tIsShiny = isShiny; gTasks[taskId].tPersonalityLo = personality; gTasks[taskId].tPersonalityHi = personality >> 16; return taskId; @@ -4039,7 +4037,7 @@ static void Task_DisplayCaughtMonDexPage(u8 taskId) gTasks[taskId].tState++; break; case 4: - spriteId = CreateMonPicSprite(NationalPokedexNumToSpecies(dexNum), 0, ((u16)gTasks[taskId].tPersonalityHi << 16) | (u16)gTasks[taskId].tPersonalityLo, TRUE, MON_PAGE_X, MON_PAGE_Y, 0, TAG_NONE); + spriteId = CreateMonPicSprite(NationalPokedexNumToSpecies(dexNum), FALSE, ((u16)gTasks[taskId].tPersonalityHi << 16) | (u16)gTasks[taskId].tPersonalityLo, TRUE, MON_PAGE_X, MON_PAGE_Y, 0, TAG_NONE); gSprites[spriteId].oam.priority = 0; BeginNormalPaletteFade(PALETTES_ALL, 0, 0x10, 0, RGB_BLACK); SetVBlankCallback(gPokedexVBlankCB); @@ -4089,7 +4087,7 @@ static void Task_ExitCaughtMonPage(u8 taskId) { if (!gPaletteFade.active) { - u32 otId; + bool32 isShiny; u32 personality; u8 paletteNum; const u32 *lzPaletteData; @@ -4104,10 +4102,10 @@ static void Task_ExitCaughtMonPage(u8 taskId) if (buffer) Free(buffer); - otId = ((u16)gTasks[taskId].tOtIdHi << 16) | (u16)gTasks[taskId].tOtIdLo; + isShiny = (bool8)gTasks[taskId].tIsShiny; personality = ((u16)gTasks[taskId].tPersonalityHi << 16) | (u16)gTasks[taskId].tPersonalityLo; paletteNum = gSprites[gTasks[taskId].tMonSpriteId].oam.paletteNum; - lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(gTasks[taskId].tSpecies, otId, personality); + lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(gTasks[taskId].tSpecies, isShiny, personality); LoadCompressedPalette(lzPaletteData, OBJ_PLTT_ID(paletteNum), PLTT_SIZE_4BPP); DestroyTask(taskId); } @@ -4654,7 +4652,7 @@ static u32 GetPokedexMonPersonality(u16 species) u16 CreateMonSpriteFromNationalDexNumber(u16 nationalNum, s16 x, s16 y, u16 paletteSlot) { nationalNum = NationalPokedexNumToSpecies(nationalNum); - return CreateMonPicSprite(nationalNum, SHINY_ODDS, GetPokedexMonPersonality(nationalNum), TRUE, x, y, paletteSlot, TAG_NONE); + return CreateMonPicSprite(nationalNum, FALSE, GetPokedexMonPersonality(nationalNum), TRUE, x, y, paletteSlot, TAG_NONE); } static u16 GetPokemonScaleFromNationalDexNumber(u16 nationalNum) diff --git a/src/pokemon.c b/src/pokemon.c index f89a37c61e..89e3f59a45 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -673,6 +673,63 @@ static const struct SpriteTemplate sSpriteTemplate_64x64 = .callback = SpriteCallbackDummy, }; +// NOTE: Reordering this array will break compatibility with existing +// saves. +static const u32 sCompressedStatuses[] = +{ + STATUS1_NONE, + STATUS1_SLEEP_TURN(1), + STATUS1_SLEEP_TURN(2), + STATUS1_SLEEP_TURN(3), + STATUS1_SLEEP_TURN(4), + STATUS1_SLEEP_TURN(5), + STATUS1_POISON, + STATUS1_BURN, + STATUS1_FREEZE, + STATUS1_PARALYSIS, + STATUS1_TOXIC_POISON, + STATUS1_FROSTBITE, +}; + +// Attempt to detect situations where the BoxPokemon struct is unable to +// contain all the values. +// TODO: Is it possible to compute: +// - The maximum experience. +// - The maximum PP. +// - The maximum HP. +// - The maximum form countdown. +STATIC_ASSERT(NUM_SPECIES < (1 << 11), PokemonSubstruct0_species_TooSmall); +STATIC_ASSERT(NUMBER_OF_MON_TYPES + 1 <= (1 << 5), PokemonSubstruct0_teraType_TooSmall); +STATIC_ASSERT(ITEMS_COUNT < (1 << 10), PokemonSubstruct0_heldItem_TooSmall); +STATIC_ASSERT(MAX_LEVEL <= 100, PokemonSubstruct0_experience_PotentiallTooSmall); // Maximum of ~2 million exp. +STATIC_ASSERT(LAST_BALL < (1 << 6), PokemonSubstruct0_pokeball_TooSmall); +STATIC_ASSERT(MOVES_COUNT_ALL < (1 << 11), PokemonSubstruct1_moves_TooSmall); +STATIC_ASSERT(ARRAY_COUNT(sCompressedStatuses) <= (1 << 4), PokemonSubstruct3_compressedStatus_TooSmall); +STATIC_ASSERT(MAX_LEVEL < (1 << 7), PokemonSubstruct3_metLevel_TooSmall); +STATIC_ASSERT(NUM_VERSIONS < (1 << 4), PokemonSubstruct3_metGame_TooSmall); +STATIC_ASSERT(MAX_DYNAMAX_LEVEL < (1 << 4), PokemonSubstruct3_dynamaxLevel_TooSmall); +STATIC_ASSERT(MAX_PER_STAT_IVS < (1 << 5), PokemonSubstruct3_ivs_TooSmall); +STATIC_ASSERT(NUM_NATURES <= (1 << 5), BoxPokemon_hiddenNatureModifier_TooSmall); + +static u32 CompressStatus(u32 status) +{ + s32 i; + for (i = 0; i < ARRAY_COUNT(sCompressedStatuses); i++) + { + if (sCompressedStatuses[i] == status) + return i; + } + return 0; // STATUS1_NONE +} + +static u32 UncompressStatus(u32 compressedStatus) +{ + if (compressedStatus < ARRAY_COUNT(sCompressedStatuses)) + return sCompressedStatuses[compressedStatus]; + else + return STATUS1_NONE; +} + void ZeroBoxMonData(struct BoxPokemon *boxMon) { u8 *raw = (u8 *)boxMon; @@ -733,6 +790,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, u8 i; u8 availableIVs[NUM_STATS]; u8 selectedIvs[LEGENDARY_PERFECT_IV_COUNT]; + bool32 isShiny; ZeroBoxMonData(boxMon); @@ -744,17 +802,13 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, // Determine original trainer ID if (otIdType == OT_ID_RANDOM_NO_SHINY) { - u32 shinyValue; - do - { - // Choose random OT IDs until one that results in a non-shiny Pokémon - value = Random32(); - shinyValue = GET_SHINY_VALUE(value, personality); - } while (shinyValue < SHINY_ODDS); + value = Random32(); + isShiny = FALSE; } else if (otIdType == OT_ID_PRESET) { value = fixedOtId; + isShiny = GET_SHINY_VALUE(value, personality) < SHINY_ODDS; } else // Player is the OT { @@ -763,26 +817,15 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, | (gSaveBlock2Ptr->playerTrainerId[2] << 16) | (gSaveBlock2Ptr->playerTrainerId[3] << 24); -#if P_FLAG_FORCE_NO_SHINY != 0 - if (FlagGet(P_FLAG_FORCE_NO_SHINY)) + if (P_FLAG_FORCE_NO_SHINY != 0 && FlagGet(P_FLAG_FORCE_NO_SHINY)) { - while (GET_SHINY_VALUE(value, personality) < SHINY_ODDS) - personality = Random32(); + isShiny = FALSE; } -#endif -#if P_FLAG_FORCE_SHINY != 0 - #if P_FLAG_FORCE_NO_SHINY != 0 - else - #endif - if (FlagGet(P_FLAG_FORCE_SHINY)) + else if (P_FLAG_FORCE_SHINY != 0 && FlagGet(P_FLAG_FORCE_SHINY)) { - while (GET_SHINY_VALUE(value, personality) >= SHINY_ODDS) - personality = Random32(); + isShiny = TRUE; } -#endif -#if P_FLAG_FORCE_SHINY != 0 || P_FLAG_FORCE_NO_SHINY != 0 else -#endif { u32 totalRerolls = 0; if (CheckBagHasItem(ITEM_SHINY_CHARM, 1)) @@ -795,6 +838,8 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, personality = Random32(); totalRerolls--; } + + isShiny = GET_SHINY_VALUE(value, personality) < SHINY_ODDS; } } @@ -804,6 +849,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV, checksum = CalculateBoxMonChecksum(boxMon); SetBoxMonData(boxMon, MON_DATA_CHECKSUM, &checksum); EncryptBoxMon(boxMon); + SetBoxMonData(boxMon, MON_DATA_IS_SHINY, &isShiny); StringCopy(speciesName, GetSpeciesName(species)); SetBoxMonData(boxMon, MON_DATA_NICKNAME, speciesName); SetBoxMonData(boxMon, MON_DATA_LANGUAGE, &gGameLanguage); @@ -1382,7 +1428,6 @@ static u16 CalculateBoxMonChecksum(struct BoxPokemon *boxMon) { \ u8 baseStat = gSpeciesInfo[species].base; \ s32 n = (((2 * baseStat + iv + ev / 4) * level) / 100) + 5; \ - u8 nature = GetNature(mon); \ n = ModifyStatByNature(nature, n, statIndex); \ if (B_FRIENDSHIP_BOOST == TRUE) \ n = n + ((n * 10 * friendship) / (MAX_FRIENDSHIP * 100));\ @@ -1393,23 +1438,25 @@ void CalculateMonStats(struct Pokemon *mon) { s32 oldMaxHP = GetMonData(mon, MON_DATA_MAX_HP, NULL); s32 currentHP = GetMonData(mon, MON_DATA_HP, NULL); - s32 hpIV = GetMonData(mon, MON_DATA_HP_IV, NULL); + s32 hpIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_HP) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_HP_IV, NULL); s32 hpEV = GetMonData(mon, MON_DATA_HP_EV, NULL); - s32 attackIV = GetMonData(mon, MON_DATA_ATK_IV, NULL); + s32 attackIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_ATK) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_ATK_IV, NULL); s32 attackEV = GetMonData(mon, MON_DATA_ATK_EV, NULL); - s32 defenseIV = GetMonData(mon, MON_DATA_DEF_IV, NULL); + s32 defenseIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_DEF) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_DEF_IV, NULL); s32 defenseEV = GetMonData(mon, MON_DATA_DEF_EV, NULL); - s32 speedIV = GetMonData(mon, MON_DATA_SPEED_IV, NULL); + s32 speedIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_SPEED) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_SPEED_IV, NULL); s32 speedEV = GetMonData(mon, MON_DATA_SPEED_EV, NULL); - s32 spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV, NULL); + s32 spAttackIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_SPATK) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_SPATK_IV, NULL); s32 spAttackEV = GetMonData(mon, MON_DATA_SPATK_EV, NULL); - s32 spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV, NULL); + s32 spDefenseIV = GetMonData(mon, MON_DATA_HYPER_TRAINED_SPDEF) ? MAX_PER_STAT_IVS : GetMonData(mon, MON_DATA_SPDEF_IV, NULL); s32 spDefenseEV = GetMonData(mon, MON_DATA_SPDEF_EV, NULL); u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL); u8 friendship = GetMonData(mon, MON_DATA_FRIENDSHIP, NULL); s32 level = GetLevelFromMonExp(mon); s32 newMaxHP; + u8 nature = GetMonData(mon, MON_DATA_HIDDEN_NATURE, NULL); + SetMonData(mon, MON_DATA_LEVEL, &level); if (species == SPECIES_SHEDINJA) @@ -1465,12 +1512,15 @@ void BoxMonToMon(const struct BoxPokemon *src, struct Pokemon *dest) { u32 value = 0; dest->box = *src; - SetMonData(dest, MON_DATA_STATUS, &value); - SetMonData(dest, MON_DATA_HP, &value); - SetMonData(dest, MON_DATA_MAX_HP, &value); + dest->status = GetBoxMonData(&dest->box, MON_DATA_STATUS, NULL); + dest->hp = 0; + dest->maxHP = 0; value = MAIL_NONE; SetMonData(dest, MON_DATA_MAIL, &value); + value = GetBoxMonData(&dest->box, MON_DATA_HP_LOST); CalculateMonStats(dest); + value = GetMonData(dest, MON_DATA_MAX_HP) - value; + SetMonData(dest, MON_DATA_HP, &value); } u8 GetLevelFromMonExp(struct Pokemon *mon) @@ -2044,6 +2094,76 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) switch (field) { + case MON_DATA_NICKNAME: + { + if (boxMon->isBadEgg) + { + for (retVal = 0; + retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS; + data[retVal] = gText_BadEgg[retVal], retVal++) {} + + data[retVal] = EOS; + } + else if (boxMon->isEgg) + { + StringCopy(data, gText_EggNickname); + retVal = StringLength(data); + } + else if (boxMon->language == LANGUAGE_JAPANESE) + { + data[0] = EXT_CTRL_CODE_BEGIN; + data[1] = EXT_CTRL_CODE_JPN; + + for (retVal = 2, i = 0; + i < 5 && boxMon->nickname[i] != EOS; + data[retVal] = boxMon->nickname[i], retVal++, i++) {} + + data[retVal++] = EXT_CTRL_CODE_BEGIN; + data[retVal++] = EXT_CTRL_CODE_ENG; + data[retVal] = EOS; + } + else + { + retVal = 0; + while (retVal < min(sizeof(boxMon->nickname), POKEMON_NAME_LENGTH)) + { + data[retVal] = boxMon->nickname[retVal]; + retVal++; + } + + // Vanilla Pokémon have 0s in nickname11 and nickname12 + // so if both are 0 we assume that this is a vanilla + // Pokémon and replace them with EOS. This means that + // two CHAR_SPACE at the end of a nickname are trimmed. + if (POKEMON_NAME_LENGTH >= 12) + { + if (substruct0->nickname11 == 0 && substruct0->nickname12 == 0) + { + data[retVal++] = EOS; + data[retVal++] = EOS; + } + else + { + data[retVal++] = substruct0->nickname11; + data[retVal++] = substruct0->nickname12; + } + } + else if (POKEMON_NAME_LENGTH >= 11) + { + if (substruct0->nickname11 == 0) + { + data[retVal++] = EOS; + } + else + { + data[retVal++] = substruct0->nickname11; + } + } + + data[retVal] = EOS; + } + break; + } case MON_DATA_SPECIES: retVal = boxMon->isBadEgg ? SPECIES_EGG : substruct0->species; break; @@ -2060,16 +2180,28 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) retVal = substruct0->friendship; break; case MON_DATA_MOVE1: + retVal = substruct1->move1; + break; case MON_DATA_MOVE2: + retVal = substruct1->move2; + break; case MON_DATA_MOVE3: + retVal = substruct1->move3; + break; case MON_DATA_MOVE4: - retVal = substruct1->moves[field - MON_DATA_MOVE1]; + retVal = substruct1->move4; break; case MON_DATA_PP1: + retVal = substruct1->pp1; + break; case MON_DATA_PP2: + retVal = substruct1->pp2; + break; case MON_DATA_PP3: + retVal = substruct1->pp3; + break; case MON_DATA_PP4: - retVal = substruct1->pp[field - MON_DATA_PP1]; + retVal = substruct1->pp4; break; case MON_DATA_HP_EV: retVal = substruct2->hpEV; @@ -2200,9 +2332,6 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) case MON_DATA_WORLD_RIBBON: retVal = substruct3->worldRibbon; break; - case MON_DATA_UNUSED_RIBBONS: - retVal = substruct3->unusedRibbons; - break; case MON_DATA_MODERN_FATEFUL_ENCOUNTER: retVal = substruct3->modernFatefulEncounter; break; @@ -2228,10 +2357,10 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) while (moves[i] != MOVES_COUNT) { u16 move = moves[i]; - if (substruct1->moves[0] == move - || substruct1->moves[1] == move - || substruct1->moves[2] == move - || substruct1->moves[3] == move) + if (substruct1->move1 == move + || substruct1->move2 == move + || substruct1->move3 == move + || substruct1->move4 == move) retVal |= gBitTable[i]; i++; } @@ -2283,6 +2412,46 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) | (substruct3->worldRibbon << 26); } break; + case MON_DATA_HYPER_TRAINED_HP: + retVal = substruct1->hyperTrainedHP; + break; + case MON_DATA_HYPER_TRAINED_ATK: + retVal = substruct1->hyperTrainedAttack; + break; + case MON_DATA_HYPER_TRAINED_DEF: + retVal = substruct1->hyperTrainedDefense; + break; + case MON_DATA_HYPER_TRAINED_SPEED: + retVal = substruct1->hyperTrainedSpeed; + break; + case MON_DATA_HYPER_TRAINED_SPATK: + retVal = substruct1->hyperTrainedSpAttack; + break; + case MON_DATA_HYPER_TRAINED_SPDEF: + retVal = substruct1->hyperTrainedSpDefense; + break; + case MON_DATA_IS_SHADOW: + retVal = substruct3->isShadow; + break; + case MON_DATA_DYNAMAX_LEVEL: + retVal = substruct3->dynamaxLevel; + break; + case MON_DATA_GIGANTAMAX_FACTOR: + retVal = substruct3->gigantamaxFactor; + break; + case MON_DATA_TERA_TYPE: + { + if (substruct0->teraType == 0) + { + const u8 *types = gSpeciesInfo[substruct0->species].types; + retVal = (boxMon->personality & 0x1) == 0 ? types[0] : types[1]; + } + else + { + retVal = substruct0->teraType - 1; + } + break; + } default: break; } @@ -2291,50 +2460,18 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) { switch (field) { + case MON_DATA_STATUS: + retVal = UncompressStatus(boxMon->compressedStatus); + break; + case MON_DATA_HP_LOST: + retVal = boxMon->hpLost; + break; case MON_DATA_PERSONALITY: retVal = boxMon->personality; break; case MON_DATA_OT_ID: retVal = boxMon->otId; break; - case MON_DATA_NICKNAME: - { - if (boxMon->isBadEgg) - { - for (retVal = 0; - retVal < POKEMON_NAME_LENGTH && gText_BadEgg[retVal] != EOS; - data[retVal] = gText_BadEgg[retVal], retVal++) {} - - data[retVal] = EOS; - } - else if (boxMon->isEgg) - { - StringCopy(data, gText_EggNickname); - retVal = StringLength(data); - } - else if (boxMon->language == LANGUAGE_JAPANESE) - { - data[0] = EXT_CTRL_CODE_BEGIN; - data[1] = EXT_CTRL_CODE_JPN; - - for (retVal = 2, i = 0; - i < 5 && boxMon->nickname[i] != EOS; - data[retVal] = boxMon->nickname[i], retVal++, i++) {} - - data[retVal++] = EXT_CTRL_CODE_BEGIN; - data[retVal++] = EXT_CTRL_CODE_ENG; - data[retVal] = EOS; - } - else - { - for (retVal = 0; - retVal < POKEMON_NAME_LENGTH; - data[retVal] = boxMon->nickname[retVal], retVal++){} - - data[retVal] = EOS; - } - break; - } case MON_DATA_LANGUAGE: retVal = boxMon->language; break; @@ -2366,9 +2503,18 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data) case MON_DATA_CHECKSUM: retVal = boxMon->checksum; break; - case MON_DATA_ENCRYPT_SEPARATOR: - retVal = boxMon->unknown; + case MON_DATA_IS_SHINY: + { + u32 shinyValue = GET_SHINY_VALUE(boxMon->otId, boxMon->personality); + retVal = (shinyValue < SHINY_ODDS) ^ boxMon->shinyModifier; break; + } + case MON_DATA_HIDDEN_NATURE: + { + u32 nature = GetNatureFromPersonality(boxMon->personality); + retVal = nature ^ boxMon->hiddenNatureModifier; + break; + } default: break; } @@ -2397,13 +2543,27 @@ void SetMonData(struct Pokemon *mon, s32 field, const void *dataArg) { case MON_DATA_STATUS: SET32(mon->status); + SetBoxMonData(&mon->box, MON_DATA_STATUS, dataArg); break; case MON_DATA_LEVEL: SET8(mon->level); break; case MON_DATA_HP: + { + u32 hpLost; SET16(mon->hp); + hpLost = mon->maxHP - mon->hp; + SetBoxMonData(&mon->box, MON_DATA_HP_LOST, &hpLost); break; + } + case MON_DATA_HP_LOST: + { + u32 hpLost; + SET16(hpLost); + mon->hp = mon->maxHP - hpLost; + SetBoxMonData(&mon->box, MON_DATA_HP_LOST, &hpLost); + break; + } case MON_DATA_MAX_HP: SET16(mon->maxHP); break; @@ -2462,6 +2622,17 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) switch (field) { + case MON_DATA_NICKNAME: + { + s32 i; + for (i = 0; i < min(sizeof(boxMon->nickname), POKEMON_NAME_LENGTH); i++) + boxMon->nickname[i] = data[i]; + if (POKEMON_NAME_LENGTH >= 11) + substruct0->nickname11 = data[10]; + if (POKEMON_NAME_LENGTH >= 12) + substruct0->nickname12 = data[11]; + break; + } case MON_DATA_SPECIES: { SET16(substruct0->species); @@ -2484,16 +2655,28 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) SET8(substruct0->friendship); break; case MON_DATA_MOVE1: + SET16(substruct1->move1); + break; case MON_DATA_MOVE2: + SET16(substruct1->move2); + break; case MON_DATA_MOVE3: + SET16(substruct1->move3); + break; case MON_DATA_MOVE4: - SET16(substruct1->moves[field - MON_DATA_MOVE1]); + SET16(substruct1->move4); break; case MON_DATA_PP1: + SET8(substruct1->pp1); + break; case MON_DATA_PP2: + SET8(substruct1->pp2); + break; case MON_DATA_PP3: + SET8(substruct1->pp3); + break; case MON_DATA_PP4: - SET8(substruct1->pp[field - MON_DATA_PP1]); + SET8(substruct1->pp4); break; case MON_DATA_HP_EV: SET8(substruct2->hpEV); @@ -2634,9 +2817,6 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) case MON_DATA_WORLD_RIBBON: SET8(substruct3->worldRibbon); break; - case MON_DATA_UNUSED_RIBBONS: - SET8(substruct3->unusedRibbons); - break; case MON_DATA_MODERN_FATEFUL_ENCOUNTER: SET8(substruct3->modernFatefulEncounter); break; @@ -2651,6 +2831,40 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) substruct3->spDefenseIV = (ivs >> 25) & MAX_IV_MASK; break; } + case MON_DATA_HYPER_TRAINED_HP: + SET8(substruct1->hyperTrainedHP); + break; + case MON_DATA_HYPER_TRAINED_ATK: + SET8(substruct1->hyperTrainedAttack); + break; + case MON_DATA_HYPER_TRAINED_DEF: + SET8(substruct1->hyperTrainedDefense); + break; + case MON_DATA_HYPER_TRAINED_SPEED: + SET8(substruct1->hyperTrainedSpeed); + break; + case MON_DATA_HYPER_TRAINED_SPATK: + SET8(substruct1->hyperTrainedSpAttack); + break; + case MON_DATA_HYPER_TRAINED_SPDEF: + SET8(substruct1->hyperTrainedSpDefense); + break; + case MON_DATA_IS_SHADOW: + SET8(substruct3->isShadow); + break; + case MON_DATA_DYNAMAX_LEVEL: + SET8(substruct3->dynamaxLevel); + break; + case MON_DATA_GIGANTAMAX_FACTOR: + SET8(substruct3->gigantamaxFactor); + break; + case MON_DATA_TERA_TYPE: + { + u32 teraType; + SET8(teraType); + substruct0->teraType = 1 + teraType; + break; + } default: break; } @@ -2659,19 +2873,22 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) { switch (field) { + case MON_DATA_STATUS: + { + u32 status; + SET32(status); + boxMon->compressedStatus = CompressStatus(status); + break; + } + case MON_DATA_HP_LOST: + SET16(boxMon->hpLost); + break; case MON_DATA_PERSONALITY: SET32(boxMon->personality); break; case MON_DATA_OT_ID: SET32(boxMon->otId); break; - case MON_DATA_NICKNAME: - { - s32 i; - for (i = 0; i < POKEMON_NAME_LENGTH; i++) - boxMon->nickname[i] = data[i]; - break; - } case MON_DATA_LANGUAGE: SET8(boxMon->language); break; @@ -2697,10 +2914,23 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) case MON_DATA_CHECKSUM: SET16(boxMon->checksum); break; - case MON_DATA_ENCRYPT_SEPARATOR: - SET16(boxMon->unknown); + case MON_DATA_IS_SHINY: + { + u32 shinyValue = GET_SHINY_VALUE(boxMon->otId, boxMon->personality); + bool32 isShiny; + SET8(isShiny); + boxMon->shinyModifier = (shinyValue < SHINY_ODDS) ^ isShiny; break; } + case MON_DATA_HIDDEN_NATURE: + { + u32 nature = GetNatureFromPersonality(boxMon->personality); + u32 hiddenNature; + SET8(hiddenNature); + boxMon->hiddenNatureModifier = nature ^ hiddenNature; + break; + } + } } if (field > MON_DATA_ENCRYPT_SEPARATOR) @@ -3764,6 +3994,18 @@ u8 GetNatureFromPersonality(u32 personality) return personality % NUM_NATURES; } +static u32 GetGMaxTargetSpecies(u32 species) +{ + const struct FormChange *formChanges = GetSpeciesFormChanges(species); + u32 i; + for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++) + { + if (formChanges[i].method == FORM_CHANGE_BATTLE_GIGANTAMAX) + return formChanges[i].targetSpecies; + } + return SPECIES_NONE; +} + u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, struct Pokemon *tradePartner) { int i, j; @@ -3776,6 +4018,7 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s u8 beauty = GetMonData(mon, MON_DATA_BEAUTY, 0); u16 upperPersonality = personality >> 16; u32 holdEffect, currentMap, partnerSpecies, partnerHeldItem, partnerHoldEffect; + bool32 consumeItem = FALSE; const struct Evolution *evolutions = GetSpeciesEvolutions(species); if (evolutions == NULL) @@ -3848,17 +4091,15 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s case EVO_ITEM_HOLD_NIGHT: if (GetTimeOfDay() == TIME_NIGHT && heldItem == evolutions[i].param) { - heldItem = ITEM_NONE; - SetMonData(mon, MON_DATA_HELD_ITEM, &heldItem); targetSpecies = evolutions[i].targetSpecies; + consumeItem = TRUE; } break; case EVO_ITEM_HOLD_DAY: if (GetTimeOfDay() != TIME_NIGHT && heldItem == evolutions[i].param) { - heldItem = ITEM_NONE; - SetMonData(mon, MON_DATA_HELD_ITEM, &heldItem); targetSpecies = evolutions[i].targetSpecies; + consumeItem = TRUE; } break; case EVO_LEVEL_DUSK: @@ -4037,9 +4278,8 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s case EVO_ITEM_HOLD: if (heldItem == evolutions[i].param) { - heldItem = 0; - SetMonData(mon, MON_DATA_HELD_ITEM, &heldItem); targetSpecies = evolutions[i].targetSpecies; + consumeItem = TRUE; } break; } @@ -4059,9 +4299,8 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s case EVO_TRADE_ITEM: if (evolutions[i].param == heldItem) { - heldItem = ITEM_NONE; - SetMonData(mon, MON_DATA_HELD_ITEM, &heldItem); targetSpecies = evolutions[i].targetSpecies; + consumeItem = TRUE; } break; case EVO_TRADE_SPECIFIC_MON: @@ -4150,6 +4389,22 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, u8 mode, u16 evolutionItem, s break; } + // Pikachu, Meowth, and Eevee cannot evolve if they have the + // Gigantamax Factor. We assume that is because their evolutions + // do not have a Gigantamax Form. + if (GetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR, NULL) + && GetGMaxTargetSpecies(species) != SPECIES_NONE + && GetGMaxTargetSpecies(targetSpecies) == SPECIES_NONE) + { + return SPECIES_NONE; + } + + if (consumeItem) + { + heldItem = ITEM_NONE; + SetMonData(mon, MON_DATA_HELD_ITEM, &heldItem); + } + return targetSpecies; } @@ -5067,20 +5322,17 @@ static void Task_PlayMapChosenOrBattleBGM(u8 taskId) const u32 *GetMonFrontSpritePal(struct Pokemon *mon) { - u16 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, 0); - u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0); - u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); - return GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality); + u16 species = GetMonData(mon, MON_DATA_SPECIES_OR_EGG, NULL); + bool32 isShiny = GetMonData(mon, MON_DATA_IS_SHINY, NULL); + u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL); + return GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality); } -const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality) +const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, bool32 isShiny, u32 personality) { - u32 shinyValue; - species = SanitizeSpeciesId(species); - shinyValue = GET_SHINY_VALUE(otId, personality); - if (shinyValue < SHINY_ODDS) + if (isShiny) { if (gSpeciesInfo[species].shinyPaletteFemale != NULL && IsPersonalityFemale(species, personality)) return gSpeciesInfo[species].shinyPaletteFemale; @@ -5278,18 +5530,7 @@ void SetWildMonHeldItem(void) bool8 IsMonShiny(struct Pokemon *mon) { - u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0); - u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0); - return IsShinyOtIdPersonality(otId, personality); -} - -bool8 IsShinyOtIdPersonality(u32 otId, u32 personality) -{ - bool8 retVal = FALSE; - u32 shinyValue = GET_SHINY_VALUE(otId, personality); - if (shinyValue < SHINY_ODDS) - retVal = TRUE; - return retVal; + return GetMonData(mon, MON_DATA_IS_SHINY, NULL); } const u8 *GetTrainerPartnerName(void) @@ -6072,6 +6313,10 @@ void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality) struct PokemonSubstruct3 *old3, *new3; struct BoxPokemon old; + bool32 isShiny = GetBoxMonData(boxMon, MON_DATA_IS_SHINY, NULL); + u32 hiddenNature = GetBoxMonData(boxMon, MON_DATA_HIDDEN_NATURE, NULL); + u32 teraType = GetBoxMonData(boxMon, MON_DATA_TERA_TYPE, NULL); + old = *boxMon; old0 = &(GetSubstruct(&old, old.personality, 0)->type0); old1 = &(GetSubstruct(&old, old.personality, 1)->type1); @@ -6091,6 +6336,36 @@ void UpdateMonPersonality(struct BoxPokemon *boxMon, u32 personality) *new3 = *old3; boxMon->checksum = CalculateBoxMonChecksum(boxMon); EncryptBoxMon(boxMon); + + SetBoxMonData(boxMon, MON_DATA_IS_SHINY, &isShiny); + SetBoxMonData(boxMon, MON_DATA_HIDDEN_NATURE, &hiddenNature); + SetBoxMonData(boxMon, MON_DATA_TERA_TYPE, &teraType); +} + +void HealPokemon(struct Pokemon *mon) +{ + u32 data; + + data = GetMonData(mon, MON_DATA_MAX_HP); + SetMonData(mon, MON_DATA_HP, &data); + + data = STATUS1_NONE; + SetMonData(mon, MON_DATA_STATUS, &data); + + MonRestorePP(mon); +} + +void HealBoxPokemon(struct BoxPokemon *boxMon) +{ + u32 data; + + data = 0; + SetBoxMonData(boxMon, MON_DATA_HP_LOST, &data); + + data = STATUS1_NONE; + SetBoxMonData(boxMon, MON_DATA_STATUS, &data); + + BoxMonRestorePP(boxMon); } u16 GetCryIdBySpecies(u16 species) diff --git a/src/pokemon_jump.c b/src/pokemon_jump.c index 6ea897c0a6..ecdcbf26d2 100755 --- a/src/pokemon_jump.c +++ b/src/pokemon_jump.c @@ -157,7 +157,8 @@ enum { struct PokemonJump_MonInfo { - u16 species; + u16 isShiny:1; + u16 species:15; u32 otId; u32 personality; }; @@ -894,6 +895,7 @@ static void InitJumpMonInfo(struct PokemonJump_MonInfo *monInfo, struct Pokemon { monInfo->species = GetMonData(mon, MON_DATA_SPECIES); monInfo->otId = GetMonData(mon, MON_DATA_OT_ID); + monInfo->isShiny = GetMonData(mon, MON_DATA_IS_SHINY); monInfo->personality = GetMonData(mon, MON_DATA_PERSONALITY); } @@ -2970,7 +2972,7 @@ static void CreateJumpMonSprite(struct PokemonJumpGfx *jumpGfx, struct PokemonJu spriteSheet.size = MON_PIC_SIZE; LoadSpriteSheet(&spriteSheet); - spritePalette.data = GetMonSpritePalFromSpeciesAndPersonality(monInfo->species, monInfo->otId, monInfo->personality); + spritePalette.data = GetMonSpritePalFromSpeciesAndPersonality(monInfo->species, monInfo->isShiny, monInfo->personality); spritePalette.tag = multiplayerId; LoadCompressedSpritePalette(&spritePalette); @@ -4161,7 +4163,8 @@ static void Task_UpdateBonus(u8 taskId) struct MonInfoPacket { u8 id; - u16 species; + u16 isShiny:1; + u16 species:15; u32 personality; u32 otId; }; @@ -4170,6 +4173,7 @@ static void SendPacket_MonInfo(struct PokemonJump_MonInfo *monInfo) { struct MonInfoPacket packet; packet.id = PACKET_MON_INFO, + packet.isShiny = monInfo->isShiny, packet.species = monInfo->species, packet.otId = monInfo->otId, packet.personality = monInfo->personality, @@ -4187,6 +4191,7 @@ static bool32 RecvPacket_MonInfo(int multiplayerId, struct PokemonJump_MonInfo * if (packet.id == PACKET_MON_INFO) { monInfo->species = packet.species; + monInfo->isShiny = packet.isShiny; monInfo->otId = packet.otId; monInfo->personality = packet.personality; return TRUE; diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index 817ec51543..95a8387066 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -6414,15 +6414,13 @@ static void SetMovingMonData(u8 boxId, u8 position) static void SetPlacedMonData(u8 boxId, u8 position) { + if (OW_PC_HEAL <= GEN_7) + HealPokemon(&sStorage->movingMon); + if (boxId == TOTAL_BOXES_COUNT) - { gPlayerParty[position] = sStorage->movingMon; - } else - { - BoxMonRestorePP(&sStorage->movingMon.box); SetBoxMonAt(boxId, position, &sStorage->movingMon.box); - } } static void PurgeMonOrBoxMon(u8 boxId, u8 position) @@ -6964,7 +6962,7 @@ static void SetDisplayMonData(void *pokemon, u8 mode) sStorage->displayMonSpecies = GetBoxMonData(pokemon, MON_DATA_SPECIES_OR_EGG); if (sStorage->displayMonSpecies != SPECIES_NONE) { - u32 otId = GetBoxMonData(boxMon, MON_DATA_OT_ID); + bool8 isShiny = GetBoxMonData(boxMon, MON_DATA_IS_SHINY); sanityIsBadEgg = GetBoxMonData(boxMon, MON_DATA_SANITY_IS_BAD_EGG); if (sanityIsBadEgg) sStorage->displayMonIsEgg = TRUE; @@ -6977,7 +6975,7 @@ static void SetDisplayMonData(void *pokemon, u8 mode) sStorage->displayMonLevel = GetLevelFromBoxMonExp(boxMon); sStorage->displayMonMarkings = GetBoxMonData(boxMon, MON_DATA_MARKINGS); sStorage->displayMonPersonality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY); - sStorage->displayMonPalette = GetMonSpritePalFromSpeciesAndPersonality(sStorage->displayMonSpecies, otId, sStorage->displayMonPersonality); + sStorage->displayMonPalette = GetMonSpritePalFromSpeciesAndPersonality(sStorage->displayMonSpecies, isShiny, sStorage->displayMonPersonality); gender = GetGenderFromSpeciesAndPersonality(sStorage->displayMonSpecies, sStorage->displayMonPersonality); sStorage->displayMonItemId = GetBoxMonData(boxMon, MON_DATA_HELD_ITEM); } @@ -8653,6 +8651,8 @@ static void MultiMove_SetPlacedMonData(void) u8 boxPosition = (IN_BOX_COLUMNS * i) + sMultiMove->minColumn; for (j = sMultiMove->minColumn; j < columnCount; j++) { + if (OW_PC_HEAL <= GEN_7) + HealBoxPokemon(&sMultiMove->boxMons[monArrayId]); if (GetBoxMonData(&sMultiMove->boxMons[monArrayId], MON_DATA_SANITY_HAS_SPECIES)) SetBoxMonAt(boxId, boxPosition, &sMultiMove->boxMons[monArrayId]); boxPosition++; @@ -10147,12 +10147,12 @@ static void UnkUtil_DmaRun(struct UnkUtilData *data) void UpdateSpeciesSpritePSS(struct BoxPokemon *boxMon) { u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES); - u32 otId = GetBoxMonData(boxMon, MON_DATA_OT_ID); + bool8 isShiny = GetBoxMonData(boxMon, MON_DATA_IS_SHINY); u32 pid = GetBoxMonData(boxMon, MON_DATA_PERSONALITY); // Update front sprite sStorage->displayMonSpecies = species; - sStorage->displayMonPalette = GetMonSpritePalFromSpeciesAndPersonality(species, otId, pid); + sStorage->displayMonPalette = GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, pid); if (!sJustOpenedBag) { LoadDisplayMonGfx(species, pid); diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 2ea61ba730..7ccc605b68 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -141,7 +141,9 @@ static EWRAM_DATA struct PokemonSummaryScreenData { u16 species; // 0x0 u16 species2; // 0x2 - u8 isEgg; // 0x4 + u8 isEgg:1; // 0x4 + u8 isShiny:1; + u8 padding:6; u8 level; // 0x5 u8 ribbonCount; // 0x6 u8 ailment; // 0x7 @@ -168,6 +170,7 @@ static EWRAM_DATA struct PokemonSummaryScreenData u8 sanity; // 0x35 u8 OTName[17]; // 0x36 u32 OTID; // 0x48 + u8 teraType; } summary; u16 bgTilemapBuffers[PSS_PAGE_COUNT][2][0x400]; u8 mode; @@ -1541,6 +1544,8 @@ static bool8 ExtractMonDataToSummaryStruct(struct Pokemon *mon) break; default: sum->ribbonCount = GetMonData(mon, MON_DATA_RIBBON_COUNT); + sum->teraType = GetMonData(mon, MON_DATA_TERA_TYPE); + sum->isShiny = GetMonData(mon, MON_DATA_IS_SHINY); return TRUE; } sMonSummaryScreen->switchCounter++; @@ -3938,6 +3943,10 @@ static void SetMonTypeIcons(void) { SetSpriteInvisibility(SPRITE_ARR_ID_TYPE + 1, TRUE); } + if (P_SHOW_TERA_TYPE >= GEN_9) + { + SetTypeSpritePosAndPal(summary->teraType, 200, 48, SPRITE_ARR_ID_TYPE + 2); + } } } @@ -4042,7 +4051,7 @@ static u8 LoadMonGfxAndSprite(struct Pokemon *mon, s16 *state) (*state)++; return 0xFF; case 1: - LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(summary->species2, summary->OTID, summary->pid), summary->species2); + LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(summary->species2, summary->isShiny, summary->pid), summary->species2); SetMultiuseSpriteTemplateToPokemon(summary->species2, B_POSITION_OPPONENT_LEFT); (*state)++; return 0xFF; diff --git a/src/pokenav_conditions.c b/src/pokenav_conditions.c index 3f662e6f3e..19cfe38b95 100644 --- a/src/pokenav_conditions.c +++ b/src/pokenav_conditions.c @@ -522,7 +522,8 @@ static void GetMonConditionGraphData(s16 listId, u8 loadId) static void ConditionGraphDrawMonPic(s16 listId, u8 loadId) { u16 boxId, monId, species; - u32 personality, tid; + u32 personality; + bool8 isShiny; struct Pokenav_ConditionMenu *menu = GetSubstructPtr(POKENAV_SUBSTRUCT_CONDITION_GRAPH_MENU); struct PokenavMonList *monListPtr = GetSubstructPtr(POKENAV_SUBSTRUCT_MON_LIST); @@ -532,10 +533,10 @@ static void ConditionGraphDrawMonPic(s16 listId, u8 loadId) boxId = monListPtr->monData[listId].boxId; monId = monListPtr->monData[listId].monId; species = GetBoxOrPartyMonData(boxId, monId, MON_DATA_SPECIES_OR_EGG, NULL); - tid = GetBoxOrPartyMonData(boxId, monId, MON_DATA_OT_ID, NULL); + isShiny = GetBoxOrPartyMonData(boxId, monId, MON_DATA_IS_SHINY, NULL); personality = GetBoxOrPartyMonData(boxId, monId, MON_DATA_PERSONALITY, NULL); LoadSpecialPokePic(menu->monPicGfx[loadId], species, personality, TRUE); - LZ77UnCompWram(GetMonSpritePalFromSpeciesAndPersonality(species, tid, personality), menu->monPal[loadId]); + LZ77UnCompWram(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), menu->monPal[loadId]); } u16 GetMonListCount(void) diff --git a/src/pokenav_ribbons_summary.c b/src/pokenav_ribbons_summary.c index f2e589e56d..1ff55dc187 100644 --- a/src/pokenav_ribbons_summary.c +++ b/src/pokenav_ribbons_summary.c @@ -401,7 +401,7 @@ static void GetMonNicknameLevelGender(u8 *nick, u8 *level, u8 *gender) StringGet_Nickname(nick); } -static void GetMonSpeciesPersonalityOtId(u16 *species, u32 *personality, u32 *otId) +static void GetMonSpeciesPersonalityShiny(u16 *species, u32 *personality, bool8 *isShiny) { struct Pokenav_RibbonsSummaryList *list = GetSubstructPtr(POKENAV_SUBSTRUCT_RIBBONS_SUMMARY_LIST); struct PokenavMonList *mons = list->monList; @@ -413,7 +413,7 @@ static void GetMonSpeciesPersonalityOtId(u16 *species, u32 *personality, u32 *ot struct Pokemon *mon = &gPlayerParty[monInfo->monId]; *species = GetMonData(mon, MON_DATA_SPECIES); *personality = GetMonData(mon, MON_DATA_PERSONALITY); - *otId = GetMonData(mon, MON_DATA_OT_ID); + *isShiny = GetMonData(mon, MON_DATA_IS_SHINY); } else { @@ -421,7 +421,7 @@ static void GetMonSpeciesPersonalityOtId(u16 *species, u32 *personality, u32 *ot struct BoxPokemon *boxMon = GetBoxedMonPtr(monInfo->boxId, monInfo->monId); *species = GetBoxMonData(boxMon, MON_DATA_SPECIES); *personality = GetBoxMonData(boxMon, MON_DATA_PERSONALITY); - *otId = GetBoxMonData(boxMon, MON_DATA_OT_ID); + *isShiny = GetBoxMonData(boxMon, MON_DATA_IS_SHINY); } } @@ -941,9 +941,10 @@ static void PrintRibbonsMonListIndex(struct Pokenav_RibbonsSummaryMenu *menu) static void ResetSpritesAndDrawMonFrontPic(struct Pokenav_RibbonsSummaryMenu *menu) { u16 species; - u32 personality, otId; + u32 personality; + bool8 isShiny; - GetMonSpeciesPersonalityOtId(&species, &personality, &otId); + GetMonSpeciesPersonalityShiny(&species, &personality, &isShiny); ResetAllPicSprites(); menu->monSpriteId = DrawRibbonsMonFrontPic(MON_SPRITE_X_ON, MON_SPRITE_Y); PokenavFillPalette(15, 0); @@ -960,10 +961,11 @@ static void DestroyRibbonsMonFrontPic(struct Pokenav_RibbonsSummaryMenu *menu) static u16 DrawRibbonsMonFrontPic(s32 x, s32 y) { u16 species, spriteId; - u32 personality, otId; + u32 personality; + bool8 isShiny; - GetMonSpeciesPersonalityOtId(&species, &personality, &otId); - spriteId = CreateMonPicSprite(species, otId, personality, TRUE, MON_SPRITE_X_ON, MON_SPRITE_Y, 15, TAG_NONE); + GetMonSpeciesPersonalityShiny(&species, &personality, &isShiny); + spriteId = CreateMonPicSprite(species, isShiny, personality, TRUE, MON_SPRITE_X_ON, MON_SPRITE_Y, 15, TAG_NONE); gSprites[spriteId].oam.priority = 0; return spriteId; } diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index ca455d544d..04448b6f6c 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -16,6 +16,7 @@ #include "party_menu.h" #include "pokedex.h" #include "pokemon.h" +#include "pokemon_storage_system.h" #include "random.h" #include "script.h" #include "sprite.h" @@ -27,35 +28,30 @@ static void CB2_ReturnFromChooseHalfParty(void); static void CB2_ReturnFromChooseBattleFrontierParty(void); +static void HealPlayerBoxes(void); void HealPlayerParty(void) { - u8 i, j; - u8 ppBonuses; - u8 arg[4]; + u32 i; + for (i = 0; i < gPlayerPartyCount; i++) + HealPokemon(&gPlayerParty[i]); + if (OW_PC_HEAL >= GEN_8) + HealPlayerBoxes(); +} - // restore HP. - for(i = 0; i < gPlayerPartyCount; i++) +static void HealPlayerBoxes(void) +{ + int boxId, boxPosition; + struct BoxPokemon *boxMon; + + for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++) { - u16 maxHP = GetMonData(&gPlayerParty[i], MON_DATA_MAX_HP); - arg[0] = maxHP; - arg[1] = maxHP >> 8; - SetMonData(&gPlayerParty[i], MON_DATA_HP, arg); - ppBonuses = GetMonData(&gPlayerParty[i], MON_DATA_PP_BONUSES); - - // restore PP. - for(j = 0; j < MAX_MON_MOVES; j++) + for (boxPosition = 0; boxPosition < IN_BOX_COUNT; boxPosition++) { - arg[0] = CalculatePPWithBonus(GetMonData(&gPlayerParty[i], MON_DATA_MOVE1 + j), ppBonuses, j); - SetMonData(&gPlayerParty[i], MON_DATA_PP1 + j, arg); + boxMon = &gPokemonStoragePtr->boxes[boxId][boxPosition]; + if (GetBoxMonData(boxMon, MON_DATA_SANITY_HAS_SPECIES)) + HealBoxPokemon(boxMon); } - - // since status is u32, the four 0 assignments here are probably for safety to prevent undefined data from reaching SetMonData. - arg[0] = 0; - arg[1] = 0; - arg[2] = 0; - arg[3] = 0; - SetMonData(&gPlayerParty[i], MON_DATA_STATUS, arg); } } @@ -273,3 +269,72 @@ void ReducePlayerPartyToSelectedMons(void) CalculatePlayerPartyCount(); } + +void CanHyperTrain(struct ScriptContext *ctx) +{ + u32 stat = ScriptReadByte(ctx); + u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + if (stat < NUM_STATS + && partyIndex < PARTY_SIZE + && !GetMonData(&gPlayerParty[partyIndex], MON_DATA_HYPER_TRAINED_HP + stat) + && GetMonData(&gPlayerParty[partyIndex], MON_DATA_HP_IV + stat) < MAX_PER_STAT_IVS) + { + gSpecialVar_Result = TRUE; + } + else + { + gSpecialVar_Result = FALSE; + } +} + +void HyperTrain(struct ScriptContext *ctx) +{ + u32 stat = ScriptReadByte(ctx); + u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + if (stat < NUM_STATS && partyIndex < PARTY_SIZE) + { + bool32 data = TRUE; + SetMonData(&gPlayerParty[partyIndex], MON_DATA_HYPER_TRAINED_HP + stat, &data); + CalculateMonStats(&gPlayerParty[partyIndex]); + } +} + +void HasGigantamaxFactor(struct ScriptContext *ctx) +{ + u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + if (partyIndex < PARTY_SIZE) + gSpecialVar_Result = GetMonData(&gPlayerParty[partyIndex], MON_DATA_GIGANTAMAX_FACTOR); + else + gSpecialVar_Result = FALSE; +} + +static const u16 sGigantaxFactorLockedSpecies[] = +{ + SPECIES_MELMETAL, +}; + +void ToggleGigantamaxFactor(struct ScriptContext *ctx) +{ + u32 i; + u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + u32 species; + + gSpecialVar_Result = FALSE; + + if (partyIndex < PARTY_SIZE) + { + bool32 gigantamaxFactor; + + species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES); + for (i = 0; i < ARRAY_COUNT(sGigantaxFactorLockedSpecies); i++) + { + if (species == sGigantaxFactorLockedSpecies[i]) + return; + } + + gigantamaxFactor = GetMonData(&gPlayerParty[partyIndex], MON_DATA_GIGANTAMAX_FACTOR); + gigantamaxFactor = !gigantamaxFactor; + SetMonData(&gPlayerParty[partyIndex], MON_DATA_GIGANTAMAX_FACTOR, &gigantamaxFactor); + gSpecialVar_Result = TRUE; + } +} diff --git a/src/starter_choose.c b/src/starter_choose.c index 3097f87f73..f1821fe04d 100644 --- a/src/starter_choose.c +++ b/src/starter_choose.c @@ -630,7 +630,7 @@ static u8 CreatePokemonFrontSprite(u16 species, u8 x, u8 y) { u8 spriteId; - spriteId = CreateMonPicSprite_Affine(species, SHINY_ODDS, 0, MON_PIC_AFFINE_FRONT, x, y, 14, TAG_NONE); + spriteId = CreateMonPicSprite_Affine(species, FALSE, 0, MON_PIC_AFFINE_FRONT, x, y, 14, TAG_NONE); gSprites[spriteId].oam.priority = 0; return spriteId; } diff --git a/src/trade.c b/src/trade.c index 5e0564a1ff..0d7765857f 100644 --- a/src/trade.c +++ b/src/trade.c @@ -4842,7 +4842,7 @@ static void CheckPartnersMonForRibbons(void) { u8 i; u8 numRibbons = 0; - for (i = 0; i < (MON_DATA_UNUSED_RIBBONS - MON_DATA_CHAMPION_RIBBON); i++) + for (i = 0; i < (MON_DATA_WORLD_RIBBON - MON_DATA_CHAMPION_RIBBON + 1); i++) numRibbons += GetMonData(&gEnemyParty[gSelectedTradeMonPositions[TRADE_PARTNER] % PARTY_SIZE], MON_DATA_CHAMPION_RIBBON + i); if (numRibbons != 0) diff --git a/src/trainer_pokemon_sprites.c b/src/trainer_pokemon_sprites.c index 6ffbc836d7..0d1954ab71 100644 --- a/src/trainer_pokemon_sprites.c +++ b/src/trainer_pokemon_sprites.c @@ -73,19 +73,19 @@ static bool16 DecompressPic(u16 species, u32 personality, bool8 isFrontPic, u8 * return FALSE; } -static void LoadPicPaletteByTagOrSlot(u16 species, u32 otId, u32 personality, u8 paletteSlot, u16 paletteTag, bool8 isTrainer) +static void LoadPicPaletteByTagOrSlot(u16 species, bool8 isShiny, u32 personality, u8 paletteSlot, u16 paletteTag, bool8 isTrainer) { if (!isTrainer) { if (paletteTag == TAG_NONE) { sCreatingSpriteTemplate.paletteTag = TAG_NONE; - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), OBJ_PLTT_ID(paletteSlot), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), OBJ_PLTT_ID(paletteSlot), PLTT_SIZE_4BPP); } else { sCreatingSpriteTemplate.paletteTag = paletteTag; - LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), species); + LoadCompressedSpritePaletteWithTag(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), species); } } else @@ -103,10 +103,10 @@ static void LoadPicPaletteByTagOrSlot(u16 species, u32 otId, u32 personality, u8 } } -static void LoadPicPaletteBySlot(u16 species, u32 otId, u32 personality, u8 paletteSlot, bool8 isTrainer) +static void LoadPicPaletteBySlot(u16 species, bool8 isShiny, u32 personality, u8 paletteSlot, bool8 isTrainer) { if (!isTrainer) - LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), PLTT_ID(paletteSlot), PLTT_SIZE_4BPP); + LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personality), PLTT_ID(paletteSlot), PLTT_SIZE_4BPP); else LoadCompressedPalette(gTrainerSprites[species].palette.data, PLTT_ID(paletteSlot), PLTT_SIZE_4BPP); } @@ -119,7 +119,7 @@ static void AssignSpriteAnimsTable(bool8 isTrainer) sCreatingSpriteTemplate.anims = gTrainerSprites[0].animation; } -static u16 CreatePicSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 isTrainer) +static u16 CreatePicSprite(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag, bool8 isTrainer) { u8 i; u8 *framePics; @@ -161,7 +161,7 @@ static u16 CreatePicSprite(u16 species, u32 otId, u32 personality, bool8 isFront sCreatingSpriteTemplate.images = images; sCreatingSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; sCreatingSpriteTemplate.callback = DummyPicSpriteCallback; - LoadPicPaletteByTagOrSlot(species, otId, personality, paletteSlot, paletteTag, isTrainer); + LoadPicPaletteByTagOrSlot(species, isShiny, personality, paletteSlot, paletteTag, isTrainer); spriteId = CreateSprite(&sCreatingSpriteTemplate, x, y, 0); if (paletteTag == TAG_NONE) gSprites[spriteId].oam.paletteNum = paletteSlot; @@ -173,7 +173,7 @@ static u16 CreatePicSprite(u16 species, u32 otId, u32 personality, bool8 isFront return spriteId; } -u16 CreateMonPicSprite_Affine(u16 species, u32 otId, u32 personality, u8 flags, s16 x, s16 y, u8 paletteSlot, u16 paletteTag) +u16 CreateMonPicSprite_Affine(u16 species, bool8 isShiny, u32 personality, u8 flags, s16 x, s16 y, u8 paletteSlot, u16 paletteTag) { u8 *framePics; struct SpriteFrameImage *images; @@ -239,7 +239,7 @@ u16 CreateMonPicSprite_Affine(u16 species, u32 otId, u32 personality, u8 flags, sCreatingSpriteTemplate.affineAnims = gDummySpriteAffineAnimTable; } sCreatingSpriteTemplate.callback = DummyPicSpriteCallback; - LoadPicPaletteByTagOrSlot(species, otId, personality, paletteSlot, paletteTag, FALSE); + LoadPicPaletteByTagOrSlot(species, isShiny, personality, paletteSlot, paletteTag, FALSE); spriteId = CreateSprite(&sCreatingSpriteTemplate, x, y, 0); if (paletteTag == TAG_NONE) gSprites[spriteId].oam.paletteNum = paletteSlot; @@ -276,16 +276,16 @@ static u16 FreeAndDestroyPicSpriteInternal(u16 spriteId) return 0; } -static u16 LoadPicSpriteInWindow(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId, bool8 isTrainer) +static u16 LoadPicSpriteInWindow(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId, bool8 isTrainer) { if (DecompressPic(species, personality, isFrontPic, (u8 *)GetWindowAttribute(windowId, WINDOW_TILE_DATA), FALSE)) return 0xFFFF; - LoadPicPaletteBySlot(species, otId, personality, paletteSlot, isTrainer); + LoadPicPaletteBySlot(species, isShiny, personality, paletteSlot, isTrainer); return 0; } -static u16 CreateTrainerCardSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId, bool8 isTrainer) +static u16 CreateTrainerCardSprite(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId, bool8 isTrainer) { u8 *framePics; @@ -293,16 +293,16 @@ static u16 CreateTrainerCardSprite(u16 species, u32 otId, u32 personality, bool8 if (framePics && !DecompressPic(species, personality, isFrontPic, framePics, isTrainer)) { BlitBitmapRectToWindow(windowId, framePics, 0, 0, TRAINER_PIC_WIDTH, TRAINER_PIC_HEIGHT, destX, destY, TRAINER_PIC_WIDTH, TRAINER_PIC_HEIGHT); - LoadPicPaletteBySlot(species, otId, personality, paletteSlot, isTrainer); + LoadPicPaletteBySlot(species, isShiny, personality, paletteSlot, isTrainer); Free(framePics); return 0; } return 0xFFFF; } -u16 CreateMonPicSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag) +u16 CreateMonPicSprite(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag) { - return CreatePicSprite(species, otId, personality, isFrontPic, x, y, paletteSlot, paletteTag, FALSE); + return CreatePicSprite(species, isShiny, personality, isFrontPic, x, y, paletteSlot, paletteTag, FALSE); } u16 FreeAndDestroyMonPicSprite(u16 spriteId) @@ -310,20 +310,20 @@ u16 FreeAndDestroyMonPicSprite(u16 spriteId) return FreeAndDestroyPicSpriteInternal(spriteId); } -static u16 UNUSED LoadMonPicInWindow(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId) +static u16 UNUSED LoadMonPicInWindow(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId) { - return LoadPicSpriteInWindow(species, otId, personality, isFrontPic, paletteSlot, windowId, FALSE); + return LoadPicSpriteInWindow(species, isShiny, personality, isFrontPic, paletteSlot, windowId, FALSE); } // Unused, FRLG only -u16 CreateTrainerCardMonIconSprite(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId) +u16 CreateTrainerCardMonIconSprite(u16 species, bool8 isShiny, u32 personality, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId) { - return CreateTrainerCardSprite(species, otId, personality, isFrontPic, destX, destY, paletteSlot, windowId, FALSE); + return CreateTrainerCardSprite(species, isShiny, personality, isFrontPic, destX, destY, paletteSlot, windowId, FALSE); } u16 CreateTrainerPicSprite(u16 species, bool8 isFrontPic, s16 x, s16 y, u8 paletteSlot, u16 paletteTag) { - return CreatePicSprite(species, 0, 0, isFrontPic, x, y, paletteSlot, paletteTag, TRUE); + return CreatePicSprite(species, FALSE, 0, isFrontPic, x, y, paletteSlot, paletteTag, TRUE); } u16 FreeAndDestroyTrainerPicSprite(u16 spriteId) @@ -333,12 +333,12 @@ u16 FreeAndDestroyTrainerPicSprite(u16 spriteId) static u16 UNUSED LoadTrainerPicInWindow(u16 species, bool8 isFrontPic, u8 paletteSlot, u8 windowId) { - return LoadPicSpriteInWindow(species, 0, 0, isFrontPic, paletteSlot, windowId, TRUE); + return LoadPicSpriteInWindow(species, FALSE, 0, isFrontPic, paletteSlot, windowId, TRUE); } u16 CreateTrainerCardTrainerPicSprite(u16 species, bool8 isFrontPic, u16 destX, u16 destY, u8 paletteSlot, u8 windowId) { - return CreateTrainerCardSprite(species, 0, 0, isFrontPic, destX, destY, paletteSlot, windowId, TRUE); + return CreateTrainerCardSprite(species, FALSE, 0, isFrontPic, destX, destY, paletteSlot, windowId, TRUE); } u16 PlayerGenderToFrontTrainerPicId_Debug(u8 gender, bool8 getClass) diff --git a/test/battle/trainer_control.c b/test/battle/trainer_control.c index 810a721fa5..e3e071745d 100644 --- a/test/battle/trainer_control.c +++ b/test/battle/trainer_control.c @@ -27,7 +27,8 @@ static const struct TrainerMon sTestParty1[] = .lvl = 67, .moves = {MOVE_AIR_SLASH, MOVE_BARRIER, MOVE_SOLAR_BEAM, MOVE_EXPLOSION}, .nature = TRAINER_PARTY_NATURE(NATURE_HASTY), - .nickname = COMPOUND_STRING("Bubbles") + .nickname = COMPOUND_STRING("Bubbles"), + .dynamaxLevel = 5, }, { .species = SPECIES_WOBBUFFET, @@ -110,6 +111,9 @@ TEST("CreateNPCTrainerPartyForTrainer generates customized Pokémon") EXPECT(GetMonGender(&testParty[0]) == MON_FEMALE); EXPECT(GetNature(&testParty[0]) == NATURE_HASTY); + EXPECT_EQ(GetMonData(&testParty[0], MON_DATA_DYNAMAX_LEVEL), 5); + EXPECT_EQ(GetMonData(&testParty[1], MON_DATA_DYNAMAX_LEVEL), 0); + Free(testParty); } diff --git a/test/dynamax.c b/test/dynamax.c index 69887d6d2f..0d6ee72172 100644 --- a/test/dynamax.c +++ b/test/dynamax.c @@ -465,16 +465,19 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon are immune to Instruct") } } -// TODO: Gigantamax factor SINGLE_BATTLE_TEST("(DYNAMAX) Pokemon with Gigantamax forms change upon Dynamaxing") { + u32 species; + bool32 gigantamaxFactor; + PARAMETRIZE { gigantamaxFactor = FALSE; species = SPECIES_VENUSAUR; } + PARAMETRIZE { gigantamaxFactor = TRUE; species = SPECIES_VENUSAUR_GIGANTAMAX; } GIVEN { - PLAYER(SPECIES_VENUSAUR); + PLAYER(SPECIES_VENUSAUR) { GigantamaxFactor(gigantamaxFactor); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { TURN { MOVE(player, MOVE_TACKLE, dynamax: TRUE); } } THEN { - EXPECT_EQ(player->species, SPECIES_VENUSAUR_GIGANTAMAX); + EXPECT_EQ(player->species, species); } } @@ -870,7 +873,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Stonesurge sets up Stealth Rocks") { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_STONESURGE].argument == MAX_EFFECT_STEALTH_ROCK); - PLAYER(SPECIES_DREDNAW); + PLAYER(SPECIES_DREDNAW) { GigantamaxFactor(TRUE); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -890,7 +893,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Steelsurge sets up sharp steel") { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_STEELSURGE].argument == MAX_EFFECT_STEELSURGE); - PLAYER(SPECIES_COPPERAJAH); + PLAYER(SPECIES_COPPERAJAH) { GigantamaxFactor(TRUE); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_HATTERENE); } WHEN { @@ -921,7 +924,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) G-Max Hydrosnipe has fixed power and ignores abili PARAMETRIZE { move = MOVE_HYDRO_CANNON; } GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_HYDROSNIPE].argument == MAX_EFFECT_FIXED_POWER); - PLAYER(SPECIES_INTELEON); + PLAYER(SPECIES_INTELEON) { GigantamaxFactor(TRUE); } OPPONENT(SPECIES_ARCTOVISH) { Ability(ABILITY_WATER_ABSORB); } } WHEN { TURN { MOVE(player, move, dynamax: TRUE); } @@ -937,7 +940,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Volt Crash paralyzes both opponents") { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_VOLT_CRASH].argument == MAX_EFFECT_PARALYZE_FOES); - PLAYER(SPECIES_PIKACHU); + PLAYER(SPECIES_PIKACHU) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_PICHU); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); @@ -964,7 +967,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock paralyzes or poisons both opponen PARAMETRIZE { statusAnim = B_ANIM_STATUS_PSN; rng = STATUS1_POISON; } GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_STUN_SHOCK].argument == MAX_EFFECT_POISON_PARALYZE_FOES); - PLAYER(SPECIES_TOXTRICITY); + PLAYER(SPECIES_TOXTRICITY) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_TOXEL); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); @@ -1001,7 +1004,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Stun Shock chooses statuses before consideri { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_STUN_SHOCK].argument == MAX_EFFECT_POISON_PARALYZE_FOES); - PLAYER(SPECIES_TOXTRICITY); + PLAYER(SPECIES_TOXTRICITY) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_TOXEL); OPPONENT(SPECIES_GARBODOR); OPPONENT(SPECIES_TRUBBISH); @@ -1034,7 +1037,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Befuddle paralyzes, poisons, or sleeps both PARAMETRIZE { statusAnim = B_ANIM_STATUS_SLP; rng = STATUS1_SLEEP; } GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_BEFUDDLE].argument == MAX_EFFECT_EFFECT_SPORE_FOES); - PLAYER(SPECIES_BUTTERFREE); + PLAYER(SPECIES_BUTTERFREE) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_CATERPIE); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -1078,7 +1081,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Gold Rush confuses both opponents and genera { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_GOLD_RUSH].argument == MAX_EFFECT_CONFUSE_FOES_PAY_DAY); - PLAYER(SPECIES_MEOWTH); + PLAYER(SPECIES_MEOWTH) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_PERSIAN); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -1098,7 +1101,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Smite confuses both opponents") { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_SMITE].argument == MAX_EFFECT_CONFUSE_FOES); - PLAYER(SPECIES_HATTERENE); + PLAYER(SPECIES_HATTERENE) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_HATENNA); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -1117,7 +1120,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Cuddle infatuates both opponents, if possibl { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_CUDDLE].argument == MAX_EFFECT_INFATUATE_FOES); - PLAYER(SPECIES_EEVEE) { Gender(MON_MALE); } + PLAYER(SPECIES_EEVEE) { Gender(MON_MALE); GigantamaxFactor(TRUE); } PLAYER(SPECIES_EEVEE); OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_FEMALE); } OPPONENT(SPECIES_WOBBUFFET) { Gender(MON_MALE); } @@ -1138,7 +1141,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Terror traps both opponents") { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_TERROR].argument == MAX_EFFECT_MEAN_LOOK); - PLAYER(SPECIES_GENGAR); + PLAYER(SPECIES_GENGAR) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_GASTLY); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -1157,7 +1160,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Meltdown torments both opponents for 3 turns { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_MELTDOWN].argument == MAX_EFFECT_TORMENT_FOES); - PLAYER(SPECIES_MELMETAL); + PLAYER(SPECIES_MELMETAL) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_MELTAN); OPPONENT(SPECIES_WOBBUFFET) { Moves(MOVE_SPLASH, MOVE_CELEBRATE); } OPPONENT(SPECIES_WYNAUT) { Moves(MOVE_SPLASH, MOVE_CELEBRATE); } @@ -1194,7 +1197,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Wildfire sets a field effect that damages no s16 damage; GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_WILDFIRE].argument == MAX_EFFECT_WILDFIRE); - PLAYER(SPECIES_CHARIZARD); + PLAYER(SPECIES_CHARIZARD) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_CHARMANDER); OPPONENT(SPECIES_WOBBUFFET) { HP(600); MaxHP(600); } OPPONENT(SPECIES_WYNAUT); @@ -1240,7 +1243,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Replenish recycles allies' berries 50\% of t PASSES_RANDOMLY(1, 2, RNG_G_MAX_REPLENISH); GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_REPLENISH].argument == MAX_EFFECT_RECYCLE_BERRIES); - PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); } + PLAYER(SPECIES_SNORLAX) { Item(ITEM_APICOT_BERRY); GigantamaxFactor(TRUE); } PLAYER(SPECIES_MUNCHLAX) { Item(ITEM_APICOT_BERRY); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); } OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_APICOT_BERRY); } @@ -1268,7 +1271,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Snooze makes only the target drowsy") PASSES_RANDOMLY(1, 2, RNG_G_MAX_SNOOZE); GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_SNOOZE].argument == MAX_EFFECT_YAWN_FOE); - PLAYER(SPECIES_GRIMMSNARL); + PLAYER(SPECIES_GRIMMSNARL) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_IMPIDIMP); OPPONENT(SPECIES_BLISSEY); OPPONENT(SPECIES_CHANSEY); @@ -1291,7 +1294,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Finale heals allies by 1/6 of their health") s16 damage1, damage2; GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_FINALE].argument == MAX_EFFECT_HEAL_TEAM); - PLAYER(SPECIES_ALCREMIE) { HP(1); } + PLAYER(SPECIES_ALCREMIE) { HP(1); GigantamaxFactor(TRUE); } PLAYER(SPECIES_MILCERY) { HP(1); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -1311,7 +1314,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Sweetness cures allies' status conditions") { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_SWEETNESS].argument == MAX_EFFECT_AROMATHERAPY); - PLAYER(SPECIES_APPLETUN) { Status1(STATUS1_POISON); } + PLAYER(SPECIES_APPLETUN) { Status1(STATUS1_POISON); GigantamaxFactor(TRUE); } PLAYER(SPECIES_APPLIN) { Status1(STATUS1_POISON); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -1331,7 +1334,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Centiferno traps both opponents in Fire Spin { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_CENTIFERNO].argument == MAX_EFFECT_FIRE_SPIN_FOES); - PLAYER(SPECIES_CENTISKORCH); + PLAYER(SPECIES_CENTISKORCH) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_SIZZLIPEDE); PLAYER(SPECIES_SIZZLIPEDE); OPPONENT(SPECIES_WOBBUFFET); @@ -1360,7 +1363,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Chi Strike boosts allies' crit chance") GIVEN { ASSUME(B_CRIT_CHANCE >= GEN_6); ASSUME(gBattleMoves[MOVE_G_MAX_CHI_STRIKE].argument == MAX_EFFECT_CRIT_PLUS); - PLAYER(SPECIES_MACHAMP); + PLAYER(SPECIES_MACHAMP) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_MACHOP); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -1389,7 +1392,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max Depletion takes away 2 PP from the target's { GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_DEPLETION].argument == MAX_EFFECT_SPITE); - PLAYER(SPECIES_DURALUDON); + PLAYER(SPECIES_DURALUDON) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_WYNAUT); // Dynamax behaves weird with test turn order because stats are recalculated. OPPONENT(SPECIES_SABLEYE) { Ability(ABILITY_PRANKSTER); } @@ -1411,7 +1414,7 @@ DOUBLE_BATTLE_TEST("(DYNAMAX) G-Max One Blow bypasses Max Guard for full damage" PARAMETRIZE { protect = FALSE; } GIVEN { ASSUME(gBattleMoves[MOVE_G_MAX_ONE_BLOW].argument == MAX_EFFECT_BYPASS_PROTECT); - PLAYER(SPECIES_URSHIFU); + PLAYER(SPECIES_URSHIFU) { GigantamaxFactor(TRUE); } PLAYER(SPECIES_KUBFU); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); diff --git a/test/pokemon.c b/test/pokemon.c new file mode 100644 index 0000000000..05d6ac15e5 --- /dev/null +++ b/test/pokemon.c @@ -0,0 +1,182 @@ +#include "global.h" +#include "battle.h" +#include "event_data.h" +#include "pokemon.h" +#include "test/overworld_script.h" +#include "test/test.h" + +TEST("Nature independent from Hidden Nature") +{ + u32 i, j, nature = 0, hiddenNature = 0; + struct Pokemon mon; + for (i = 0; i < NUM_NATURES; i++) + { + for (j = 0; j < NUM_NATURES; j++) + { + PARAMETRIZE { nature = i; hiddenNature = j; } + } + } + CreateMonWithNature(&mon, SPECIES_WOBBUFFET, 100, 0, nature); + SetMonData(&mon, MON_DATA_HIDDEN_NATURE, &hiddenNature); + EXPECT_EQ(GetNature(&mon), nature); + EXPECT_EQ(GetMonData(&mon, MON_DATA_HIDDEN_NATURE), hiddenNature); +} + +TEST("Terastallization type defaults to primary or secondary type") +{ + u32 i, teraType; + struct Pokemon mon; + for (i = 0; i < 128; i++) PARAMETRIZE {} + CreateMon(&mon, SPECIES_PIDGEY, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + teraType = GetMonData(&mon, MON_DATA_TERA_TYPE); + EXPECT(teraType == gSpeciesInfo[SPECIES_PIDGEY].types[0] + || teraType == gSpeciesInfo[SPECIES_PIDGEY].types[1]); +} + +TEST("Terastallization type can be set to any type") +{ + u32 i, teraType; + struct Pokemon mon; + for (i = 0; i < NUMBER_OF_MON_TYPES; i++) + { + PARAMETRIZE { teraType = i; } + } + CreateMon(&mon, SPECIES_WOBBUFFET, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + SetMonData(&mon, MON_DATA_TERA_TYPE, &teraType); + EXPECT_EQ(teraType, GetMonData(&mon, MON_DATA_TERA_TYPE)); +} + +TEST("Shininess independent from PID and OTID") +{ + u32 pid, otId, data; + bool32 isShiny; + struct Pokemon mon; + PARAMETRIZE { pid = 0; otId = 0; } + CreateMon(&mon, SPECIES_WOBBUFFET, 100, 0, TRUE, pid, OT_ID_PRESET, otId); + isShiny = IsMonShiny(&mon); + data = !isShiny; + SetMonData(&mon, MON_DATA_IS_SHINY, &data); + EXPECT_EQ(pid, GetMonData(&mon, MON_DATA_PERSONALITY)); + EXPECT_EQ(otId, GetMonData(&mon, MON_DATA_OT_ID)); + EXPECT_EQ(!isShiny, GetMonData(&mon, MON_DATA_IS_SHINY)); +} + +TEST("Hyper Training increases stats without affecting IVs") +{ + u32 data, hp, atk, def, speed, spatk, spdef; + struct Pokemon mon; + CreateMon(&mon, SPECIES_WOBBUFFET, 100, 3, TRUE, 0, OT_ID_PRESET, 0); + + hp = GetMonData(&mon, MON_DATA_HP); + atk = GetMonData(&mon, MON_DATA_ATK); + def = GetMonData(&mon, MON_DATA_DEF); + speed = GetMonData(&mon, MON_DATA_SPEED); + spatk = GetMonData(&mon, MON_DATA_SPATK); + spdef = GetMonData(&mon, MON_DATA_SPDEF); + + data = TRUE; + SetMonData(&mon, MON_DATA_HYPER_TRAINED_HP, &data); + SetMonData(&mon, MON_DATA_HYPER_TRAINED_ATK, &data); + SetMonData(&mon, MON_DATA_HYPER_TRAINED_DEF, &data); + SetMonData(&mon, MON_DATA_HYPER_TRAINED_SPEED, &data); + SetMonData(&mon, MON_DATA_HYPER_TRAINED_SPATK, &data); + SetMonData(&mon, MON_DATA_HYPER_TRAINED_SPDEF, &data); + CalculateMonStats(&mon); + + EXPECT_EQ(GetMonData(&mon, MON_DATA_HP_IV), 3); + EXPECT_EQ(GetMonData(&mon, MON_DATA_ATK_IV), 3); + EXPECT_EQ(GetMonData(&mon, MON_DATA_DEF_IV), 3); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPEED_IV), 3); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPATK_IV), 3); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPDEF_IV), 3); + EXPECT_EQ(GetMonData(&mon, MON_DATA_SPEED_IV), 3); + + EXPECT_EQ(hp - 3 + MAX_PER_STAT_IVS, GetMonData(&mon, MON_DATA_HP)); + EXPECT_EQ(atk - 3 + MAX_PER_STAT_IVS, GetMonData(&mon, MON_DATA_ATK)); + EXPECT_EQ(def - 3 + MAX_PER_STAT_IVS, GetMonData(&mon, MON_DATA_DEF)); + EXPECT_EQ(speed - 3 + MAX_PER_STAT_IVS, GetMonData(&mon, MON_DATA_SPEED)); + EXPECT_EQ(spatk - 3 + MAX_PER_STAT_IVS, GetMonData(&mon, MON_DATA_SPATK)); + EXPECT_EQ(spdef - 3 + MAX_PER_STAT_IVS, GetMonData(&mon, MON_DATA_SPDEF)); +} + +TEST("Status1 round-trips through BoxPokemon") +{ + u32 status1; + struct Pokemon mon1, mon2; + PARAMETRIZE { status1 = STATUS1_NONE; } + PARAMETRIZE { status1 = STATUS1_SLEEP_TURN(1); } + PARAMETRIZE { status1 = STATUS1_SLEEP_TURN(2); } + PARAMETRIZE { status1 = STATUS1_SLEEP_TURN(3); } + PARAMETRIZE { status1 = STATUS1_SLEEP_TURN(4); } + PARAMETRIZE { status1 = STATUS1_SLEEP_TURN(5); } + PARAMETRIZE { status1 = STATUS1_POISON; } + PARAMETRIZE { status1 = STATUS1_BURN; } + PARAMETRIZE { status1 = STATUS1_FREEZE; } + PARAMETRIZE { status1 = STATUS1_PARALYSIS; } + PARAMETRIZE { status1 = STATUS1_TOXIC_POISON; } + PARAMETRIZE { status1 = STATUS1_FROSTBITE; } + CreateMon(&mon1, SPECIES_WOBBUFFET, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + SetMonData(&mon1, MON_DATA_STATUS, &status1); + BoxMonToMon(&mon1.box, &mon2); + EXPECT_EQ(GetMonData(&mon2, MON_DATA_STATUS), status1); +} + +TEST("canhypertrain/hypertrain affect MON_DATA_HYPER_TRAINED_* and recalculate stats") +{ + u32 atk; + CreateMon(&gPlayerParty[0], SPECIES_WOBBUFFET, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + atk = GetMonData(&gPlayerParty[0], MON_DATA_ATK); + + RUN_OVERWORLD_SCRIPT( + canhypertrain STAT_ATK, 0; + ); + EXPECT(VarGet(VAR_RESULT)); + + RUN_OVERWORLD_SCRIPT( + hypertrain STAT_ATK, 0; + canhypertrain STAT_ATK, 0; + ); + EXPECT(GetMonData(&gPlayerParty[0], MON_DATA_HYPER_TRAINED_ATK)); + EXPECT_EQ(atk + 31, GetMonData(&gPlayerParty[0], MON_DATA_ATK)); + EXPECT(!VarGet(VAR_RESULT)); +} + +TEST("hasgigantamaxfactor/togglegigantamaxfactor affect MON_DATA_GIGANTAMAX_FACTOR") +{ + CreateMon(&gPlayerParty[0], SPECIES_WOBBUFFET, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + + RUN_OVERWORLD_SCRIPT( + hasgigantamaxfactor 0; + ); + EXPECT(!VarGet(VAR_RESULT)); + + RUN_OVERWORLD_SCRIPT( + togglegigantamaxfactor 0; + hasgigantamaxfactor 0; + ); + EXPECT(VarGet(VAR_RESULT)); + EXPECT(GetMonData(&gPlayerParty[0], MON_DATA_GIGANTAMAX_FACTOR)); + + RUN_OVERWORLD_SCRIPT( + togglegigantamaxfactor 0; + hasgigantamaxfactor 0; + ); + EXPECT(!VarGet(VAR_RESULT)); + EXPECT(!GetMonData(&gPlayerParty[0], MON_DATA_GIGANTAMAX_FACTOR)); +} + +TEST("togglegigantamaxfactor fails for Melmetal") +{ + CreateMon(&gPlayerParty[0], SPECIES_MELMETAL, 100, 0, FALSE, 0, OT_ID_PRESET, 0); + + RUN_OVERWORLD_SCRIPT( + hasgigantamaxfactor 0; + ); + EXPECT(!VarGet(VAR_RESULT)); + + RUN_OVERWORLD_SCRIPT( + togglegigantamaxfactor 0; + ); + EXPECT(!VarGet(VAR_RESULT)); + EXPECT(!GetMonData(&gPlayerParty[0], MON_DATA_GIGANTAMAX_FACTOR)); +} diff --git a/test/species.c b/test/species.c index 9ea20638c8..d412dd005a 100644 --- a/test/species.c +++ b/test/species.c @@ -34,6 +34,8 @@ TEST("Form change tables contain only forms in the form species ID table") for (i = 0; formChangeTable[i].method != FORM_CHANGE_TERMINATOR; i++) { + if (formChangeTable[i].targetSpecies == SPECIES_NONE) + continue; for (j = 0; formSpeciesIdTable[j] != FORM_SPECIES_END; j++) { if (formChangeTable[i].targetSpecies == formSpeciesIdTable[j]) diff --git a/test/test_runner.c b/test/test_runner.c index 93d859654a..577ea1dbc1 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -398,11 +398,21 @@ static void FunctionTest_TearDown(void *data) FREE_AND_SET_NULL(gFunctionTestRunnerState); } +static bool32 FunctionTest_CheckProgress(void *data) +{ + bool32 madeProgress; + (void)data; + madeProgress = gFunctionTestRunnerState->checkProgressParameter < gFunctionTestRunnerState->runParameter; + gFunctionTestRunnerState->checkProgressParameter = gFunctionTestRunnerState->runParameter; + return madeProgress; +} + const struct TestRunner gFunctionTestRunner = { .setUp = FunctionTest_SetUp, .run = FunctionTest_Run, .tearDown = FunctionTest_TearDown, + .checkProgress = FunctionTest_CheckProgress, }; static void Assumptions_Run(void *data) diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 1528a3ccf9..caccdb2042 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1587,6 +1587,7 @@ static u32 GenerateNature(u32 nature, u32 offset) void ClosePokemon(u32 sourceLine) { s32 i; + u32 data; INVALID_IF(DATA.hasExplicitSpeeds && !(DATA.explicitSpeeds[DATA.currentSide] & (1 << DATA.currentPartyIndex)), "Speed required"); for (i = 0; i < STATE->battlersCount; i++) { @@ -1596,6 +1597,8 @@ void ClosePokemon(u32 sourceLine) INVALID_IF(GetMonData(DATA.currentMon, MON_DATA_HP) == 0, "Battlers cannot be fainted"); } } + data = FALSE; + SetMonData(DATA.currentMon, MON_DATA_IS_SHINY, &data); UpdateMonPersonality(&DATA.currentMon->box, GenerateNature(DATA.nature, DATA.gender % NUM_NATURES) | DATA.gender); DATA.currentMon = NULL; } @@ -1766,10 +1769,34 @@ void Status1_(u32 sourceLine, u32 status1) void OTName_(u32 sourceLine, const u8 *otName) { - INVALID_IF(!DATA.currentMon, "Traded outside of PLAYER/OPPONENT"); + INVALID_IF(!DATA.currentMon, "OTName outside of PLAYER/OPPONENT"); SetMonData(DATA.currentMon, MON_DATA_OT_NAME, &otName); } +void DynamaxLevel_(u32 sourceLine, u32 dynamaxLevel) +{ + INVALID_IF(!DATA.currentMon, "DynamaxLevel outside of PLAYER/OPPONENT"); + SetMonData(DATA.currentMon, MON_DATA_DYNAMAX_LEVEL, &dynamaxLevel); +} + +void GigantamaxFactor_(u32 sourceLine, bool32 gigantamaxFactor) +{ + INVALID_IF(!DATA.currentMon, "GigantamaxFactor outside of PLAYER/OPPONENT"); + SetMonData(DATA.currentMon, MON_DATA_GIGANTAMAX_FACTOR, &gigantamaxFactor); +} + +void TeraType_(u32 sourceLine, u32 teraType) +{ + INVALID_IF(!DATA.currentMon, "TeraType outside of PLAYER/OPPONENT"); + SetMonData(DATA.currentMon, MON_DATA_TERA_TYPE, &teraType); +} + +void Shadow_(u32 sourceLine, bool32 isShadow) +{ + INVALID_IF(!DATA.currentMon, "Shadow outside of PLAYER/OPPONENT"); + SetMonData(DATA.currentMon, MON_DATA_IS_SHADOW, &isShadow); +} + static const char *const sBattlerIdentifiersSingles[] = { "player", From f5e0b3df2317140d5d227815340eb19efbcd0e5a Mon Sep 17 00:00:00 2001 From: Frank DeBlasio <35279583+fdeblasio@users.noreply.github.com> Date: Wed, 27 Dec 2023 14:28:44 -0500 Subject: [PATCH 02/13] Changed SHINY_ODDS to FALSE in pokedex_plus_hgss.c (#3832) --- src/pokedex_plus_hgss.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index 27fac583ae..95c899edc4 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -4738,7 +4738,7 @@ static u32 GetPokedexMonPersonality(u16 species) static u16 CreateMonSpriteFromNationalDexNumberHGSS(u16 nationalNum, s16 x, s16 y, u16 paletteSlot) { nationalNum = NationalPokedexNumToSpeciesHGSS(nationalNum); - return CreateMonPicSprite(nationalNum, SHINY_ODDS, GetPokedexMonPersonality(nationalNum), TRUE, x, y, paletteSlot, TAG_NONE); + return CreateMonPicSprite(nationalNum, FALSE, GetPokedexMonPersonality(nationalNum), TRUE, x, y, paletteSlot, TAG_NONE); } static u16 GetPokemonScaleFromNationalDexNumber(u16 nationalNum) From 3e321d11726cf0cff479c34963cdf6cf1d0b74e2 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Wed, 27 Dec 2023 21:35:42 +0100 Subject: [PATCH 03/13] fix ally switch dig issue (#3835) --- src/battle_anim_effects_1.c | 8 ++++++++ test/battle/move_effect/ally_switch.c | 21 +++++++++++++++++++++ 2 files changed, 29 insertions(+) diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index d14005b1ae..abcdd44c35 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -6575,12 +6575,14 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId) SwapStructData(&gProtectStructs[battlerAtk], &gProtectStructs[battlerPartner], data, sizeof(struct ProtectStruct)); SwapStructData(&gBattleSpritesDataPtr->battlerData[battlerAtk], &gBattleSpritesDataPtr->battlerData[battlerPartner], data, sizeof(struct BattleSpriteInfo)); + SWAP(gBattleSpritesDataPtr->battlerData[battlerAtk].invisible, gBattleSpritesDataPtr->battlerData[battlerPartner].invisible, temp); SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp); SWAP(gTransformedShininess[battlerAtk], gTransformedShininess[battlerPartner], temp); SWAP(gStatuses3[battlerAtk], gStatuses3[battlerPartner], temp); SWAP(gStatuses4[battlerAtk], gStatuses4[battlerPartner], temp); SWAP(gBattleStruct->chosenMovePositions[battlerAtk], gBattleStruct->chosenMovePositions[battlerPartner], temp); SWAP(gChosenMoveByBattler[battlerAtk], gChosenMoveByBattler[battlerPartner], temp); + SWAP(gLockedMoves[battlerAtk], gLockedMoves[battlerPartner], temp); SWAP(gBattleStruct->moveTarget[battlerAtk], gBattleStruct->moveTarget[battlerPartner], temp); SWAP(gMoveSelectionCursor[battlerAtk], gMoveSelectionCursor[battlerPartner], temp); // Swap turn order, so that all the battlers take action @@ -6688,6 +6690,12 @@ void AnimTask_AllySwitchAttacker(u8 taskId) PrepareDoubleTeamAnim(taskId, ANIM_ATTACKER, TRUE); gSprites[gBattlerSpriteIds[gBattlerAttacker]].invisible = TRUE; gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattlerAttacker)]].invisible = TRUE; + // Edge case: Partner's sprite is invisible(i.e. after using Dig). + if (gBattleSpritesDataPtr->battlerData[BATTLE_PARTNER(gBattlerAttacker)].invisible) + { + gBattleSpritesDataPtr->battlerData[BATTLE_PARTNER(gBattlerAttacker)].invisible = FALSE; + gBattleSpritesDataPtr->battlerData[gBattlerAttacker].invisible = TRUE; + } } void AnimTask_AllySwitchPartner(u8 taskId) diff --git a/test/battle/move_effect/ally_switch.c b/test/battle/move_effect/ally_switch.c index 3271fd0cbe..bbfb774539 100644 --- a/test/battle/move_effect/ally_switch.c +++ b/test/battle/move_effect/ally_switch.c @@ -207,3 +207,24 @@ DOUBLE_BATTLE_TEST("Ally Switch increases the Protect-like moves counter") EXPECT(gDisableStructs[B_POSITION_PLAYER_RIGHT].protectUses == 1); } } + +DOUBLE_BATTLE_TEST("Ally Switch works if ally used two-turn move like Dig") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerRight, MOVE_DIG, target:opponentRight); } + TURN { MOVE(playerLeft, MOVE_ALLY_SWITCH); SKIP_TURN(playerRight); } + } SCENE { + MESSAGE("Wynaut used Dig!"); + MESSAGE("Wobbuffet used Ally Switch!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_ALLY_SWITCH, playerLeft); + MESSAGE("Wobbuffet and Wynaut switched places!"); + NOT MESSAGE("Wynaut used -!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DIG); + HP_BAR(opponentRight); + } +} From 88b0bd639421d562cf69cc97eb3900d961153831 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Wed, 27 Dec 2023 22:48:56 +0100 Subject: [PATCH 04/13] Add gen9 item prices + configs (#3834) * Add gen9 item prices + configs * Adjust gen 1 PP item costs --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- include/config/item.h | 2 + include/item.h | 2 +- src/data/items.h | 753 +++++++++++++++++++++--------------------- src/item.c | 2 +- 4 files changed, 383 insertions(+), 376 deletions(-) diff --git a/include/config/item.h b/include/config/item.h index 195a78e457..4ab75611cb 100644 --- a/include/config/item.h +++ b/include/config/item.h @@ -14,6 +14,8 @@ #define I_USE_EVO_HELD_ITEMS_FROM_BAG FALSE // If TRUE, items such as Razor Claw or Electirizer will be usable from the bag to evolve a Pokémon just like in LA. #define I_TYPE_BOOST_POWER GEN_LATEST // In Gen4+, all regular type boosting held items had their power increased from 10% to 20%. eg. Charcoal #define I_SELL_VALUE_FRACTION GEN_LATEST // In Gen9+, items sell for 1/4 of their value instead of 1/2. +#define I_PRICE GEN_LATEST // Some items have varied in value across generations. +#define I_BERRY_PRICE GEN_7 // Since Berries have become unplantable (Gen8+), their price has gone up. // TM config #define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1. diff --git a/include/item.h b/include/item.h index da6faa4864..33f8ea9ee0 100644 --- a/include/item.h +++ b/include/item.h @@ -62,7 +62,7 @@ u16 CountTotalItemQuantityInBag(u16 itemId); bool8 AddPyramidBagItem(u16 itemId, u16 count); bool8 RemovePyramidBagItem(u16 itemId, u16 count); const u8 *ItemId_GetName(u16 itemId); -u16 ItemId_GetPrice(u16 itemId); +u32 ItemId_GetPrice(u16 itemId); u32 ItemId_GetHoldEffect(u32 itemId); u32 ItemId_GetHoldEffectParam(u32 itemId); const u8 *ItemId_GetDescription(u16 itemId); diff --git a/src/data/items.h b/src/data/items.h index 7c1f3e2472..457e00a058 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -22,6 +22,8 @@ #define X_ITEM_STAGES (B_X_ITEMS_BUFF >= GEN_7) ? 2 : 1 +#define TREASURE_FACTOR (I_SELL_VALUE_FRACTION >= GEN_9) ? 2: 1 + // Shared Item Description entries static const u8 sFullHealDesc[] = _("Heals all the\n" @@ -185,7 +187,7 @@ const struct Item gItems[] = [ITEM_ULTRA_BALL] = { .name = _("Ultra Ball"), - .price = 800, + .price = (I_PRICE >= GEN_7) ? 800 : 1200, .description = COMPOUND_STRING("A better Ball with\n" "a higher catch rate\n" "than a Great Ball."), @@ -211,7 +213,7 @@ const struct Item gItems[] = [ITEM_PREMIER_BALL] = { .name = _("Premier Ball"), - .price = 20, + .price = (I_PRICE >= GEN_7) ? 20 : 200, .description = COMPOUND_STRING("A rare Ball made\n" "in commemoration\n" "of some event."), @@ -328,7 +330,7 @@ const struct Item gItems[] = [ITEM_LUXURY_BALL] = { .name = _("Luxury Ball"), - .price = 1000, + .price = (I_PRICE >= GEN_8) ? 3000 : 1000, .description = COMPOUND_STRING("A cozy Ball that\n" "makes Pokémon\n" "more friendly."), @@ -341,7 +343,7 @@ const struct Item gItems[] = [ITEM_LEVEL_BALL] = { .name = _("Level Ball"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING("A Ball that works\n" "well on lower\n" "level Pokémon."), @@ -354,7 +356,7 @@ const struct Item gItems[] = [ITEM_LURE_BALL] = { .name = _("Lure Ball"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING("A Ball that works\n" "well on fished\n" "up Pokémon."), @@ -367,7 +369,7 @@ const struct Item gItems[] = [ITEM_MOON_BALL] = { .name = _("Moon Ball"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING("A Ball that works\n" "well on Moon\n" "Stone users."), @@ -380,7 +382,7 @@ const struct Item gItems[] = [ITEM_FRIEND_BALL] = { .name = _("Friend Ball"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING("A Ball that makes\n" "a Pokémon friendly\n" "when caught."), @@ -393,7 +395,7 @@ const struct Item gItems[] = [ITEM_LOVE_BALL] = { .name = _("Love Ball"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING("Works well on\n" "Pokémon of the\n" "opposite gender."), @@ -406,7 +408,7 @@ const struct Item gItems[] = [ITEM_FAST_BALL] = { .name = _("Fast Ball"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING("Works well on\n" "very fast\n" "Pokémon."), @@ -419,7 +421,7 @@ const struct Item gItems[] = [ITEM_HEAVY_BALL] = { .name = _("Heavy Ball"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 300, .description = COMPOUND_STRING("Works well on\n" "very heavy\n" "Pokémon."), @@ -463,7 +465,7 @@ const struct Item gItems[] = [ITEM_SPORT_BALL] = { .name = _("Sport Ball"), - .price = 0, + .price = (I_PRICE < GEN_3 || I_PRICE >= GEN_9) ? 0 : 300, .description = COMPOUND_STRING("A special Ball used\n" "in the Bug-Catching\n" "Contest."), @@ -515,7 +517,7 @@ const struct Item gItems[] = [ITEM_POTION] = { .name = _("Potion"), - .price = 200, + .price = (I_PRICE >= GEN_7) ? 200 : 300, .holdEffectParam = 20, .description = COMPOUND_STRING("Restores the HP of\n" "a Pokémon by\n" @@ -551,7 +553,7 @@ const struct Item gItems[] = [ITEM_HYPER_POTION] = { .name = _("Hyper Potion"), - .price = 1500, + .price = (I_PRICE >= GEN_2 || I_PRICE <= GEN_6) ? 1200 : 1500, .holdEffectParam = 120, #if I_HEALTH_RECOVERY >= GEN_7 .description = COMPOUND_STRING("Restores the HP of\n" @@ -601,7 +603,7 @@ const struct Item gItems[] = [ITEM_REVIVE] = { .name = _("Revive"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 1500, .description = COMPOUND_STRING("Revives a fainted\n" "Pokémon with half\n" "its HP."), @@ -669,7 +671,7 @@ const struct Item gItems[] = [ITEM_LEMONADE] = { .name = _("Lemonade"), - .price = 400, + .price = (I_PRICE >= GEN_7) ? 400 : 350, .holdEffectParam = 70, #if I_HEALTH_RECOVERY >= GEN_7 .description = COMPOUND_STRING("A very sweet drink\n" @@ -690,7 +692,7 @@ const struct Item gItems[] = [ITEM_MOOMOO_MILK] = { .name = _("Moomoo Milk"), - .price = 600, + .price = (I_PRICE >= GEN_7) ? 600 : 500, .holdEffectParam = 100, .description = COMPOUND_STRING("A nutritious milk\n" "that restores HP\n" @@ -725,7 +727,7 @@ const struct Item gItems[] = [ITEM_ENERGY_ROOT] = { .name = _("Energy Root"), - .price = 1200, + .price = (I_PRICE >= GEN_7) ? 1200 : 800, #if I_HEALTH_RECOVERY >= GEN_7 .description = COMPOUND_STRING("A bitter root\n" "that restores HP\n" @@ -745,7 +747,7 @@ const struct Item gItems[] = [ITEM_HEAL_POWDER] = { .name = _("Heal Powder"), - .price = 300, + .price = (I_PRICE >= GEN_7) ? 300 : 450, .description = COMPOUND_STRING("A bitter powder\n" "that heals all\n" "status problems."), @@ -773,7 +775,7 @@ const struct Item gItems[] = [ITEM_ANTIDOTE] = { .name = _("Antidote"), - .price = 200, + .price = (I_PRICE >= GEN_7) ? 200 : 100, .description = COMPOUND_STRING("Heals a poisoned\n" "Pokémon."), .pocket = POCKET_ITEMS, @@ -786,7 +788,7 @@ const struct Item gItems[] = [ITEM_PARALYZE_HEAL] = { .name = _("Paralyze Heal"), - .price = 300, + .price = (I_PRICE == GEN_7) ? 300 : 200, .description = COMPOUND_STRING("Heals a paralyzed\n" "Pokémon."), .pocket = POCKET_ITEMS, @@ -799,7 +801,7 @@ const struct Item gItems[] = [ITEM_BURN_HEAL] = { .name = _("Burn Heal"), - .price = 300, + .price = (I_PRICE == GEN_7) ? 300 : ((I_PRICE <= GEN_7) ? 250 : 200), .description = COMPOUND_STRING("Heals Pokémon\n" "of a burn."), .pocket = POCKET_ITEMS, @@ -812,7 +814,7 @@ const struct Item gItems[] = [ITEM_ICE_HEAL] = { .name = _("Ice Heal"), - .price = 100, + .price = (I_PRICE == GEN_7) ? 100 : ((I_PRICE <= GEN_7) ? 250 : 200), .description = COMPOUND_STRING("Defrosts a frozen\n" "Pokémon."), .pocket = POCKET_ITEMS, @@ -825,7 +827,7 @@ const struct Item gItems[] = [ITEM_AWAKENING] = { .name = _("Awakening"), - .price = 100, + .price = (I_PRICE >= GEN_2 && I_PRICE <= GEN_6) ? 250 : ((I_PRICE == GEN_7) ? 100 : 200), .description = COMPOUND_STRING("Awakens a sleeping\n" "Pokémon."), .pocket = POCKET_ITEMS, @@ -838,7 +840,7 @@ const struct Item gItems[] = [ITEM_FULL_HEAL] = { .name = _("Full Heal"), - .price = 400, + .price = (I_PRICE >= GEN_7) ? 400 : 600, .description = sFullHealDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -850,7 +852,7 @@ const struct Item gItems[] = [ITEM_ETHER] = { .name = _("Ether"), - .price = 1200, + .price = (I_PRICE >= GEN_2) ? 1200 : 1, .holdEffectParam = 10, .description = COMPOUND_STRING("Restores the PP\n" "of a selected move\n" @@ -865,7 +867,7 @@ const struct Item gItems[] = [ITEM_MAX_ETHER] = { .name = _("Max Ether"), - .price = 2000, + .price = (I_PRICE >= GEN_2) ? 2000 : 1, .holdEffectParam = 255, .description = COMPOUND_STRING("Fully restores the\n" "PP of a selected\n" @@ -880,7 +882,7 @@ const struct Item gItems[] = [ITEM_ELIXIR] = { .name = _("Elixir"), - .price = 3000, + .price = (I_PRICE >= GEN_2) ? 3000 : 1, .holdEffectParam = 10, .description = COMPOUND_STRING("Restores the PP\n" "of all moves by 10."), @@ -894,7 +896,7 @@ const struct Item gItems[] = [ITEM_MAX_ELIXIR] = { .name = _("Max Elixir"), - .price = 4500, + .price = (I_PRICE >= GEN_2) ? 4500 : 1, .holdEffectParam = 255, .description = COMPOUND_STRING("Fully restores the\n" "PP of a Pokémon's\n" @@ -909,7 +911,7 @@ const struct Item gItems[] = [ITEM_BERRY_JUICE] = { .name = _("Berry Juice"), - .price = 200, + .price = 100, .holdEffect = HOLD_EFFECT_RESTORE_HP, .holdEffectParam = 20, .description = COMPOUND_STRING("A 100% pure juice\n" @@ -925,7 +927,7 @@ const struct Item gItems[] = [ITEM_SACRED_ASH] = { .name = _("Sacred Ash"), - .price = 50000, + .price = (I_PRICE >= GEN_7) ? 50000 : 200, .description = COMPOUND_STRING("Fully revives and\n" "restores all\n" "fainted Pokémon."), @@ -938,7 +940,7 @@ const struct Item gItems[] = [ITEM_SWEET_HEART] = { .name = _("Sweet Heart"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 100, .holdEffectParam = 20, .description = COMPOUND_STRING("A sweet chocolate\n" "that restores HP\n" @@ -979,7 +981,7 @@ const struct Item gItems[] = [ITEM_RAGE_CANDY_BAR] = { .name = _("RageCandyBar"), - .price = 350, + .price = (I_PRICE >= GEN_7) ? 350 : 300, .description = sFullHealDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -991,7 +993,7 @@ const struct Item gItems[] = [ITEM_LAVA_COOKIE] = { .name = _("Lava Cookie"), - .price = 350, + .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = COMPOUND_STRING("A local specialty\n" "that heals all\n" "status problems."), @@ -1005,7 +1007,7 @@ const struct Item gItems[] = [ITEM_OLD_GATEAU] = { .name = _("Old Gateau"), - .price = 350, + .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1017,7 +1019,7 @@ const struct Item gItems[] = [ITEM_CASTELIACONE] = { .name = _("Casteliacone"), - .price = 350, + .price = (I_PRICE >= GEN_7) ? 350 : 100, .description = sFullHealDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1029,7 +1031,7 @@ const struct Item gItems[] = [ITEM_LUMIOSE_GALETTE] = { .name = _("LumioseGlete"), - .price = 350, + .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1041,7 +1043,7 @@ const struct Item gItems[] = [ITEM_SHALOUR_SABLE] = { .name = _("ShalourSable"), - .price = 350, + .price = (I_PRICE >= GEN_7) ? 350 : 200, .description = sFullHealDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1067,7 +1069,7 @@ const struct Item gItems[] = [ITEM_HP_UP] = { .name = _("HP Up"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING("Raises the base HP\n" "of one Pokémon."), .pocket = POCKET_ITEMS, @@ -1079,7 +1081,7 @@ const struct Item gItems[] = [ITEM_PROTEIN] = { .name = _("Protein"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING("Raises the base\n" "Attack stat of one\n" "Pokémon."), @@ -1092,7 +1094,7 @@ const struct Item gItems[] = [ITEM_IRON] = { .name = _("Iron"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING("Raises the base\n" "Defense stat of\n" "one Pokémon."), @@ -1105,7 +1107,7 @@ const struct Item gItems[] = [ITEM_CALCIUM] = { .name = _("Calcium"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING("Raises the base\n" "Sp. Atk stat of one\n" "Pokémon."), @@ -1118,7 +1120,7 @@ const struct Item gItems[] = [ITEM_ZINC] = { .name = _("Zinc"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING("Raises the base\n" "Sp. Def stat of one\n" "Pokémon."), @@ -1131,7 +1133,7 @@ const struct Item gItems[] = [ITEM_CARBOS] = { .name = _("Carbos"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING("Raises the base\n" "Speed stat of one\n" "Pokémon."), @@ -1144,7 +1146,7 @@ const struct Item gItems[] = [ITEM_PP_UP] = { .name = _("PP Up"), - .price = 10000, + .price = (I_PRICE == GEN_1) ? 1 : ((I_PRICE >= GEN_7) ? 10000 : 9800), .description = COMPOUND_STRING("Raises the maximum\n" "PP of a selected\n" "move."), @@ -1157,7 +1159,7 @@ const struct Item gItems[] = [ITEM_PP_MAX] = { .name = _("PP Max"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 9800, .description = COMPOUND_STRING("Raises the PP of a\n" "move to its maximum\n" "points."), @@ -1172,7 +1174,7 @@ const struct Item gItems[] = [ITEM_HEALTH_FEATHER] = { .name = _("HealthFeather"), - .price = 300, + .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sHealthFeatherDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1183,7 +1185,7 @@ const struct Item gItems[] = [ITEM_MUSCLE_FEATHER] = { .name = _("MuscleFeather"), - .price = 300, + .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sMuscleFeatherDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1194,7 +1196,7 @@ const struct Item gItems[] = [ITEM_RESIST_FEATHER] = { .name = _("ResistFeather"), - .price = 300, + .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sResistFeatherDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1205,7 +1207,7 @@ const struct Item gItems[] = [ITEM_GENIUS_FEATHER] = { .name = _("GeniusFeather"), - .price = 300, + .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sGeniusFeatherDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1216,7 +1218,7 @@ const struct Item gItems[] = [ITEM_CLEVER_FEATHER] = { .name = _("CleverFeather"), - .price = 300, + .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sCleverFeatherDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1227,7 +1229,7 @@ const struct Item gItems[] = [ITEM_SWIFT_FEATHER] = { .name = _("SwiftFeather"), - .price = 300, + .price = (I_PRICE >= GEN_7) ? 300 : 3000, .description = sSwiftFeatherDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -1240,7 +1242,7 @@ const struct Item gItems[] = [ITEM_ABILITY_CAPSULE] = { .name = _("AbilityCapsle"), - .price = 10000, + .price = (I_PRICE < GEN_7) ? 1000 : ((I_PRICE < GEN_9) ? 10000 : 100000), .holdEffectParam = 0, .description = COMPOUND_STRING("Switches a Poké-\n" "mon's ability."), @@ -1252,7 +1254,7 @@ const struct Item gItems[] = [ITEM_ABILITY_PATCH] = { .name = _("AbilityPatch"), - .price = 0, + .price = (I_PRICE >= GEN_9) ? 250000 : 20, .holdEffectParam = 0, .description = COMPOUND_STRING("Turns the ability\n" "of a Pokémon into\n" @@ -1267,7 +1269,7 @@ const struct Item gItems[] = [ITEM_LONELY_MINT] = { .name = _("Lonely Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Attack, but\n" "reduces Defense."), @@ -1281,7 +1283,7 @@ const struct Item gItems[] = [ITEM_ADAMANT_MINT] = { .name = _("Adamant Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Attack, but\n" "reduces Sp. Atk."), @@ -1295,7 +1297,7 @@ const struct Item gItems[] = [ITEM_NAUGHTY_MINT] = { .name = _("Naughty Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Attack, but\n" "reduces Sp. Def."), @@ -1309,7 +1311,7 @@ const struct Item gItems[] = [ITEM_BRAVE_MINT] = { .name = _("Brave Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Attack, but\n" "reduces Speed."), @@ -1323,7 +1325,7 @@ const struct Item gItems[] = [ITEM_BOLD_MINT] = { .name = _("Bold Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Defense, but\n" "reduces Attack."), @@ -1337,7 +1339,7 @@ const struct Item gItems[] = [ITEM_IMPISH_MINT] = { .name = _("Impish Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Defense, but\n" "reduces Sp. Atk."), @@ -1351,7 +1353,7 @@ const struct Item gItems[] = [ITEM_LAX_MINT] = { .name = _("Lax Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Defense, but\n" "reduces Sp. Def."), @@ -1365,7 +1367,7 @@ const struct Item gItems[] = [ITEM_RELAXED_MINT] = { .name = _("Relaxed Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Defense, but\n" "reduces Speed."), @@ -1379,7 +1381,7 @@ const struct Item gItems[] = [ITEM_MODEST_MINT] = { .name = _("Modest Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Sp. Atk, but\n" "reduces Attack."), @@ -1393,7 +1395,7 @@ const struct Item gItems[] = [ITEM_MILD_MINT] = { .name = _("Mild Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Sp. Atk, but\n" "reduces Defense."), @@ -1407,7 +1409,7 @@ const struct Item gItems[] = [ITEM_RASH_MINT] = { .name = _("Rash Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Sp. Atk, but\n" "reduces Sp. Def."), @@ -1421,7 +1423,7 @@ const struct Item gItems[] = [ITEM_QUIET_MINT] = { .name = _("Quiet Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Sp. Atk, but\n" "reduces Speed."), @@ -1435,7 +1437,7 @@ const struct Item gItems[] = [ITEM_CALM_MINT] = { .name = _("Calm Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Sp. Def, but\n" "reduces Attack."), @@ -1449,7 +1451,7 @@ const struct Item gItems[] = [ITEM_GENTLE_MINT] = { .name = _("Gentle Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Sp. Def, but\n" "reduces Defense."), @@ -1463,7 +1465,7 @@ const struct Item gItems[] = [ITEM_CAREFUL_MINT] = { .name = _("Careful Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Sp. Def, but\n" "reduces Sp. Atk."), @@ -1477,7 +1479,7 @@ const struct Item gItems[] = [ITEM_SASSY_MINT] = { .name = _("Sassy Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Sp. Def, but\n" "reduces Speed."), @@ -1491,7 +1493,7 @@ const struct Item gItems[] = [ITEM_TIMID_MINT] = { .name = _("Timid Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Speed, but\n" "reduces Attack."), @@ -1505,7 +1507,7 @@ const struct Item gItems[] = [ITEM_HASTY_MINT] = { .name = _("Hasty Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Speed, but\n" "reduces Defense."), @@ -1519,7 +1521,7 @@ const struct Item gItems[] = [ITEM_JOLLY_MINT] = { .name = _("Jolly Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Speed, but\n" "reduces Sp. Atk."), @@ -1533,7 +1535,7 @@ const struct Item gItems[] = [ITEM_NAIVE_MINT] = { .name = _("Naive Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "ups Speed, but\n" "reduces Sp. Def."), @@ -1547,7 +1549,7 @@ const struct Item gItems[] = [ITEM_SERIOUS_MINT] = { .name = _("Serious Mint"), - .price = 20, + .price = (I_PRICE >= GEN_9) ? 20000 : 20, .description = COMPOUND_STRING("Can be smelled. It\n" "makes each stat\n" "grow equally."), @@ -1563,7 +1565,7 @@ const struct Item gItems[] = [ITEM_RARE_CANDY] = { .name = _("Rare Candy"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 4800, .description = COMPOUND_STRING("Raises the level\n" "of a Pokémon by\n" "one."), @@ -1661,7 +1663,7 @@ const struct Item gItems[] = [ITEM_BLUE_FLUTE] = { .name = _("Blue Flute"), - .price = 20, + .price = (I_PRICE >= GEN_7) ? 20 : 100, .description = COMPOUND_STRING("A glass flute that\n" "awakens sleeping\n" "Pokémon."), @@ -1675,7 +1677,7 @@ const struct Item gItems[] = [ITEM_YELLOW_FLUTE] = { .name = _("Yellow Flute"), - .price = 20, + .price = (I_PRICE >= GEN_7) ? 20 : 300, .description = COMPOUND_STRING("A glass flute that\n" "snaps Pokémon\n" "out of confusion."), @@ -1689,7 +1691,7 @@ const struct Item gItems[] = [ITEM_RED_FLUTE] = { .name = _("Red Flute"), - .price = 20, + .price = (I_PRICE >= GEN_7) ? 20 : 200, .description = COMPOUND_STRING("A glass flute that\n" "snaps Pokémon\n" "out of attraction."), @@ -1705,7 +1707,7 @@ const struct Item gItems[] = [ITEM_BLACK_FLUTE] = { .name = _("Black Flute"), - .price = 20, + .price = (I_PRICE >= GEN_7) ? 20 : 400, .holdEffectParam = 50, .description = COMPOUND_STRING("A glass flute that\n" "keeps away wild\n" @@ -1719,7 +1721,7 @@ const struct Item gItems[] = [ITEM_WHITE_FLUTE] = { .name = _("White Flute"), - .price = 20, + .price = (I_PRICE >= GEN_7) ? 20 : 500, .holdEffectParam = 150, .description = COMPOUND_STRING("A glass flute that\n" "lures wild Pokémon."), @@ -1734,7 +1736,7 @@ const struct Item gItems[] = [ITEM_REPEL] = { .name = _("Repel"), - .price = 400, + .price = (I_PRICE >= GEN_7) ? 400 : 350, .holdEffectParam = 100, .description = COMPOUND_STRING("Repels weak wild\n" "Pokémon for 100\n" @@ -1748,7 +1750,7 @@ const struct Item gItems[] = [ITEM_SUPER_REPEL] = { .name = _("Super Repel"), - .price = 700, + .price = (I_PRICE >= GEN_7) ? 700 : 500, .holdEffectParam = 200, .description = COMPOUND_STRING("Repels weak wild\n" "Pokémon for 200\n" @@ -1762,7 +1764,7 @@ const struct Item gItems[] = [ITEM_MAX_REPEL] = { .name = _("Max Repel"), - .price = 900, + .price = (I_PRICE >= GEN_7) ? 900 : 700, .holdEffectParam = 250, .description = COMPOUND_STRING("Repels weak wild\n" "Pokémon for 250\n" @@ -1829,7 +1831,7 @@ const struct Item gItems[] = .importance = 1, .pocket = POCKET_KEY_ITEMS, #else - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 550, .pocket = POCKET_ITEMS, #endif .type = ITEM_USE_FIELD, @@ -1842,7 +1844,7 @@ const struct Item gItems[] = [ITEM_X_ATTACK] = { .name = _("X Attack"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 500, .holdEffectParam = X_ITEM_STAGES, #if B_X_ITEMS_BUFF >= GEN_7 .description = COMPOUND_STRING("Sharply raises stat\n" @@ -1863,7 +1865,7 @@ const struct Item gItems[] = [ITEM_X_DEFENSE] = { .name = _("X Defense"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 550, .holdEffectParam = X_ITEM_STAGES, #if B_X_ITEMS_BUFF >= GEN_7 .description = COMPOUND_STRING("Sharply raises stat\n" @@ -1884,7 +1886,7 @@ const struct Item gItems[] = [ITEM_X_SP_ATK] = { .name = _("X Sp. Atk"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 350, .holdEffectParam = X_ITEM_STAGES, #if B_X_ITEMS_BUFF >= GEN_7 .description = COMPOUND_STRING("Sharply raises stat\n" @@ -1905,7 +1907,7 @@ const struct Item gItems[] = [ITEM_X_SP_DEF] = { .name = _("X Sp. Def"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 350, .holdEffectParam = X_ITEM_STAGES, #if B_X_ITEMS_BUFF >= GEN_7 .description = COMPOUND_STRING("Sharply raises stat\n" @@ -1926,7 +1928,7 @@ const struct Item gItems[] = [ITEM_X_SPEED] = { .name = _("X Speed"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 350, .holdEffectParam = X_ITEM_STAGES, #if B_X_ITEMS_BUFF >= GEN_7 .description = COMPOUND_STRING("Sharply raises stat\n" @@ -1947,7 +1949,7 @@ const struct Item gItems[] = [ITEM_X_ACCURACY] = { .name = _("X Accuracy"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 950, .holdEffectParam = X_ITEM_STAGES, #if B_X_ITEMS_BUFF >= GEN_7 .description = COMPOUND_STRING("Sharply raises move\n" @@ -1968,7 +1970,7 @@ const struct Item gItems[] = [ITEM_DIRE_HIT] = { .name = _("Dire Hit"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 650, .description = COMPOUND_STRING("Raises the\n" "critical-hit ratio\n" "during one battle."), @@ -1982,7 +1984,7 @@ const struct Item gItems[] = [ITEM_GUARD_SPEC] = { .name = _("Guard Spec."), - .price = 1500, + .price = (I_PRICE >= GEN_7) ? 1500 : 700, .description = COMPOUND_STRING("Prevents stat\n" "reduction when\n" "used in battle."), @@ -1996,7 +1998,7 @@ const struct Item gItems[] = [ITEM_POKE_DOLL] = { .name = _("Poké Doll"), - .price = 100, + .price = (I_PRICE < GEN_7) ? 1000 : ((I_PRICE == GEN_7) ? 100 : 300), .description = sPokeDollDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2008,7 +2010,7 @@ const struct Item gItems[] = [ITEM_FLUFFY_TAIL] = { .name = _("Fluffy Tail"), - .price = 100, + .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2020,7 +2022,7 @@ const struct Item gItems[] = [ITEM_POKE_TOY] = { .name = _("Poké Toy"), - .price = 100, + .price = (I_PRICE >= GEN_7) ? 100 : 1000, .description = sPokeDollDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2048,7 +2050,7 @@ const struct Item gItems[] = [ITEM_BOTTLE_CAP] = { .name = _("Bottle Cap"), - .price = 5000, + .price = (I_PRICE >= GEN_9) ? 20000 : 5000, .description = COMPOUND_STRING("A beautiful bottle\n" "cap that gives off\n" "a silver gleam."), @@ -2061,7 +2063,7 @@ const struct Item gItems[] = [ITEM_GOLD_BOTTLE_CAP] = { .name = _("GoldBottlCap"), - .price = 10000, + .price = (I_PRICE >= GEN_9) ? 60000 : 10000, .description = COMPOUND_STRING("A beautiful bottle\n" "cap that gives off\n" "a golden gleam."), @@ -2087,7 +2089,7 @@ const struct Item gItems[] = [ITEM_BIG_NUGGET] = { .name = _("Big Nugget"), - .price = 40000, + .price = (I_PRICE >= GEN_7) ? (40000 * TREASURE_FACTOR) : 20000, .description = COMPOUND_STRING("A big nugget made\n" "of gold, sellable\n" "at a high price."), @@ -2113,7 +2115,7 @@ const struct Item gItems[] = [ITEM_BIG_MUSHROOM] = { .name = _("Big Mushroom"), - .price = 5000, + .price = 5000 * TREASURE_FACTOR, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2124,7 +2126,7 @@ const struct Item gItems[] = [ITEM_BALM_MUSHROOM] = { .name = _("Balm Mushroom"), - .price = 15000, + .price = (I_PRICE >= GEN_7) ? 15000 * TREASURE_FACTOR: 12500, .description = sBigMushroomDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2135,7 +2137,7 @@ const struct Item gItems[] = [ITEM_PEARL] = { .name = _("Pearl"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR: 1400, .description = COMPOUND_STRING("A pretty pearl\n" "that would sell at a\n" "cheap price."), @@ -2148,7 +2150,7 @@ const struct Item gItems[] = [ITEM_BIG_PEARL] = { .name = _("Big Pearl"), - .price = 8000, + .price = (I_PRICE >= GEN_7) ? 8000 * TREASURE_FACTOR: 7500, .description = COMPOUND_STRING("A lovely large pearl\n" "that would sell at a\n" "high price."), @@ -2161,7 +2163,7 @@ const struct Item gItems[] = [ITEM_PEARL_STRING] = { .name = _("Pearl String"), - .price = 20000, + .price = (I_PRICE >= GEN_8) ? 15000 * TREASURE_FACTOR: ((I_PRICE == GEN_7) ? 30000 : 15000), .description = COMPOUND_STRING("Very large pearls\n" "that would sell at a\n" "high price."), @@ -2174,7 +2176,7 @@ const struct Item gItems[] = [ITEM_STARDUST] = { .name = _("Stardust"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 * TREASURE_FACTOR: 2000, .description = COMPOUND_STRING("Beautiful red sand.\n" "Can be sold at a\n" "high price."), @@ -2187,7 +2189,7 @@ const struct Item gItems[] = [ITEM_STAR_PIECE] = { .name = _("Star Piece"), - .price = 12000, + .price = (I_PRICE >= GEN_7) ? 12000 * TREASURE_FACTOR: 9800, .description = COMPOUND_STRING("A red gem shard.\n" "It would sell for a\n" "very high price."), @@ -2200,7 +2202,7 @@ const struct Item gItems[] = [ITEM_COMET_SHARD] = { .name = _("Comet Shard"), - .price = 25000, + .price = (I_PRICE <= GEN_5) ? 0 : ((I_PRICE == GEN_6) ? 30000 : ((I_PRICE == GEN_7) ? 60000 : 25000 * TREASURE_FACTOR)), .description = COMPOUND_STRING("A comet's shard.\n" "It would sell for a\n" "high price."), @@ -2239,7 +2241,7 @@ const struct Item gItems[] = [ITEM_RED_SHARD] = { .name = _("Red Shard"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2250,7 +2252,7 @@ const struct Item gItems[] = [ITEM_BLUE_SHARD] = { .name = _("Blue Shard"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2261,7 +2263,7 @@ const struct Item gItems[] = [ITEM_YELLOW_SHARD] = { .name = _("Yellow Shard"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2272,7 +2274,7 @@ const struct Item gItems[] = [ITEM_GREEN_SHARD] = { .name = _("Green Shard"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 200, .description = sShardsDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, @@ -2296,7 +2298,7 @@ const struct Item gItems[] = [ITEM_HONEY] = { .name = _("Honey"), - .price = 300, + .price = (I_PRICE < GEN_5) ? 100 : ((I_PRICE < GEN_8) ? 300 : 900), .description = COMPOUND_STRING("Sweet honey that\n" "attracts wild\n" "Pokémon when used."), @@ -2309,7 +2311,7 @@ const struct Item gItems[] = [ITEM_RARE_BONE] = { .name = _("Rare Bone"), - .price = 5000, + .price = (I_PRICE >= GEN_7) ? 5000 * TREASURE_FACTOR: 10000, .description = COMPOUND_STRING("A very rare bone.\n" "It can be sold at\n" "a high price."), @@ -2335,7 +2337,7 @@ const struct Item gItems[] = [ITEM_PRETTY_FEATHER] = { .name = _("PrettyFeather"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 * TREASURE_FACTOR: 200, .description = COMPOUND_STRING("A beautiful yet\n" "plain feather that\n" "does nothing."), @@ -2439,7 +2441,7 @@ const struct Item gItems[] = [ITEM_STRANGE_SOUVENIR] = { .name = _("StrngeSouvnr"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 10, .description = COMPOUND_STRING("An ornament that\n" "depicts a Pokémon\n" "from Alola."), @@ -2458,7 +2460,7 @@ const struct Item gItems[] = "ancient marine\n" "Pokémon's seashell."), #if I_KEY_FOSSILS >= GEN_4 - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, #else .price = 0, @@ -2477,7 +2479,7 @@ const struct Item gItems[] = "ancient marine\n" "Pokémon's shell."), #if I_KEY_FOSSILS >= GEN_4 - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, #else .price = 0, @@ -2496,7 +2498,7 @@ const struct Item gItems[] = "the genes of an\n" "ancient Pokémon."), #if I_KEY_FOSSILS >= GEN_4 - .price = 10000, + .price = 1000, .pocket = POCKET_ITEMS, #else .price = 0, @@ -2513,7 +2515,7 @@ const struct Item gItems[] = .name = _("Root Fossil"), .description = sRootFossilDesc, #if I_KEY_FOSSILS >= GEN_4 - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, #else .price = 0, @@ -2530,7 +2532,7 @@ const struct Item gItems[] = .name = _("Claw Fossil"), .description = sRootFossilDesc, #if I_KEY_FOSSILS >= GEN_4 - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .pocket = POCKET_ITEMS, #else .price = 0, @@ -2545,7 +2547,7 @@ const struct Item gItems[] = [ITEM_ARMOR_FOSSIL] = { .name = _("Armor Fossil"), - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING("A piece of a\n" "prehistoric Poké-\n" "mon's head."), @@ -2558,7 +2560,7 @@ const struct Item gItems[] = [ITEM_SKULL_FOSSIL] = { .name = _("Skull Fossil"), - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING("A piece of a\n" "prehistoric Poké-\n" "mon's collar."), @@ -2571,7 +2573,7 @@ const struct Item gItems[] = [ITEM_COVER_FOSSIL] = { .name = _("Cover Fossil"), - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING("A piece of a\n" "prehistoric Poké-\n" "mon's back."), @@ -2584,7 +2586,7 @@ const struct Item gItems[] = [ITEM_PLUME_FOSSIL] = { .name = _("Plume Fossil"), - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING("A piece of a\n" "prehistoric Poké-\n" "mon's wing."), @@ -2597,7 +2599,7 @@ const struct Item gItems[] = [ITEM_JAW_FOSSIL] = { .name = _("Jaw Fossil"), - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING("A piece of a prehis-\n" "toric Pokémon's\n" "large jaw."), @@ -2610,7 +2612,7 @@ const struct Item gItems[] = [ITEM_SAIL_FOSSIL] = { .name = _("Sail Fossil"), - .price = 7000, + .price = (I_PRICE >= GEN_7) ? 7000: 1000, .description = COMPOUND_STRING("A piece of a prehis-\n" "toric Pokémon's\n" "skin sail."), @@ -2779,7 +2781,7 @@ const struct Item gItems[] = [ITEM_RED_APRICORN] = { .name = _("Red Apricorn"), - .price = 200, + .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING("A red apricorn.\n" "It assails your\n" "nostrils."), @@ -2791,7 +2793,7 @@ const struct Item gItems[] = [ITEM_BLUE_APRICORN] = { .name = _("Blue Apricorn"), - .price = 200, + .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING("A blue apricorn.\n" "It smells a bit\n" "like grass."), @@ -2803,7 +2805,7 @@ const struct Item gItems[] = [ITEM_YELLOW_APRICORN] = { .name = _("YellwApricorn"), - .price = 200, + .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING("A yellow apricorn.\n" "It has an invigor-\n" "ating scent."), @@ -2815,7 +2817,7 @@ const struct Item gItems[] = [ITEM_GREEN_APRICORN] = { .name = _("GreenApricorn"), - .price = 200, + .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING("A green apricorn.\n" "It has a strange,\n" "aromatic scent."), @@ -2827,7 +2829,7 @@ const struct Item gItems[] = [ITEM_PINK_APRICORN] = { .name = _("Pink Apricorn"), - .price = 200, + .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING("A pink apricorn.\n" "It has a nice,\n" "sweet scent."), @@ -2839,7 +2841,7 @@ const struct Item gItems[] = [ITEM_WHITE_APRICORN] = { .name = _("WhiteApricorn"), - .price = 200, + .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING("A white apricorn.\n" "It doesn't smell\n" "like anything."), @@ -2851,7 +2853,7 @@ const struct Item gItems[] = [ITEM_BLACK_APRICORN] = { .name = _("BlackApricorn"), - .price = 200, + .price = (I_PRICE == GEN_4) ? 0 : ((I_PRICE >= GEN_5 && I_PRICE <= GEN_7) ? 20 : 200), .description = COMPOUND_STRING("A black apricorn.\n" "It has an inde-\n" "scribable scent."), @@ -2876,7 +2878,7 @@ const struct Item gItems[] = [ITEM_GALARICA_TWIG] = { .name = _("GalaricaTwig"), - .price = 40, + .price = 20 * TREASURE_FACTOR, .description = COMPOUND_STRING("A twig from a tree\n" "in Galar called\n" "Galarica."), @@ -2889,7 +2891,7 @@ const struct Item gItems[] = [ITEM_ARMORITE_ORE] = { .name = _("Armorite Ore"), - .price = 40, + .price = 20, .description = COMPOUND_STRING("A rare ore. Can be\n" "found in the Isle\n" "of Armor at Galar."), @@ -3071,7 +3073,7 @@ const struct Item gItems[] = [ITEM_FIRE_STONE] = { .name = _("Fire Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3082,7 +3084,7 @@ const struct Item gItems[] = [ITEM_WATER_STONE] = { .name = _("Water Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3093,7 +3095,7 @@ const struct Item gItems[] = [ITEM_THUNDER_STONE] = { .name = _("Thunder Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3104,7 +3106,7 @@ const struct Item gItems[] = [ITEM_LEAF_STONE] = { .name = _("Leaf Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3115,7 +3117,7 @@ const struct Item gItems[] = [ITEM_ICE_STONE] = { .name = _("Ice Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3126,7 +3128,7 @@ const struct Item gItems[] = [ITEM_SUN_STONE] = { .name = _("Sun Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3137,7 +3139,7 @@ const struct Item gItems[] = [ITEM_MOON_STONE] = { .name = _("Moon Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3148,7 +3150,7 @@ const struct Item gItems[] = [ITEM_SHINY_STONE] = { .name = _("Shiny Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3159,7 +3161,7 @@ const struct Item gItems[] = [ITEM_DUSK_STONE] = { .name = _("Dusk Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3170,7 +3172,7 @@ const struct Item gItems[] = [ITEM_DAWN_STONE] = { .name = _("Dawn Stone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 2100, .description = sEvolutionStoneDesc, .pocket = POCKET_ITEMS, .type = ITEM_USE_PARTY_MENU, @@ -3233,7 +3235,7 @@ const struct Item gItems[] = [ITEM_GALARICA_CUFF] = { .name = _("GalaricaCuff"), - .price = 6000, + .price = (I_PRICE >= GEN_9) ? 3000 : 6000, .description = COMPOUND_STRING("A cuff from Galar\n" "that makes certain\n" "Pokémon evolve."), @@ -3246,7 +3248,7 @@ const struct Item gItems[] = [ITEM_GALARICA_WREATH] = { .name = _("GalrcaWreath"), - .price = 6000, + .price = (I_PRICE >= GEN_9) ? 3000 : 6000, .description = COMPOUND_STRING("A wreath made in\n" "Galar. Makes some\n" "Pokémon evolve."), @@ -3259,7 +3261,7 @@ const struct Item gItems[] = [ITEM_DRAGON_SCALE] = { .name = _("Dragon Scale"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .holdEffect = HOLD_EFFECT_DRAGON_SCALE, .holdEffectParam = 10, .description = COMPOUND_STRING("A strange scale\n" @@ -3274,7 +3276,7 @@ const struct Item gItems[] = [ITEM_UPGRADE] = { .name = _("Upgrade"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .holdEffect = HOLD_EFFECT_UPGRADE, .description = COMPOUND_STRING("A peculiar box made\n" "by Silph Co."), @@ -3287,7 +3289,7 @@ const struct Item gItems[] = [ITEM_PROTECTOR] = { .name = _("Protector"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING("Loved by a certain\n" "Pokémon. It's stiff\n" "and heavy."), @@ -3300,7 +3302,7 @@ const struct Item gItems[] = [ITEM_ELECTIRIZER] = { .name = _("Electirizer"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING("Loved by a certain\n" "Pokémon. It's full\n" "of electric energy."), @@ -3313,7 +3315,7 @@ const struct Item gItems[] = [ITEM_MAGMARIZER] = { .name = _("Magmarizer"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING("Loved by a certain\n" "Pokémon. It's full\n" "of magma energy."), @@ -3326,7 +3328,7 @@ const struct Item gItems[] = [ITEM_DUBIOUS_DISC] = { .name = _("Dubious Disc"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING("A transparent device\n" "overflowing with\n" "dubious data."), @@ -3339,7 +3341,7 @@ const struct Item gItems[] = [ITEM_REAPER_CLOTH] = { .name = _("Reaper Cloth"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING("Loved by a certain\n" "Pokémon. Imbued with\n" "spiritual energy."), @@ -3352,7 +3354,7 @@ const struct Item gItems[] = [ITEM_PRISM_SCALE] = { .name = _("Prism Scale"), - .price = 2000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 2000 : 500), .description = COMPOUND_STRING("A mysterious scale\n" "that evolves certain\n" "Pokémon. It shines."), @@ -3365,7 +3367,7 @@ const struct Item gItems[] = [ITEM_WHIPPED_DREAM] = { .name = _("Whipped Dream"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING("A soft and sweet\n" "treat loved by\n" "a certain Pokémon."), @@ -3378,7 +3380,7 @@ const struct Item gItems[] = [ITEM_SACHET] = { .name = _("Sachet"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 * TREASURE_FACTOR : 2100, .description = COMPOUND_STRING("A sachet filled with\n" "perfumes loved by\n" "a certain Pokémon."), @@ -3391,7 +3393,7 @@ const struct Item gItems[] = [ITEM_OVAL_STONE] = { .name = _("Oval Stone"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 2100, .description = COMPOUND_STRING("Makes a certain\n" "Pokémon evolve. It's\n" "shaped like an egg."), @@ -3404,7 +3406,7 @@ const struct Item gItems[] = [ITEM_STRAWBERRY_SWEET] = { .name = _("StrwbrySweet"), - .price = 500, + .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING("Strawberry-shaped\n" "sweet loved by\n" "Milcery."), @@ -3417,7 +3419,7 @@ const struct Item gItems[] = [ITEM_LOVE_SWEET] = { .name = _("Love Sweet"), - .price = 500, + .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING("A heart-shaped\n" "sweet loved by\n" "Milcery."), @@ -3430,7 +3432,7 @@ const struct Item gItems[] = [ITEM_BERRY_SWEET] = { .name = _("Berry Sweet"), - .price = 500, + .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING("A berry-shaped\n" "sweet loved by\n" "Milcery."), @@ -3443,7 +3445,7 @@ const struct Item gItems[] = [ITEM_CLOVER_SWEET] = { .name = _("Clover Sweet"), - .price = 500, + .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING("A clover-shaped\n" "sweet loved by\n" "Milcery."), @@ -3456,7 +3458,7 @@ const struct Item gItems[] = [ITEM_FLOWER_SWEET] = { .name = _("Flower Sweet"), - .price = 500, + .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING("A flower-shaped\n" "sweet loved by\n" "Milcery."), @@ -3469,7 +3471,7 @@ const struct Item gItems[] = [ITEM_STAR_SWEET] = { .name = _("Star Sweet"), - .price = 500, + .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING("A star-shaped\n" "sweet loved by\n" "Milcery."), @@ -3482,7 +3484,7 @@ const struct Item gItems[] = [ITEM_RIBBON_SWEET] = { .name = _("Ribbon Sweet"), - .price = 500, + .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING("A ribbon-shaped\n" "sweet loved by\n" "Milcery."), @@ -3495,7 +3497,7 @@ const struct Item gItems[] = [ITEM_EVERSTONE] = { .name = _("Everstone"), - .price = 3000, + .price = (I_PRICE >= GEN_7) ? 3000 : 200, .holdEffect = HOLD_EFFECT_PREVENT_EVOLVE, .description = COMPOUND_STRING("A wondrous hold\n" "item that prevents\n" @@ -3835,7 +3837,7 @@ const struct Item gItems[] = [ITEM_DOUSE_DRIVE] = { .name = _("Douse Drive"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING("Changes Genesect's\n" "Techno Blast to\n" @@ -3850,7 +3852,7 @@ const struct Item gItems[] = [ITEM_SHOCK_DRIVE] = { .name = _("Shock Drive"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING("Changes Genesect's\n" "Techno Blast to\n" @@ -3865,7 +3867,7 @@ const struct Item gItems[] = [ITEM_BURN_DRIVE] = { .name = _("Burn Drive"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING("Changes Genesect's\n" "Techno Blast to\n" @@ -3880,7 +3882,7 @@ const struct Item gItems[] = [ITEM_CHILL_DRIVE] = { .name = _("Chill Drive"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 1000, .holdEffect = HOLD_EFFECT_DRIVE, .description = COMPOUND_STRING("Changes Genesect's\n" "Techno Blast to\n" @@ -4875,7 +4877,7 @@ const struct Item gItems[] = [ITEM_NORMAL_GEM] = { .name = _("Normal Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -4890,7 +4892,7 @@ const struct Item gItems[] = [ITEM_FIRE_GEM] = { .name = _("Fire Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -4905,7 +4907,7 @@ const struct Item gItems[] = [ITEM_WATER_GEM] = { .name = _("Water Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -4920,7 +4922,7 @@ const struct Item gItems[] = [ITEM_ELECTRIC_GEM] = { .name = _("Electric Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -4935,7 +4937,7 @@ const struct Item gItems[] = [ITEM_GRASS_GEM] = { .name = _("Grass Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -4950,7 +4952,7 @@ const struct Item gItems[] = [ITEM_ICE_GEM] = { .name = _("Ice Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -4965,7 +4967,7 @@ const struct Item gItems[] = [ITEM_FIGHTING_GEM] = { .name = _("Fighting Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -4980,7 +4982,7 @@ const struct Item gItems[] = [ITEM_POISON_GEM] = { .name = _("Poison Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -4995,7 +4997,7 @@ const struct Item gItems[] = [ITEM_GROUND_GEM] = { .name = _("Ground Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5010,7 +5012,7 @@ const struct Item gItems[] = [ITEM_FLYING_GEM] = { .name = _("Flying Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5025,7 +5027,7 @@ const struct Item gItems[] = [ITEM_PSYCHIC_GEM] = { .name = _("Psychic Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5040,7 +5042,7 @@ const struct Item gItems[] = [ITEM_BUG_GEM] = { .name = _("Bug Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5055,7 +5057,7 @@ const struct Item gItems[] = [ITEM_ROCK_GEM] = { .name = _("Rock Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5070,7 +5072,7 @@ const struct Item gItems[] = [ITEM_GHOST_GEM] = { .name = _("Ghost Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5085,7 +5087,7 @@ const struct Item gItems[] = [ITEM_DRAGON_GEM] = { .name = _("Dragon Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5100,7 +5102,7 @@ const struct Item gItems[] = [ITEM_DARK_GEM] = { .name = _("Dark Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5115,7 +5117,7 @@ const struct Item gItems[] = [ITEM_STEEL_GEM] = { .name = _("Steel Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5130,7 +5132,7 @@ const struct Item gItems[] = [ITEM_FAIRY_GEM] = { .name = _("Fairy Gem"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GEMS, .holdEffectParam = GEM_BOOST_PARAM, .description = COMPOUND_STRING("Increases the\n" @@ -5639,7 +5641,7 @@ const struct Item gItems[] = [ITEM_LIGHT_BALL] = { .name = _("Light Ball"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 100, .holdEffect = HOLD_EFFECT_LIGHT_BALL, .description = COMPOUND_STRING("A hold item that\n" "raises the Atk and\n" @@ -5653,7 +5655,7 @@ const struct Item gItems[] = [ITEM_LEEK] = { .name = _("Leek"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 200, .holdEffect = HOLD_EFFECT_LEEK, .description = COMPOUND_STRING("A hold item that\n" "raises Farfetch'd's\n" @@ -5667,7 +5669,7 @@ const struct Item gItems[] = [ITEM_THICK_CLUB] = { .name = _("Thick Club"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 500, .holdEffect = HOLD_EFFECT_THICK_CLUB, .description = COMPOUND_STRING("A hold item that \n" "raises Cubone or\n" @@ -5681,7 +5683,7 @@ const struct Item gItems[] = [ITEM_LUCKY_PUNCH] = { .name = _("Lucky Punch"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_LUCKY_PUNCH, .description = COMPOUND_STRING("A hold item that\n" "raises Chansey's\n" @@ -5695,7 +5697,7 @@ const struct Item gItems[] = [ITEM_METAL_POWDER] = { .name = _("Metal Powder"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_METAL_POWDER, .description = COMPOUND_STRING("A hold item that\n" "raises Ditto's\n" @@ -5709,7 +5711,7 @@ const struct Item gItems[] = [ITEM_QUICK_POWDER] = { .name = _("Quick Powder"), - .price = 1000, + .price = (I_PRICE >= GEN_7) ? 1000 : 10, .holdEffect = HOLD_EFFECT_QUICK_POWDER, .description = COMPOUND_STRING("An item to be held\n" "by Ditto. This odd\n" @@ -5723,7 +5725,7 @@ const struct Item gItems[] = [ITEM_DEEP_SEA_SCALE] = { .name = _("DeepSeaScale"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 200, .holdEffect = HOLD_EFFECT_DEEP_SEA_SCALE, .description = COMPOUND_STRING("A hold item that\n" "raises the Sp. Def\n" @@ -5737,7 +5739,7 @@ const struct Item gItems[] = [ITEM_DEEP_SEA_TOOTH] = { .name = _("DeepSeaTooth"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 200, .holdEffect = HOLD_EFFECT_DEEP_SEA_TOOTH, .description = COMPOUND_STRING("A hold item that\n" "raises the Sp. Atk\n" @@ -5751,7 +5753,7 @@ const struct Item gItems[] = [ITEM_SOUL_DEW] = { .name = _("Soul Dew"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 200, .holdEffect = HOLD_EFFECT_SOUL_DEW, .holdEffectParam = B_SOUL_DEW_BOOST >= GEN_7 ? 20 : 50, #if B_SOUL_DEW_BOOST >= GEN_7 @@ -5772,7 +5774,7 @@ const struct Item gItems[] = [ITEM_ADAMANT_ORB] = { .name = _("Adamant Orb"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_ADAMANT_ORB, .holdEffectParam = 20, .description = COMPOUND_STRING("Boosts the power of\n" @@ -5787,7 +5789,7 @@ const struct Item gItems[] = [ITEM_LUSTROUS_ORB] = { .name = _("Lustrous Orb"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_LUSTROUS_ORB, .holdEffectParam = 20, .description = COMPOUND_STRING("Boosts the power of\n" @@ -5802,7 +5804,7 @@ const struct Item gItems[] = [ITEM_GRISEOUS_ORB] = { .name = _("Griseous Orb"), - .price = 0, + .price = (I_PRICE >= GEN_7) ? 0 : 10000, .holdEffect = HOLD_EFFECT_GRISEOUS_ORB, .holdEffectParam = 20, .description = COMPOUND_STRING("Powers up Giratina's\n" @@ -5819,7 +5821,7 @@ const struct Item gItems[] = [ITEM_SEA_INCENSE] = { .name = _("Sea Incense"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_WATER_POWER, .holdEffectParam = 20, .description = sSeaIncenseDesc, @@ -5832,7 +5834,7 @@ const struct Item gItems[] = [ITEM_LAX_INCENSE] = { .name = _("Lax Incense"), - .price = 5000, + .price = (I_PRICE >= GEN_7) ? 5000 : 9600, .holdEffect = HOLD_EFFECT_EVASION_UP, .holdEffectParam = 10, .description = COMPOUND_STRING("A hold item that\n" @@ -5847,7 +5849,7 @@ const struct Item gItems[] = [ITEM_ODD_INCENSE] = { .name = _("Odd Incense"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_PSYCHIC_POWER, .holdEffectParam = 20, .description = sOddIncenseDesc, @@ -5860,7 +5862,7 @@ const struct Item gItems[] = [ITEM_ROCK_INCENSE] = { .name = _("Rock Incense"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_ROCK_POWER, .holdEffectParam = 20, .description = sRockIncenseDesc, @@ -5873,7 +5875,7 @@ const struct Item gItems[] = [ITEM_FULL_INCENSE] = { .name = _("Full Incense"), - .price = 5000, + .price = (I_PRICE >= GEN_7) ? 5000 : 9600, .holdEffect = HOLD_EFFECT_LAGGING_TAIL, .holdEffectParam = 5, .description = sFullIncenseDesc, @@ -5886,7 +5888,7 @@ const struct Item gItems[] = [ITEM_WAVE_INCENSE] = { .name = _("Wave Incense"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_WATER_POWER, .holdEffectParam = 20, .description = sSeaIncenseDesc, @@ -5899,7 +5901,7 @@ const struct Item gItems[] = [ITEM_ROSE_INCENSE] = { .name = _("Rose Incense"), - .price = 2000, + .price = (I_PRICE >= GEN_7) ? 2000 : 9600, .holdEffect = HOLD_EFFECT_GRASS_POWER, .holdEffectParam = 20, .description = sRoseIncenseDesc, @@ -5912,7 +5914,7 @@ const struct Item gItems[] = [ITEM_LUCK_INCENSE] = { .name = _("Luck Incense"), - .price = 11000, + .price = (I_PRICE >= GEN_7) ? 11000 : 9600, .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, .pocket = POCKET_ITEMS, @@ -5924,7 +5926,7 @@ const struct Item gItems[] = [ITEM_PURE_INCENSE] = { .name = _("Pure Incense"), - .price = 6000, + .price = (I_PRICE >= GEN_7) ? 6000 : 9600, .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, .pocket = POCKET_ITEMS, @@ -6019,7 +6021,7 @@ const struct Item gItems[] = [ITEM_POWER_WEIGHT] = { .name = _("Power Weight"), - .price = 3000, + .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = 8, .description = COMPOUND_STRING("A hold item that\n" @@ -6035,7 +6037,7 @@ const struct Item gItems[] = [ITEM_POWER_BRACER] = { .name = _("Power Bracer"), - .price = 3000, + .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = 8, .description = COMPOUND_STRING("A hold item that\n" @@ -6051,7 +6053,7 @@ const struct Item gItems[] = [ITEM_POWER_BELT] = { .name = _("Power Belt"), - .price = 3000, + .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = 8, .description = COMPOUND_STRING("A hold item that\n" @@ -6067,7 +6069,7 @@ const struct Item gItems[] = [ITEM_POWER_LENS] = { .name = _("Power Lens"), - .price = 3000, + .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = 8, .description = COMPOUND_STRING("Hold item that pro-\n" @@ -6083,7 +6085,7 @@ const struct Item gItems[] = [ITEM_POWER_BAND] = { .name = _("Power Band"), - .price = 3000, + .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = 8, .description = COMPOUND_STRING("Hold item that pro-\n" @@ -6099,7 +6101,7 @@ const struct Item gItems[] = [ITEM_POWER_ANKLET] = { .name = _("Power Anklet"), - .price = 3000, + .price = (I_PRICE >= GEN_9) ? 10000 : 3000, .holdEffect = HOLD_EFFECT_POWER_ITEM, .holdEffectParam = 8, .description = COMPOUND_STRING("A hold item that\n" @@ -6117,7 +6119,7 @@ const struct Item gItems[] = [ITEM_SILK_SCARF] = { .name = _("Silk Scarf"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_NORMAL_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6132,7 +6134,7 @@ const struct Item gItems[] = [ITEM_CHARCOAL] = { .name = _("Charcoal"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 9800), .holdEffect = HOLD_EFFECT_FIRE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6147,7 +6149,7 @@ const struct Item gItems[] = [ITEM_MYSTIC_WATER] = { .name = _("Mystic Water"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_WATER_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6162,7 +6164,7 @@ const struct Item gItems[] = [ITEM_MAGNET] = { .name = _("Magnet"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_ELECTRIC_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6177,7 +6179,7 @@ const struct Item gItems[] = [ITEM_MIRACLE_SEED] = { .name = _("Miracle Seed"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_GRASS_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = sRoseIncenseDesc, @@ -6190,7 +6192,7 @@ const struct Item gItems[] = [ITEM_NEVER_MELT_ICE] = { .name = _("Never-MeltIce"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_ICE_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6205,7 +6207,7 @@ const struct Item gItems[] = [ITEM_BLACK_BELT] = { .name = _("Black Belt"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_FIGHTING_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6220,7 +6222,7 @@ const struct Item gItems[] = [ITEM_POISON_BARB] = { .name = _("Poison Barb"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_POISON_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6235,7 +6237,7 @@ const struct Item gItems[] = [ITEM_SOFT_SAND] = { .name = _("Soft Sand"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_GROUND_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6250,7 +6252,7 @@ const struct Item gItems[] = [ITEM_SHARP_BEAK] = { .name = _("Sharp Beak"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_FLYING_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6265,7 +6267,7 @@ const struct Item gItems[] = [ITEM_TWISTED_SPOON] = { .name = _("Twisted Spoon"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_PSYCHIC_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = sOddIncenseDesc, @@ -6278,7 +6280,7 @@ const struct Item gItems[] = [ITEM_SILVER_POWDER] = { .name = _("Silver Powder"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_BUG_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6293,7 +6295,7 @@ const struct Item gItems[] = [ITEM_HARD_STONE] = { .name = _("Hard Stone"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_ROCK_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = sRockIncenseDesc, @@ -6306,7 +6308,7 @@ const struct Item gItems[] = [ITEM_SPELL_TAG] = { .name = _("Spell Tag"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_GHOST_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6321,7 +6323,7 @@ const struct Item gItems[] = [ITEM_DRAGON_FANG] = { .name = _("Dragon Fang"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_DRAGON_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6336,7 +6338,7 @@ const struct Item gItems[] = [ITEM_BLACK_GLASSES] = { .name = _("Black Glasses"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 1000 : 100), .holdEffect = HOLD_EFFECT_DARK_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6351,7 +6353,7 @@ const struct Item gItems[] = [ITEM_METAL_COAT] = { .name = _("Metal Coat"), - .price = 2000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 2000 : 100), .holdEffect = HOLD_EFFECT_STEEL_POWER, .holdEffectParam = TYPE_BOOST_PARAM, .description = COMPOUND_STRING("A hold item that\n" @@ -6368,11 +6370,11 @@ const struct Item gItems[] = [ITEM_CHOICE_BAND] = { .name = _("Choice Band"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_BAND, - .description = COMPOUND_STRING("Raises a move's\n" - "power, but permits\n" - "only that move."), + .description = COMPOUND_STRING("Boosts Attack, but\n" + "allows the use of\n" + "only one move."), .pocket = POCKET_ITEMS, .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, @@ -6382,7 +6384,7 @@ const struct Item gItems[] = [ITEM_CHOICE_SPECS] = { .name = _("Choice Specs"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_SPECS, .description = COMPOUND_STRING("Boosts Sp. Atk, but\n" "allows the use of\n" @@ -6396,7 +6398,7 @@ const struct Item gItems[] = [ITEM_CHOICE_SCARF] = { .name = _("Choice Scarf"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 100000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_CHOICE_SCARF, .description = COMPOUND_STRING("Boosts Speed, but\n" "allows the use of\n" @@ -6412,7 +6414,7 @@ const struct Item gItems[] = [ITEM_FLAME_ORB] = { .name = _("Flame Orb"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FLAME_ORB, .description = COMPOUND_STRING("A bizarre orb that\n" "inflicts a burn on\n" @@ -6426,7 +6428,7 @@ const struct Item gItems[] = [ITEM_TOXIC_ORB] = { .name = _("Toxic Orb"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_TOXIC_ORB, .description = COMPOUND_STRING("A bizarre orb that\n" "badly poisons the\n" @@ -6442,7 +6444,7 @@ const struct Item gItems[] = [ITEM_DAMP_ROCK] = { .name = _("Damp Rock"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_DAMP_ROCK, .description = COMPOUND_STRING("Extends the length\n" "of Rain Dance if\n" @@ -6456,7 +6458,7 @@ const struct Item gItems[] = [ITEM_HEAT_ROCK] = { .name = _("Heat Rock"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_HEAT_ROCK, .description = COMPOUND_STRING("Extends the length\n" "of Sunny Day if\n" @@ -6470,7 +6472,7 @@ const struct Item gItems[] = [ITEM_SMOOTH_ROCK] = { .name = _("Smooth Rock"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SMOOTH_ROCK, .description = COMPOUND_STRING("Extends the length\n" "of Sandstorm if\n" @@ -6484,7 +6486,7 @@ const struct Item gItems[] = [ITEM_ICY_ROCK] = { .name = _("Icy Rock"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ICY_ROCK, .description = COMPOUND_STRING("Extends the length\n" "of the move Hail\n" @@ -6500,7 +6502,7 @@ const struct Item gItems[] = [ITEM_ELECTRIC_SEED] = { .name = _("Electric Seed"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_ELECTRIC_TERRAIN, .description = COMPOUND_STRING("Boosts Defense on\n" @@ -6515,7 +6517,7 @@ const struct Item gItems[] = [ITEM_PSYCHIC_SEED] = { .name = _("Psychic Seed"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_PSYCHIC_TERRAIN, .description = COMPOUND_STRING("Boosts Sp. Def. on\n" @@ -6530,7 +6532,7 @@ const struct Item gItems[] = [ITEM_MISTY_SEED] = { .name = _("Misty Seed"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_MISTY_TERRAIN, .description = COMPOUND_STRING("Boosts Sp. Def. on\n" @@ -6545,7 +6547,7 @@ const struct Item gItems[] = [ITEM_GRASSY_SEED] = { .name = _("Grassy Seed"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_SEEDS, .holdEffectParam = HOLD_EFFECT_PARAM_GRASSY_TERRAIN, .description = COMPOUND_STRING("Boosts Defense on\n" @@ -6562,7 +6564,7 @@ const struct Item gItems[] = [ITEM_ABSORB_BULB] = { .name = _("Absorb Bulb"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ABSORB_BULB, .holdEffectParam = 0, .description = COMPOUND_STRING("Raises Sp. Atk if\n" @@ -6577,7 +6579,7 @@ const struct Item gItems[] = [ITEM_CELL_BATTERY] = { .name = _("Cell Battery"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_CELL_BATTERY, .holdEffectParam = 0, .description = COMPOUND_STRING("Raises Atk if the\n" @@ -6592,7 +6594,7 @@ const struct Item gItems[] = [ITEM_LUMINOUS_MOSS] = { .name = _("Luminous Moss"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 1000), .holdEffect = HOLD_EFFECT_LUMINOUS_MOSS, .holdEffectParam = 0, .description = COMPOUND_STRING("Raises Sp. Def if\n" @@ -6607,7 +6609,7 @@ const struct Item gItems[] = [ITEM_SNOWBALL] = { .name = _("Snowball"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SNOWBALL, .holdEffectParam = 0, .description = COMPOUND_STRING("Raises Atk if its\n" @@ -6624,7 +6626,7 @@ const struct Item gItems[] = [ITEM_BRIGHT_POWDER] = { .name = _("Bright Powder"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 10), .holdEffect = HOLD_EFFECT_EVASION_UP, .holdEffectParam = 10, .description = COMPOUND_STRING("A hold item that\n" @@ -6639,7 +6641,7 @@ const struct Item gItems[] = [ITEM_WHITE_HERB] = { .name = _("White Herb"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_RESTORE_STATS, .description = COMPOUND_STRING("A hold item that\n" "restores any\n" @@ -6653,13 +6655,14 @@ const struct Item gItems[] = [ITEM_EXP_SHARE] = { .name = _("Exp. Share"), - .price = 3000, .holdEffect = HOLD_EFFECT_EXP_SHARE, #if I_EXP_SHARE_ITEM >= GEN_6 + .price = 0, .description = COMPOUND_STRING("This device gives\n" "exp. to other\n" "party members."), #else + .price = 3000, .description = COMPOUND_STRING("A hold item that\n" "gets Exp. points\n" "from battles."), @@ -6673,7 +6676,7 @@ const struct Item gItems[] = [ITEM_QUICK_CLAW] = { .name = _("Quick Claw"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_QUICK_CLAW, .holdEffectParam = 20, .description = COMPOUND_STRING("A hold item that\n" @@ -6688,7 +6691,7 @@ const struct Item gItems[] = [ITEM_SOOTHE_BELL] = { .name = _("Soothe Bell"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_FRIENDSHIP_UP, .description = COMPOUND_STRING("A hold item that\n" "calms spirits and\n" @@ -6702,7 +6705,7 @@ const struct Item gItems[] = [ITEM_MENTAL_HERB] = { .name = _("Mental Herb"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_MENTAL_HERB, #if B_MENTAL_HERB >= GEN_5 .description = COMPOUND_STRING("Snaps Pokémon out\n" @@ -6722,7 +6725,7 @@ const struct Item gItems[] = [ITEM_KINGS_ROCK] = { .name = _("King's Rock"), - .price = 5000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 5000 : 100), .holdEffect = HOLD_EFFECT_FLINCH, .holdEffectParam = 10, .description = sKingsRockDesc, @@ -6735,7 +6738,7 @@ const struct Item gItems[] = [ITEM_AMULET_COIN] = { .name = _("Amulet Coin"), - .price = 10000, + .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 10000 : 100), .holdEffect = HOLD_EFFECT_DOUBLE_PRIZE, .description = sLuckIncenseDesc, .pocket = POCKET_ITEMS, @@ -6747,7 +6750,7 @@ const struct Item gItems[] = [ITEM_CLEANSE_TAG] = { .name = _("Cleanse Tag"), - .price = 5000, + .price = (I_PRICE >= GEN_7) ? 5000 : 200, .holdEffect = HOLD_EFFECT_REPEL, .description = sPureIncenseDesc, .pocket = POCKET_ITEMS, @@ -6759,7 +6762,7 @@ const struct Item gItems[] = [ITEM_SMOKE_BALL] = { .name = _("Smoke Ball"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_CAN_ALWAYS_RUN, .description = COMPOUND_STRING("A hold item that\n" "assures fleeing\n" @@ -6773,7 +6776,7 @@ const struct Item gItems[] = [ITEM_FOCUS_BAND] = { .name = _("Focus Band"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FOCUS_BAND, .holdEffectParam = 10, .description = COMPOUND_STRING("A hold item that\n" @@ -6788,7 +6791,7 @@ const struct Item gItems[] = [ITEM_LUCKY_EGG] = { .name = _("Lucky Egg"), - .price = 10000, + .price = (I_PRICE >= GEN_7) ? 10000 : 200, .holdEffect = HOLD_EFFECT_LUCKY_EGG, .description = COMPOUND_STRING("A hold item that\n" "boosts Exp. points\n" @@ -6802,7 +6805,7 @@ const struct Item gItems[] = [ITEM_SCOPE_LENS] = { .name = _("Scope Lens"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_SCOPE_LENS, .description = COMPOUND_STRING("A hold item that\n" "improves the\n" @@ -6816,7 +6819,7 @@ const struct Item gItems[] = [ITEM_LEFTOVERS] = { .name = _("Leftovers"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LEFTOVERS, .holdEffectParam = 10, .description = COMPOUND_STRING("A hold item that\n" @@ -6831,7 +6834,7 @@ const struct Item gItems[] = [ITEM_SHELL_BELL] = { .name = _("Shell Bell"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_SHELL_BELL, .holdEffectParam = 8, .description = COMPOUND_STRING("A hold item that\n" @@ -6846,7 +6849,7 @@ const struct Item gItems[] = [ITEM_WIDE_LENS] = { .name = _("Wide Lens"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_WIDE_LENS, .holdEffectParam = 10, .description = COMPOUND_STRING("A magnifying lens\n" @@ -6861,7 +6864,7 @@ const struct Item gItems[] = [ITEM_MUSCLE_BAND] = { .name = _("Muscle Band"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_MUSCLE_BAND, .holdEffectParam = 10, .description = COMPOUND_STRING("A headband that\n" @@ -6876,7 +6879,7 @@ const struct Item gItems[] = [ITEM_WISE_GLASSES] = { .name = _("Wise Glasses"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 8000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_WISE_GLASSES, .holdEffectParam = 10, .description = COMPOUND_STRING("A pair of glasses\n" @@ -6891,7 +6894,7 @@ const struct Item gItems[] = [ITEM_EXPERT_BELT] = { .name = _("Expert Belt"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EXPERT_BELT, .holdEffectParam = 20, .description = COMPOUND_STRING("A belt that boosts\n" @@ -6906,7 +6909,7 @@ const struct Item gItems[] = [ITEM_LIGHT_CLAY] = { .name = _("Light Clay"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LIGHT_CLAY, .description = COMPOUND_STRING("Extends the length\n" "of barrier moves\n" @@ -6920,7 +6923,7 @@ const struct Item gItems[] = [ITEM_LIFE_ORB] = { .name = _("Life Orb"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LIFE_ORB, .description = COMPOUND_STRING("Boosts the power of\n" "moves at the cost\n" @@ -6934,7 +6937,7 @@ const struct Item gItems[] = [ITEM_POWER_HERB] = { .name = _("Power Herb"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_POWER_HERB, .description = COMPOUND_STRING("Allows immediate\n" "use of a move that\n" @@ -6948,7 +6951,7 @@ const struct Item gItems[] = [ITEM_FOCUS_SASH] = { .name = _("Focus Sash"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FOCUS_SASH, .description = COMPOUND_STRING("If the holder has\n" "full HP, it endures\n" @@ -6962,7 +6965,7 @@ const struct Item gItems[] = [ITEM_ZOOM_LENS] = { .name = _("Zoom Lens"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ZOOM_LENS, .holdEffectParam = 20, .description = COMPOUND_STRING("If the holder moves\n" @@ -6977,7 +6980,7 @@ const struct Item gItems[] = [ITEM_METRONOME] = { .name = _("Metronome"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_METRONOME, .holdEffectParam = 20, .description = COMPOUND_STRING("A held item that\n" @@ -6992,7 +6995,7 @@ const struct Item gItems[] = [ITEM_IRON_BALL] = { .name = _("Iron Ball"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_IRON_BALL, .description = COMPOUND_STRING("Cuts Speed and lets\n" "Flying-types be hit\n" @@ -7006,7 +7009,7 @@ const struct Item gItems[] = [ITEM_LAGGING_TAIL] = { .name = _("Lagging Tail"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_LAGGING_TAIL, .description = sFullIncenseDesc, .pocket = POCKET_ITEMS, @@ -7018,7 +7021,7 @@ const struct Item gItems[] = [ITEM_DESTINY_KNOT] = { .name = _("Destiny Knot"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_DESTINY_KNOT, .description = COMPOUND_STRING("If the holder falls\n" "in love, the foe\n" @@ -7032,7 +7035,7 @@ const struct Item gItems[] = [ITEM_BLACK_SLUDGE] = { .name = _("Black Sludge"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BLACK_SLUDGE, .description = COMPOUND_STRING("Gradually restores\n" "HP of Poison-types.\n" @@ -7046,7 +7049,7 @@ const struct Item gItems[] = [ITEM_GRIP_CLAW] = { .name = _("Grip Claw"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_GRIP_CLAW, .description = COMPOUND_STRING("Makes binding moves\n" "used by the holder\n" @@ -7060,7 +7063,7 @@ const struct Item gItems[] = [ITEM_STICKY_BARB] = { .name = _("Sticky Barb"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_STICKY_BARB, .description = COMPOUND_STRING("Damages the holder\n" "each turn. May latch\n" @@ -7074,7 +7077,7 @@ const struct Item gItems[] = [ITEM_SHED_SHELL] = { .name = _("Shed Shell"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 100), .holdEffect = HOLD_EFFECT_SHED_SHELL, .description = COMPOUND_STRING("Enables the holder\n" "to switch out of\n" @@ -7088,7 +7091,7 @@ const struct Item gItems[] = [ITEM_BIG_ROOT] = { .name = _("Big Root"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BIG_ROOT, .holdEffectParam = 30, .description = COMPOUND_STRING("A held item that\n" @@ -7103,7 +7106,7 @@ const struct Item gItems[] = [ITEM_RAZOR_CLAW] = { .name = _("Razor Claw"), - .price = 5000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 5000 : 2100), .holdEffect = HOLD_EFFECT_SCOPE_LENS, .description = COMPOUND_STRING("A hooked claw that\n" "ups the holder's\n" @@ -7117,7 +7120,7 @@ const struct Item gItems[] = [ITEM_RAZOR_FANG] = { .name = _("Razor Fang"), - .price = 5000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 5000 : 2100), .holdEffect = HOLD_EFFECT_FLINCH, .holdEffectParam = 10, .description = sKingsRockDesc, @@ -7130,7 +7133,7 @@ const struct Item gItems[] = [ITEM_EVIOLITE] = { .name = _("Eviolite"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EVIOLITE, .holdEffectParam = 50, .description = COMPOUND_STRING("Raises the Def and\n" @@ -7145,7 +7148,7 @@ const struct Item gItems[] = [ITEM_FLOAT_STONE] = { .name = _("Float Stone"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_FLOAT_STONE, .description = COMPOUND_STRING("It's so light that\n" "when held, it halves\n" @@ -7159,7 +7162,7 @@ const struct Item gItems[] = [ITEM_ROCKY_HELMET] = { .name = _("Rocky Helmet"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 50000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_ROCKY_HELMET, .holdEffectParam = 0, .description = COMPOUND_STRING("Hurts the foe if\n" @@ -7174,7 +7177,7 @@ const struct Item gItems[] = [ITEM_AIR_BALLOON] = { .name = _("Air Balloon"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_AIR_BALLOON, .holdEffectParam = 0, .description = COMPOUND_STRING("Elevates the holder\n" @@ -7189,7 +7192,7 @@ const struct Item gItems[] = [ITEM_RED_CARD] = { .name = _("Red Card"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 3000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_RED_CARD, .holdEffectParam = 0, .description = COMPOUND_STRING("Switches out the\n" @@ -7204,7 +7207,7 @@ const struct Item gItems[] = [ITEM_RING_TARGET] = { .name = _("Ring Target"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 10000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_RING_TARGET, .holdEffectParam = 0, .description = COMPOUND_STRING("Moves that wouldn't\n" @@ -7219,7 +7222,7 @@ const struct Item gItems[] = [ITEM_BINDING_BAND] = { .name = _("Binding Band"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_BINDING_BAND, .description = COMPOUND_STRING("Increases the\n" "power of binding\n" @@ -7233,7 +7236,7 @@ const struct Item gItems[] = [ITEM_EJECT_BUTTON] = { .name = _("Eject Button"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 30000 : ((I_PRICE >= GEN_7) ? 4000 : 200), .holdEffect = HOLD_EFFECT_EJECT_BUTTON, .holdEffectParam = 0, .description = COMPOUND_STRING("Switches out the\n" @@ -7248,7 +7251,7 @@ const struct Item gItems[] = [ITEM_WEAKNESS_POLICY] = { .name = _("WeaknssPolicy"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 50000 : 1000, .holdEffect = HOLD_EFFECT_WEAKNESS_POLICY, .holdEffectParam = 0, .description = COMPOUND_STRING("If hit by a Super\n" @@ -7263,7 +7266,7 @@ const struct Item gItems[] = [ITEM_ASSAULT_VEST] = { .name = _("Assault Vest"), - .price = 1000, + .price = (I_PRICE >= GEN_9) ? 50000 : 1000, .holdEffect = HOLD_EFFECT_ASSAULT_VEST, .holdEffectParam = 50, .description = COMPOUND_STRING("Raises Sp. Def but\n" @@ -7278,7 +7281,7 @@ const struct Item gItems[] = [ITEM_SAFETY_GOGGLES] = { .name = _("SafetyGoggles"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : ((I_PRICE >= GEN_7) ? 4000 : 1000), .holdEffect = HOLD_EFFECT_SAFETY_GOGGLES, .description = COMPOUND_STRING("Protect from\n" "weather damage and\n" @@ -7292,7 +7295,7 @@ const struct Item gItems[] = [ITEM_ADRENALINE_ORB] = { .name = _("AdrenalineOrb"), - .price = 300, + .price = (I_PRICE >= GEN_9) ? 5000 : ((I_PRICE >= GEN_8) ? 4000 : 300), .holdEffect = HOLD_EFFECT_ADRENALINE_ORB, .description = COMPOUND_STRING("Boosts Speed if the\n" "user is intimidated,\n" @@ -7306,7 +7309,7 @@ const struct Item gItems[] = [ITEM_TERRAIN_EXTENDER] = { .name = _("TerainExtendr"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_TERRAIN_EXTENDER, .description = COMPOUND_STRING("Extends the length\n" "of the active\n" @@ -7320,7 +7323,7 @@ const struct Item gItems[] = [ITEM_PROTECTIVE_PADS] = { .name = _("ProtectvePads"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_PROTECTIVE_PADS, .description = COMPOUND_STRING("Guard the holder\n" "from contact move\n" @@ -7334,7 +7337,7 @@ const struct Item gItems[] = [ITEM_THROAT_SPRAY] = { .name = _("Throat Spray"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_THROAT_SPRAY, .description = COMPOUND_STRING("Raises Sp. Atk. if\n" "the holder uses a\n" @@ -7348,7 +7351,7 @@ const struct Item gItems[] = [ITEM_EJECT_PACK] = { .name = _("Eject Pack"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 30000 : 4000, .holdEffect = HOLD_EFFECT_EJECT_PACK, .description = COMPOUND_STRING("Forces the user to\n" "switch if its stats\n" @@ -7362,7 +7365,7 @@ const struct Item gItems[] = [ITEM_HEAVY_DUTY_BOOTS] = { .name = _("Heavy-DtyBts"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_HEAVY_DUTY_BOOTS, .description = COMPOUND_STRING("Boots that prevent\n" "effects of traps\n" @@ -7376,7 +7379,7 @@ const struct Item gItems[] = [ITEM_BLUNDER_POLICY] = { .name = _("BlundrPolicy"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 30000 : 4000, .holdEffect = HOLD_EFFECT_BLUNDER_POLICY, .description = COMPOUND_STRING("Raises Speed if\n" "the user misses\n" @@ -7390,7 +7393,7 @@ const struct Item gItems[] = [ITEM_ROOM_SERVICE] = { .name = _("Room Service"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 20000 : 4000, .holdEffect = HOLD_EFFECT_ROOM_SERVICE, .description = COMPOUND_STRING("Lowers Speed if\n" "Trick Room is\n" @@ -7404,7 +7407,7 @@ const struct Item gItems[] = [ITEM_UTILITY_UMBRELLA] = { .name = _("UtltyUmbrlla"), - .price = 4000, + .price = (I_PRICE >= GEN_9) ? 15000 : 4000, .holdEffect = HOLD_EFFECT_UTILITY_UMBRELLA, .description = COMPOUND_STRING("An umbrella that\n" "protects from\n" @@ -7420,7 +7423,7 @@ const struct Item gItems[] = [ITEM_CHERI_BERRY] = { .name = _("Cheri Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_PAR, .description = COMPOUND_STRING("A hold item that\n" "heals paralysis\n" @@ -7435,7 +7438,7 @@ const struct Item gItems[] = [ITEM_CHESTO_BERRY] = { .name = _("Chesto Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_SLP, .description = COMPOUND_STRING("A hold item that\n" "awakens Pokémon\n" @@ -7450,7 +7453,7 @@ const struct Item gItems[] = [ITEM_PECHA_BERRY] = { .name = _("Pecha Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_PSN, .description = COMPOUND_STRING("A hold item that\n" "heals poisoning\n" @@ -7465,7 +7468,7 @@ const struct Item gItems[] = [ITEM_RAWST_BERRY] = { .name = _("Rawst Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_BRN, .description = COMPOUND_STRING("A hold item that\n" "heals a burn in\n" @@ -7480,7 +7483,7 @@ const struct Item gItems[] = [ITEM_ASPEAR_BERRY] = { .name = _("Aspear Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_FRZ, .description = COMPOUND_STRING("A hold item that\n" "defrosts Pokémon\n" @@ -7495,7 +7498,7 @@ const struct Item gItems[] = [ITEM_LEPPA_BERRY] = { .name = _("Leppa Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESTORE_PP, .holdEffectParam = 10, .description = COMPOUND_STRING("A hold item that\n" @@ -7511,7 +7514,7 @@ const struct Item gItems[] = [ITEM_ORAN_BERRY] = { .name = _("Oran Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESTORE_HP, .holdEffectParam = 10, .description = COMPOUND_STRING("A hold item that\n" @@ -7527,7 +7530,7 @@ const struct Item gItems[] = [ITEM_PERSIM_BERRY] = { .name = _("Persim Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_CONFUSION, .description = COMPOUND_STRING("A hold item that\n" "heals confusion\n" @@ -7542,7 +7545,7 @@ const struct Item gItems[] = [ITEM_LUM_BERRY] = { .name = _("Lum Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CURE_STATUS, .description = COMPOUND_STRING("A hold item that\n" "heals any status\n" @@ -7557,7 +7560,7 @@ const struct Item gItems[] = [ITEM_SITRUS_BERRY] = { .name = _("Sitrus Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, #if I_SITRUS_BERRY_HEAL >= GEN_4 .holdEffect = HOLD_EFFECT_RESTORE_PCT_HP, .holdEffectParam = 25, @@ -7581,7 +7584,7 @@ const struct Item gItems[] = [ITEM_FIGY_BERRY] = { .name = _("Figy Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SPICY, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, .description = sFigyBerryDesc, @@ -7594,7 +7597,7 @@ const struct Item gItems[] = [ITEM_WIKI_BERRY] = { .name = _("Wiki Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_DRY, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, .description = sFigyBerryDesc, @@ -7607,7 +7610,7 @@ const struct Item gItems[] = [ITEM_MAGO_BERRY] = { .name = _("Mago Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SWEET, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, .description = sFigyBerryDesc, @@ -7620,7 +7623,7 @@ const struct Item gItems[] = [ITEM_AGUAV_BERRY] = { .name = _("Aguav Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_BITTER, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, .description = sFigyBerryDesc, @@ -7633,7 +7636,7 @@ const struct Item gItems[] = [ITEM_IAPAPA_BERRY] = { .name = _("Iapapa Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CONFUSE_SOUR, .holdEffectParam = CONFUSE_BERRY_HEAL_FRACTION, .description = sFigyBerryDesc, @@ -7646,7 +7649,7 @@ const struct Item gItems[] = [ITEM_RAZZ_BERRY] = { .name = _("Razz Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Razz."), @@ -7659,7 +7662,7 @@ const struct Item gItems[] = [ITEM_BLUK_BERRY] = { .name = _("Bluk Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Bluk."), @@ -7672,7 +7675,7 @@ const struct Item gItems[] = [ITEM_NANAB_BERRY] = { .name = _("Nanab Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Nanab."), @@ -7685,7 +7688,7 @@ const struct Item gItems[] = [ITEM_WEPEAR_BERRY] = { .name = _("Wepear Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Wepear."), @@ -7698,7 +7701,7 @@ const struct Item gItems[] = [ITEM_PINAP_BERRY] = { .name = _("Pinap Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Pinap."), @@ -7711,7 +7714,7 @@ const struct Item gItems[] = [ITEM_POMEG_BERRY] = { .name = _("Pomeg Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("Makes a Pokémon\n" "friendly but lowers\n" "base HP."), @@ -7724,7 +7727,7 @@ const struct Item gItems[] = [ITEM_KELPSY_BERRY] = { .name = _("Kelpsy Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("Makes a Pokémon\n" "friendly but lowers\n" "base Attack."), @@ -7737,7 +7740,7 @@ const struct Item gItems[] = [ITEM_QUALOT_BERRY] = { .name = _("Qualot Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("Makes a Pokémon\n" "friendly but lowers\n" "base Defense."), @@ -7750,7 +7753,7 @@ const struct Item gItems[] = [ITEM_HONDEW_BERRY] = { .name = _("Hondew Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("Makes a Pokémon\n" "friendly but lowers\n" "base Sp. Atk."), @@ -7763,7 +7766,7 @@ const struct Item gItems[] = [ITEM_GREPA_BERRY] = { .name = _("Grepa Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("Makes a Pokémon\n" "friendly but lowers\n" "base Sp. Def."), @@ -7776,7 +7779,7 @@ const struct Item gItems[] = [ITEM_TAMATO_BERRY] = { .name = _("Tamato Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("Makes a Pokémon\n" "friendly but lowers\n" "base Speed."), @@ -7789,7 +7792,7 @@ const struct Item gItems[] = [ITEM_CORNN_BERRY] = { .name = _("Cornn Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Cornn."), @@ -7802,7 +7805,7 @@ const struct Item gItems[] = [ITEM_MAGOST_BERRY] = { .name = _("Magost Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Magost."), @@ -7815,7 +7818,7 @@ const struct Item gItems[] = [ITEM_RABUTA_BERRY] = { .name = _("Rabuta Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Rabuta."), @@ -7828,7 +7831,7 @@ const struct Item gItems[] = [ITEM_NOMEL_BERRY] = { .name = _("Nomel Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Nomel."), @@ -7841,7 +7844,7 @@ const struct Item gItems[] = [ITEM_SPELON_BERRY] = { .name = _("Spelon Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Spelon."), @@ -7854,7 +7857,7 @@ const struct Item gItems[] = [ITEM_PAMTRE_BERRY] = { .name = _("Pamtre Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Pamtre."), @@ -7867,7 +7870,7 @@ const struct Item gItems[] = [ITEM_WATMEL_BERRY] = { .name = _("Watmel Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Watmel."), @@ -7880,7 +7883,7 @@ const struct Item gItems[] = [ITEM_DURIN_BERRY] = { .name = _("Durin Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Durin."), @@ -7893,7 +7896,7 @@ const struct Item gItems[] = [ITEM_BELUE_BERRY] = { .name = _("Belue Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow Belue."), @@ -7906,7 +7909,7 @@ const struct Item gItems[] = [ITEM_CHILAN_BERRY] = { .name = _("Chilan Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_NORMAL, .description = COMPOUND_STRING("A hold item that\n" @@ -7921,7 +7924,7 @@ const struct Item gItems[] = [ITEM_OCCA_BERRY] = { .name = _("Occa Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FIRE, .description = COMPOUND_STRING("A hold item that\n" @@ -7936,7 +7939,7 @@ const struct Item gItems[] = [ITEM_PASSHO_BERRY] = { .name = _("Passho Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_WATER, .description = COMPOUND_STRING("A hold item that\n" @@ -7951,7 +7954,7 @@ const struct Item gItems[] = [ITEM_WACAN_BERRY] = { .name = _("Wacan Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ELECTRIC, .description = COMPOUND_STRING("A hold item that\n" @@ -7966,7 +7969,7 @@ const struct Item gItems[] = [ITEM_RINDO_BERRY] = { .name = _("Rindo Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GRASS, .description = COMPOUND_STRING("A hold item that\n" @@ -7981,7 +7984,7 @@ const struct Item gItems[] = [ITEM_YACHE_BERRY] = { .name = _("Yache Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ICE, .description = COMPOUND_STRING("A hold item that\n" @@ -7996,7 +7999,7 @@ const struct Item gItems[] = [ITEM_CHOPLE_BERRY] = { .name = _("Chople Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FIGHTING, .description = COMPOUND_STRING("A hold item that\n" @@ -8011,7 +8014,7 @@ const struct Item gItems[] = [ITEM_KEBIA_BERRY] = { .name = _("Kebia Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_POISON, .description = COMPOUND_STRING("A hold item that\n" @@ -8026,7 +8029,7 @@ const struct Item gItems[] = [ITEM_SHUCA_BERRY] = { .name = _("Shuca Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GROUND, .description = COMPOUND_STRING("A hold item that\n" @@ -8041,7 +8044,7 @@ const struct Item gItems[] = [ITEM_COBA_BERRY] = { .name = _("Coba Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FLYING, .description = COMPOUND_STRING("A hold item that\n" @@ -8056,7 +8059,7 @@ const struct Item gItems[] = [ITEM_PAYAPA_BERRY] = { .name = _("Payapa Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_PSYCHIC, .description = COMPOUND_STRING("A hold item that\n" @@ -8071,7 +8074,7 @@ const struct Item gItems[] = [ITEM_TANGA_BERRY] = { .name = _("Tanga Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_BUG, .description = COMPOUND_STRING("A hold item that\n" @@ -8086,7 +8089,7 @@ const struct Item gItems[] = [ITEM_CHARTI_BERRY] = { .name = _("Charti Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_ROCK, .description = COMPOUND_STRING("A hold item that\n" @@ -8101,7 +8104,7 @@ const struct Item gItems[] = [ITEM_KASIB_BERRY] = { .name = _("Kasib Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_GHOST, .description = COMPOUND_STRING("A hold item that\n" @@ -8116,7 +8119,7 @@ const struct Item gItems[] = [ITEM_HABAN_BERRY] = { .name = _("Haban Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_DRAGON, .description = COMPOUND_STRING("A hold item that\n" @@ -8131,7 +8134,7 @@ const struct Item gItems[] = [ITEM_COLBUR_BERRY] = { .name = _("Colbur Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_DARK, .description = COMPOUND_STRING("A hold item that\n" @@ -8146,7 +8149,7 @@ const struct Item gItems[] = [ITEM_BABIRI_BERRY] = { .name = _("Babiri Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_STEEL, .description = COMPOUND_STRING("A hold item that\n" @@ -8161,7 +8164,7 @@ const struct Item gItems[] = [ITEM_ROSELI_BERRY] = { .name = _("Roseli Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RESIST_BERRY, .holdEffectParam = TYPE_FAIRY, .description = COMPOUND_STRING("A hold item that\n" @@ -8176,7 +8179,7 @@ const struct Item gItems[] = [ITEM_LIECHI_BERRY] = { .name = _("Liechi Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ATTACK_UP, .holdEffectParam = 4, .description = COMPOUND_STRING("A hold item that\n" @@ -8191,7 +8194,7 @@ const struct Item gItems[] = [ITEM_GANLON_BERRY] = { .name = _("Ganlon Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_DEFENSE_UP, .holdEffectParam = 4, .description = COMPOUND_STRING("A hold item that\n" @@ -8206,7 +8209,7 @@ const struct Item gItems[] = [ITEM_SALAC_BERRY] = { .name = _("Salac Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SPEED_UP, .holdEffectParam = 4, .description = COMPOUND_STRING("A hold item that\n" @@ -8221,7 +8224,7 @@ const struct Item gItems[] = [ITEM_PETAYA_BERRY] = { .name = _("Petaya Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SP_ATTACK_UP, .holdEffectParam = 4, .description = COMPOUND_STRING("A hold item that\n" @@ -8236,7 +8239,7 @@ const struct Item gItems[] = [ITEM_APICOT_BERRY] = { .name = _("Apicot Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_SP_DEFENSE_UP, .holdEffectParam = 4, .description = COMPOUND_STRING("A hold item that\n" @@ -8251,7 +8254,7 @@ const struct Item gItems[] = [ITEM_LANSAT_BERRY] = { .name = _("Lansat Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CRITICAL_UP, .holdEffectParam = 4, .description = COMPOUND_STRING("A hold item that\n" @@ -8266,7 +8269,7 @@ const struct Item gItems[] = [ITEM_STARF_BERRY] = { .name = _("Starf Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_RANDOM_STAT_UP, .holdEffectParam = 4, .description = COMPOUND_STRING("A hold item that\n" @@ -8281,7 +8284,7 @@ const struct Item gItems[] = [ITEM_ENIGMA_BERRY] = { .name = _("Enigma Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ENIGMA_BERRY, .description = COMPOUND_STRING("A hold item that\n" "heals from super\n" @@ -8295,7 +8298,7 @@ const struct Item gItems[] = [ITEM_MICLE_BERRY] = { .name = _("Micle Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_MICLE_BERRY, .holdEffectParam = 4, .description = COMPOUND_STRING("When held, it ups\n" @@ -8310,7 +8313,7 @@ const struct Item gItems[] = [ITEM_CUSTAP_BERRY] = { .name = _("Custap Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_CUSTAP_BERRY, .holdEffectParam = 4, .description = COMPOUND_STRING("It allows a Pokémon\n" @@ -8325,7 +8328,7 @@ const struct Item gItems[] = [ITEM_JABOCA_BERRY] = { .name = _("Jaboca Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_JABOCA_BERRY, .description = COMPOUND_STRING("If hit by a physical\n" "move, it will hurt\n" @@ -8339,7 +8342,7 @@ const struct Item gItems[] = [ITEM_ROWAP_BERRY] = { .name = _("Rowap Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_ROWAP_BERRY, .description = COMPOUND_STRING("If hit by a special\n" "move, it will hurt\n" @@ -8353,7 +8356,7 @@ const struct Item gItems[] = [ITEM_KEE_BERRY] = { .name = _("Kee Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_KEE_BERRY, .description = COMPOUND_STRING("If hit by a physical\n" "move, it raises the\n" @@ -8367,7 +8370,7 @@ const struct Item gItems[] = [ITEM_MARANGA_BERRY] = { .name = _("Maranga Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .holdEffect = HOLD_EFFECT_MARANGA_BERRY, .description = COMPOUND_STRING("If hit by a special\n" "move, it raises the\n" @@ -8381,7 +8384,7 @@ const struct Item gItems[] = [ITEM_ENIGMA_BERRY_E_READER] = { .name = _("Enigma Berry"), - .price = 20, + .price = (I_BERRY_PRICE >= GEN_8) ? 80 : 20, .description = COMPOUND_STRING("{POKEBLOCK} ingredient.\n" "Plant in loamy soil\n" "to grow a mystery."), @@ -10714,6 +10717,8 @@ const struct Item gItems[] = .flingPower = 30, }, +// GEN 9 ITEMS + [ITEM_CLEAR_AMULET] = { .name = _("Clear Amulet"), diff --git a/src/item.c b/src/item.c index 52af1c5f0b..e751624747 100644 --- a/src/item.c +++ b/src/item.c @@ -878,7 +878,7 @@ const u8 *ItemId_GetName(u16 itemId) return gItems[SanitizeItemId(itemId)].name; } -u16 ItemId_GetPrice(u16 itemId) +u32 ItemId_GetPrice(u16 itemId) { return gItems[SanitizeItemId(itemId)].price; } From 4f61d44dfe89c6c98712da930b46cf795fa08d6e Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Wed, 27 Dec 2023 17:02:51 -0600 Subject: [PATCH 05/13] Add Treasure Factor to Nugget and Tiny Mushroom (#3836) --- src/data/items.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/data/items.h b/src/data/items.h index 457e00a058..4bb19b4c9a 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -2076,7 +2076,7 @@ const struct Item gItems[] = [ITEM_NUGGET] = { .name = _("Nugget"), - .price = 10000, + .price = 10000 * TREASURE_FACTOR, .description = COMPOUND_STRING("A nugget of pure\n" "gold. Can be sold at\n" "a high price."), @@ -2102,7 +2102,7 @@ const struct Item gItems[] = [ITEM_TINY_MUSHROOM] = { .name = _("Tiny Mushroom"), - .price = 500, + .price = 500 * TREASURE_FACTOR, .description = COMPOUND_STRING("A plain mushroom\n" "that would sell\n" "at a cheap price."), From c57b1548a07d9d1ad9e855bdad1c8444b6f19a12 Mon Sep 17 00:00:00 2001 From: tertu Date: Thu, 28 Dec 2023 03:58:35 -0600 Subject: [PATCH 06/13] Replace at least some shuffle algorithms with Shuffle (#3801) Most of these are the poor-quality and slow "naive shuffle", but some might be better. In any case, Shuffle is known good. --- src/apprentice.c | 37 ++++++++----------------------------- src/battle_pike.c | 20 +++----------------- src/mauville_old_man.c | 24 ++---------------------- src/mirage_tower.c | 19 +++++-------------- src/tv.c | 8 +------- src/wild_encounter.c | 13 +------------ 6 files changed, 20 insertions(+), 101 deletions(-) diff --git a/src/apprentice.c b/src/apprentice.c index dc7ac92a86..8c9128b718 100644 --- a/src/apprentice.c +++ b/src/apprentice.c @@ -207,14 +207,7 @@ static void ShuffleApprenticeSpecies(void) for (i = 0; i < ARRAY_COUNT(species); i++) species[i] = i; - // Shuffle the possible species an arbitrary 50 times - for (i = 0; i < 50; i++) - { - u8 temp; - u8 rand1 = Random() % ARRAY_COUNT(species); - u8 rand2 = Random() % ARRAY_COUNT(species); - SWAP(species[rand1], species[rand2], temp); - } + Shuffle(species, APPRENTICE_SPECIES_COUNT, sizeof(species[0])); for (i = 0; i < MULTI_PARTY_SIZE; i++) PLAYER_APPRENTICE.speciesIds[i] = ((species[i * 2] & 0xF) << 4) | ((species[i * 2 + 1]) & 0xF); @@ -254,33 +247,19 @@ static void SetRandomQuestionData(void) u8 questionOrder[APPRENTICE_MAX_QUESTIONS + 1]; u8 partyOrder[MULTI_PARTY_SIZE]; u8 partySlot; + u8 rand; u8 i, j; - u8 rand1, rand2; u8 id; for (i = 0; i < ARRAY_COUNT(partyOrder); i++) partyOrder[i] = i; - // Shuffle the party an arbitrary 10 times - for (i = 0; i < 10; i++) - { - u8 temp; - rand1 = Random() % ARRAY_COUNT(partyOrder); - rand2 = Random() % ARRAY_COUNT(partyOrder); - SWAP(partyOrder[rand1], partyOrder[rand2], temp); - } + Shuffle(partyOrder, MULTI_PARTY_SIZE, sizeof(partyOrder[0])); for (i = 0; i < ARRAY_COUNT(questionOrder); i++) questionOrder[i] = sQuestionPossibilities[i]; - // Shuffle the questions an arbitrary 50 times - for (i = 0; i < 50; i++) - { - u8 temp; - rand1 = Random() % ARRAY_COUNT(questionOrder); - rand2 = Random() % ARRAY_COUNT(questionOrder); - SWAP(questionOrder[rand1], questionOrder[rand2], temp); - } + Shuffle(questionOrder, APPRENTICE_MAX_QUESTIONS + 1, sizeof(questionOrder[0])); gApprenticePartyMovesData = AllocZeroed(sizeof(*gApprenticePartyMovesData)); gApprenticePartyMovesData->moveCounter = 0; @@ -302,16 +281,16 @@ static void SetRandomQuestionData(void) { do { - rand1 = Random() % MAX_MON_MOVES; + rand = Random() % MAX_MON_MOVES; for (j = 0; j < gApprenticePartyMovesData->moveCounter + 1; j++) { - if (gApprenticePartyMovesData->moveSlots[id][j] == rand1) + if (gApprenticePartyMovesData->moveSlots[id][j] == rand) break; } } while (j != gApprenticePartyMovesData->moveCounter + 1); - gApprenticePartyMovesData->moveSlots[id][gApprenticePartyMovesData->moveCounter] = rand1; - PLAYER_APPRENTICE.questions[i].moveSlot = rand1; + gApprenticePartyMovesData->moveSlots[id][gApprenticePartyMovesData->moveCounter] = rand; + PLAYER_APPRENTICE.questions[i].moveSlot = rand; PLAYER_APPRENTICE.questions[i].data = GetRandomAlternateMove(PLAYER_APPRENTICE.questions[i].monId); } } diff --git a/src/battle_pike.c b/src/battle_pike.c index 0692b68063..4a2065be44 100644 --- a/src/battle_pike.c +++ b/src/battle_pike.c @@ -886,14 +886,8 @@ static bool8 TryInflictRandomStatus(void) for (i = 0; i < FRONTIER_PARTY_SIZE; i++) indices[i] = i; - for (j = 0; j < 10; j++) - { - u8 temp, id; - i = Random() % FRONTIER_PARTY_SIZE; - id = Random() % FRONTIER_PARTY_SIZE; - SWAP(indices[i], indices[id], temp); - } + Shuffle(indices, FRONTIER_PARTY_SIZE, sizeof(indices[0])); if (gSaveBlock2Ptr->frontier.curChallengeBattleNum <= 4) count = 1; @@ -1265,7 +1259,7 @@ static void Task_DoStatusInflictionScreenFlash(u8 taskId) static void TryHealMons(u8 healCount) { - u8 j, i, k; + u8 j, i; u8 indices[FRONTIER_PARTY_SIZE]; if (healCount == 0) @@ -1276,15 +1270,7 @@ static void TryHealMons(u8 healCount) // Only 'healCount' number of pokemon will be healed. // The order in which they're (attempted to be) healed is random, - // and determined by performing 10 random swaps to this index array. - for (k = 0; k < 10; k++) - { - u8 temp; - - i = Random() % FRONTIER_PARTY_SIZE; - j = Random() % FRONTIER_PARTY_SIZE; - SWAP(indices[i], indices[j], temp); - } + Shuffle(indices, FRONTIER_PARTY_SIZE, sizeof(indices[0])); for (i = 0; i < FRONTIER_PARTY_SIZE; i++) { diff --git a/src/mauville_old_man.c b/src/mauville_old_man.c index 0b4a950ad5..0c0714354a 100644 --- a/src/mauville_old_man.c +++ b/src/mauville_old_man.c @@ -320,11 +320,7 @@ static void InitGiddyTaleList(void) // Shuffle question list for (i = 0; i < GIDDY_MAX_QUESTIONS; i++) giddy->questionList[i] = i; - for (i = 0; i < GIDDY_MAX_QUESTIONS; i++) - { - var = Random() % (i + 1); - SWAP(giddy->questionList[i], giddy->questionList[var], temp); - } + Shuffle(giddy->questionList, GIDDY_MAX_QUESTIONS, sizeof(giddy->questionList[0])); // Count total number of words in above word groups totalWords = 0; @@ -1265,27 +1261,12 @@ static void StorytellerRecordNewStat(u32 player, u32 stat) sStorytellerPtr->language[player] = gGameLanguage; } -static void ScrambleStatList(u8 *arr, s32 count) -{ - s32 i; - - for (i = 0; i < count; i++) - arr[i] = i; - for (i = 0; i < count; i++) - { - u32 a = Random() % count; - u32 b = Random() % count; - u8 temp; - SWAP(arr[a], arr[b], temp); - } -} - static bool8 StorytellerInitializeRandomStat(void) { u8 storyIds[sNumStories]; s32 i, j; - ScrambleStatList(storyIds, sNumStories); + Shuffle(storyIds, sNumStories, sizeof(storyIds[0])); for (i = 0; i < sNumStories; i++) { u8 stat = sStorytellerStories[storyIds[i]].stat; @@ -1427,4 +1408,3 @@ bool8 Script_StorytellerInitializeRandomStat(void) sStorytellerPtr = &gSaveBlock1Ptr->oldMan.storyteller; return StorytellerInitializeRandomStat(); } - diff --git a/src/mirage_tower.c b/src/mirage_tower.c index b1e2e5003b..78dec7a15b 100644 --- a/src/mirage_tower.c +++ b/src/mirage_tower.c @@ -598,13 +598,9 @@ static void DoMirageTowerDisintegration(u8 taskId) sFallingTower[index].disintegrateRand[i] = i; // Randomize disintegration pattern - for (i = 0; i <= (INNER_BUFFER_LENGTH - 1); i++) - { - u16 rand1, rand2, temp; - rand1 = Random() % INNER_BUFFER_LENGTH; - rand2 = Random() % INNER_BUFFER_LENGTH; - SWAP(sFallingTower[index].disintegrateRand[rand2], sFallingTower[index].disintegrateRand[rand1], temp); - } + Shuffle(sFallingTower[index].disintegrateRand, INNER_BUFFER_LENGTH, + sizeof(sFallingTower[index].disintegrateRand[0])); + if (gTasks[taskId].data[3] <= (OUTER_BUFFER_LENGTH - 1)) gTasks[taskId].data[3]++; gTasks[taskId].data[1] = 0; @@ -702,13 +698,8 @@ static void Task_FossilFallAndSink(u8 taskId) break; case 6: // Randomize disintegration pattern - for (i = 0; i < FOSSIL_DISINTEGRATE_LENGTH * sizeof(u16); i++) - { - u16 rand1, rand2, temp; - rand1 = Random() % FOSSIL_DISINTEGRATE_LENGTH; - rand2 = Random() % FOSSIL_DISINTEGRATE_LENGTH; - SWAP(sFallingFossil->disintegrateRand[rand2], sFallingFossil->disintegrateRand[rand1], temp); - } + Shuffle(sFallingFossil->disintegrateRand, FOSSIL_DISINTEGRATE_LENGTH, + sizeof(sFallingFossil->disintegrateRand[0])); gSprites[sFallingFossil->spriteId].callback = SpriteCB_FallingFossil; break; case 7: diff --git a/src/tv.c b/src/tv.c index 306d0fc9e3..0211ef71e2 100644 --- a/src/tv.c +++ b/src/tv.c @@ -1956,7 +1956,6 @@ void AlertTVThatPlayerPlayedRoulette(u16 nCoinsSpent) static void SecretBaseVisit_CalculateDecorationData(TVShow *show) { u8 i, j; - u16 k; u8 n; u8 decoration; @@ -2002,12 +2001,7 @@ static void SecretBaseVisit_CalculateDecorationData(TVShow *show) break; default: // More than 1 decoration, randomize the full list - for (k = 0; k < n * n; k++) - { - decoration = Random() % n; - j = Random() % n; - SWAP(sTV_DecorationsBuffer[decoration], sTV_DecorationsBuffer[j], i); - } + Shuffle(sTV_DecorationsBuffer, n, sizeof(sTV_DecorationsBuffer[0])); // Pick the first decorations in the randomized list to talk about on the show for (i = 0; i < show->secretBaseVisit.numDecorations; i++) diff --git a/src/wild_encounter.c b/src/wild_encounter.c index 13b92136f8..f4412c479a 100644 --- a/src/wild_encounter.c +++ b/src/wild_encounter.c @@ -385,7 +385,6 @@ static u16 GetCurrentMapWildMonHeaderId(void) u8 PickWildMonNature(void) { u8 i; - u8 j; struct Pokeblock *safariPokeblock; u8 natures[NUM_NATURES]; @@ -396,17 +395,7 @@ u8 PickWildMonNature(void) { for (i = 0; i < NUM_NATURES; i++) natures[i] = i; - for (i = 0; i < NUM_NATURES - 1; i++) - { - for (j = i + 1; j < NUM_NATURES; j++) - { - if (Random() & 1) - { - u8 temp; - SWAP(natures[i], natures[j], temp); - } - } - } + Shuffle(natures, NUM_NATURES, sizeof(natures[0])); for (i = 0; i < NUM_NATURES; i++) { if (PokeblockGetGain(natures[i], safariPokeblock) > 0) From 28f17772ec95ee33320caa97216919a9b7891751 Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Thu, 28 Dec 2023 04:47:00 -0600 Subject: [PATCH 07/13] Implement Pokemon Box Link functionality (#3837) * Implement Pokemon Box Link functionality * Update item_use.c * Update item_use.c * Can only use box link if the map allows escape * Revert "Can only use box link if the map allows escape" This reverts commit be5b46b6c4420cd350ac1932d4c3562f7bfbebe5. * Overworld_IsEscapingAllowed --------- Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- data/scripts/pc.inc | 8 ++++++++ include/event_scripts.h | 1 + include/item_use.h | 1 + src/data/items.h | 4 ++-- src/item_use.c | 13 +++++++++++++ 5 files changed, 25 insertions(+), 2 deletions(-) diff --git a/data/scripts/pc.inc b/data/scripts/pc.inc index 1993aaf63f..e4e37f5b43 100644 --- a/data/scripts/pc.inc +++ b/data/scripts/pc.inc @@ -64,3 +64,11 @@ EventScript_AccessHallOfFame:: waitstate goto EventScript_AccessPC end + +EventScript_AccessPokemonBoxLink:: + playse SE_PC_LOGIN + msgbox gText_StorageSystemOpened, MSGBOX_DEFAULT + special ShowPokemonStorageSystemPC + waitstate + goto EventScript_TurnOffPC + end diff --git a/include/event_scripts.h b/include/event_scripts.h index 1539356959..8df303ca33 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -515,6 +515,7 @@ extern const u8 MauvilleCity_PokemonCenter_1F_Text_HotSpringsStory[]; extern const u8 LittlerootTown_BrendansHouse_2F_EventScript_PC[]; extern const u8 LittlerootTown_MaysHouse_2F_EventScript_PC[]; extern const u8 EventScript_PC[]; +extern const u8 EventScript_AccessPokemonBoxLink[]; extern const u8 EventScript_TestSignpostMsg[]; extern const u8 EventScript_HiddenItemScript[]; extern const u8 EventScript_TV[]; diff --git a/include/item_use.h b/include/item_use.h index d073e9d3ea..a5fe1ee97f 100644 --- a/include/item_use.h +++ b/include/item_use.h @@ -7,6 +7,7 @@ void ItemUseOutOfBattle_Rod(u8); void ItemUseOutOfBattle_Itemfinder(u8); void ItemUseOutOfBattle_PokeblockCase(u8); void ItemUseOutOfBattle_CoinCase(u8); +void ItemUseOutOfBattle_PokemonBoxLink(u8); void ItemUseOutOfBattle_PowderJar(u8); void ItemUseOutOfBattle_SSTicket(u8); void ItemUseOutOfBattle_WailmerPail(u8); diff --git a/src/data/items.h b/src/data/items.h index 4bb19b4c9a..6646ab98c6 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -10186,8 +10186,8 @@ const struct Item gItems[] = "Storage System."), .importance = 1, .pocket = POCKET_KEY_ITEMS, - .type = ITEM_USE_BAG_MENU, - .fieldUseFunc = ItemUseOutOfBattle_CannotUse, // Todo + .type = ITEM_USE_FIELD, + .fieldUseFunc = ItemUseOutOfBattle_PokemonBoxLink, }, [ITEM_COIN_CASE] = diff --git a/src/item_use.c b/src/item_use.c index 344122e8b3..b16169a9ba 100644 --- a/src/item_use.c +++ b/src/item_use.c @@ -58,6 +58,7 @@ static u8 GetDirectionToHiddenItem(s16, s16); static void PlayerFaceHiddenItem(u8); static void CheckForHiddenItemsInMapConnection(u8); static void Task_OpenRegisteredPokeblockCase(u8); +static void Task_AccessPokemonBoxLink(u8); static void ItemUseOnFieldCB_Bike(u8); static void ItemUseOnFieldCB_Rod(u8); static void ItemUseOnFieldCB_Itemfinder(u8); @@ -680,6 +681,18 @@ static void Task_OpenRegisteredPokeblockCase(u8 taskId) } } +void ItemUseOutOfBattle_PokemonBoxLink(u8 taskId) +{ + sItemUseOnFieldCB = Task_AccessPokemonBoxLink; + SetUpItemUseOnFieldCallback(taskId); +} + +static void Task_AccessPokemonBoxLink(u8 taskId) +{ + ScriptContext_SetupScript(EventScript_AccessPokemonBoxLink); + DestroyTask(taskId); +} + void ItemUseOutOfBattle_CoinCase(u8 taskId) { ConvertIntToDecimalStringN(gStringVar1, GetCoins(), STR_CONV_MODE_LEFT_ALIGN, 4); From 872ddf32c6cf8be3b2e8783c52a454f15fa9786c Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Thu, 28 Dec 2023 12:21:52 +0100 Subject: [PATCH 08/13] The Indigo Disk Moves (#3704) * Draft Indigo Disk move data * Add basic defines (flags, targets and priority missing) * Update move flags * Temper Flare is Stomping Tantrum * Forgot to push, please squash :D * Fix failing tests --- data/battle_anim_scripts.s | 45 ++++-- include/config/battle.h | 1 + include/constants/moves.h | 32 ++-- include/pokemon.h | 1 + src/battle_script_commands.c | 4 +- src/data/battle_moves.h | 241 +++++++++++++++++++++++++++++- src/data/contest_moves.h | 30 ++++ src/data/text/move_descriptions.h | 63 ++++++++ src/data/text/move_names.h | 30 ++++ test/battle/ai_check_viability.c | 8 +- 10 files changed, 414 insertions(+), 41 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 4cdb0ecb99..389af990e6 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -860,21 +860,21 @@ gBattleAnims_Moves:: .4byte Move_MATCHA_GOTCHA .4byte Move_SYRUP_BOMB .4byte Move_IVY_CUDGEL - .4byte Move_833 - .4byte Move_834 - .4byte Move_835 - .4byte Move_836 - .4byte Move_837 - .4byte Move_838 - .4byte Move_839 - .4byte Move_840 - .4byte Move_841 - .4byte Move_842 - .4byte Move_843 - .4byte Move_844 - .4byte Move_845 - .4byte Move_846 - .4byte Move_847 + .4byte Move_ELECTRO_SHOT + .4byte Move_TERA_STARSTORM + .4byte Move_FICKLE_BEAM + .4byte Move_BURNING_BULWARK + .4byte Move_THUNDERCLAP + .4byte Move_MIGHTY_CLEAVE + .4byte Move_TACHYON_CUTTER + .4byte Move_HARD_PRESS + .4byte Move_DRAGON_CHEER + .4byte Move_ALLURING_VOICE + .4byte Move_TEMPER_FLARE + .4byte Move_SUPERCELL_SLAM + .4byte Move_PSYCHIC_NOISE + .4byte Move_UPPER_HAND + .4byte Move_MALIGNANT_CHAIN @@@@ Z MOVES .4byte Move_BREAKNECK_BLITZ .4byte Move_ALL_OUT_PUMMELING @@ -16977,6 +16977,21 @@ Move_HYDRO_STEAM:: Move_BLOOD_MOON:: Move_MATCHA_GOTCHA:: Move_IVY_CUDGEL:: +Move_ELECTRO_SHOT:: +Move_TERA_STARSTORM:: +Move_FICKLE_BEAM:: +Move_BURNING_BULWARK:: +Move_THUNDERCLAP:: +Move_MIGHTY_CLEAVE:: +Move_TACHYON_CUTTER:: +Move_HARD_PRESS:: +Move_DRAGON_CHEER:: +Move_ALLURING_VOICE:: +Move_TEMPER_FLARE:: +Move_SUPERCELL_SLAM:: +Move_PSYCHIC_NOISE:: +Move_UPPER_HAND:: +Move_MALIGNANT_CHAIN:: end @to do @@@@@@@@@@@@@@@@@@@@@@@ GEN 1-3 @@@@@@@@@@@@@@@@@@@@@@@ diff --git a/include/config/battle.h b/include/config/battle.h index 7e0f05a819..5f2b8e29ff 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -113,6 +113,7 @@ #define B_QUICK_GUARD GEN_LATEST // In Gen5 only, Wide Guard has a chance to fail if used consecutively. #define B_IMPRISON GEN_LATEST // In Gen5+, Imprison doesn't fail if opposing pokemon don't have any moves the user knows. #define B_ALLY_SWITCH_FAIL_CHANCE GEN_LATEST // In Gen9, using Ally Switch consecutively decreases the chance of success for each consecutive use. +#define B_SKETCH_BANS GEN_LATEST // In Gen9+, Sketch is unable to copy more moves than in previous generations. // Ability settings #define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters. diff --git a/include/constants/moves.h b/include/constants/moves.h index 54b366e18b..a0c0eaf3b3 100644 --- a/include/constants/moves.h +++ b/include/constants/moves.h @@ -886,25 +886,27 @@ #define MOVE_MAGICAL_TORQUE 826 #define MOVE_PSYBLADE 827 #define MOVE_HYDRO_STEAM 828 +// The Teal Mask Moves #define MOVE_BLOOD_MOON 829 #define MOVE_MATCHA_GOTCHA 830 #define MOVE_SYRUP_BOMB 831 #define MOVE_IVY_CUDGEL 832 -#define MOVE_833 833 -#define MOVE_834 834 -#define MOVE_835 835 -#define MOVE_836 836 -#define MOVE_837 837 -#define MOVE_838 838 -#define MOVE_839 839 -#define MOVE_840 840 -#define MOVE_841 841 -#define MOVE_842 842 -#define MOVE_843 843 -#define MOVE_844 844 -#define MOVE_845 845 -#define MOVE_846 846 -#define MOVE_847 847 +// The Indigo Disk Moves +#define MOVE_ELECTRO_SHOT 833 +#define MOVE_TERA_STARSTORM 834 +#define MOVE_FICKLE_BEAM 835 +#define MOVE_BURNING_BULWARK 836 +#define MOVE_THUNDERCLAP 837 +#define MOVE_MIGHTY_CLEAVE 838 +#define MOVE_TACHYON_CUTTER 839 +#define MOVE_HARD_PRESS 840 +#define MOVE_DRAGON_CHEER 841 +#define MOVE_ALLURING_VOICE 842 +#define MOVE_TEMPER_FLARE 843 +#define MOVE_SUPERCELL_SLAM 844 +#define MOVE_PSYCHIC_NOISE 845 +#define MOVE_UPPER_HAND 846 +#define MOVE_MALIGNANT_CHAIN 847 #define MOVES_COUNT_GEN9 848 diff --git a/include/pokemon.h b/include/pokemon.h index dda784629a..ae93f5fa92 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -504,6 +504,7 @@ struct BattleMove u32 encoreBanned:1; u32 parentalBondBanned:1; u32 skyBattleBanned:1; + u32 sketchBanned:1; u16 argument; }; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 290895a80b..4d773c6e9a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -12693,10 +12693,8 @@ static void Cmd_copymovepermanently(void) gChosenMove = MOVE_UNAVAILABLE; if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED) - && gLastPrintedMoves[gBattlerTarget] != MOVE_STRUGGLE - && gLastPrintedMoves[gBattlerTarget] != MOVE_NONE && gLastPrintedMoves[gBattlerTarget] != MOVE_UNAVAILABLE - && gLastPrintedMoves[gBattlerTarget] != MOVE_SKETCH) + && !gBattleMoves[gLastPrintedMoves[gBattlerTarget]].sketchBanned) { s32 i; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 8284bbe664..10a626c029 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -13,6 +13,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .category = BATTLE_CATEGORY_PHYSICAL, .metronomeBanned = TRUE, .mirrorMoveBanned = TRUE, + .sketchBanned = TRUE, }, [MOVE_POUND] = @@ -2844,6 +2845,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, + .sketchBanned = TRUE, }, [MOVE_SKETCH] = @@ -2868,6 +2870,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, + .sketchBanned = TRUE, }, [MOVE_TRIPLE_KICK] = @@ -3063,6 +3066,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .target = MOVE_TARGET_SELECTED, .priority = 0, .category = BATTLE_CATEGORY_SPECIAL, + .windMove = TRUE, }, [MOVE_COTTON_SPORE] = @@ -5117,7 +5121,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_LUSTER_PURGE] = { .effect = EFFECT_SPECIAL_DEFENSE_DOWN_HIT, - .power = 70, + .power = (B_UPDATED_MOVE_DATA >= GEN_9) ? 95 : 70, .type = TYPE_PSYCHIC, .accuracy = 100, .pp = 5, @@ -5131,7 +5135,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_MIST_BALL] = { .effect = EFFECT_SPECIAL_ATTACK_DOWN_HIT, - .power = 70, + .power = (B_UPDATED_MOVE_DATA >= GEN_9) ? 95 : 70, .type = TYPE_PSYCHIC, .accuracy = 100, .pp = 5, @@ -7900,6 +7904,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .category = BATTLE_CATEGORY_STATUS, .zMove = { .effect = Z_EFFECT_RESET_STATS }, .magicCoatAffected = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), }, [MOVE_SEED_FLARE] = @@ -10463,6 +10468,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .ignoresProtect = TRUE, .ignoresSubstitute = TRUE, .metronomeBanned = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), }, [MOVE_SHORE_UP] = @@ -13220,6 +13226,8 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .ignoresProtect = TRUE, .mirrorMoveBanned = TRUE, .metronomeBanned = TRUE, + .healBlockBanned = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), }, [MOVE_SALT_CURE] = @@ -13620,7 +13628,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .category = BATTLE_CATEGORY_PHYSICAL, .makesContact = TRUE, .slicingMove = TRUE, - .healBlockBanned = B_EXTRAPOLATED_MOVE_FLAGS, + .healBlockBanned = TRUE, }, [MOVE_DOUBLE_SHOCK] = @@ -13704,6 +13712,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), }, [MOVE_WICKED_TORQUE] = @@ -13727,6 +13736,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), }, [MOVE_NOXIOUS_TORQUE] = @@ -13750,6 +13760,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), }, [MOVE_COMBAT_TORQUE] = @@ -13773,6 +13784,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), }, [MOVE_MAGICAL_TORQUE] = @@ -13796,6 +13808,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .instructBanned = TRUE, .encoreBanned = TRUE, .assistBanned = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), }, [MOVE_PSYBLADE] = @@ -13854,7 +13867,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .category = BATTLE_CATEGORY_SPECIAL, .thawsUser = TRUE, .metronomeBanned = TRUE, - .healBlockBanned = B_EXTRAPOLATED_MOVE_FLAGS, + .healBlockBanned = TRUE, }, [MOVE_SYRUP_BOMB] = @@ -13888,6 +13901,226 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = .metronomeBanned = TRUE, }, + [MOVE_ELECTRO_SHOT] = + { + .effect = EFFECT_PLACEHOLDER, //EFFECT_ELECTRO_SHOT + .power = 130, + .type = TYPE_ELECTRIC, + .accuracy = 100, + .pp = 10, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_SPECIAL, + //.sheerForceBoost = TRUE, (uncomment when effect is implemented, otherwise it breaks the Sheer Force Test) + }, + + [MOVE_TERA_STARSTORM] = + { + .effect = EFFECT_PLACEHOLDER, //EFFECT_TERA_STARSTORM + .power = 120, + .type = TYPE_NORMAL, // Stellar type if used by Terapagos-Stellar + .accuracy = 100, + .pp = 5, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, // MOVE_TARGET_BOTH if used by Terapagos-Stellar + .priority = 0, + .category = BATTLE_CATEGORY_SPECIAL, + .assistBanned = TRUE, + .copycatBanned = TRUE, + .mimicBanned = TRUE, + .sketchBanned = (B_SKETCH_BANS >= GEN_9), + }, + + [MOVE_FICKLE_BEAM] = + { + .effect = EFFECT_PLACEHOLDER, //EFFECT_FICKLE_BEAM + .power = 80, + .type = TYPE_DRAGON, + .accuracy = 100, + .pp = 5, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_SPECIAL, + }, + + [MOVE_BURNING_BULWARK] = + { + .effect = EFFECT_PROTECT, // NEEDS ACTUAL PROTECT SIDE EFFECT + .power = 0, + .type = TYPE_FIRE, + .accuracy = 0, + .pp = 10, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_USER, + .priority = 4, + .category = BATTLE_CATEGORY_STATUS, + .zMove = { .effect = Z_EFFECT_RESET_STATS }, + .protectionMove = TRUE, + .ignoresProtect = TRUE, + .mirrorMoveBanned = TRUE, + .metronomeBanned = TRUE, + .copycatBanned = TRUE, + .assistBanned = TRUE, + }, + + [MOVE_THUNDERCLAP] = + { + .effect = EFFECT_SUCKER_PUNCH, + .power = 70, + .type = TYPE_ELECTRIC, + .accuracy = 100, + .pp = 5, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 1, + .category = BATTLE_CATEGORY_SPECIAL, + }, + + [MOVE_MIGHTY_CLEAVE] = + { + .effect = EFFECT_FEINT, + .power = 95, + .type = TYPE_ROCK, + .accuracy = 100, + .pp = 5, + .secondaryEffectChance = 100, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_PHYSICAL, + .makesContact = TRUE, + .slicingMove = TRUE, + }, + + [MOVE_TACHYON_CUTTER] = + { + .effect = EFFECT_HIT, + .power = 50, + .type = TYPE_STEEL, + .accuracy = 0, + .pp = 10, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_SPECIAL, + .strikeCount = 2, + .slicingMove = TRUE, + }, + + [MOVE_HARD_PRESS] = + { + .effect = EFFECT_WRING_OUT, + .power = 1, + .type = TYPE_STEEL, + .accuracy = 100, + .pp = 10, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_PHYSICAL, + .makesContact = TRUE, + }, + + [MOVE_DRAGON_CHEER] = + { + .effect = EFFECT_PLACEHOLDER, //EFFECT_DRAGON_CHEER + .power = 0, + .type = TYPE_DRAGON, + .accuracy = 0, + .pp = 15, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_ALLY, + .priority = 0, + .category = BATTLE_CATEGORY_STATUS, + .ignoresSubstitute = TRUE, + }, + + [MOVE_ALLURING_VOICE] = + { + .effect = EFFECT_PLACEHOLDER, //EFFECT_ALLURING_VOICE + .power = 80, + .type = TYPE_FAIRY, + .accuracy = 100, + .pp = 10, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_SPECIAL, + .soundMove = TRUE, + .ignoresSubstitute = TRUE, + }, + + [MOVE_TEMPER_FLARE] = + { + .effect = EFFECT_STOMPING_TANTRUM, + .power = 75, + .type = TYPE_FIRE, + .accuracy = 100, + .pp = 10, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_PHYSICAL, + .makesContact = TRUE, + }, + + [MOVE_SUPERCELL_SLAM] = + { + .effect = EFFECT_RECOIL_IF_MISS, + .power = 100, + .type = TYPE_ELECTRIC, + .accuracy = 95, + .pp = 15, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_PHYSICAL, + .makesContact = TRUE, + }, + + [MOVE_PSYCHIC_NOISE] = + { + .effect = EFFECT_PLACEHOLDER, //EFFECT_PSYCHIC_NOISE + .power = 75, + .type = TYPE_PSYCHIC, + .accuracy = 100, + .pp = 10, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_SPECIAL, + .soundMove = TRUE, + .ignoresSubstitute = TRUE, + }, + + [MOVE_UPPER_HAND] = + { + .effect = EFFECT_PLACEHOLDER, //EFFECT_UPPER_HAND + .power = 65, + .type = TYPE_FIGHTING, + .accuracy = 100, + .pp = 15, + .secondaryEffectChance = 0, + .target = MOVE_TARGET_SELECTED, + .priority = 3, + .category = BATTLE_CATEGORY_PHYSICAL, + .makesContact = TRUE, + }, + + [MOVE_MALIGNANT_CHAIN] = + { + .effect = EFFECT_POISON_FANG, + .power = 100, + .type = TYPE_POISON, + .accuracy = 100, + .pp = 5, + .secondaryEffectChance = 50, + .target = MOVE_TARGET_SELECTED, + .priority = 0, + .category = BATTLE_CATEGORY_SPECIAL, + }, + // Z-Moves [MOVE_BREAKNECK_BLITZ] = { diff --git a/src/data/contest_moves.h b/src/data/contest_moves.h index 6084091683..8167f25104 100644 --- a/src/data/contest_moves.h +++ b/src/data/contest_moves.h @@ -6074,6 +6074,36 @@ const struct ContestMove gContestMoves[MOVES_COUNT] = [MOVE_SYRUP_BOMB] = {0}, // TODO [MOVE_IVY_CUDGEL] = {0}, // TODO + + [MOVE_ELECTRO_SHOT] = {0}, // TODO + + [MOVE_TERA_STARSTORM] = {0}, // TODO + + [MOVE_FICKLE_BEAM] = {0}, // TODO + + [MOVE_BURNING_BULWARK] = {0}, // TODO + + [MOVE_THUNDERCLAP] = {0}, // TODO + + [MOVE_MIGHTY_CLEAVE] = {0}, // TODO + + [MOVE_TACHYON_CUTTER] = {0}, // TODO + + [MOVE_HARD_PRESS] = {0}, // TODO + + [MOVE_DRAGON_CHEER] = {0}, // TODO + + [MOVE_ALLURING_VOICE] = {0}, // TODO + + [MOVE_TEMPER_FLARE] = {0}, // TODO + + [MOVE_SUPERCELL_SLAM] = {0}, // TODO + + [MOVE_PSYCHIC_NOISE] = {0}, // TODO + + [MOVE_UPPER_HAND] = {0}, // TODO + + [MOVE_MALIGNANT_CHAIN] = {0}, // TODO }; const struct ContestEffect gContestEffects[] = diff --git a/src/data/text/move_descriptions.h b/src/data/text/move_descriptions.h index c321a844b1..4aa7293036 100644 --- a/src/data/text/move_descriptions.h +++ b/src/data/text/move_descriptions.h @@ -3284,6 +3284,54 @@ static const u8 sIvyCudgelDescription[] = _( "Type changes with held mask.\n" "High critical-hit ratio."); +static const u8 sElectroShotDescription[] = _( + "Absorbs electricity in one turn,\n" + "then attacks next turn."); + +static const u8 sTeraStarstormDescription[] = _( + "Damages all opponents if user is\n" + "Stellar form Terapagos."); + +static const u8 sFickleBeamDescription[] = _( + "Shoots a beam of light. Sometimes\n" + "twice as strong."); + +static const u8 sBurningBulwarkDescription[] = _( + "Evades attack, and burns\n" + "the foe if struck."); + +static const u8 sTachyonCutterDescription[] = _( + "Launches particle blades at\n" + "the target. Strikes twice."); + +static const u8 sDragonCheerDescription[] = _( + "Increases allies' critical hit\n" + "ration, especially if Dragons."); + +static const u8 sAlluringVoiceDescription[] = _( + "Confuses the target if their\n" + "stats were boosted this turn."); + +static const u8 sTemperFlareDescription[] = _( + "A desperation attack. Power\n" + "doubles if last move failed."); + +static const u8 sSupercellSlamDescription[] = _( + "An electrified slam. If it\n" + "misses, the user is hurt."); + +static const u8 sPsychicNoiseDescription[] = _( + "Unpleasant sound waves that\n" + "damage and prevent healing."); + +static const u8 sUpperHandDescription[] = _( + "Makes the target flinch if\n" + "readying a priority move."); + +static const u8 sMalignantChainDescription[] = _( + "A corrosive chain attack\n" + "that may badly poison."); + const u8 gNotDoneYetDescription[] = _( "This move can't be used. Its\n" "effect is in development."); @@ -4127,4 +4175,19 @@ const u8 *const gMoveDescriptionPointers[MOVES_COUNT - 1] = [MOVE_MATCHA_GOTCHA - 1] = sMatchaGotchaDescription, [MOVE_SYRUP_BOMB - 1] = sSyrupBombDescription, [MOVE_IVY_CUDGEL - 1] = sIvyCudgelDescription, + [MOVE_ELECTRO_SHOT - 1] = sElectroShotDescription, + [MOVE_TERA_STARSTORM - 1] = sTeraStarstormDescription, + [MOVE_FICKLE_BEAM - 1] = sFickleBeamDescription, + [MOVE_BURNING_BULWARK - 1] = sBurningBulwarkDescription, + [MOVE_THUNDERCLAP - 1] = sSuckerPunchDescription, + [MOVE_MIGHTY_CLEAVE - 1] = sFeintDescription, + [MOVE_TACHYON_CUTTER - 1] = sTachyonCutterDescription, + [MOVE_HARD_PRESS - 1] = sWringOutDescription, + [MOVE_DRAGON_CHEER - 1] = sDragonCheerDescription, + [MOVE_ALLURING_VOICE - 1] = sAlluringVoiceDescription, + [MOVE_TEMPER_FLARE - 1] = sTemperFlareDescription, + [MOVE_SUPERCELL_SLAM - 1] = sSupercellSlamDescription, + [MOVE_PSYCHIC_NOISE - 1] = sPsychicNoiseDescription, + [MOVE_UPPER_HAND - 1] = sUpperHandDescription, + [MOVE_MALIGNANT_CHAIN - 1] = sMalignantChainDescription, }; diff --git a/src/data/text/move_names.h b/src/data/text/move_names.h index 01d613751e..f69b1f96a7 100644 --- a/src/data/text/move_names.h +++ b/src/data/text/move_names.h @@ -835,6 +835,21 @@ const u8 gMoveNames[MOVES_COUNT_DYNAMAX][MOVE_NAME_LENGTH + 1] = [MOVE_MATCHA_GOTCHA] = _("Matcha Gotcha"), [MOVE_SYRUP_BOMB] = _("Syrup Bomb"), [MOVE_IVY_CUDGEL] = _("Ivy Cudgel"), + [MOVE_ELECTRO_SHOT] = _("Electro Shot"), + [MOVE_TERA_STARSTORM] = _("Tera Starstorm"), + [MOVE_FICKLE_BEAM] = _("Fickle Beam"), + [MOVE_BURNING_BULWARK] = _("Burning Bulwark"), + [MOVE_THUNDERCLAP] = _("Thunderclap"), + [MOVE_MIGHTY_CLEAVE] = _("Mighty Cleave"), + [MOVE_TACHYON_CUTTER] = _("Tachyon Cutter"), + [MOVE_HARD_PRESS] = _("Hard Press"), + [MOVE_DRAGON_CHEER] = _("Dragon Cheer"), + [MOVE_ALLURING_VOICE] = _("Alluring Voice"), + [MOVE_TEMPER_FLARE] = _("Temper Flare"), + [MOVE_SUPERCELL_SLAM] = _("Supercell Slam"), + [MOVE_PSYCHIC_NOISE] = _("Psychic Noise"), + [MOVE_UPPER_HAND] = _("Upper Hand"), + [MOVE_MALIGNANT_CHAIN] = _("Malignant Chain"), // Max Moves [MOVE_MAX_GUARD] = _("Max Guard"), [MOVE_MAX_STRIKE] = _("Max Strike"), @@ -1727,6 +1742,21 @@ const u8 gMoveNames[MOVES_COUNT_DYNAMAX][MOVE_NAME_LENGTH + 1] = [MOVE_MATCHA_GOTCHA] = _("MatchaGotcha"), [MOVE_SYRUP_BOMB] = _("Syrup Bomb"), [MOVE_IVY_CUDGEL] = _("Ivy Cudgel"), + [MOVE_ELECTRO_SHOT] = _("Electro Shot"), + [MOVE_TERA_STARSTORM] = _("TeraStarstrm"), + [MOVE_FICKLE_BEAM] = _("Fickle Beam"), + [MOVE_BURNING_BULWARK] = _("BurnngBulwrk"), + [MOVE_THUNDERCLAP] = _("Thunderclap"), + [MOVE_MIGHTY_CLEAVE] = _("MightyCleave"), + [MOVE_TACHYON_CUTTER] = _("TachyonCuttr"), + [MOVE_HARD_PRESS] = _("Hard Press"), + [MOVE_DRAGON_CHEER] = _("Dragon Cheer"), + [MOVE_ALLURING_VOICE] = _("AllurngVoice"), + [MOVE_TEMPER_FLARE] = _("Temper Flare"), + [MOVE_SUPERCELL_SLAM] = _("SuprcellSlam"), + [MOVE_PSYCHIC_NOISE] = _("PsychicNoise"), + [MOVE_UPPER_HAND] = _("Upper Hand"), + [MOVE_MALIGNANT_CHAIN] = _("MalignntChan"), // Max Moves [MOVE_MAX_GUARD] = _("M-Guard"), [MOVE_MAX_STRIKE] = _("M-Strike"), diff --git a/test/battle/ai_check_viability.c b/test/battle/ai_check_viability.c index 4666eca7cb..2f229e3aca 100644 --- a/test/battle/ai_check_viability.c +++ b/test/battle/ai_check_viability.c @@ -177,15 +177,15 @@ AI_SINGLE_BATTLE_TEST("AI chooses moves with secondary effect that have a 100% c AI_LOG; ASSUME(gBattleMoves[MOVE_SHADOW_BALL].effect == EFFECT_SPECIAL_DEFENSE_DOWN_HIT); ASSUME(gBattleMoves[MOVE_SHADOW_BALL].secondaryEffectChance == 20); - ASSUME(gBattleMoves[MOVE_LUSTER_PURGE].effect == EFFECT_SPECIAL_DEFENSE_DOWN_HIT); - ASSUME(gBattleMoves[MOVE_LUSTER_PURGE].secondaryEffectChance == 50); + ASSUME(gBattleMoves[MOVE_OCTAZOOKA].effect == EFFECT_ACCURACY_DOWN_HIT); + ASSUME(gBattleMoves[MOVE_OCTAZOOKA].secondaryEffectChance == 50); AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); PLAYER(SPECIES_REGICE); - OPPONENT(SPECIES_REGIROCK) { Ability(ability); Moves(MOVE_SHADOW_BALL, MOVE_LUSTER_PURGE); } + OPPONENT(SPECIES_REGIROCK) { Ability(ability); Moves(MOVE_SHADOW_BALL, MOVE_OCTAZOOKA); } } WHEN { if (ability == ABILITY_NONE) TURN { EXPECT_MOVE(opponent, MOVE_SHADOW_BALL); } else - TURN { EXPECT_MOVES(opponent, MOVE_LUSTER_PURGE); } + TURN { EXPECT_MOVES(opponent, MOVE_OCTAZOOKA); } } } From bc3737772aa688edfd7712d6451c1d3707af9328 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Thu, 28 Dec 2023 12:33:29 +0100 Subject: [PATCH 09/13] Define new abilities (#3838) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- include/constants/abilities.h | 8 ++++---- src/data/text/abilities.h | 16 ++++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/include/constants/abilities.h b/include/constants/abilities.h index 7e3b1728d9..3cced68bb1 100644 --- a/include/constants/abilities.h +++ b/include/constants/abilities.h @@ -332,10 +332,10 @@ #define ABILITY_EMBODY_ASPECT_CORNERSTONE 304 #define ABILITY_TOXIC_CHAIN 305 #define ABILITY_SUPERSWEET_SYRUP 306 -#define ABILITY_307 307 -#define ABILITY_308 308 -#define ABILITY_309 309 -#define ABILITY_310 310 +#define ABILITY_TERA_SHIFT 307 +#define ABILITY_TERA_SHELL 308 +#define ABILITY_TERAFORM_ZERO 309 +#define ABILITY_POISON_PUPPETEER 310 #define ABILITIES_COUNT_GEN9 311 diff --git a/src/data/text/abilities.h b/src/data/text/abilities.h index dc1ad9d4e5..d8ed29cf39 100644 --- a/src/data/text/abilities.h +++ b/src/data/text/abilities.h @@ -297,6 +297,10 @@ static const u8 sEmbodyAspectWellspringDescription[] = _("Raises Sp. Def."); static const u8 sEmbodyAspectCornerstoneDescription[] = _("Raises Defense."); static const u8 sToxicChainDescription[] = _("Moves can poison."); static const u8 sSupersweetSyrupDescription[] = _("Lowers the foe's Speed."); +static const u8 sTeraShiftDescription[] = _("Terasteralizes upon entry."); +static const u8 sTeraShellDescription[] = _("Resistant to types at full HP."); +static const u8 sTeraformZeroDescription[] = _("Removes weather and terrain."); +static const u8 sPoisonPuppeteerDescription[] = _("Confuses poisoned foes."); #if B_EXPANDED_ABILITY_NAMES == TRUE const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = @@ -608,6 +612,10 @@ const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = [ABILITY_EMBODY_ASPECT_CORNERSTONE] = _("Embody Aspect"), [ABILITY_TOXIC_CHAIN] = _("Toxic Chain"), [ABILITY_SUPERSWEET_SYRUP] = _("Supersweet Syrup"), + [ABILITY_TERA_SHIFT] = _("Tera Shift"), + [ABILITY_TERA_SHELL] = _("Tera Shell"), + [ABILITY_TERAFORM_ZERO] = _("Teraform Zero"), + [ABILITY_POISON_PUPPETEER] = _("Poison Puppeteer"), }; #else // 12 characters const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = @@ -919,6 +927,10 @@ const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = [ABILITY_EMBODY_ASPECT_CORNERSTONE] = _("EmbodyAspect"), [ABILITY_TOXIC_CHAIN] = _("Toxic Chain"), [ABILITY_SUPERSWEET_SYRUP] = _("SuprswtSyrup"), + [ABILITY_TERA_SHIFT] = _("Tera Shift"), + [ABILITY_TERA_SHELL] = _("Tera Shell"), + [ABILITY_TERAFORM_ZERO] = _("TeraformZero"), + [ABILITY_POISON_PUPPETEER] = _("PoisnPuppter"), }; #endif @@ -1231,4 +1243,8 @@ const u8 *const gAbilityDescriptionPointers[ABILITIES_COUNT] = [ABILITY_EMBODY_ASPECT_CORNERSTONE] = sEmbodyAspectCornerstoneDescription, [ABILITY_TOXIC_CHAIN] = sToxicChainDescription, [ABILITY_SUPERSWEET_SYRUP] = sSupersweetSyrupDescription, + [ABILITY_TERA_SHIFT] = sTeraShiftDescription, + [ABILITY_TERA_SHELL] = sTeraShellDescription, + [ABILITY_TERAFORM_ZERO] = sTeraformZeroDescription, + [ABILITY_POISON_PUPPETEER] = sPoisonPuppeteerDescription, }; From 1e958ada8c11505631f98c666292dac6f97d7daa Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Thu, 28 Dec 2023 16:00:34 -0600 Subject: [PATCH 10/13] Add Indigo Disk item data (#3854) --- graphics/items/icon_palettes/metal_alloy.pal | 18 +++++++++++++++ graphics/items/icons/metal_alloy.png | Bin 0 -> 299 bytes include/constants/items.h | 4 ++-- include/graphics.h | 2 ++ src/data/graphics/items.h | 3 +++ src/data/item_icon_table.h | 2 ++ src/data/items.h | 22 +++++++++++++++++++ 7 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 graphics/items/icon_palettes/metal_alloy.pal create mode 100644 graphics/items/icons/metal_alloy.png diff --git a/graphics/items/icon_palettes/metal_alloy.pal b/graphics/items/icon_palettes/metal_alloy.pal new file mode 100644 index 0000000000..8375639923 --- /dev/null +++ b/graphics/items/icon_palettes/metal_alloy.pal @@ -0,0 +1,18 @@ +JASC-PAL +0100 +15 +0 0 0 +249 253 255 +224 232 243 +169 163 177 +136 130 156 +178 194 220 +123 146 180 +162 164 202 +153 208 247 +85 96 152 +136 150 213 +186 212 247 +90 118 181 +154 195 255 +49 49 49 diff --git a/graphics/items/icons/metal_alloy.png b/graphics/items/icons/metal_alloy.png new file mode 100644 index 0000000000000000000000000000000000000000..408e13dd5b9b80019730fd92cbc35c53d28f65c5 GIT binary patch literal 299 zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM3?#3wJbMaAF%}28J29*~C-V}>(GBnkaRt&p z|NejQ;`7SI8#|ijY&vwOdeW9fOHR$a@I5qPM#r?PyRLkXD%(2i@P9)?!}U?Z9zYHJ zB|(0{4F6HU)82W@fKn4ZT^vI+CT^YREyk?Kaez(mxPSX^`Rz?zTh{H$nAZ7AWc_RT z4^K8Q2skl(@XRqda4Kex&6-03Iwjp5d;Y}raNTx%P}-B%?jm6pRdC$pd9{L)rt|VC z*Ggx$FdSZ1QqR`3^1W=)IiV}lg1#Nz?6hLn6XAnkgCjd*kQN9*6YT kCf8fFZ+mb3Reuj-d>Om#lnB>-K*uq7y85}Sb4q9e0FYdWWB>pF literal 0 HcmV?d00001 diff --git a/include/constants/items.h b/include/constants/items.h index dbe8c9acd2..0be82dcb5f 100644 --- a/include/constants/items.h +++ b/include/constants/items.h @@ -986,8 +986,8 @@ #define ITEM_SWIFT_MOCHI 811 #define ITEM_FRESH_START_MOCHI 812 #define ITEM_GLIMMERING_CHARM 813 -#define ITEM_814 814 // TWV0YWwgQWxsb3k= -#define ITEM_815 815 // U3RlbGxhciBUZXJhIFNoYXJk +#define ITEM_METAL_ALLOY 814 +#define ITEM_STELLAR_TERA_SHARD 815 #define ITEMS_COUNT 816 #define ITEM_FIELD_ARROW ITEMS_COUNT diff --git a/include/graphics.h b/include/graphics.h index 9d7258e32d..d8248575f8 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -785,6 +785,8 @@ extern const u32 gItemIcon_UnremarkableTeacup[]; extern const u32 gItemIconPalette_UnremarkableTeacup[]; extern const u32 gItemIcon_MasterpieceTeacup[]; extern const u32 gItemIconPalette_MasterpieceTeacup[]; +extern const u32 gItemIcon_MetalAlloy[]; +extern const u32 gItemIconPalette_MetalAlloy[]; // Nectars extern const u32 gItemIcon_RedNectar[]; extern const u32 gItemIconPalette_RedNectar[]; diff --git a/src/data/graphics/items.h b/src/data/graphics/items.h index f273b6d3b0..0a41ce6279 100644 --- a/src/data/graphics/items.h +++ b/src/data/graphics/items.h @@ -663,6 +663,9 @@ const u32 gItemIconPalette_UnremarkableTeacup[] = INCBIN_U32("graphics/items/ico const u32 gItemIcon_MasterpieceTeacup[] = INCBIN_U32("graphics/items/icons/masterpiece_teacup.4bpp.lz"); const u32 gItemIconPalette_MasterpieceTeacup[] = INCBIN_U32("graphics/items/icon_palettes/masterpiece_teacup.gbapal.lz"); +const u32 gItemIcon_MetalAlloy[] = INCBIN_U32("graphics/items/icons/metal_alloy.4bpp.lz"); +const u32 gItemIconPalette_MetalAlloy[] = INCBIN_U32("graphics/items/icon_palettes/metal_alloy.gbapal.lz"); + // Nectars const u32 gItemIcon_RedNectar[] = INCBIN_U32("graphics/items/icons/red_nectar.4bpp.lz"); diff --git a/src/data/item_icon_table.h b/src/data/item_icon_table.h index 33ed4aed8d..e048cf8d4e 100644 --- a/src/data/item_icon_table.h +++ b/src/data/item_icon_table.h @@ -859,6 +859,8 @@ const u32 *const gItemIconTable[ITEMS_COUNT + 1][2] = [ITEM_SWIFT_MOCHI] = {gItemIcon_Mochi, gItemIconPalette_SwiftMochi}, [ITEM_FRESH_START_MOCHI] = {gItemIcon_Mochi, gItemIconPalette_FreshStartMochi}, [ITEM_GLIMMERING_CHARM] = {gItemIcon_GlimmeringCharm, gItemIconPalette_GlimmeringCharm}, + [ITEM_METAL_ALLOY] = {gItemIcon_MetalAlloy, gItemIconPalette_MetalAlloy}, + [ITEM_STELLAR_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, //{gItemIcon_TeraShard, gItemIconPalette_StellarTeraShard}, // Return to field arrow [ITEMS_COUNT] = {gItemIcon_ReturnToFieldArrow, gItemIconPalette_ReturnToFieldArrow}, }; diff --git a/src/data/items.h b/src/data/items.h index 6646ab98c6..cc8c646223 100644 --- a/src/data/items.h +++ b/src/data/items.h @@ -11377,4 +11377,26 @@ const struct Item gItems[] = .type = ITEM_USE_BAG_MENU, .fieldUseFunc = ItemUseOutOfBattle_CannotUse, }, + + [ITEM_METAL_ALLOY] = + { + .name = _("Metal Alloy"), + .price = 6000, + .description = COMPOUND_STRING("A peculiar metal\n" + "that makes certain\n" + "Pokémon evolve."), + .pocket = POCKET_ITEMS, + .type = ITEM_USE_PARTY_MENU, + .fieldUseFunc = ItemUseOutOfBattle_EvolutionStone, + }, + + [ITEM_STELLAR_TERA_SHARD] = + { + .name = _("StllrTeraShrd"), + .price = 0, + .description = sTeraShardDesc, + .pocket = POCKET_ITEMS, + .type = ITEM_USE_BAG_MENU, + .fieldUseFunc = ItemUseOutOfBattle_CannotUse, + }, }; From 94a650a2031763025855ae3bc634fe386fcbb57b Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Thu, 28 Dec 2023 16:27:09 -0600 Subject: [PATCH 11/13] Add Fillet Away + Belly Drum tweaks (#3616) * Add Fillet Away * Fillet Away and Belly Drum tests * More tests * Update fillet_away.c * Update fillet_away.c * Newlines * Update battle_scripts_1.s * Update belly_drum.c * Address reviews * Fix order * Swords Dance assume * Update belly_drum.c * Try some stuff * Fix hp not being halved in certain cases * Update battle_scripts_1.s * AI stuff --- asm/macros/battle_script.inc | 2 +- data/battle_scripts_1.s | 41 ++++++++++- include/constants/battle_move_effects.h | 3 +- src/battle_ai_main.c | 18 +++-- src/battle_ai_util.c | 2 + src/battle_dome.c | 3 +- src/battle_script_commands.c | 13 ++-- src/data/battle_moves.h | 2 +- test/battle/ability/contrary.c | 34 +++++++++ test/battle/move_effect/belly_drum.c | 92 +++++++++++++++++++++++++ test/battle/move_effect/fillet_away.c | 58 ++++++++++++++++ 11 files changed, 248 insertions(+), 20 deletions(-) create mode 100644 test/battle/move_effect/belly_drum.c create mode 100644 test/battle/move_effect/fillet_away.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 30b0ab0ee2..ff3eca273c 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -980,7 +980,7 @@ .byte 0xbb .endm - .macro maxattackhalvehp failInstr:req + .macro halvehp failInstr:req .byte 0xbc .4byte \failInstr .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 09eb969168..c70c76740a 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -440,6 +440,41 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectBrickBreak @ EFFECT_RAGING_BULL .4byte BattleScript_EffectHit @ EFFECT_RAGE_FIST .4byte BattleScript_EffectDoodle @ EFFECT_DOODLE + .4byte BattleScript_EffectFilletAway @ EFFECT_FILLET_AWAY + +BattleScript_EffectFilletAway: + attackcanceler + attackstring + ppreduce + jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_FilletAwayTryAttack + jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_FilletAwayTryAttack + jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ButItFailed +BattleScript_FilletAwayTryAttack:: + halvehp BattleScript_ButItFailed + orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE + attackanimation + waitanimation + setbyte sSTAT_ANIM_PLAYED, FALSE + playstatchangeanimation BS_ATTACKER, BIT_ATK | BIT_SPATK | BIT_SPEED, STAT_CHANGE_BY_TWO + setstatchanger STAT_ATK, 2, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_FilletAwayTrySpAtk + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_FilletAwayTrySpAtk:: + setstatchanger STAT_SPATK, 2, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_FilletAwayTrySpeed + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_FilletAwayTrySpeed:: + setstatchanger STAT_SPEED, 2, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_FilletAwayEnd + printfromtable gStatUpStringIds + waitmessage B_WAIT_TIME_LONG +BattleScript_FilletAwayEnd:: + bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT + healthbarupdate BS_ATTACKER + datahpupdate BS_ATTACKER + goto BattleScript_MoveEnd BattleScript_EffectDoodle: attackcanceler @@ -5343,12 +5378,16 @@ BattleScript_EffectBellyDrum:: attackcanceler attackstring ppreduce - maxattackhalvehp BattleScript_ButItFailed + jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed + halvehp BattleScript_ButItFailed orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE attackanimation waitanimation healthbarupdate BS_ATTACKER datahpupdate BS_ATTACKER + playstatchangeanimation BS_ATTACKER, BIT_ATK, STAT_CHANGE_BY_TWO + setstatchanger STAT_ATK, MAX_STAT_STAGE, FALSE + statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_MoveEnd printstring STRINGID_PKMNCUTHPMAXEDATTACK waitmessage B_WAIT_TIME_LONG goto BattleScript_MoveEnd diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 420433bd02..dbaa21f14d 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -417,7 +417,8 @@ #define EFFECT_RAGING_BULL 411 #define EFFECT_RAGE_FIST 412 #define EFFECT_DOODLE 413 +#define EFFECT_FILLET_AWAY 414 -#define NUM_BATTLE_MOVE_EFFECTS 414 +#define NUM_BATTLE_MOVE_EFFECTS 415 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index abe780db68..25b0b96414 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -143,7 +143,7 @@ static u32 GetWildAiFlags(void) static u32 GetAiFlags(u16 trainerId) { u32 flags = 0; - + if (!(gBattleTypeFlags & BATTLE_TYPE_HAS_AI) && !IsWildMonSmart()) return 0; if (trainerId == 0xFFFF) @@ -167,26 +167,26 @@ static u32 GetAiFlags(u16 trainerId) else flags = gTrainers[trainerId].aiFlags; } - + if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE) flags |= AI_FLAG_DOUBLE_BATTLE; - + return flags; } void BattleAI_SetupFlags(void) { AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_LEFT] = 0; // player has no AI - + #if DEBUG_OVERWORLD_MENU == TRUE if (gIsDebugBattle) { AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_LEFT] = gDebugAIFlags; AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_RIGHT] = gDebugAIFlags; return; - } + } #endif - + if (IsWildMonSmart() && !(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_TRAINER))) { // smart wild AI @@ -201,7 +201,7 @@ void BattleAI_SetupFlags(void) else AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_RIGHT] = AI_THINKING_STRUCT->aiFlags[B_POSITION_OPPONENT_LEFT]; } - + if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER) { AI_THINKING_STRUCT->aiFlags[B_POSITION_PLAYER_RIGHT] = GetAiFlags(gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)); @@ -1699,6 +1699,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-6); break; case EFFECT_BELLY_DRUM: + case EFFECT_FILLET_AWAY: if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] <= 60) @@ -5043,6 +5044,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_FOCUS_PUNCH: case EFFECT_REVENGE: case EFFECT_TEETER_DANCE: + case EFFECT_FILLET_AWAY: if (Random() & 1) ADJUST_SCORE(2); break; @@ -5193,6 +5195,7 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_CONVERSION_2: case EFFECT_SAFEGUARD: case EFFECT_BELLY_DRUM: + case EFFECT_FILLET_AWAY: ADJUST_SCORE(-2); break; default: @@ -5228,6 +5231,7 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_HAIL: case EFFECT_SNOWSCAPE: case EFFECT_RAIN_DANCE: + case EFFECT_FILLET_AWAY: ADJUST_SCORE(-2); break; default: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 2cb7878d42..e11700dba9 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -361,6 +361,7 @@ static const u16 sEncouragedEncoreEffects[] = EFFECT_WATER_SPORT, EFFECT_DRAGON_DANCE, EFFECT_CAMOUFLAGE, + EFFECT_FILLET_AWAY, }; // Functions @@ -2126,6 +2127,7 @@ bool32 IsAttackBoostMoveEffect(u32 effect) case EFFECT_BELLY_DRUM: case EFFECT_BULK_UP: case EFFECT_GROWTH: + case EFFECT_FILLET_AWAY: return TRUE; default: return FALSE; diff --git a/src/battle_dome.c b/src/battle_dome.c index 05b8ebec4a..d098d1cae7 100644 --- a/src/battle_dome.c +++ b/src/battle_dome.c @@ -4152,6 +4152,7 @@ static bool32 IsDomeComboMoveEffect(u32 effect) case EFFECT_CHARGE: case EFFECT_BULK_UP: case EFFECT_ATTACK_ACCURACY_UP: + case EFFECT_FILLET_AWAY: // Others case EFFECT_FOCUS_ENERGY: case EFFECT_LOCK_ON: @@ -4343,7 +4344,7 @@ static void DisplayTrainerInfoOnCard(u8 flags, u8 trainerTourneyId) move = gSaveBlock2Ptr->frontier.domePlayerPartyData[i].moves[j]; else move = gFacilityTrainerMons[DOME_MONS[trainerTourneyId][i]].moves[j]; - + switch (k) { case MOVE_POINTS_COMBO: diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4d773c6e9a..91fcfd4aee 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -543,7 +543,7 @@ static void Cmd_setsafeguard(void); static void Cmd_magnitudedamagecalculation(void); static void Cmd_jumpifnopursuitswitchdmg(void); static void Cmd_setsunny(void); -static void Cmd_maxattackhalvehp(void); +static void Cmd_halvehp(void); static void Cmd_copyfoestats(void); static void Cmd_rapidspinfree(void); static void Cmd_setdefensecurlbit(void); @@ -802,7 +802,7 @@ void (* const gBattleScriptingCommandsTable[])(void) = Cmd_magnitudedamagecalculation, //0xB9 Cmd_jumpifnopursuitswitchdmg, //0xBA Cmd_setsunny, //0xBB - Cmd_maxattackhalvehp, //0xBC + Cmd_halvehp, //0xBC Cmd_copyfoestats, //0xBD Cmd_rapidspinfree, //0xBE Cmd_setdefensecurlbit, //0xBF @@ -13322,8 +13322,8 @@ static void Cmd_setsunny(void) gBattlescriptCurrInstr = cmd->nextInstr; } -// Belly Drum -static void Cmd_maxattackhalvehp(void) +// Belly Drum, Fillet Away +static void Cmd_halvehp(void) { CMD_ARGS(const u8 *failInstr); @@ -13332,11 +13332,8 @@ static void Cmd_maxattackhalvehp(void) if (!(GetNonDynamaxMaxHP(gBattlerAttacker) / 2)) halfHp = 1; - // Belly Drum fails if the user's current HP is less than half its maximum, or if the user's Attack is already at +6 (even if the user has Contrary). - if (gBattleMons[gBattlerAttacker].statStages[STAT_ATK] < MAX_STAT_STAGE - && gBattleMons[gBattlerAttacker].hp > halfHp) + if (gBattleMons[gBattlerAttacker].hp > halfHp) { - gBattleMons[gBattlerAttacker].statStages[STAT_ATK] = MAX_STAT_STAGE; gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 2; if (gBattleMoveDamage == 0) gBattleMoveDamage = 1; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 10a626c029..4e26d9e4b3 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -13293,7 +13293,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] = [MOVE_FILLET_AWAY] = { - .effect = EFFECT_PLACEHOLDER, // EFFECT_FILLET_AWAY + .effect = EFFECT_FILLET_AWAY, .power = 0, .type = TYPE_NORMAL, .accuracy = 0, diff --git a/test/battle/ability/contrary.c b/test/battle/ability/contrary.c index 03af17bdc0..af71b211c8 100644 --- a/test/battle/ability/contrary.c +++ b/test/battle/ability/contrary.c @@ -187,3 +187,37 @@ SINGLE_BATTLE_TEST("Contrary raises a stat after using a move which would normal EXPECT_MUL_EQ(results[1].damage, Q_4_12(2.125), results[0].damage); } } + +SINGLE_BATTLE_TEST("Contrary lowers a stat after using a move which would normally raise it: Belly Drum", s16 damageBefore, s16 damageAfter) +{ + u32 ability; + PARAMETRIZE { ability = ABILITY_CONTRARY; } + PARAMETRIZE { ability = ABILITY_TANGLED_FEET; } + GIVEN { + ASSUME(gBattleMoves[MOVE_BELLY_DRUM].effect == EFFECT_BELLY_DRUM); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_SPINDA) { Ability(ability); } + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); } + TURN { MOVE(opponent, MOVE_BELLY_DRUM); } + TURN { MOVE(opponent, MOVE_TACKLE); } + } SCENE { + MESSAGE("Foe Spinda used Tackle!"); + HP_BAR(player, captureDamage: &results[i].damageBefore); + + if (ability == ABILITY_CONTRARY) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Spinda cut its own HP and maximized ATTACK!"); //Message stays the same + } + else { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("Foe Spinda cut its own HP and maximized ATTACK!"); + } + + HP_BAR(player, captureDamage: &results[i].damageAfter); + } + FINALLY { + EXPECT_MUL_EQ(results[0].damageBefore, UQ_4_12(0.25), results[0].damageAfter); + EXPECT_MUL_EQ(results[1].damageBefore, UQ_4_12(4.0), results[1].damageAfter); + } +} diff --git a/test/battle/move_effect/belly_drum.c b/test/battle/move_effect/belly_drum.c new file mode 100644 index 0000000000..b3f02f7a19 --- /dev/null +++ b/test/battle/move_effect/belly_drum.c @@ -0,0 +1,92 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_BELLY_DRUM].effect == EFFECT_BELLY_DRUM); +} + +SINGLE_BATTLE_TEST("Belly Drum cuts the user's HP in half") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BELLY_DRUM); } + } SCENE { + s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); + HP_BAR(player, hp: maxHP / 2); + } +} + +SINGLE_BATTLE_TEST("Belly Drum maximizes the user's Attack stat", s16 damage) +{ + bool32 raiseAttack; + PARAMETRIZE { raiseAttack = FALSE; } + PARAMETRIZE { raiseAttack = TRUE; } + GIVEN { + ASSUME(gBattleMoves[MOVE_TACKLE].category == BATTLE_CATEGORY_PHYSICAL); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + if (raiseAttack) TURN { MOVE(player, MOVE_BELLY_DRUM); } + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + if (raiseAttack) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet cut its own HP and maximized ATTACK!"); + } + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(4), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Belly Drum fails if user's current HP is half or less than half its maximum") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(100); HP(50);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BELLY_DRUM); } + } SCENE { + MESSAGE("But it failed!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player); + HP_BAR(player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } + } +} + +SINGLE_BATTLE_TEST("Belly Drum fails if the user's Attack is already at +6") +{ + GIVEN { + ASSUME(gBattleMoves[MOVE_SWORDS_DANCE].effect == EFFECT_ATTACK_UP_2); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SWORDS_DANCE); } + TURN { MOVE(player, MOVE_SWORDS_DANCE); } + TURN { MOVE(player, MOVE_SWORDS_DANCE); } + TURN { MOVE(player, MOVE_BELLY_DRUM); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Attack sharply rose!"); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Attack sharply rose!"); + + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Attack sharply rose!"); + + MESSAGE("But it failed!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BELLY_DRUM, player); + HP_BAR(player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } + } +} diff --git a/test/battle/move_effect/fillet_away.c b/test/battle/move_effect/fillet_away.c new file mode 100644 index 0000000000..ea403e16d6 --- /dev/null +++ b/test/battle/move_effect/fillet_away.c @@ -0,0 +1,58 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gBattleMoves[MOVE_FILLET_AWAY].effect == EFFECT_FILLET_AWAY); +} + +SINGLE_BATTLE_TEST("Fillet Away cuts the user's HP in half") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FILLET_AWAY); } + } SCENE { + s32 maxHP = GetMonData(&PLAYER_PARTY[0], MON_DATA_MAX_HP); + HP_BAR(player, hp: maxHP / 2); + } +} + +SINGLE_BATTLE_TEST("Fillet Away sharply raises Attack, Sp. Atk, and Speed") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FILLET_AWAY); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FILLET_AWAY, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + MESSAGE("Wobbuffet's Attack sharply rose!"); + MESSAGE("Wobbuffet's Sp. Atk sharply rose!"); + MESSAGE("Wobbuffet's Speed sharply rose!"); + HP_BAR(player); + } THEN { + EXPECT_EQ(player->statStages[STAT_ATK], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(player->statStages[STAT_SPATK], DEFAULT_STAT_STAGE + 2); + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2); + } +} + +SINGLE_BATTLE_TEST("Fillet Away fails if user's current HP is half or less than half its maximum") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { MaxHP(100); HP(50);} + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_FILLET_AWAY); } + } SCENE { + MESSAGE("But it failed!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FILLET_AWAY, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + HP_BAR(player); + } + } +} From 16a3954f0ea31b5beca36d335a269ad4c017fd7f Mon Sep 17 00:00:00 2001 From: Ninjdai <65647523+Ninjdai1@users.noreply.github.com> Date: Fri, 29 Dec 2023 14:12:17 +0100 Subject: [PATCH 12/13] Add MOVES_COUNT and NUM_SPECIES to RHH rom header (#3831) * Add MOVES_COUNT and NUM_SPECIES to RHH rom header --- src/rom_header_rhh.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/rom_header_rhh.c b/src/rom_header_rhh.c index 2e141670a7..f1e16f385e 100644 --- a/src/rom_header_rhh.c +++ b/src/rom_header_rhh.c @@ -1,5 +1,7 @@ #include "global.h" #include "constants/expansion.h" +#include "constants/moves.h" +#include "constants/species.h" // Similar to the GF ROM header, this struct allows external programs to // detect details about Expansion. @@ -14,6 +16,8 @@ struct RHHRomHeader /*0x07*/ u8 expansionVersionMinor; /*0x08*/ u8 expansionVersionPatch; /*0x09*/ u8 expansionVersionFlags; + /*0x0C*/ u32 movesCount; + /*0x10*/ u32 numSpecies; }; static const struct RHHRomHeader sRHHRomHeader = @@ -23,4 +27,6 @@ static const struct RHHRomHeader sRHHRomHeader = .expansionVersionMinor = EXPANSION_VERSION_MINOR, .expansionVersionPatch = EXPANSION_VERSION_PATCH, .expansionVersionFlags = (EXPANSION_TAGGED_RELEASE << 0), + .movesCount = MOVES_COUNT, + .numSpecies = NUM_SPECIES, }; From 6bc0bf9f8bb8abbdc6eba6013ddfd49d0a9b7bc4 Mon Sep 17 00:00:00 2001 From: Bassoonian Date: Fri, 29 Dec 2023 14:25:24 +0100 Subject: [PATCH 13/13] Ability refactor (#3861) * Ability refactor * Adds abilities to RHH rom header --------- Co-authored-by: Martin Griffin --- include/battle_main.h | 2 - include/pokemon.h | 7 + src/battle_debug.c | 6 +- src/battle_interface.c | 2 +- src/battle_main.c | 2 - src/battle_message.c | 12 +- src/data/abilities.h | 2068 ++++++++++++++++++++++++++++++++++ src/data/text/abilities.h | 1250 -------------------- src/debug.c | 4 +- src/party_menu.c | 4 +- src/pokedex_plus_hgss.c | 12 +- src/pokemon.c | 1 + src/pokemon_summary_screen.c | 4 +- src/rom_header_gf.c | 4 +- src/rom_header_rhh.c | 5 + 15 files changed, 2105 insertions(+), 1278 deletions(-) create mode 100644 src/data/abilities.h delete mode 100644 src/data/text/abilities.h diff --git a/include/battle_main.h b/include/battle_main.h index b171b2f289..2c5d887018 100644 --- a/include/battle_main.h +++ b/include/battle_main.h @@ -84,8 +84,6 @@ extern const struct OamData gOamData_BattleSpriteOpponentSide; extern const struct OamData gOamData_BattleSpritePlayerSide; extern const u8 gTypeNames[NUMBER_OF_MON_TYPES][TYPE_NAME_LENGTH + 1]; extern const struct TrainerMoney gTrainerMoneyTable[]; -extern const u8 gAbilityNames[][ABILITY_NAME_LENGTH + 1]; -extern const u8 *const gAbilityDescriptionPointers[]; extern const u8 gStatusConditionString_PoisonJpn[8]; extern const u8 gStatusConditionString_SleepJpn[8]; diff --git a/include/pokemon.h b/include/pokemon.h index ae93f5fa92..6ce793a19e 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -509,6 +509,12 @@ struct BattleMove u16 argument; }; +struct Ability +{ + u8 name[ABILITY_NAME_LENGTH + 1]; + const u8 *description; +}; + #define SPINDA_SPOT_WIDTH 16 #define SPINDA_SPOT_HEIGHT 16 @@ -577,6 +583,7 @@ extern const u16 gUnionRoomFacilityClasses[]; extern const struct SpriteTemplate gBattlerSpriteTemplates[]; extern const s8 gNatureStatTable[][5]; extern const u32 sExpCandyExperienceTable[]; +extern const struct Ability gAbilities[]; void ZeroBoxMonData(struct BoxPokemon *boxMon); void ZeroMonData(struct Pokemon *mon); diff --git a/src/battle_debug.c b/src/battle_debug.c index 24ec2d13cd..8e4046b565 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -864,7 +864,7 @@ static void PutAiInfoText(struct BattleDebugMenu *data) u16 holdEffect = AI_DATA->holdEffects[i]; u16 item = AI_DATA->items[i]; u8 x = (i == B_POSITION_PLAYER_LEFT) ? 83 + (i) * 75 : 83 + (i-1) * 75; - AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, gAbilityNames[ability], x, 0, 0, NULL); + AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, gAbilities[ability].name, x, 0, 0, NULL); AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, ItemId_GetName(item), x, 15, 0, NULL); AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, GetHoldEffectName(holdEffect), x, 30, 0, NULL); } @@ -897,7 +897,7 @@ static void PutAiPartyText(struct BattleDebugMenu *data) AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL_NARROW, text, i * 41, 0, 0, NULL, 0, 0); } - txtPtr = StringCopyN(text, gAbilityNames[aiMons[i].ability], 7); // The screen is too small to fit the whole string, so we need to drop the last letters. + txtPtr = StringCopyN(text, gAbilities[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); @@ -1433,7 +1433,7 @@ static void PrintSecondaryEntries(struct BattleDebugMenu *data) } break; case LIST_ITEM_ABILITY: - PadString(gAbilityNames[gBattleMons[data->battlerId].ability], text); + PadString(gAbilities[gBattleMons[data->battlerId].ability].name, text); printer.currentY = printer.y = sSecondaryListTemplate.upText_Y; AddTextPrinter(&printer, 0, NULL); break; diff --git a/src/battle_interface.c b/src/battle_interface.c index b07cb3ee07..3357fd9939 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -3113,7 +3113,7 @@ static void PrintBattlerOnAbilityPopUp(u8 battlerId, u8 spriteId1, u8 spriteId2) static void PrintAbilityOnAbilityPopUp(u32 ability, u8 spriteId1, u8 spriteId2) { - PrintOnAbilityPopUp(gAbilityNames[ability], + PrintOnAbilityPopUp(gAbilities[ability].name, (void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32) + 256, (void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32) + 256, 5, 12, diff --git a/src/battle_main.c b/src/battle_main.c index d5186b7ef2..944a386861 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -409,8 +409,6 @@ static const u16 sTrainerBallTable[TRAINER_CLASS_COUNT] = }; #endif -#include "data/text/abilities.h" - static void (* const sTurnActionsFuncsTable[])(void) = { [B_ACTION_USE_MOVE] = HandleAction_UseMove, diff --git a/src/battle_message.c b/src/battle_message.c index 35ff5379ec..7d2c60d67a 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3407,19 +3407,19 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) } break; case B_TXT_LAST_ABILITY: // last used ability - toCpy = gAbilityNames[gLastUsedAbility]; + toCpy = gAbilities[gLastUsedAbility].name; break; case B_TXT_ATK_ABILITY: // attacker ability - toCpy = gAbilityNames[sBattlerAbilities[gBattlerAttacker]]; + toCpy = gAbilities[sBattlerAbilities[gBattlerAttacker]].name; break; case B_TXT_DEF_ABILITY: // target ability - toCpy = gAbilityNames[sBattlerAbilities[gBattlerTarget]]; + toCpy = gAbilities[sBattlerAbilities[gBattlerTarget]].name; break; case B_TXT_SCR_ACTIVE_ABILITY: // scripting active ability - toCpy = gAbilityNames[sBattlerAbilities[gBattleScripting.battler]]; + toCpy = gAbilities[sBattlerAbilities[gBattleScripting.battler]].name; break; case B_TXT_EFF_ABILITY: // effect battler ability - toCpy = gAbilityNames[sBattlerAbilities[gEffectBattler]]; + toCpy = gAbilities[sBattlerAbilities[gEffectBattler]].name; break; case B_TXT_TRAINER1_CLASS: // trainer class name toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A); @@ -3781,7 +3781,7 @@ void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst) srcID += 2; break; case B_BUFF_ABILITY: // ability names - StringAppend(dst, gAbilityNames[T1_READ_16(&src[srcID + 1])]); + StringAppend(dst, gAbilities[T1_READ_16(&src[srcID + 1])].name); srcID += 3; break; case B_BUFF_ITEM: // item name diff --git a/src/data/abilities.h b/src/data/abilities.h new file mode 100644 index 0000000000..2ff80f3ab3 --- /dev/null +++ b/src/data/abilities.h @@ -0,0 +1,2068 @@ +const struct Ability gAbilities[ABILITIES_COUNT] = +{ + [ABILITY_NONE] = + { + .name = _("-------"), + .description = COMPOUND_STRING("No special ability."), + }, + + [ABILITY_STENCH] = + { + .name = _("Stench"), + .description = COMPOUND_STRING("May cause a foe to flinch."), + }, + + [ABILITY_DRIZZLE] = + { + .name = _("Drizzle"), + .description = COMPOUND_STRING("Summons rain in battle."), + }, + + [ABILITY_SPEED_BOOST] = + { + .name = _("Speed Boost"), + .description = COMPOUND_STRING("Gradually boosts Speed."), + }, + + [ABILITY_BATTLE_ARMOR] = + { + .name = _("Battle Armor"), + .description = COMPOUND_STRING("Blocks critical hits."), + }, + + [ABILITY_STURDY] = + { + .name = _("Sturdy"), + .description = COMPOUND_STRING("Negates 1-hit KO attacks."), + }, + + [ABILITY_DAMP] = + { + .name = _("Damp"), + .description = COMPOUND_STRING("Prevents self-destruction."), + }, + + [ABILITY_LIMBER] = + { + .name = _("Limber"), + .description = COMPOUND_STRING("Prevents paralysis."), + }, + + [ABILITY_SAND_VEIL] = + { + .name = _("Sand Veil"), + .description = COMPOUND_STRING("Ups evasion in a sandstorm."), + }, + + [ABILITY_STATIC] = + { + .name = _("Static"), + .description = COMPOUND_STRING("Paralyzes on contact."), + }, + + [ABILITY_VOLT_ABSORB] = + { + .name = _("Volt Absorb"), + .description = COMPOUND_STRING("Turns electricity into HP."), + }, + + [ABILITY_WATER_ABSORB] = + { + .name = _("Water Absorb"), + .description = COMPOUND_STRING("Changes water into HP."), + }, + + [ABILITY_OBLIVIOUS] = + { + .name = _("Oblivious"), + .description = COMPOUND_STRING("Prevents attraction."), + }, + + [ABILITY_CLOUD_NINE] = + { + .name = _("Cloud Nine"), + .description = COMPOUND_STRING("Negates weather effects."), + }, + + [ABILITY_COMPOUND_EYES] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Compound Eyes"), + #else + .name = _("CompoundEyes"), + #endif + .description = COMPOUND_STRING("Raises accuracy."), + }, + + [ABILITY_INSOMNIA] = + { + .name = _("Insomnia"), + .description = COMPOUND_STRING("Prevents sleep."), + }, + + [ABILITY_COLOR_CHANGE] = + { + .name = _("Color Change"), + .description = COMPOUND_STRING("Changes type to foe's move."), + }, + + [ABILITY_IMMUNITY] = + { + .name = _("Immunity"), + .description = COMPOUND_STRING("Prevents poisoning."), + }, + + [ABILITY_FLASH_FIRE] = + { + .name = _("Flash Fire"), + .description = COMPOUND_STRING("Powers up if hit by fire."), + }, + + [ABILITY_SHIELD_DUST] = + { + .name = _("Shield Dust"), + .description = COMPOUND_STRING("Prevents added effects."), + }, + + [ABILITY_OWN_TEMPO] = + { + .name = _("Own Tempo"), + .description = COMPOUND_STRING("Prevents confusion."), + }, + + [ABILITY_SUCTION_CUPS] = + { + .name = _("Suction Cups"), + .description = COMPOUND_STRING("Firmly anchors the body."), + }, + + [ABILITY_INTIMIDATE] = + { + .name = _("Intimidate"), + .description = COMPOUND_STRING("Lowers the foe's Attack."), + }, + + [ABILITY_SHADOW_TAG] = + { + .name = _("Shadow Tag"), + .description = COMPOUND_STRING("Prevents the foe's escape."), + }, + + [ABILITY_ROUGH_SKIN] = + { + .name = _("Rough Skin"), + .description = COMPOUND_STRING("Hurts to touch."), + }, + + [ABILITY_WONDER_GUARD] = + { + .name = _("Wonder Guard"), + .description = COMPOUND_STRING("“Supereffective” hits."), + }, + + [ABILITY_LEVITATE] = + { + .name = _("Levitate"), + .description = COMPOUND_STRING("Not hit by Ground attacks."), + }, + + [ABILITY_EFFECT_SPORE] = + { + .name = _("Effect Spore"), + .description = COMPOUND_STRING("Leaves spores on contact."), + }, + + [ABILITY_SYNCHRONIZE] = + { + .name = _("Synchronize"), + .description = COMPOUND_STRING("Passes on status problems."), + }, + + [ABILITY_CLEAR_BODY] = + { + .name = _("Clear Body"), + .description = COMPOUND_STRING("Prevents ability reduction."), + }, + + [ABILITY_NATURAL_CURE] = + { + .name = _("Natural Cure"), + .description = COMPOUND_STRING("Heals upon switching out."), + }, + + [ABILITY_LIGHTNING_ROD] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Lightning Rod"), + #else + .name = _("LightningRod"), + #endif + .description = COMPOUND_STRING("Draws electrical moves."), + }, + + [ABILITY_SERENE_GRACE] = + { + .name = _("Serene Grace"), + .description = COMPOUND_STRING("Promotes added effects."), + }, + + [ABILITY_SWIFT_SWIM] = + { + .name = _("Swift Swim"), + .description = COMPOUND_STRING("Raises Speed in rain."), + }, + + [ABILITY_CHLOROPHYLL] = + { + .name = _("Chlorophyll"), + .description = COMPOUND_STRING("Raises Speed in sunshine."), + }, + + [ABILITY_ILLUMINATE] = + { + .name = _("Illuminate"), + .description = COMPOUND_STRING("Encounter rate increases."), + }, + + [ABILITY_TRACE] = + { + .name = _("Trace"), + .description = COMPOUND_STRING("Copies special ability."), + }, + + [ABILITY_HUGE_POWER] = + { + .name = _("Huge Power"), + .description = COMPOUND_STRING("Raises Attack."), + }, + + [ABILITY_POISON_POINT] = + { + .name = _("Poison Point"), + .description = COMPOUND_STRING("Poisons foe on contact."), + }, + + [ABILITY_INNER_FOCUS] = + { + .name = _("Inner Focus"), + .description = COMPOUND_STRING("Prevents flinching."), + }, + + [ABILITY_MAGMA_ARMOR] = + { + .name = _("Magma Armor"), + .description = COMPOUND_STRING("Prevents freezing."), + }, + + [ABILITY_WATER_VEIL] = + { + .name = _("Water Veil"), + .description = COMPOUND_STRING("Prevents burns."), + }, + + [ABILITY_MAGNET_PULL] = + { + .name = _("Magnet Pull"), + .description = COMPOUND_STRING("Traps Steel-type Pokémon."), + }, + + [ABILITY_SOUNDPROOF] = + { + .name = _("Soundproof"), + .description = COMPOUND_STRING("Avoids sound-based moves."), + }, + + [ABILITY_RAIN_DISH] = + { + .name = _("Rain Dish"), + .description = COMPOUND_STRING("Slight HP recovery in rain."), + }, + + [ABILITY_SAND_STREAM] = + { + .name = _("Sand Stream"), + .description = COMPOUND_STRING("Summons a sandstorm."), + }, + + [ABILITY_PRESSURE] = + { + .name = _("Pressure"), + .description = COMPOUND_STRING("Raises foe's PP usage."), + }, + + [ABILITY_THICK_FAT] = + { + .name = _("Thick Fat"), + .description = COMPOUND_STRING("Heat-and-cold protection."), + }, + + [ABILITY_EARLY_BIRD] = + { + .name = _("Early Bird"), + .description = COMPOUND_STRING("Awakens quickly from sleep."), + }, + + [ABILITY_FLAME_BODY] = + { + .name = _("Flame Body"), + .description = COMPOUND_STRING("Burns the foe on contact."), + }, + + [ABILITY_RUN_AWAY] = + { + .name = _("Run Away"), + .description = COMPOUND_STRING("Makes escaping easier."), + }, + + [ABILITY_KEEN_EYE] = + { + .name = _("Keen Eye"), + .description = COMPOUND_STRING("Prevents loss of accuracy."), + }, + + [ABILITY_HYPER_CUTTER] = + { + .name = _("Hyper Cutter"), + .description = COMPOUND_STRING("Prevents Attack reduction."), + }, + + [ABILITY_PICKUP] = + { + .name = _("Pickup"), + .description = COMPOUND_STRING("May pick up items."), + }, + + [ABILITY_TRUANT] = + { + .name = _("Truant"), + .description = COMPOUND_STRING("Moves only every two turns."), + }, + + [ABILITY_HUSTLE] = + { + .name = _("Hustle"), + .description = COMPOUND_STRING("Trades accuracy for power."), + }, + + [ABILITY_CUTE_CHARM] = + { + .name = _("Cute Charm"), + .description = COMPOUND_STRING("Infatuates on contact."), + }, + + [ABILITY_PLUS] = + { + .name = _("Plus"), + .description = COMPOUND_STRING("Powers up with Minus."), + }, + + [ABILITY_MINUS] = + { + .name = _("Minus"), + .description = COMPOUND_STRING("Powers up with Plus."), + }, + + [ABILITY_FORECAST] = + { + .name = _("Forecast"), + .description = COMPOUND_STRING("Changes with the weather."), + }, + + [ABILITY_STICKY_HOLD] = + { + .name = _("Sticky Hold"), + .description = COMPOUND_STRING("Prevents item theft."), + }, + + [ABILITY_SHED_SKIN] = + { + .name = _("Shed Skin"), + .description = COMPOUND_STRING("Heals the body by shedding."), + }, + + [ABILITY_GUTS] = + { + .name = _("Guts"), + .description = COMPOUND_STRING("Ups Attack if suffering."), + }, + + [ABILITY_MARVEL_SCALE] = + { + .name = _("Marvel Scale"), + .description = COMPOUND_STRING("Ups Defense if suffering."), + }, + + [ABILITY_LIQUID_OOZE] = + { + .name = _("Liquid Ooze"), + .description = COMPOUND_STRING("Draining causes injury."), + }, + + [ABILITY_OVERGROW] = + { + .name = _("Overgrow"), + .description = COMPOUND_STRING("Ups Grass moves in a pinch."), + }, + + [ABILITY_BLAZE] = + { + .name = _("Blaze"), + .description = COMPOUND_STRING("Ups Fire moves in a pinch."), + }, + + [ABILITY_TORRENT] = + { + .name = _("Torrent"), + .description = COMPOUND_STRING("Ups Water moves in a pinch."), + }, + + [ABILITY_SWARM] = + { + .name = _("Swarm"), + .description = COMPOUND_STRING("Ups Bug moves in a pinch."), + }, + + [ABILITY_ROCK_HEAD] = + { + .name = _("Rock Head"), + .description = COMPOUND_STRING("Prevents recoil damage."), + }, + + [ABILITY_DROUGHT] = + { + .name = _("Drought"), + .description = COMPOUND_STRING("Summons sunlight in battle."), + }, + + [ABILITY_ARENA_TRAP] = + { + .name = _("Arena Trap"), + .description = COMPOUND_STRING("Prevents fleeing."), + }, + + [ABILITY_VITAL_SPIRIT] = + { + .name = _("Vital Spirit"), + .description = COMPOUND_STRING("Prevents sleep."), + }, + + [ABILITY_WHITE_SMOKE] = + { + .name = _("White Smoke"), + .description = COMPOUND_STRING("Prevents ability reduction."), + }, + + [ABILITY_PURE_POWER] = + { + .name = _("Pure Power"), + .description = COMPOUND_STRING("Raises Attack."), + }, + + [ABILITY_SHELL_ARMOR] = + { + .name = _("Shell Armor"), + .description = COMPOUND_STRING("Blocks critical hits."), + }, + + [ABILITY_AIR_LOCK] = + { + .name = _("Air Lock"), + .description = COMPOUND_STRING("Negates weather effects."), + }, + + [ABILITY_TANGLED_FEET] = + { + .name = _("Tangled Feet"), + .description = COMPOUND_STRING("Ups evasion if confused."), + }, + + [ABILITY_MOTOR_DRIVE] = + { + .name = _("Motor Drive"), + .description = COMPOUND_STRING("Electricity raises Speed."), + }, + + [ABILITY_RIVALRY] = + { + .name = _("Rivalry"), + .description = COMPOUND_STRING("Powers up against rivals."), + }, + + [ABILITY_STEADFAST] = + { + .name = _("Steadfast"), + .description = COMPOUND_STRING("Flinching raises Speed."), + }, + + [ABILITY_SNOW_CLOAK] = + { + .name = _("Snow Cloak"), + .description = COMPOUND_STRING("Ups evasion in Hail or Snow."), + }, + + [ABILITY_GLUTTONY] = + { + .name = _("Gluttony"), + .description = COMPOUND_STRING("Eats Berries early."), + }, + + [ABILITY_ANGER_POINT] = + { + .name = _("Anger Point"), + .description = COMPOUND_STRING("Critical hits raise Attack."), + }, + + [ABILITY_UNBURDEN] = + { + .name = _("Unburden"), + .description = COMPOUND_STRING("Using a hold item ups Speed."), + }, + + [ABILITY_HEATPROOF] = + { + .name = _("Heatproof"), + .description = COMPOUND_STRING("Heat and burn protection."), + }, + + [ABILITY_SIMPLE] = + { + .name = _("Simple"), + .description = COMPOUND_STRING("Prone to wild stat changes."), + }, + + [ABILITY_DRY_SKIN] = + { + .name = _("Dry Skin"), + .description = COMPOUND_STRING("Prefers moisture to heat."), + }, + + [ABILITY_DOWNLOAD] = + { + .name = _("Download"), + .description = COMPOUND_STRING("Adjusts power favorably."), + }, + + [ABILITY_IRON_FIST] = + { + .name = _("Iron Fist"), + .description = COMPOUND_STRING("Boosts punching moves."), + }, + + [ABILITY_POISON_HEAL] = + { + .name = _("Poison Heal"), + .description = COMPOUND_STRING("Restores HP if poisoned."), + }, + + [ABILITY_ADAPTABILITY] = + { + .name = _("Adaptability"), + .description = COMPOUND_STRING("Boosts same type attacks."), + }, + + [ABILITY_SKILL_LINK] = + { + .name = _("Skill Link"), + .description = COMPOUND_STRING("Multi-hit moves hit 5 times."), + }, + + [ABILITY_HYDRATION] = + { + .name = _("Hydration"), + .description = COMPOUND_STRING("Cures status in rain."), + }, + + [ABILITY_SOLAR_POWER] = + { + .name = _("Solar Power"), + .description = COMPOUND_STRING("Powers up in sunshine."), + }, + + [ABILITY_QUICK_FEET] = + { + .name = _("Quick Feet"), + .description = COMPOUND_STRING("Ups Speed if suffering."), + }, + + [ABILITY_NORMALIZE] = + { + .name = _("Normalize"), + .description = COMPOUND_STRING("Moves become Normal-type."), + }, + + [ABILITY_SNIPER] = + { + .name = _("Sniper"), + .description = COMPOUND_STRING("Boosts critical hits."), + }, + + [ABILITY_MAGIC_GUARD] = + { + .name = _("Magic Guard"), + .description = COMPOUND_STRING("Only damaged by attacks."), + }, + + [ABILITY_NO_GUARD] = + { + .name = _("No Guard"), + .description = COMPOUND_STRING("Ensures that all moves hit."), + }, + + [ABILITY_STALL] = + { + .name = _("Stall"), + .description = COMPOUND_STRING("Always moves last."), + }, + + [ABILITY_TECHNICIAN] = + { + .name = _("Technician"), + .description = COMPOUND_STRING("Boosts weaker moves."), + }, + + [ABILITY_LEAF_GUARD] = + { + .name = _("Leaf Guard"), + .description = COMPOUND_STRING("Blocks status in sunshine."), + }, + + [ABILITY_KLUTZ] = + { + .name = _("Klutz"), + .description = COMPOUND_STRING("Can't use hold items."), + }, + + [ABILITY_MOLD_BREAKER] = + { + .name = _("Mold Breaker"), + .description = COMPOUND_STRING("Moves hit through abilities."), + }, + + [ABILITY_SUPER_LUCK] = + { + .name = _("Super Luck"), + .description = COMPOUND_STRING("Critical hits land often."), + }, + + [ABILITY_AFTERMATH] = + { + .name = _("Aftermath"), + .description = COMPOUND_STRING("Fainting damages the foe."), + }, + + [ABILITY_ANTICIPATION] = + { + .name = _("Anticipation"), + .description = COMPOUND_STRING("Senses dangerous moves."), + }, + + [ABILITY_FOREWARN] = + { + .name = _("Forewarn"), + .description = COMPOUND_STRING("Determines a foe's move."), + }, + + [ABILITY_UNAWARE] = + { + .name = _("Unaware"), + .description = COMPOUND_STRING("Ignores stat changes."), + }, + + [ABILITY_TINTED_LENS] = + { + .name = _("Tinted Lens"), + .description = COMPOUND_STRING("Ups “not very effective”."), + }, + + [ABILITY_FILTER] = + { + .name = _("Filter"), + .description = COMPOUND_STRING("Weakens “supereffective”."), + }, + + [ABILITY_SLOW_START] = + { + .name = _("Slow Start"), + .description = COMPOUND_STRING("Takes a while to get going."), + }, + + [ABILITY_SCRAPPY] = + { + .name = _("Scrappy"), + .description = COMPOUND_STRING("Hits Ghost-type Pokémon."), + }, + + [ABILITY_STORM_DRAIN] = + { + .name = _("Storm Drain"), + .description = COMPOUND_STRING("Draws in Water moves."), + }, + + [ABILITY_ICE_BODY] = + { + .name = _("Ice Body"), + .description = COMPOUND_STRING("HP recovery in Hail or Snow."), + }, + + [ABILITY_SOLID_ROCK] = + { + .name = _("Solid Rock"), + .description = COMPOUND_STRING("Weakens “supereffective”."), + }, + + [ABILITY_SNOW_WARNING] = + { + .name = _("Snow Warning"), + .description = COMPOUND_STRING("Summons a Hailstorm."), + }, + + [ABILITY_HONEY_GATHER] = + { + .name = _("Honey Gather"), + .description = COMPOUND_STRING("May gather Honey."), + }, + + [ABILITY_FRISK] = + { + .name = _("Frisk"), + .description = COMPOUND_STRING("Checks a foe's item."), + }, + + [ABILITY_RECKLESS] = + { + .name = _("Reckless"), + .description = COMPOUND_STRING("Boosts moves with recoil."), + }, + + [ABILITY_MULTITYPE] = + { + .name = _("Multitype"), + .description = COMPOUND_STRING("Changes type to its Plate."), + }, + + [ABILITY_FLOWER_GIFT] = + { + .name = _("Flower Gift"), + .description = COMPOUND_STRING("Allies power up in sunshine."), + }, + + [ABILITY_BAD_DREAMS] = + { + .name = _("Bad Dreams"), + .description = COMPOUND_STRING("Damages sleeping Pokémon."), + }, + + [ABILITY_PICKPOCKET] = + { + .name = _("Pickpocket"), + .description = COMPOUND_STRING("Steals the foe's held item."), + }, + + [ABILITY_SHEER_FORCE] = + { + .name = _("Sheer Force"), + .description = COMPOUND_STRING("Trades effects for power."), + }, + + [ABILITY_CONTRARY] = + { + .name = _("Contrary"), + .description = COMPOUND_STRING("Inverts stat changes."), + }, + + [ABILITY_UNNERVE] = + { + .name = _("Unnerve"), + .description = COMPOUND_STRING("Foes can't eat Berries."), + }, + + [ABILITY_DEFIANT] = + { + .name = _("Defiant"), + .description = COMPOUND_STRING("Lowered stats up Attack."), + }, + + [ABILITY_DEFEATIST] = + { + .name = _("Defeatist"), + .description = COMPOUND_STRING("Gives up at half HP."), + }, + + [ABILITY_CURSED_BODY] = + { + .name = _("Cursed Body"), + .description = COMPOUND_STRING("Disables moves on contact."), + }, + + [ABILITY_HEALER] = + { + .name = _("Healer"), + .description = COMPOUND_STRING("Heals partner Pokémon."), + }, + + [ABILITY_FRIEND_GUARD] = + { + .name = _("Friend Guard"), + .description = COMPOUND_STRING("Lowers damage to partner."), + }, + + [ABILITY_WEAK_ARMOR] = + { + .name = _("Weak Armor"), + .description = COMPOUND_STRING("Its stats change when hit."), + }, + + [ABILITY_HEAVY_METAL] = + { + .name = _("Heavy Metal"), + .description = COMPOUND_STRING("Doubles weight."), + }, + + [ABILITY_LIGHT_METAL] = + { + .name = _("Light Metal"), + .description = COMPOUND_STRING("Halves weight."), + }, + + [ABILITY_MULTISCALE] = + { + .name = _("Multiscale"), + .description = COMPOUND_STRING("Halves damage at full HP."), + }, + + [ABILITY_TOXIC_BOOST] = + { + .name = _("Toxic Boost"), + .description = COMPOUND_STRING("Ups Attack if poisoned."), + }, + + [ABILITY_FLARE_BOOST] = + { + .name = _("Flare Boost"), + .description = COMPOUND_STRING("Ups Sp. Atk if burned."), + }, + + [ABILITY_HARVEST] = + { + .name = _("Harvest"), + .description = COMPOUND_STRING("May recycle a used Berry."), + }, + + [ABILITY_TELEPATHY] = + { + .name = _("Telepathy"), + .description = COMPOUND_STRING("Can't be damaged by an ally."), + }, + + [ABILITY_MOODY] = + { + .name = _("Moody"), + .description = COMPOUND_STRING("Stats change gradually."), + }, + + [ABILITY_OVERCOAT] = + { + .name = _("Overcoat"), + .description = COMPOUND_STRING("Blocks weather and powder."), + }, + + [ABILITY_POISON_TOUCH] = + { + .name = _("Poison Touch"), + .description = COMPOUND_STRING("Poisons foe on contact."), + }, + + [ABILITY_REGENERATOR] = + { + .name = _("Regenerator"), + .description = COMPOUND_STRING("Heals upon switching out."), + }, + + [ABILITY_BIG_PECKS] = + { + .name = _("Big Pecks"), + .description = COMPOUND_STRING("Prevents Defense loss."), + }, + + [ABILITY_SAND_RUSH] = + { + .name = _("Sand Rush"), + .description = COMPOUND_STRING("Ups Speed in a sandstorm."), + }, + + [ABILITY_WONDER_SKIN] = + { + .name = _("Wonder Skin"), + .description = COMPOUND_STRING("May avoid status problems."), + }, + + [ABILITY_ANALYTIC] = + { + .name = _("Analytic"), + .description = COMPOUND_STRING("Moving last boosts power."), + }, + + [ABILITY_ILLUSION] = + { + .name = _("Illusion"), + .description = COMPOUND_STRING("Appears as a partner."), + }, + + [ABILITY_IMPOSTER] = + { + .name = _("Imposter"), + .description = COMPOUND_STRING("Transforms into the foe."), + }, + + [ABILITY_INFILTRATOR] = + { + .name = _("Infiltrator"), + .description = COMPOUND_STRING("Passes through barriers."), + }, + + [ABILITY_MUMMY] = + { + .name = _("Mummy"), + .description = COMPOUND_STRING("Spreads with contact."), + }, + + [ABILITY_MOXIE] = + { + .name = _("Moxie"), + .description = COMPOUND_STRING("KOs raise Attack."), + }, + + [ABILITY_JUSTIFIED] = + { + .name = _("Justified"), + .description = COMPOUND_STRING("Dark hits raise Attack."), + }, + + [ABILITY_RATTLED] = + { + .name = _("Rattled"), + .description = COMPOUND_STRING("Raises Speed when scared."), + }, + + [ABILITY_MAGIC_BOUNCE] = + { + .name = _("Magic Bounce"), + .description = COMPOUND_STRING("Reflects status moves."), + }, + + [ABILITY_SAP_SIPPER] = + { + .name = _("Sap Sipper"), + .description = COMPOUND_STRING("Grass increases Attack."), + }, + + [ABILITY_PRANKSTER] = + { + .name = _("Prankster"), + .description = COMPOUND_STRING("Status moves go first."), + }, + + [ABILITY_SAND_FORCE] = + { + .name = _("Sand Force"), + .description = COMPOUND_STRING("Powers up in a sandstorm."), + }, + + [ABILITY_IRON_BARBS] = + { + .name = _("Iron Barbs"), + .description = COMPOUND_STRING("Hurts to touch."), + }, + + [ABILITY_ZEN_MODE] = + { + .name = _("Zen Mode"), + .description = COMPOUND_STRING("Transforms at half HP."), + }, + + [ABILITY_VICTORY_STAR] = + { + .name = _("Victory Star"), + .description = COMPOUND_STRING("Raises party accuracy."), + }, + + [ABILITY_TURBOBLAZE] = + { + .name = _("Turboblaze"), + .description = COMPOUND_STRING("Moves hit through abilities."), + }, + + [ABILITY_TERAVOLT] = + { + .name = _("Teravolt"), + .description = COMPOUND_STRING("Moves hit through abilities."), + }, + + [ABILITY_AROMA_VEIL] = + { + .name = _("Aroma Veil"), + .description = COMPOUND_STRING("Prevents limiting of moves."), + }, + + [ABILITY_FLOWER_VEIL] = + { + .name = _("Flower Veil"), + .description = COMPOUND_STRING("Protects Grass-types."), + }, + + [ABILITY_CHEEK_POUCH] = + { + .name = _("Cheek Pouch"), + .description = COMPOUND_STRING("Eating Berries restores HP."), + }, + + [ABILITY_PROTEAN] = + { + .name = _("Protean"), + .description = COMPOUND_STRING("Changes type to used move."), + }, + + [ABILITY_FUR_COAT] = + { + .name = _("Fur Coat"), + .description = COMPOUND_STRING("Raises Defense."), + }, + + [ABILITY_MAGICIAN] = + { + .name = _("Magician"), + .description = COMPOUND_STRING("Steals the foe's held item."), + }, + + [ABILITY_BULLETPROOF] = + { + .name = _("Bulletproof"), + .description = COMPOUND_STRING("Avoids some projectiles."), + }, + + [ABILITY_COMPETITIVE] = + { + .name = _("Competitive"), + .description = COMPOUND_STRING("Lowered stats up Sp. Atk."), + }, + + [ABILITY_STRONG_JAW] = + { + .name = _("Strong Jaw"), + .description = COMPOUND_STRING("Boosts biting moves."), + }, + + [ABILITY_REFRIGERATE] = + { + .name = _("Refrigerate"), + .description = COMPOUND_STRING("Normal moves become Ice."), + }, + + [ABILITY_SWEET_VEIL] = + { + .name = _("Sweet Veil"), + .description = COMPOUND_STRING("Prevents party from sleep."), + }, + + [ABILITY_STANCE_CHANGE] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Stance Change"), + #else + .name = _("StanceChange"), + #endif + .description = COMPOUND_STRING("Transforms as it battles."), + }, + + [ABILITY_GALE_WINGS] = + { + .name = _("Gale Wings"), + .description = COMPOUND_STRING("Flying moves go first."), + }, + + [ABILITY_MEGA_LAUNCHER] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Mega Launcher"), + #else + .name = _("MegaLauncher"), + #endif + .description = COMPOUND_STRING("Boosts pulse moves."), + }, + + [ABILITY_GRASS_PELT] = + { + .name = _("Grass Pelt"), + .description = COMPOUND_STRING("Ups Defense in grass."), + }, + + [ABILITY_SYMBIOSIS] = + { + .name = _("Symbiosis"), + .description = COMPOUND_STRING("Passes its item to an ally."), + }, + + [ABILITY_TOUGH_CLAWS] = + { + .name = _("Tough Claws"), + .description = COMPOUND_STRING("Boosts contact moves."), + }, + + [ABILITY_PIXILATE] = + { + .name = _("Pixilate"), + .description = COMPOUND_STRING("Normal moves become Fairy."), + }, + + [ABILITY_GOOEY] = + { + .name = _("Gooey"), + .description = COMPOUND_STRING("Lowers Speed on contact."), + }, + + [ABILITY_AERILATE] = + { + .name = _("Aerilate"), + .description = COMPOUND_STRING("Normal moves become Flying."), + }, + + [ABILITY_PARENTAL_BOND] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Parental Bond"), + #else + .name = _("ParentalBond"), + #endif + .description = COMPOUND_STRING("Moves hit twice."), + }, + + [ABILITY_DARK_AURA] = + { + .name = _("Dark Aura"), + .description = COMPOUND_STRING("Boosts Dark moves."), + }, + + [ABILITY_FAIRY_AURA] = + { + .name = _("Fairy Aura"), + .description = COMPOUND_STRING("Boosts Fairy moves."), + }, + + [ABILITY_AURA_BREAK] = + { + .name = _("Aura Break"), + .description = COMPOUND_STRING("Reverse aura abilities."), + }, + + [ABILITY_PRIMORDIAL_SEA] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Primordial Sea"), + #else + .name = _("PrimrdialSea"), + #endif + .description = COMPOUND_STRING("Summons heavy rain."), + }, + + [ABILITY_DESOLATE_LAND] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Desolate Land"), + #else + .name = _("DesolateLand"), + #endif + .description = COMPOUND_STRING("Summons intense sunlight."), + }, + + [ABILITY_DELTA_STREAM] = + { + .name = _("Delta Stream"), + .description = COMPOUND_STRING("Summons strong winds."), + }, + + [ABILITY_STAMINA] = + { + .name = _("Stamina"), + .description = COMPOUND_STRING("Boosts Defense when hit."), + }, + + [ABILITY_WIMP_OUT] = + { + .name = _("Wimp Out"), + .description = COMPOUND_STRING("Flees at half HP."), + }, + + [ABILITY_EMERGENCY_EXIT] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Emergency Exit"), + #else + .name = _("EmergncyExit"), + #endif + .description = COMPOUND_STRING("Flees at half HP."), + }, + + [ABILITY_WATER_COMPACTION] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Water Compaction"), + #else + .name = _("WtrCmpaction"), + #endif + .description = COMPOUND_STRING("Water boosts Defense."), + }, + + [ABILITY_MERCILESS] = + { + .name = _("Merciless"), + .description = COMPOUND_STRING("Criticals poisoned foes."), + }, + + [ABILITY_SHIELDS_DOWN] = + { + .name = _("Shields Down"), + .description = COMPOUND_STRING("Shell breaks at half HP."), + }, + + [ABILITY_STAKEOUT] = + { + .name = _("Stakeout"), + .description = COMPOUND_STRING("Stronger as foes switch in."), + }, + + [ABILITY_WATER_BUBBLE] = + { + .name = _("Water Bubble"), + .description = COMPOUND_STRING("Guards from fire and burns."), + }, + + [ABILITY_STEELWORKER] = + { + .name = _("Steelworker"), + .description = COMPOUND_STRING("Powers up Steel moves."), + }, + + [ABILITY_BERSERK] = + { + .name = _("Berserk"), + .description = COMPOUND_STRING("Boosts Sp. Atk at low HP."), + }, + + [ABILITY_SLUSH_RUSH] = + { + .name = _("Slush Rush"), + .description = COMPOUND_STRING("Raises Speed in Hail or Snow."), + }, + + [ABILITY_LONG_REACH] = + { + .name = _("Long Reach"), + .description = COMPOUND_STRING("Never makes contact."), + }, + + [ABILITY_LIQUID_VOICE] = + { + .name = _("Liquid Voice"), + .description = COMPOUND_STRING("Makes sound moves Water."), + }, + + [ABILITY_TRIAGE] = + { + .name = _("Triage"), + .description = COMPOUND_STRING("Healing moves go first."), + }, + + [ABILITY_GALVANIZE] = + { + .name = _("Galvanize"), + .description = COMPOUND_STRING("Normal moves turn Electric."), + }, + + [ABILITY_SURGE_SURFER] = + { + .name = _("Surge Surfer"), + .description = COMPOUND_STRING("Faster on electricity."), + }, + + [ABILITY_SCHOOLING] = + { + .name = _("Schooling"), + .description = COMPOUND_STRING("Forms a school when strong."), + }, + + [ABILITY_DISGUISE] = + { + .name = _("Disguise"), + .description = COMPOUND_STRING("Decoy protects it once."), + }, + + [ABILITY_BATTLE_BOND] = + { + .name = _("Battle Bond"), + .description = COMPOUND_STRING("Changes form after a KO."), + }, + + [ABILITY_POWER_CONSTRUCT] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Power Construct"), + #else + .name = _("PwrConstruct"), + #endif + .description = COMPOUND_STRING("Cells aid it when weakened."), + }, + + [ABILITY_CORROSION] = + { + .name = _("Corrosion"), + .description = COMPOUND_STRING("Poisons any type."), + }, + + [ABILITY_COMATOSE] = + { + .name = _("Comatose"), + .description = COMPOUND_STRING("Always drowsing."), + }, + + [ABILITY_QUEENLY_MAJESTY] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Queenly Majesty"), + #else + .name = _("QueenlyMjsty"), + #endif + .description = COMPOUND_STRING("Protects from priority."), + }, + + [ABILITY_INNARDS_OUT] = + { + .name = _("Innards Out"), + .description = COMPOUND_STRING("Hurts foe when defeated."), + }, + + [ABILITY_DANCER] = + { + .name = _("Dancer"), + .description = COMPOUND_STRING("Dances along with others."), + }, + + [ABILITY_BATTERY] = + { + .name = _("Battery"), + .description = COMPOUND_STRING("Boosts ally's Sp. Atk."), + }, + + [ABILITY_FLUFFY] = + { + .name = _("Fluffy"), + .description = COMPOUND_STRING("Tougher but flammable."), + }, + + [ABILITY_DAZZLING] = + { + .name = _("Dazzling"), + .description = COMPOUND_STRING("Protects from priority."), + }, + + [ABILITY_SOUL_HEART] = + { + .name = _("Soul-Heart"), + .description = COMPOUND_STRING("KOs raise Sp. Atk."), + }, + + [ABILITY_TANGLING_HAIR] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Tangling Hair"), + #else + .name = _("TanglingHair"), + #endif + .description = COMPOUND_STRING("Lowers Speed on contact."), + }, + + [ABILITY_RECEIVER] = + { + .name = _("Receiver"), + .description = COMPOUND_STRING("Copies ally's ability."), + }, + + [ABILITY_POWER_OF_ALCHEMY] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Power Of Alchemy"), + #else + .name = _("PwrOfAlchemy"), + #endif + .description = COMPOUND_STRING("Copies ally's ability."), + }, + + [ABILITY_BEAST_BOOST] = + { + .name = _("Beast Boost"), + .description = COMPOUND_STRING("KOs boost best stat."), + }, + + [ABILITY_RKS_SYSTEM] = + { + .name = _("RKS System"), + .description = COMPOUND_STRING("Memories change its type."), + }, + + [ABILITY_ELECTRIC_SURGE] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Electric Surge"), + #else + .name = _("ElectrcSurge"), + #endif + .description = COMPOUND_STRING("Field becomes Electric."), + }, + + [ABILITY_PSYCHIC_SURGE] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Psychic Surge"), + #else + .name = _("PsychicSurge"), + #endif + .description = COMPOUND_STRING("Field becomes weird."), + }, + + [ABILITY_MISTY_SURGE] = + { + .name = _("Misty Surge"), + .description = COMPOUND_STRING("Field becomes misty."), + }, + + [ABILITY_GRASSY_SURGE] = + { + .name = _("Grassy Surge"), + .description = COMPOUND_STRING("Field becomes grassy."), + }, + + [ABILITY_FULL_METAL_BODY] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Full Metal Body"), + #else + .name = _("FullMetalBdy"), + #endif + .description = COMPOUND_STRING("Prevents stat reduction."), + }, + + [ABILITY_SHADOW_SHIELD] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Shadow Shield"), + #else + .name = _("ShadowShield"), + #endif + .description = COMPOUND_STRING("Halves damage at full HP."), + }, + + [ABILITY_PRISM_ARMOR] = + { + .name = _("Prism Armor"), + .description = COMPOUND_STRING("Weakens “supereffective”."), + }, + + [ABILITY_NEUROFORCE] = + { + .name = _("Neuroforce"), + .description = COMPOUND_STRING("Ups “supereffective”."), + }, + + [ABILITY_INTREPID_SWORD] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Intrepid Sword"), + #else + .name = _("IntrepidSwrd"), + #endif + .description = COMPOUND_STRING("Ups Attack on entry."), + }, + + [ABILITY_DAUNTLESS_SHIELD] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Dauntless Shield"), + #else + .name = _("DauntlssShld"), + #endif + .description = COMPOUND_STRING("Ups Defense on entry."), + }, + + [ABILITY_LIBERO] = + { + .name = _("Libero"), + .description = COMPOUND_STRING("Changes type to move's."), + }, + + [ABILITY_BALL_FETCH] = + { + .name = _("Ball Fetch"), + .description = COMPOUND_STRING("Fetches failed Poké Ball."), + }, + + [ABILITY_COTTON_DOWN] = + { + .name = _("Cotton Down"), + .description = COMPOUND_STRING("Lower Speed of all when hit."), + }, + + [ABILITY_PROPELLER_TAIL] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Propeller Tail"), + #else + .name = _("PropellrTail"), + #endif + .description = COMPOUND_STRING("Ignores foe's redirection."), + }, + + [ABILITY_MIRROR_ARMOR] = + { + .name = _("Mirror Armor"), + .description = COMPOUND_STRING("Reflect stat decreases."), + }, + + [ABILITY_GULP_MISSILE] = + { + .name = _("Gulp Missile"), + .description = COMPOUND_STRING("If hit, spits prey from sea."), + }, + + [ABILITY_STALWART] = + { + .name = _("Stalwart"), + .description = COMPOUND_STRING("Ignores foe's redirection."), + }, + + [ABILITY_STEAM_ENGINE] = + { + .name = _("Steam Engine"), + .description = COMPOUND_STRING("Fire or Water hits up Speed."), + }, + + [ABILITY_PUNK_ROCK] = + { + .name = _("Punk Rock"), + .description = COMPOUND_STRING("Ups and resists sound."), + }, + + [ABILITY_SAND_SPIT] = + { + .name = _("Sand Spit"), + .description = COMPOUND_STRING("Creates a sandstorm if hit."), + }, + + [ABILITY_ICE_SCALES] = + { + .name = _("Ice Scales"), + .description = COMPOUND_STRING("Halves special damage."), + }, + + [ABILITY_RIPEN] = + { + .name = _("Ripen"), + .description = COMPOUND_STRING("Doubles effect of Berries."), + }, + + [ABILITY_ICE_FACE] = + { + .name = _("Ice Face"), + .description = COMPOUND_STRING("Hail or Snow renew free hit."), + }, + + [ABILITY_POWER_SPOT] = + { + .name = _("Power Spot"), + .description = COMPOUND_STRING("Powers up ally moves."), + }, + + [ABILITY_MIMICRY] = + { + .name = _("Mimicry"), + .description = COMPOUND_STRING("Changes type on terrain."), + }, + + [ABILITY_SCREEN_CLEANER] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Screen Cleaner"), + #else + .name = _("ScreenCleanr"), + #endif + .description = COMPOUND_STRING("Removes walls of light."), + }, + + [ABILITY_STEELY_SPIRIT] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Steely Spirit"), + #else + .name = _("SteelySpirit"), + #endif + .description = COMPOUND_STRING("Boosts ally's Steel moves."), + }, + + [ABILITY_PERISH_BODY] = + { + .name = _("Perish Body"), + .description = COMPOUND_STRING("Foe faints in 3 turns if hit."), + }, + + [ABILITY_WANDERING_SPIRIT] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Wandering Spirit"), + #else + .name = _("WandrngSprit"), + #endif + .description = COMPOUND_STRING("Trade abilities on contact."), + }, + + [ABILITY_GORILLA_TACTICS] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Gorilla Tactics"), + #else + .name = _("GorillaTacti"), + #endif + .description = COMPOUND_STRING("Ups Attack and locks move."), + }, + + [ABILITY_NEUTRALIZING_GAS] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Neutralizing Gas"), + #else + .name = _("NeutrlzngGas"), + #endif + .description = COMPOUND_STRING("All Abilities are nullified."), + }, + + [ABILITY_PASTEL_VEIL] = + { + .name = _("Pastel Veil"), + .description = COMPOUND_STRING("Protects team from poison."), + }, + + [ABILITY_HUNGER_SWITCH] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Hunger Switch"), + #else + .name = _("HungerSwitch"), + #endif + .description = COMPOUND_STRING("Changes form each turn."), + }, + + [ABILITY_QUICK_DRAW] = + { + .name = _("Quick Draw"), + .description = COMPOUND_STRING("Moves first occasionally."), + }, + + [ABILITY_UNSEEN_FIST] = + { + .name = _("Unseen Fist"), + .description = COMPOUND_STRING("Contact evades protection."), + }, + + [ABILITY_CURIOUS_MEDICINE] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Curious Medicine"), + #else + .name = _("CuriusMedicn"), + #endif + .description = COMPOUND_STRING("Remove ally's stat changes."), + }, + + [ABILITY_TRANSISTOR] = + { + .name = _("Transistor"), + .description = COMPOUND_STRING("Ups Electric-type moves."), + }, + + [ABILITY_DRAGONS_MAW] = + { + .name = _("Dragon's Maw"), + .description = COMPOUND_STRING("Ups Dragon-type moves."), + }, + + [ABILITY_CHILLING_NEIGH] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Chilling Neigh"), + #else + .name = _("ChillngNeigh"), + #endif + .description = COMPOUND_STRING("KOs boost Attack stat."), + }, + + [ABILITY_GRIM_NEIGH] = + { + .name = _("Grim Neigh"), + .description = COMPOUND_STRING("KOs boost Sp. Atk stat."), + }, + + [ABILITY_AS_ONE_ICE_RIDER] = + { + .name = _("As One"), + .description = COMPOUND_STRING("Unnerve and Chilling Neigh."), + }, + + [ABILITY_AS_ONE_SHADOW_RIDER] = + { + .name = _("As One"), + .description = COMPOUND_STRING("Unnerve and Grim Neigh."), + }, + + [ABILITY_LINGERING_AROMA] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Lingering Aroma"), + #else + .name = _("LngerngAroma"), + #endif + .description = COMPOUND_STRING("Spreads with contact."), + }, + + [ABILITY_SEED_SOWER] = + { + .name = _("Seed Sower"), + .description = COMPOUND_STRING("Affects terrain when hit."), + }, + + [ABILITY_THERMAL_EXCHANGE] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Thermal Exchange"), + #else + .name = _("ThrmlExchnge"), + #endif + .description = COMPOUND_STRING("Fire hits up Attack."), + }, + + [ABILITY_ANGER_SHELL] = + { + .name = _("Anger Shell"), + .description = COMPOUND_STRING("Gets angry at half HP."), + }, + + [ABILITY_PURIFYING_SALT] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Purifying Salt"), + #else + .name = _("PurfyingSalt"), + #endif + .description = COMPOUND_STRING("Protected by pure salts."), + }, + + [ABILITY_WELL_BAKED_BODY] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Well-Baked Body"), + #else + .name = _("WellBakedBdy"), + #endif + .description = COMPOUND_STRING("Strengthened by Fire."), + }, + + [ABILITY_WIND_RIDER] = + { + .name = _("Wind Rider"), + .description = COMPOUND_STRING("Ups Attack if hit by wind."), + }, + + [ABILITY_GUARD_DOG] = + { + .name = _("Guard Dog"), + .description = COMPOUND_STRING("Cannot be intimidated."), + }, + + [ABILITY_ROCKY_PAYLOAD] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Rocky Payload"), + #else + .name = _("RockyPayload"), + #endif + .description = COMPOUND_STRING("Powers up Rock moves."), + }, + + [ABILITY_WIND_POWER] = + { + .name = _("Wind Power"), + .description = COMPOUND_STRING("Gets charged by wind."), + }, + + [ABILITY_ZERO_TO_HERO] = + { + .name = _("Zero to Hero"), + .description = COMPOUND_STRING("Changes form on switch out."), + }, + + [ABILITY_COMMANDER] = + { + .name = _("Commander"), + .description = COMPOUND_STRING("Commands from Dondozo."), + }, + + [ABILITY_ELECTROMORPHOSIS] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Electromorphosis"), + #else + .name = _("Elecmrphosis"), + #endif + .description = COMPOUND_STRING("Gets Charged on contact."), + }, + + [ABILITY_PROTOSYNTHESIS] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Protosynthesis"), + #else + .name = _("Protosnthsis"), + #endif + .description = COMPOUND_STRING("Sun boosts best stat."), + }, + + [ABILITY_QUARK_DRIVE] = + { + .name = _("Quark Drive"), + .description = COMPOUND_STRING("Elec. field ups best stat."), + }, + + [ABILITY_GOOD_AS_GOLD] = + { + .name = _("Good as Gold"), + .description = COMPOUND_STRING("Avoids status problems."), + }, + + [ABILITY_VESSEL_OF_RUIN] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Vessel of Ruin"), + #else + .name = _("VesselOfRuin"), + #endif + .description = COMPOUND_STRING("Lowers foes' sp. damage."), + }, + + [ABILITY_SWORD_OF_RUIN] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Sword of Ruin"), + #else + .name = _("SwordOfRuin"), + #endif + .description = COMPOUND_STRING("Lowers foes' defense."), + }, + + [ABILITY_TABLETS_OF_RUIN] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Tablets of Ruin"), + #else + .name = _("TabltsOfRuin"), + #endif + .description = COMPOUND_STRING("Lowers foes' damage."), + }, + + [ABILITY_BEADS_OF_RUIN] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Beads of Ruin"), + #else + .name = _("BeadsOfRuin"), + #endif + .description = COMPOUND_STRING("Lowers foes' sp. defense."), + }, + + [ABILITY_ORICHALCUM_PULSE] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Orichalcum Pulse"), + #else + .name = _("OrchlcumPlse"), + #endif + .description = COMPOUND_STRING("Summons sunlight in battle."), + }, + + [ABILITY_HADRON_ENGINE] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Hadron Engine"), + #else + .name = _("HadronEngine"), + #endif + .description = COMPOUND_STRING("Field becomes Electric."), + }, + + [ABILITY_OPPORTUNIST] = + { + .name = _("Opportunist"), + .description = COMPOUND_STRING("Copies foe's stat change."), + }, + + [ABILITY_CUD_CHEW] = + { + .name = _("Cud Chew"), + .description = COMPOUND_STRING("Eats a used berry again."), + }, + + [ABILITY_SHARPNESS] = + { + .name = _("Sharpness"), + .description = COMPOUND_STRING("Strengthens slicing moves."), + }, + + [ABILITY_SUPREME_OVERLORD] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Supreme Overlord"), + #else + .name = _("SuprmeOvrlrd"), + #endif + .description = COMPOUND_STRING("Inherits fallen's strength."), + }, + + [ABILITY_COSTAR] = + { + .name = _("Costar"), + .description = COMPOUND_STRING("Copies ally's stat changes."), + }, + + [ABILITY_TOXIC_DEBRIS] = + { + .name = _("Toxic Debris"), + .description = COMPOUND_STRING("Throws poison spikes if hit."), + }, + + [ABILITY_ARMOR_TAIL] = + { + .name = _("Armor Tail"), + .description = COMPOUND_STRING("Protects from priority."), + }, + + [ABILITY_EARTH_EATER] = + { + .name = _("Earth Eater"), + .description = COMPOUND_STRING("Eats ground to heal HP."), + }, + + [ABILITY_MYCELIUM_MIGHT] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Mycelium Might"), + #else + .name = _("MceliumMight"), + #endif + .description = COMPOUND_STRING("Status moves never fail."), + }, + + [ABILITY_HOSPITALITY] = + { + .name = _("Hospitality"), + .description = COMPOUND_STRING("Restores ally's HP."), + }, + + [ABILITY_MINDS_EYE] = + { + .name = _("Mind's Eye"), + .description = COMPOUND_STRING("Keen Eye and Scrappy."), + }, + + [ABILITY_EMBODY_ASPECT_TEAL] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Embody Aspect"), + #else + .name = _("EmbodyAspect"), + #endif + .description = COMPOUND_STRING("Raises Speed."), + }, + + [ABILITY_EMBODY_ASPECT_HEARTHFLAME] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Embody Aspect"), + #else + .name = _("EmbodyAspect"), + #endif + .description = COMPOUND_STRING("Raises Attack."), + }, + + [ABILITY_EMBODY_ASPECT_WELLSPRING] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Embody Aspect"), + #else + .name = _("EmbodyAspect"), + #endif + .description = COMPOUND_STRING("Raises Sp. Def."), + }, + + [ABILITY_EMBODY_ASPECT_CORNERSTONE] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Embody Aspect"), + #else + .name = _("EmbodyAspect"), + #endif + .description = COMPOUND_STRING("Raises Defense."), + }, + + [ABILITY_TOXIC_CHAIN] = + { + .name = _("Toxic Chain"), + .description = COMPOUND_STRING("Moves can poison."), + }, + + [ABILITY_SUPERSWEET_SYRUP] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Supersweet Syrup"), + #else + .name = _("SuprswtSyrup"), + #endif + .description = COMPOUND_STRING("Lowers the foe's Speed."), + }, + + [ABILITY_TERA_SHIFT] = + { + .name = _("Tera Shift"), + .description = COMPOUND_STRING("Terasteralizes upon entry."), + }, + + [ABILITY_TERA_SHELL] = + { + .name = _("Tera Shell"), + .description = COMPOUND_STRING("Resistant to types at full HP."), + }, + + [ABILITY_TERAFORM_ZERO] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Teraform Zero"), + #else + .name = _("TeraformZero"), + #endif + .description = COMPOUND_STRING("Removes weather and terrain."), + }, + + [ABILITY_POISON_PUPPETEER] = + { + #if B_EXPANDED_ABILITY_NAMES == TRUE + .name = _("Poison Puppeteer"), + #else + .name = _("PoisnPuppter"), + #endif + .description = COMPOUND_STRING("Confuses poisoned foes."), + }, +}; diff --git a/src/data/text/abilities.h b/src/data/text/abilities.h deleted file mode 100644 index d8ed29cf39..0000000000 --- a/src/data/text/abilities.h +++ /dev/null @@ -1,1250 +0,0 @@ -static const u8 sNoneDescription[] = _("No special ability."); -static const u8 sStenchDescription[] = _("May cause a foe to flinch."); -static const u8 sDrizzleDescription[] = _("Summons rain in battle."); -static const u8 sSpeedBoostDescription[] = _("Gradually boosts Speed."); -static const u8 sBattleArmorDescription[] = _("Blocks critical hits."); -static const u8 sSturdyDescription[] = _("Negates 1-hit KO attacks."); -static const u8 sDampDescription[] = _("Prevents self-destruction."); -static const u8 sLimberDescription[] = _("Prevents paralysis."); -static const u8 sSandVeilDescription[] = _("Ups evasion in a sandstorm."); -static const u8 sStaticDescription[] = _("Paralyzes on contact."); -static const u8 sVoltAbsorbDescription[] = _("Turns electricity into HP."); -static const u8 sWaterAbsorbDescription[] = _("Changes water into HP."); -static const u8 sObliviousDescription[] = _("Prevents attraction."); -static const u8 sCloudNineDescription[] = _("Negates weather effects."); -static const u8 sCompoundEyesDescription[] = _("Raises accuracy."); -static const u8 sInsomniaDescription[] = _("Prevents sleep."); -static const u8 sColorChangeDescription[] = _("Changes type to foe's move."); -static const u8 sImmunityDescription[] = _("Prevents poisoning."); -static const u8 sFlashFireDescription[] = _("Powers up if hit by fire."); -static const u8 sShieldDustDescription[] = _("Prevents added effects."); -static const u8 sOwnTempoDescription[] = _("Prevents confusion."); -static const u8 sSuctionCupsDescription[] = _("Firmly anchors the body."); -static const u8 sIntimidateDescription[] = _("Lowers the foe's Attack."); -static const u8 sShadowTagDescription[] = _("Prevents the foe's escape."); -static const u8 sRoughSkinDescription[] = _("Hurts to touch."); -static const u8 sWonderGuardDescription[] = _("“Supereffective” hits."); -static const u8 sLevitateDescription[] = _("Not hit by Ground attacks."); -static const u8 sEffectSporeDescription[] = _("Leaves spores on contact."); -static const u8 sSynchronizeDescription[] = _("Passes on status problems."); -static const u8 sClearBodyDescription[] = _("Prevents ability reduction."); -static const u8 sNaturalCureDescription[] = _("Heals upon switching out."); -static const u8 sLightningRodDescription[] = _("Draws electrical moves."); -static const u8 sSereneGraceDescription[] = _("Promotes added effects."); -static const u8 sSwiftSwimDescription[] = _("Raises Speed in rain."); -static const u8 sChlorophyllDescription[] = _("Raises Speed in sunshine."); -static const u8 sIlluminateDescription[] = _("Encounter rate increases."); -static const u8 sTraceDescription[] = _("Copies special ability."); -static const u8 sHugePowerDescription[] = _("Raises Attack."); -static const u8 sPoisonPointDescription[] = _("Poisons foe on contact."); -static const u8 sInnerFocusDescription[] = _("Prevents flinching."); -static const u8 sMagmaArmorDescription[] = _("Prevents freezing."); -static const u8 sWaterVeilDescription[] = _("Prevents burns."); -static const u8 sMagnetPullDescription[] = _("Traps Steel-type Pokémon."); -static const u8 sSoundproofDescription[] = _("Avoids sound-based moves."); -static const u8 sRainDishDescription[] = _("Slight HP recovery in rain."); -static const u8 sSandStreamDescription[] = _("Summons a sandstorm."); -static const u8 sPressureDescription[] = _("Raises foe's PP usage."); -static const u8 sThickFatDescription[] = _("Heat-and-cold protection."); -static const u8 sEarlyBirdDescription[] = _("Awakens quickly from sleep."); -static const u8 sFlameBodyDescription[] = _("Burns the foe on contact."); -static const u8 sRunAwayDescription[] = _("Makes escaping easier."); -static const u8 sKeenEyeDescription[] = _("Prevents loss of accuracy."); -static const u8 sHyperCutterDescription[] = _("Prevents Attack reduction."); -static const u8 sPickupDescription[] = _("May pick up items."); -static const u8 sTruantDescription[] = _("Moves only every two turns."); -static const u8 sHustleDescription[] = _("Trades accuracy for power."); -static const u8 sCuteCharmDescription[] = _("Infatuates on contact."); -static const u8 sPlusDescription[] = _("Powers up with Minus."); -static const u8 sMinusDescription[] = _("Powers up with Plus."); -static const u8 sForecastDescription[] = _("Changes with the weather."); -static const u8 sStickyHoldDescription[] = _("Prevents item theft."); -static const u8 sShedSkinDescription[] = _("Heals the body by shedding."); -static const u8 sGutsDescription[] = _("Ups Attack if suffering."); -static const u8 sMarvelScaleDescription[] = _("Ups Defense if suffering."); -static const u8 sLiquidOozeDescription[] = _("Draining causes injury."); -static const u8 sOvergrowDescription[] = _("Ups Grass moves in a pinch."); -static const u8 sBlazeDescription[] = _("Ups Fire moves in a pinch."); -static const u8 sTorrentDescription[] = _("Ups Water moves in a pinch."); -static const u8 sSwarmDescription[] = _("Ups Bug moves in a pinch."); -static const u8 sRockHeadDescription[] = _("Prevents recoil damage."); -static const u8 sDroughtDescription[] = _("Summons sunlight in battle."); -static const u8 sArenaTrapDescription[] = _("Prevents fleeing."); -static const u8 sVitalSpiritDescription[] = _("Prevents sleep."); -static const u8 sWhiteSmokeDescription[] = _("Prevents ability reduction."); -static const u8 sPurePowerDescription[] = _("Raises Attack."); -static const u8 sShellArmorDescription[] = _("Blocks critical hits."); -static const u8 sAirLockDescription[] = _("Negates weather effects."); -static const u8 sTangledFeetDescription[] = _("Ups evasion if confused."); -static const u8 sMotorDriveDescription[] = _("Electricity raises Speed."); -static const u8 sRivalryDescription[] = _("Powers up against rivals."); -static const u8 sSteadfastDescription[] = _("Flinching raises Speed."); -static const u8 sSnowCloakDescription[] = _("Ups evasion in Hail or Snow."); -static const u8 sGluttonyDescription[] = _("Eats Berries early."); -static const u8 sAngerPointDescription[] = _("Critical hits raise Attack."); -static const u8 sUnburdenDescription[] = _("Using a hold item ups Speed."); -static const u8 sHeatproofDescription[] = _("Heat and burn protection."); -static const u8 sSimpleDescription[] = _("Prone to wild stat changes."); -static const u8 sDrySkinDescription[] = _("Prefers moisture to heat."); -static const u8 sDownloadDescription[] = _("Adjusts power favorably."); -static const u8 sIronFistDescription[] = _("Boosts punching moves."); -static const u8 sPoisonHealDescription[] = _("Restores HP if poisoned."); -static const u8 sAdaptabilityDescription[] = _("Boosts same type attacks."); -static const u8 sSkillLinkDescription[] = _("Multi-hit moves hit 5 times."); -static const u8 sHydrationDescription[] = _("Cures status in rain."); -static const u8 sSolarPowerDescription[] = _("Powers up in sunshine."); -static const u8 sQuickFeetDescription[] = _("Ups Speed if suffering."); -static const u8 sNormalizeDescription[] = _("Moves become Normal-type."); -static const u8 sSniperDescription[] = _("Boosts critical hits."); -static const u8 sMagicGuardDescription[] = _("Only damaged by attacks."); -static const u8 sNoGuardDescription[] = _("Ensures that all moves hit."); -static const u8 sStallDescription[] = _("Always moves last."); -static const u8 sTechnicianDescription[] = _("Boosts weaker moves."); -static const u8 sLeafGuardDescription[] = _("Blocks status in sunshine."); -static const u8 sKlutzDescription[] = _("Can't use hold items."); -static const u8 sMoldBreakerDescription[] = _("Moves hit through abilities."); -static const u8 sSuperLuckDescription[] = _("Critical hits land often."); -static const u8 sAftermathDescription[] = _("Fainting damages the foe."); -static const u8 sAnticipationDescription[] = _("Senses dangerous moves."); -static const u8 sForewarnDescription[] = _("Determines a foe's move."); -static const u8 sUnawareDescription[] = _("Ignores stat changes."); -static const u8 sTintedLensDescription[] = _("Ups “not very effective”."); -static const u8 sFilterDescription[] = _("Weakens “supereffective”."); -static const u8 sSlowStartDescription[] = _("Takes a while to get going."); -static const u8 sScrappyDescription[] = _("Hits Ghost-type Pokémon."); -static const u8 sStormDrainDescription[] = _("Draws in Water moves."); -static const u8 sIceBodyDescription[] = _("HP recovery in Hail or Snow."); -#if B_SNOW_WARNING < GEN_9 -static const u8 sSnowWarningDescription[] = _("Summons a Hailstorm."); -#elif B_SNOW_WARNING >= GEN_9 -static const u8 sSnowWarningDescription[] = _("Summons a Snowstorm."); -#endif -static const u8 sHoneyGatherDescription[] = _("May gather Honey."); -static const u8 sFriskDescription[] = _("Checks a foe's item."); -static const u8 sRecklessDescription[] = _("Boosts moves with recoil."); -static const u8 sMultitypeDescription[] = _("Changes type to its Plate."); -static const u8 sFlowerGiftDescription[] = _("Allies power up in sunshine."); -static const u8 sBadDreamsDescription[] = _("Damages sleeping Pokémon."); -static const u8 sPickpocketDescription[] = _("Steals the foe's held item."); -static const u8 sSheerForceDescription[] = _("Trades effects for power."); -static const u8 sContraryDescription[] = _("Inverts stat changes."); -static const u8 sUnnerveDescription[] = _("Foes can't eat Berries."); -static const u8 sDefiantDescription[] = _("Lowered stats up Attack."); -static const u8 sDefeatistDescription[] = _("Gives up at half HP."); -static const u8 sCursedBodyDescription[] = _("Disables moves on contact."); -static const u8 sHealerDescription[] = _("Heals partner Pokémon."); -static const u8 sFriendGuardDescription[] = _("Lowers damage to partner."); -static const u8 sWeakArmorDescription[] = _("Its stats change when hit."); -static const u8 sHeavyMetalDescription[] = _("Doubles weight."); -static const u8 sLightMetalDescription[] = _("Halves weight."); -static const u8 sMultiscaleDescription[] = _("Halves damage at full HP."); -static const u8 sToxicBoostDescription[] = _("Ups Attack if poisoned."); -static const u8 sFlareBoostDescription[] = _("Ups Sp. Atk if burned."); -static const u8 sHarvestDescription[] = _("May recycle a used Berry."); -static const u8 sTelepathyDescription[] = _("Can't be damaged by an ally."); -static const u8 sMoodyDescription[] = _("Stats change gradually."); -static const u8 sOvercoatDescription[] = _("Blocks weather and powder."); -static const u8 sBigPecksDescription[] = _("Prevents Defense loss."); -static const u8 sSandRushDescription[] = _("Ups Speed in a sandstorm."); -static const u8 sWonderSkinDescription[] = _("May avoid status problems."); -static const u8 sAnalyticDescription[] = _("Moving last boosts power."); -static const u8 sIllusionDescription[] = _("Appears as a partner."); -static const u8 sImposterDescription[] = _("Transforms into the foe."); -static const u8 sInfiltratorDescription[] = _("Passes through barriers."); -static const u8 sMummyDescription[] = _("Spreads with contact."); -static const u8 sMoxieDescription[] = _("KOs raise Attack."); -static const u8 sJustifiedDescription[] = _("Dark hits raise Attack."); -static const u8 sRattledDescription[] = _("Raises Speed when scared."); -static const u8 sMagicBounceDescription[] = _("Reflects status moves."); -static const u8 sSapSipperDescription[] = _("Grass increases Attack."); -static const u8 sPranksterDescription[] = _("Status moves go first."); -static const u8 sSandForceDescription[] = _("Powers up in a sandstorm."); -static const u8 sZenModeDescription[] = _("Transforms at half HP."); -static const u8 sVictoryStarDescription[] = _("Raises party accuracy."); -static const u8 sAromaVeilDescription[] = _("Prevents limiting of moves."); -static const u8 sFlowerVeilDescription[] = _("Protects Grass-types."); -static const u8 sCheekPouchDescription[] = _("Eating Berries restores HP."); -static const u8 sProteanDescription[] = _("Changes type to used move."); -static const u8 sFurCoatDescription[] = _("Raises Defense."); -static const u8 sBulletproofDescription[] = _("Avoids some projectiles."); -static const u8 sCompetitiveDescription[] = _("Lowered stats up Sp. Atk."); -static const u8 sStrongJawDescription[] = _("Boosts biting moves."); -static const u8 sRefrigerateDescription[] = _("Normal moves become Ice."); -static const u8 sSweetVeilDescription[] = _("Prevents party from sleep."); -static const u8 sStanceChangeDescription[] = _("Transforms as it battles."); -static const u8 sGaleWingsDescription[] = _("Flying moves go first."); -static const u8 sMegaLauncherDescription[] = _("Boosts pulse moves."); -static const u8 sGrassPeltDescription[] = _("Ups Defense in grass."); -static const u8 sSymbiosisDescription[] = _("Passes its item to an ally."); -static const u8 sToughClawsDescription[] = _("Boosts contact moves."); -static const u8 sPixilateDescription[] = _("Normal moves become Fairy."); -static const u8 sGooeyDescription[] = _("Lowers Speed on contact."); -static const u8 sAerilateDescription[] = _("Normal moves become Flying."); -static const u8 sParentalBondDescription[] = _("Moves hit twice."); -static const u8 sDarkAuraDescription[] = _("Boosts Dark moves."); -static const u8 sFairyAuraDescription[] = _("Boosts Fairy moves."); -static const u8 sAuraBreakDescription[] = _("Reverse aura abilities."); -static const u8 sPrimordialSeaDescription[] = _("Summons heavy rain."); -static const u8 sDesolateLandDescription[] = _("Summons intense sunlight."); -static const u8 sDeltaStreamDescription[] = _("Summons strong winds."); -static const u8 sStaminaDescription[] = _("Boosts Defense when hit."); -static const u8 sWimpOutDescription[] = _("Flees at half HP."); -static const u8 sWaterCompactionDescription[] = _("Water boosts Defense."); -static const u8 sMercilessDescription[] = _("Criticals poisoned foes."); -static const u8 sShieldsDownDescription[] = _("Shell breaks at half HP."); -static const u8 sStakeoutDescription[] = _("Stronger as foes switch in."); -static const u8 sWaterBubbleDescription[] = _("Guards from fire and burns."); -static const u8 sSteelworkerDescription[] = _("Powers up Steel moves."); -static const u8 sBerserkDescription[] = _("Boosts Sp. Atk at low HP."); -static const u8 sSlushRushDescription[] = _("Raises Speed in Hail or Snow."); -static const u8 sLongReachDescription[] = _("Never makes contact."); -static const u8 sLiquidVoiceDescription[] = _("Makes sound moves Water."); -static const u8 sTriageDescription[] = _("Healing moves go first."); -static const u8 sGalvanizeDescription[] = _("Normal moves turn Electric."); -static const u8 sSurgeSurferDescription[] = _("Faster on electricity."); -static const u8 sSchoolingDescription[] = _("Forms a school when strong."); -static const u8 sDisguiseDescription[] = _("Decoy protects it once."); -static const u8 sBattleBondDescription[] = _("Changes form after a KO."); -static const u8 sPowerConstructDescription[] = _("Cells aid it when weakened."); -static const u8 sCorrosionDescription[] = _("Poisons any type."); -static const u8 sComatoseDescription[] = _("Always drowsing."); -static const u8 sQueenlyMajestyDescription[] = _("Protects from priority."); -static const u8 sInnardsOutDescription[] = _("Hurts foe when defeated."); -static const u8 sDancerDescription[] = _("Dances along with others."); -static const u8 sBatteryDescription[] = _("Boosts ally's Sp. Atk."); -static const u8 sFluffyDescription[] = _("Tougher but flammable."); -static const u8 sSoulHeartDescription[] = _("KOs raise Sp. Atk."); -static const u8 sTanglingHairDescription[] = _("Contact lowers Speed."); -static const u8 sReceiverDescription[] = _("Copies ally's ability."); -static const u8 sBeastBoostDescription[] = _("KOs boost best stat."); -static const u8 sRKSSystemDescription[] = _("Memories change its type."); -static const u8 sElectricSurgeDescription[] = _("Field becomes Electric."); -static const u8 sPsychicSurgeDescription[] = _("Field becomes weird."); -static const u8 sMistySurgeDescription[] = _("Field becomes misty."); -static const u8 sGrassySurgeDescription[] = _("Field becomes grassy."); -static const u8 sFullMetalBodyDescription[] = _("Prevents stat reduction."); -static const u8 sNeuroforceDescription[] = _("Ups “supereffective”."); -static const u8 sIntrepidSwordDescription[] = _("Ups Attack on entry."); -static const u8 sDauntlessShieldDescription[] = _("Ups Defense on entry."); -static const u8 sLiberoDescription[] = _("Changes type to move's."); -static const u8 sBallFetchDescription[] = _("Fetches failed Poké Ball."); -static const u8 sCottonDownDescription[] = _("Lower Speed of all when hit."); -static const u8 sPropellerTailDescription[] = _("Ignores foe's redirection."); -static const u8 sMirrorArmorDescription[] = _("Reflect stat decreases."); -static const u8 sGulpMissileDescription[] = _("If hit, spits prey from sea."); -static const u8 sStalwartDescription[] = _("Ignores foe's redirection."); -static const u8 sSteamEngineDescription[] = _("Fire or Water hits up Speed."); -static const u8 sPunkRockDescription[] = _("Ups and resists sound."); -static const u8 sSandSpitDescription[] = _("Creates a sandstorm if hit."); -static const u8 sIceScalesDescription[] = _("Halves special damage."); -static const u8 sRipenDescription[] = _("Doubles effect of Berries."); -static const u8 sIceFaceDescription[] = _("Hail or Snow renew free hit."); -static const u8 sPowerSpotDescription[] = _("Powers up ally moves."); -static const u8 sMimicryDescription[] = _("Changes type on terrain."); -static const u8 sScreenCleanerDescription[] = _("Removes walls of light."); -static const u8 sSteelySpiritDescription[] = _("Boosts ally's Steel moves."); -static const u8 sPerishBodyDescription[] = _("Foe faints in 3 turns if hit."); -static const u8 sWanderingSpiritDescription[] = _("Trade abilities on contact."); -static const u8 sGorillaTacticsDescription[] = _("Ups Attack and locks move."); -static const u8 sNeutralizingGasDescription[] = _("All Abilities are nullified."); -static const u8 sPastelVeilDescription[] = _("Protects team from poison."); -static const u8 sHungerSwitchDescription[] = _("Changes form each turn.");; -static const u8 sQuickDrawDescription[] = _("Moves first occasionally."); -static const u8 sUnseenFistDescription[] = _("Contact evades protection."); -static const u8 sCuriousMedicineDescription[] = _("Remove ally's stat changes."); -static const u8 sTransistorDescription[] = _("Ups Electric-type moves."); -static const u8 sDragonsMawDescription[] = _("Ups Dragon-type moves."); -static const u8 sChillingNeighDescription[] = _("KOs boost Attack stat."); -static const u8 sGrimNeighDescription[] = _("KOs boost Sp. Atk stat."); -static const u8 sAsOneIceRiderDescription[] = _("Unnerve and Chilling Neigh."); -static const u8 sAsOneShadowRiderDescription[] = _("Unnerve and Grim Neigh."); -static const u8 sLingeringAromaDescription[] = _("Spreads with contact."); -static const u8 sSeedSowerDescription[] = _("Affects terrain when hit."); -static const u8 sThermalExchangeDescription[] = _("Fire hits up Attack."); -static const u8 sAngerShellDescription[] = _("Gets angry at half HP."); -static const u8 sPurifyingSaltDescription[] = _("Protected by pure salts."); -static const u8 sWellBakedBodyDescription[] = _("Strengthened by Fire."); -static const u8 sWindRiderDescription[] = _("Ups Attack if hit by wind."); -static const u8 sGuardDogDescription[] = _("Cannot be intimidated."); -static const u8 sRockyPayloadDescription[] = _("Powers up Rock moves."); -static const u8 sWindPowerDescription[] = _("Gets charged by wind."); -static const u8 sZeroToHeroDescription[] = _("Changes form on switch out."); -static const u8 sCommanderDescription[] = _("Commands from Dondozo."); -static const u8 sElectromorphosisDescription[] = _("Gets Charged on contact."); -static const u8 sProtosynthesisDescription[] = _("Sun boosts best stat."); -static const u8 sQuarkDriveDescription[] = _("Elec. field ups best stat."); -static const u8 sGoodAsGoldDescription[] = _("Avoids status problems."); -static const u8 sVesselOfRuinDescription[] = _("Lowers foes' sp. damage."); -static const u8 sSwordOfRuinDescription[] = _("Lowers foes' defense."); -static const u8 sTabletsOfRuinDescription[] = _("Lowers foes' damage."); -static const u8 sBeadsOfRuinDescription[] = _("Lowers foes' sp. defense."); -static const u8 sOrichalcumPulseDescription[] = _("Summons sunlight in battle."); -static const u8 sHadronEngineDescription[] = _("Field becomes Electric."); -static const u8 sOpportunistDescription[] = _("Copies foe's stat change."); -static const u8 sCudChewDescription[] = _("Eats a used berry again."); -static const u8 sSharpnessDescription[] = _("Strengthens slicing moves."); -static const u8 sSupremeOverlordDescription[] = _("Inherits fallen's strength."); -static const u8 sCostarDescription[] = _("Copies ally's stat changes."); -static const u8 sToxicDebrisDescription[] = _("Throws poison spikes if hit."); -static const u8 sArmorTailDescription[] = _("Protects from priority."); -static const u8 sEarthEaterDescription[] = _("Eats ground to heal HP."); -static const u8 sMyceliumMightDescription[] = _("Status moves never fail."); -static const u8 sHospitalityDescription[] = _("Restores ally's HP."); -static const u8 sMindsEyeDescription[] = _("Keen Eye and Scrappy."); -static const u8 sEmbodyAspectTealDescription[] = _("Raises Speed."); -static const u8 sEmbodyAspectHearthflameDescription[] = _("Raises Attack."); -static const u8 sEmbodyAspectWellspringDescription[] = _("Raises Sp. Def."); -static const u8 sEmbodyAspectCornerstoneDescription[] = _("Raises Defense."); -static const u8 sToxicChainDescription[] = _("Moves can poison."); -static const u8 sSupersweetSyrupDescription[] = _("Lowers the foe's Speed."); -static const u8 sTeraShiftDescription[] = _("Terasteralizes upon entry."); -static const u8 sTeraShellDescription[] = _("Resistant to types at full HP."); -static const u8 sTeraformZeroDescription[] = _("Removes weather and terrain."); -static const u8 sPoisonPuppeteerDescription[] = _("Confuses poisoned foes."); - -#if B_EXPANDED_ABILITY_NAMES == TRUE -const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = -{ - [ABILITY_NONE] = _("-------"), - [ABILITY_STENCH] = _("Stench"), - [ABILITY_DRIZZLE] = _("Drizzle"), - [ABILITY_SPEED_BOOST] = _("Speed Boost"), - [ABILITY_BATTLE_ARMOR] = _("Battle Armor"), - [ABILITY_STURDY] = _("Sturdy"), - [ABILITY_DAMP] = _("Damp"), - [ABILITY_LIMBER] = _("Limber"), - [ABILITY_SAND_VEIL] = _("Sand Veil"), - [ABILITY_STATIC] = _("Static"), - [ABILITY_VOLT_ABSORB] = _("Volt Absorb"), - [ABILITY_WATER_ABSORB] = _("Water Absorb"), - [ABILITY_OBLIVIOUS] = _("Oblivious"), - [ABILITY_CLOUD_NINE] = _("Cloud Nine"), - [ABILITY_COMPOUND_EYES] = _("Compound Eyes"), - [ABILITY_INSOMNIA] = _("Insomnia"), - [ABILITY_COLOR_CHANGE] = _("Color Change"), - [ABILITY_IMMUNITY] = _("Immunity"), - [ABILITY_FLASH_FIRE] = _("Flash Fire"), - [ABILITY_SHIELD_DUST] = _("Shield Dust"), - [ABILITY_OWN_TEMPO] = _("Own Tempo"), - [ABILITY_SUCTION_CUPS] = _("Suction Cups"), - [ABILITY_INTIMIDATE] = _("Intimidate"), - [ABILITY_SHADOW_TAG] = _("Shadow Tag"), - [ABILITY_ROUGH_SKIN] = _("Rough Skin"), - [ABILITY_WONDER_GUARD] = _("Wonder Guard"), - [ABILITY_LEVITATE] = _("Levitate"), - [ABILITY_EFFECT_SPORE] = _("Effect Spore"), - [ABILITY_SYNCHRONIZE] = _("Synchronize"), - [ABILITY_CLEAR_BODY] = _("Clear Body"), - [ABILITY_NATURAL_CURE] = _("Natural Cure"), - [ABILITY_LIGHTNING_ROD] = _("Lightning Rod"), - [ABILITY_SERENE_GRACE] = _("Serene Grace"), - [ABILITY_SWIFT_SWIM] = _("Swift Swim"), - [ABILITY_CHLOROPHYLL] = _("Chlorophyll"), - [ABILITY_ILLUMINATE] = _("Illuminate"), - [ABILITY_TRACE] = _("Trace"), - [ABILITY_HUGE_POWER] = _("Huge Power"), - [ABILITY_POISON_POINT] = _("Poison Point"), - [ABILITY_INNER_FOCUS] = _("Inner Focus"), - [ABILITY_MAGMA_ARMOR] = _("Magma Armor"), - [ABILITY_WATER_VEIL] = _("Water Veil"), - [ABILITY_MAGNET_PULL] = _("Magnet Pull"), - [ABILITY_SOUNDPROOF] = _("Soundproof"), - [ABILITY_RAIN_DISH] = _("Rain Dish"), - [ABILITY_SAND_STREAM] = _("Sand Stream"), - [ABILITY_PRESSURE] = _("Pressure"), - [ABILITY_THICK_FAT] = _("Thick Fat"), - [ABILITY_EARLY_BIRD] = _("Early Bird"), - [ABILITY_FLAME_BODY] = _("Flame Body"), - [ABILITY_RUN_AWAY] = _("Run Away"), - [ABILITY_KEEN_EYE] = _("Keen Eye"), - [ABILITY_HYPER_CUTTER] = _("Hyper Cutter"), - [ABILITY_PICKUP] = _("Pickup"), - [ABILITY_TRUANT] = _("Truant"), - [ABILITY_HUSTLE] = _("Hustle"), - [ABILITY_CUTE_CHARM] = _("Cute Charm"), - [ABILITY_PLUS] = _("Plus"), - [ABILITY_MINUS] = _("Minus"), - [ABILITY_FORECAST] = _("Forecast"), - [ABILITY_STICKY_HOLD] = _("Sticky Hold"), - [ABILITY_SHED_SKIN] = _("Shed Skin"), - [ABILITY_GUTS] = _("Guts"), - [ABILITY_MARVEL_SCALE] = _("Marvel Scale"), - [ABILITY_LIQUID_OOZE] = _("Liquid Ooze"), - [ABILITY_OVERGROW] = _("Overgrow"), - [ABILITY_BLAZE] = _("Blaze"), - [ABILITY_TORRENT] = _("Torrent"), - [ABILITY_SWARM] = _("Swarm"), - [ABILITY_ROCK_HEAD] = _("Rock Head"), - [ABILITY_DROUGHT] = _("Drought"), - [ABILITY_ARENA_TRAP] = _("Arena Trap"), - [ABILITY_VITAL_SPIRIT] = _("Vital Spirit"), - [ABILITY_WHITE_SMOKE] = _("White Smoke"), - [ABILITY_PURE_POWER] = _("Pure Power"), - [ABILITY_SHELL_ARMOR] = _("Shell Armor"), - [ABILITY_AIR_LOCK] = _("Air Lock"), - [ABILITY_TANGLED_FEET] = _("Tangled Feet"), - [ABILITY_MOTOR_DRIVE] = _("Motor Drive"), - [ABILITY_RIVALRY] = _("Rivalry"), - [ABILITY_STEADFAST] = _("Steadfast"), - [ABILITY_SNOW_CLOAK] = _("Snow Cloak"), - [ABILITY_GLUTTONY] = _("Gluttony"), - [ABILITY_ANGER_POINT] = _("Anger Point"), - [ABILITY_UNBURDEN] = _("Unburden"), - [ABILITY_HEATPROOF] = _("Heatproof"), - [ABILITY_SIMPLE] = _("Simple"), - [ABILITY_DRY_SKIN] = _("Dry Skin"), - [ABILITY_DOWNLOAD] = _("Download"), - [ABILITY_IRON_FIST] = _("Iron Fist"), - [ABILITY_POISON_HEAL] = _("Poison Heal"), - [ABILITY_ADAPTABILITY] = _("Adaptability"), - [ABILITY_SKILL_LINK] = _("Skill Link"), - [ABILITY_HYDRATION] = _("Hydration"), - [ABILITY_SOLAR_POWER] = _("Solar Power"), - [ABILITY_QUICK_FEET] = _("Quick Feet"), - [ABILITY_NORMALIZE] = _("Normalize"), - [ABILITY_SNIPER] = _("Sniper"), - [ABILITY_MAGIC_GUARD] = _("Magic Guard"), - [ABILITY_NO_GUARD] = _("No Guard"), - [ABILITY_STALL] = _("Stall"), - [ABILITY_TECHNICIAN] = _("Technician"), - [ABILITY_LEAF_GUARD] = _("Leaf Guard"), - [ABILITY_KLUTZ] = _("Klutz"), - [ABILITY_MOLD_BREAKER] = _("Mold Breaker"), - [ABILITY_SUPER_LUCK] = _("Super Luck"), - [ABILITY_AFTERMATH] = _("Aftermath"), - [ABILITY_ANTICIPATION] = _("Anticipation"), - [ABILITY_FOREWARN] = _("Forewarn"), - [ABILITY_UNAWARE] = _("Unaware"), - [ABILITY_TINTED_LENS] = _("Tinted Lens"), - [ABILITY_FILTER] = _("Filter"), - [ABILITY_SLOW_START] = _("Slow Start"), - [ABILITY_SCRAPPY] = _("Scrappy"), - [ABILITY_STORM_DRAIN] = _("Storm Drain"), - [ABILITY_ICE_BODY] = _("Ice Body"), - [ABILITY_SOLID_ROCK] = _("Solid Rock"), - [ABILITY_SNOW_WARNING] = _("Snow Warning"), - [ABILITY_HONEY_GATHER] = _("Honey Gather"), - [ABILITY_FRISK] = _("Frisk"), - [ABILITY_RECKLESS] = _("Reckless"), - [ABILITY_MULTITYPE] = _("Multitype"), - [ABILITY_FLOWER_GIFT] = _("Flower Gift"), - [ABILITY_BAD_DREAMS] = _("Bad Dreams"), - [ABILITY_PICKPOCKET] = _("Pickpocket"), - [ABILITY_SHEER_FORCE] = _("Sheer Force"), - [ABILITY_CONTRARY] = _("Contrary"), - [ABILITY_UNNERVE] = _("Unnerve"), - [ABILITY_DEFIANT] = _("Defiant"), - [ABILITY_DEFEATIST] = _("Defeatist"), - [ABILITY_CURSED_BODY] = _("Cursed Body"), - [ABILITY_HEALER] = _("Healer"), - [ABILITY_FRIEND_GUARD] = _("Friend Guard"), - [ABILITY_WEAK_ARMOR] = _("Weak Armor"), - [ABILITY_HEAVY_METAL] = _("Heavy Metal"), - [ABILITY_LIGHT_METAL] = _("Light Metal"), - [ABILITY_MULTISCALE] = _("Multiscale"), - [ABILITY_TOXIC_BOOST] = _("Toxic Boost"), - [ABILITY_FLARE_BOOST] = _("Flare Boost"), - [ABILITY_HARVEST] = _("Harvest"), - [ABILITY_TELEPATHY] = _("Telepathy"), - [ABILITY_MOODY] = _("Moody"), - [ABILITY_OVERCOAT] = _("Overcoat"), - [ABILITY_POISON_TOUCH] = _("Poison Touch"), - [ABILITY_REGENERATOR] = _("Regenerator"), - [ABILITY_BIG_PECKS] = _("Big Pecks"), - [ABILITY_SAND_RUSH] = _("Sand Rush"), - [ABILITY_WONDER_SKIN] = _("Wonder Skin"), - [ABILITY_ANALYTIC] = _("Analytic"), - [ABILITY_ILLUSION] = _("Illusion"), - [ABILITY_IMPOSTER] = _("Imposter"), - [ABILITY_INFILTRATOR] = _("Infiltrator"), - [ABILITY_MUMMY] = _("Mummy"), - [ABILITY_MOXIE] = _("Moxie"), - [ABILITY_JUSTIFIED] = _("Justified"), - [ABILITY_RATTLED] = _("Rattled"), - [ABILITY_MAGIC_BOUNCE] = _("Magic Bounce"), - [ABILITY_SAP_SIPPER] = _("Sap Sipper"), - [ABILITY_PRANKSTER] = _("Prankster"), - [ABILITY_SAND_FORCE] = _("Sand Force"), - [ABILITY_IRON_BARBS] = _("Iron Barbs"), - [ABILITY_ZEN_MODE] = _("Zen Mode"), - [ABILITY_VICTORY_STAR] = _("Victory Star"), - [ABILITY_TURBOBLAZE] = _("Turboblaze"), - [ABILITY_TERAVOLT] = _("Teravolt"), - [ABILITY_AROMA_VEIL] = _("Aroma Veil"), - [ABILITY_FLOWER_VEIL] = _("Flower Veil"), - [ABILITY_CHEEK_POUCH] = _("Cheek Pouch"), - [ABILITY_PROTEAN] = _("Protean"), - [ABILITY_FUR_COAT] = _("Fur Coat"), - [ABILITY_MAGICIAN] = _("Magician"), - [ABILITY_BULLETPROOF] = _("Bulletproof"), - [ABILITY_COMPETITIVE] = _("Competitive"), - [ABILITY_STRONG_JAW] = _("Strong Jaw"), - [ABILITY_REFRIGERATE] = _("Refrigerate"), - [ABILITY_SWEET_VEIL] = _("Sweet Veil"), - [ABILITY_STANCE_CHANGE] = _("Stance Change"), - [ABILITY_GALE_WINGS] = _("Gale Wings"), - [ABILITY_MEGA_LAUNCHER] = _("Mega Launcher"), - [ABILITY_GRASS_PELT] = _("Grass Pelt"), - [ABILITY_SYMBIOSIS] = _("Symbiosis"), - [ABILITY_TOUGH_CLAWS] = _("Tough Claws"), - [ABILITY_PIXILATE] = _("Pixilate"), - [ABILITY_GOOEY] = _("Gooey"), - [ABILITY_AERILATE] = _("Aerilate"), - [ABILITY_PARENTAL_BOND] = _("Parental Bond"), - [ABILITY_DARK_AURA] = _("Dark Aura"), - [ABILITY_FAIRY_AURA] = _("Fairy Aura"), - [ABILITY_AURA_BREAK] = _("Aura Break"), - [ABILITY_PRIMORDIAL_SEA] = _("Primordial Sea"), - [ABILITY_DESOLATE_LAND] = _("Desolate Land"), - [ABILITY_DELTA_STREAM] = _("Delta Stream"), - [ABILITY_STAMINA] = _("Stamina"), - [ABILITY_WIMP_OUT] = _("Wimp Out"), - [ABILITY_EMERGENCY_EXIT] = _("Emergency Exit"), - [ABILITY_WATER_COMPACTION] = _("Water Compaction"), - [ABILITY_MERCILESS] = _("Merciless"), - [ABILITY_SHIELDS_DOWN] = _("Shields Down"), - [ABILITY_STAKEOUT] = _("Stakeout"), - [ABILITY_WATER_BUBBLE] = _("Water Bubble"), - [ABILITY_STEELWORKER] = _("Steelworker"), - [ABILITY_BERSERK] = _("Berserk"), - [ABILITY_SLUSH_RUSH] = _("Slush Rush"), - [ABILITY_LONG_REACH] = _("Long Reach"), - [ABILITY_LIQUID_VOICE] = _("Liquid Voice"), - [ABILITY_TRIAGE] = _("Triage"), - [ABILITY_GALVANIZE] = _("Galvanize"), - [ABILITY_SURGE_SURFER] = _("Surge Surfer"), - [ABILITY_SCHOOLING] = _("Schooling"), - [ABILITY_DISGUISE] = _("Disguise"), - [ABILITY_BATTLE_BOND] = _("Battle Bond"), - [ABILITY_POWER_CONSTRUCT] = _("Power Construct"), - [ABILITY_CORROSION] = _("Corrosion"), - [ABILITY_COMATOSE] = _("Comatose"), - [ABILITY_QUEENLY_MAJESTY] = _("Queenly Majesty"), - [ABILITY_INNARDS_OUT] = _("Innards Out"), - [ABILITY_DANCER] = _("Dancer"), - [ABILITY_BATTERY] = _("Battery"), - [ABILITY_FLUFFY] = _("Fluffy"), - [ABILITY_DAZZLING] = _("Dazzling"), - [ABILITY_SOUL_HEART] = _("Soul-Heart"), - [ABILITY_TANGLING_HAIR] = _("Tangling Hair"), - [ABILITY_RECEIVER] = _("Receiver"), - [ABILITY_POWER_OF_ALCHEMY] = _("Power Of Alchemy"), - [ABILITY_BEAST_BOOST] = _("Beast Boost"), - [ABILITY_RKS_SYSTEM] = _("RKS System"), - [ABILITY_ELECTRIC_SURGE] = _("Electric Surge"), - [ABILITY_PSYCHIC_SURGE] = _("Psychic Surge"), - [ABILITY_MISTY_SURGE] = _("Misty Surge"), - [ABILITY_GRASSY_SURGE] = _("Grassy Surge"), - [ABILITY_FULL_METAL_BODY] = _("Full Metal Body"), - [ABILITY_SHADOW_SHIELD] = _("Shadow Shield"), - [ABILITY_PRISM_ARMOR] = _("Prism Armor"), - [ABILITY_NEUROFORCE] = _("Neuroforce"), - [ABILITY_INTREPID_SWORD] = _("Intrepid Sword"), - [ABILITY_DAUNTLESS_SHIELD] = _("Dauntless Shield"), - [ABILITY_LIBERO] = _("Libero"), - [ABILITY_BALL_FETCH] = _("Ball Fetch"), - [ABILITY_COTTON_DOWN] = _("Cotton Down"), - [ABILITY_PROPELLER_TAIL] = _("Propeller Tail"), - [ABILITY_MIRROR_ARMOR] = _("Mirror Armor"), - [ABILITY_GULP_MISSILE] = _("Gulp Missile"), - [ABILITY_STALWART] = _("Stalwart"), - [ABILITY_STEAM_ENGINE] = _("Steam Engine"), - [ABILITY_PUNK_ROCK] = _("Punk Rock"), - [ABILITY_SAND_SPIT] = _("Sand Spit"), - [ABILITY_ICE_SCALES] = _("Ice Scales"), - [ABILITY_RIPEN] = _("Ripen"), - [ABILITY_ICE_FACE] = _("Ice Face"), - [ABILITY_POWER_SPOT] = _("Power Spot"), - [ABILITY_MIMICRY] = _("Mimicry"), - [ABILITY_SCREEN_CLEANER] = _("Screen Cleaner"), - [ABILITY_STEELY_SPIRIT] = _("Steely Spirit"), - [ABILITY_PERISH_BODY] = _("Perish Body"), - [ABILITY_WANDERING_SPIRIT] = _("Wandering Spirit"), - [ABILITY_GORILLA_TACTICS] = _("Gorilla Tactics"), - [ABILITY_NEUTRALIZING_GAS] = _("Neutralizing Gas"), - [ABILITY_PASTEL_VEIL] = _("Pastel Veil"), - [ABILITY_HUNGER_SWITCH] = _("Hunger Switch"), - [ABILITY_QUICK_DRAW] = _("Quick Draw"), - [ABILITY_UNSEEN_FIST] = _("Unseen Fist"), - [ABILITY_CURIOUS_MEDICINE] = _("Curious Medicine"), - [ABILITY_TRANSISTOR] = _("Transistor"), - [ABILITY_DRAGONS_MAW] = _("Dragon's Maw"), - [ABILITY_CHILLING_NEIGH] = _("Chilling Neigh"), - [ABILITY_GRIM_NEIGH] = _("Grim Neigh"), - [ABILITY_AS_ONE_ICE_RIDER] = _("As One"), - [ABILITY_AS_ONE_SHADOW_RIDER] = _("As One"), - [ABILITY_LINGERING_AROMA] = _("Lingering Aroma"), - [ABILITY_SEED_SOWER] = _("Seed Sower"), - [ABILITY_THERMAL_EXCHANGE] = _("Thermal Exchange"), - [ABILITY_ANGER_SHELL] = _("Anger Shell"), - [ABILITY_PURIFYING_SALT] = _("Purifying Salt"), - [ABILITY_WELL_BAKED_BODY] = _("Well-Baked Body"), - [ABILITY_WIND_RIDER] = _("Wind Rider"), - [ABILITY_GUARD_DOG] = _("Guard Dog"), - [ABILITY_ROCKY_PAYLOAD] = _("Rocky Payload"), - [ABILITY_WIND_POWER] = _("Wind Power"), - [ABILITY_ZERO_TO_HERO] = _("Zero to Hero"), - [ABILITY_COMMANDER] = _("Commander"), - [ABILITY_ELECTROMORPHOSIS] = _("Electromorphosis"), - [ABILITY_PROTOSYNTHESIS] = _("Protosynthesis"), - [ABILITY_QUARK_DRIVE] = _("Quark Drive"), - [ABILITY_GOOD_AS_GOLD] = _("Good as Gold"), - [ABILITY_VESSEL_OF_RUIN] = _("Vessel of Ruin"), - [ABILITY_SWORD_OF_RUIN] = _("Sword of Ruin"), - [ABILITY_TABLETS_OF_RUIN] = _("Tablets of Ruin"), - [ABILITY_BEADS_OF_RUIN] = _("Beads of Ruin"), - [ABILITY_ORICHALCUM_PULSE] = _("Orichalcum Pulse"), - [ABILITY_HADRON_ENGINE] = _("Hadron Engine"), - [ABILITY_OPPORTUNIST] = _("Opportunist"), - [ABILITY_CUD_CHEW] = _("Cud Chew"), - [ABILITY_SHARPNESS] = _("Sharpness"), - [ABILITY_SUPREME_OVERLORD] = _("Supreme Overlord"), - [ABILITY_COSTAR] = _("Costar"), - [ABILITY_TOXIC_DEBRIS] = _("Toxic Debris"), - [ABILITY_ARMOR_TAIL] = _("Armor Tail"), - [ABILITY_EARTH_EATER] = _("Earth Eater"), - [ABILITY_MYCELIUM_MIGHT] = _("Mycelium Might"), - [ABILITY_HOSPITALITY] = _("Hospitality"), - [ABILITY_MINDS_EYE] = _("Mind's Eye"), - [ABILITY_EMBODY_ASPECT_TEAL] = _("Embody Aspect"), - [ABILITY_EMBODY_ASPECT_HEARTHFLAME] = _("Embody Aspect"), - [ABILITY_EMBODY_ASPECT_WELLSPRING] = _("Embody Aspect"), - [ABILITY_EMBODY_ASPECT_CORNERSTONE] = _("Embody Aspect"), - [ABILITY_TOXIC_CHAIN] = _("Toxic Chain"), - [ABILITY_SUPERSWEET_SYRUP] = _("Supersweet Syrup"), - [ABILITY_TERA_SHIFT] = _("Tera Shift"), - [ABILITY_TERA_SHELL] = _("Tera Shell"), - [ABILITY_TERAFORM_ZERO] = _("Teraform Zero"), - [ABILITY_POISON_PUPPETEER] = _("Poison Puppeteer"), -}; -#else // 12 characters -const u8 gAbilityNames[ABILITIES_COUNT][ABILITY_NAME_LENGTH + 1] = -{ - [ABILITY_NONE] = _("-------"), - [ABILITY_STENCH] = _("Stench"), - [ABILITY_DRIZZLE] = _("Drizzle"), - [ABILITY_SPEED_BOOST] = _("Speed Boost"), - [ABILITY_BATTLE_ARMOR] = _("Battle Armor"), - [ABILITY_STURDY] = _("Sturdy"), - [ABILITY_DAMP] = _("Damp"), - [ABILITY_LIMBER] = _("Limber"), - [ABILITY_SAND_VEIL] = _("Sand Veil"), - [ABILITY_STATIC] = _("Static"), - [ABILITY_VOLT_ABSORB] = _("Volt Absorb"), - [ABILITY_WATER_ABSORB] = _("Water Absorb"), - [ABILITY_OBLIVIOUS] = _("Oblivious"), - [ABILITY_CLOUD_NINE] = _("Cloud Nine"), - [ABILITY_COMPOUND_EYES] = _("CompoundEyes"), - [ABILITY_INSOMNIA] = _("Insomnia"), - [ABILITY_COLOR_CHANGE] = _("Color Change"), - [ABILITY_IMMUNITY] = _("Immunity"), - [ABILITY_FLASH_FIRE] = _("Flash Fire"), - [ABILITY_SHIELD_DUST] = _("Shield Dust"), - [ABILITY_OWN_TEMPO] = _("Own Tempo"), - [ABILITY_SUCTION_CUPS] = _("Suction Cups"), - [ABILITY_INTIMIDATE] = _("Intimidate"), - [ABILITY_SHADOW_TAG] = _("Shadow Tag"), - [ABILITY_ROUGH_SKIN] = _("Rough Skin"), - [ABILITY_WONDER_GUARD] = _("Wonder Guard"), - [ABILITY_LEVITATE] = _("Levitate"), - [ABILITY_EFFECT_SPORE] = _("Effect Spore"), - [ABILITY_SYNCHRONIZE] = _("Synchronize"), - [ABILITY_CLEAR_BODY] = _("Clear Body"), - [ABILITY_NATURAL_CURE] = _("Natural Cure"), - [ABILITY_LIGHTNING_ROD] = _("LightningRod"), - [ABILITY_SERENE_GRACE] = _("Serene Grace"), - [ABILITY_SWIFT_SWIM] = _("Swift Swim"), - [ABILITY_CHLOROPHYLL] = _("Chlorophyll"), - [ABILITY_ILLUMINATE] = _("Illuminate"), - [ABILITY_TRACE] = _("Trace"), - [ABILITY_HUGE_POWER] = _("Huge Power"), - [ABILITY_POISON_POINT] = _("Poison Point"), - [ABILITY_INNER_FOCUS] = _("Inner Focus"), - [ABILITY_MAGMA_ARMOR] = _("Magma Armor"), - [ABILITY_WATER_VEIL] = _("Water Veil"), - [ABILITY_MAGNET_PULL] = _("Magnet Pull"), - [ABILITY_SOUNDPROOF] = _("Soundproof"), - [ABILITY_RAIN_DISH] = _("Rain Dish"), - [ABILITY_SAND_STREAM] = _("Sand Stream"), - [ABILITY_PRESSURE] = _("Pressure"), - [ABILITY_THICK_FAT] = _("Thick Fat"), - [ABILITY_EARLY_BIRD] = _("Early Bird"), - [ABILITY_FLAME_BODY] = _("Flame Body"), - [ABILITY_RUN_AWAY] = _("Run Away"), - [ABILITY_KEEN_EYE] = _("Keen Eye"), - [ABILITY_HYPER_CUTTER] = _("Hyper Cutter"), - [ABILITY_PICKUP] = _("Pickup"), - [ABILITY_TRUANT] = _("Truant"), - [ABILITY_HUSTLE] = _("Hustle"), - [ABILITY_CUTE_CHARM] = _("Cute Charm"), - [ABILITY_PLUS] = _("Plus"), - [ABILITY_MINUS] = _("Minus"), - [ABILITY_FORECAST] = _("Forecast"), - [ABILITY_STICKY_HOLD] = _("Sticky Hold"), - [ABILITY_SHED_SKIN] = _("Shed Skin"), - [ABILITY_GUTS] = _("Guts"), - [ABILITY_MARVEL_SCALE] = _("Marvel Scale"), - [ABILITY_LIQUID_OOZE] = _("Liquid Ooze"), - [ABILITY_OVERGROW] = _("Overgrow"), - [ABILITY_BLAZE] = _("Blaze"), - [ABILITY_TORRENT] = _("Torrent"), - [ABILITY_SWARM] = _("Swarm"), - [ABILITY_ROCK_HEAD] = _("Rock Head"), - [ABILITY_DROUGHT] = _("Drought"), - [ABILITY_ARENA_TRAP] = _("Arena Trap"), - [ABILITY_VITAL_SPIRIT] = _("Vital Spirit"), - [ABILITY_WHITE_SMOKE] = _("White Smoke"), - [ABILITY_PURE_POWER] = _("Pure Power"), - [ABILITY_SHELL_ARMOR] = _("Shell Armor"), - [ABILITY_AIR_LOCK] = _("Air Lock"), - [ABILITY_TANGLED_FEET] = _("Tangled Feet"), - [ABILITY_MOTOR_DRIVE] = _("Motor Drive"), - [ABILITY_RIVALRY] = _("Rivalry"), - [ABILITY_STEADFAST] = _("Steadfast"), - [ABILITY_SNOW_CLOAK] = _("Snow Cloak"), - [ABILITY_GLUTTONY] = _("Gluttony"), - [ABILITY_ANGER_POINT] = _("Anger Point"), - [ABILITY_UNBURDEN] = _("Unburden"), - [ABILITY_HEATPROOF] = _("Heatproof"), - [ABILITY_SIMPLE] = _("Simple"), - [ABILITY_DRY_SKIN] = _("Dry Skin"), - [ABILITY_DOWNLOAD] = _("Download"), - [ABILITY_IRON_FIST] = _("Iron Fist"), - [ABILITY_POISON_HEAL] = _("Poison Heal"), - [ABILITY_ADAPTABILITY] = _("Adaptability"), - [ABILITY_SKILL_LINK] = _("Skill Link"), - [ABILITY_HYDRATION] = _("Hydration"), - [ABILITY_SOLAR_POWER] = _("Solar Power"), - [ABILITY_QUICK_FEET] = _("Quick Feet"), - [ABILITY_NORMALIZE] = _("Normalize"), - [ABILITY_SNIPER] = _("Sniper"), - [ABILITY_MAGIC_GUARD] = _("Magic Guard"), - [ABILITY_NO_GUARD] = _("No Guard"), - [ABILITY_STALL] = _("Stall"), - [ABILITY_TECHNICIAN] = _("Technician"), - [ABILITY_LEAF_GUARD] = _("Leaf Guard"), - [ABILITY_KLUTZ] = _("Klutz"), - [ABILITY_MOLD_BREAKER] = _("Mold Breaker"), - [ABILITY_SUPER_LUCK] = _("Super Luck"), - [ABILITY_AFTERMATH] = _("Aftermath"), - [ABILITY_ANTICIPATION] = _("Anticipation"), - [ABILITY_FOREWARN] = _("Forewarn"), - [ABILITY_UNAWARE] = _("Unaware"), - [ABILITY_TINTED_LENS] = _("Tinted Lens"), - [ABILITY_FILTER] = _("Filter"), - [ABILITY_SLOW_START] = _("Slow Start"), - [ABILITY_SCRAPPY] = _("Scrappy"), - [ABILITY_STORM_DRAIN] = _("Storm Drain"), - [ABILITY_ICE_BODY] = _("Ice Body"), - [ABILITY_SOLID_ROCK] = _("Solid Rock"), - [ABILITY_SNOW_WARNING] = _("Snow Warning"), - [ABILITY_HONEY_GATHER] = _("Honey Gather"), - [ABILITY_FRISK] = _("Frisk"), - [ABILITY_RECKLESS] = _("Reckless"), - [ABILITY_MULTITYPE] = _("Multitype"), - [ABILITY_FLOWER_GIFT] = _("Flower Gift"), - [ABILITY_BAD_DREAMS] = _("Bad Dreams"), - [ABILITY_PICKPOCKET] = _("Pickpocket"), - [ABILITY_SHEER_FORCE] = _("Sheer Force"), - [ABILITY_CONTRARY] = _("Contrary"), - [ABILITY_UNNERVE] = _("Unnerve"), - [ABILITY_DEFIANT] = _("Defiant"), - [ABILITY_DEFEATIST] = _("Defeatist"), - [ABILITY_CURSED_BODY] = _("Cursed Body"), - [ABILITY_HEALER] = _("Healer"), - [ABILITY_FRIEND_GUARD] = _("Friend Guard"), - [ABILITY_WEAK_ARMOR] = _("Weak Armor"), - [ABILITY_HEAVY_METAL] = _("Heavy Metal"), - [ABILITY_LIGHT_METAL] = _("Light Metal"), - [ABILITY_MULTISCALE] = _("Multiscale"), - [ABILITY_TOXIC_BOOST] = _("Toxic Boost"), - [ABILITY_FLARE_BOOST] = _("Flare Boost"), - [ABILITY_HARVEST] = _("Harvest"), - [ABILITY_TELEPATHY] = _("Telepathy"), - [ABILITY_MOODY] = _("Moody"), - [ABILITY_OVERCOAT] = _("Overcoat"), - [ABILITY_POISON_TOUCH] = _("Poison Touch"), - [ABILITY_REGENERATOR] = _("Regenerator"), - [ABILITY_BIG_PECKS] = _("Big Pecks"), - [ABILITY_SAND_RUSH] = _("Sand Rush"), - [ABILITY_WONDER_SKIN] = _("Wonder Skin"), - [ABILITY_ANALYTIC] = _("Analytic"), - [ABILITY_ILLUSION] = _("Illusion"), - [ABILITY_IMPOSTER] = _("Imposter"), - [ABILITY_INFILTRATOR] = _("Infiltrator"), - [ABILITY_MUMMY] = _("Mummy"), - [ABILITY_MOXIE] = _("Moxie"), - [ABILITY_JUSTIFIED] = _("Justified"), - [ABILITY_RATTLED] = _("Rattled"), - [ABILITY_MAGIC_BOUNCE] = _("Magic Bounce"), - [ABILITY_SAP_SIPPER] = _("Sap Sipper"), - [ABILITY_PRANKSTER] = _("Prankster"), - [ABILITY_SAND_FORCE] = _("Sand Force"), - [ABILITY_IRON_BARBS] = _("Iron Barbs"), - [ABILITY_ZEN_MODE] = _("Zen Mode"), - [ABILITY_VICTORY_STAR] = _("Victory Star"), - [ABILITY_TURBOBLAZE] = _("Turboblaze"), - [ABILITY_TERAVOLT] = _("Teravolt"), - [ABILITY_AROMA_VEIL] = _("Aroma Veil"), - [ABILITY_FLOWER_VEIL] = _("Flower Veil"), - [ABILITY_CHEEK_POUCH] = _("Cheek Pouch"), - [ABILITY_PROTEAN] = _("Protean"), - [ABILITY_FUR_COAT] = _("Fur Coat"), - [ABILITY_MAGICIAN] = _("Magician"), - [ABILITY_BULLETPROOF] = _("Bulletproof"), - [ABILITY_COMPETITIVE] = _("Competitive"), - [ABILITY_STRONG_JAW] = _("Strong Jaw"), - [ABILITY_REFRIGERATE] = _("Refrigerate"), - [ABILITY_SWEET_VEIL] = _("Sweet Veil"), - [ABILITY_STANCE_CHANGE] = _("StanceChange"), - [ABILITY_GALE_WINGS] = _("Gale Wings"), - [ABILITY_MEGA_LAUNCHER] = _("MegaLauncher"), - [ABILITY_GRASS_PELT] = _("Grass Pelt"), - [ABILITY_SYMBIOSIS] = _("Symbiosis"), - [ABILITY_TOUGH_CLAWS] = _("Tough Claws"), - [ABILITY_PIXILATE] = _("Pixilate"), - [ABILITY_GOOEY] = _("Gooey"), - [ABILITY_AERILATE] = _("Aerilate"), - [ABILITY_PARENTAL_BOND] = _("ParentalBond"), - [ABILITY_DARK_AURA] = _("Dark Aura"), - [ABILITY_FAIRY_AURA] = _("Fairy Aura"), - [ABILITY_AURA_BREAK] = _("Aura Break"), - [ABILITY_PRIMORDIAL_SEA] = _("PrimrdialSea"), - [ABILITY_DESOLATE_LAND] = _("DesolateLand"), - [ABILITY_DELTA_STREAM] = _("Delta Stream"), - [ABILITY_STAMINA] = _("Stamina"), - [ABILITY_WIMP_OUT] = _("Wimp Out"), - [ABILITY_EMERGENCY_EXIT] = _("EmergncyExit"), - [ABILITY_WATER_COMPACTION] = _("WtrCmpaction"), - [ABILITY_MERCILESS] = _("Merciless"), - [ABILITY_SHIELDS_DOWN] = _("Shields Down"), - [ABILITY_STAKEOUT] = _("Stakeout"), - [ABILITY_WATER_BUBBLE] = _("Water Bubble"), - [ABILITY_STEELWORKER] = _("Steelworker"), - [ABILITY_BERSERK] = _("Berserk"), - [ABILITY_SLUSH_RUSH] = _("Slush Rush"), - [ABILITY_LONG_REACH] = _("Long Reach"), - [ABILITY_LIQUID_VOICE] = _("Liquid Voice"), - [ABILITY_TRIAGE] = _("Triage"), - [ABILITY_GALVANIZE] = _("Galvanize"), - [ABILITY_SURGE_SURFER] = _("Surge Surfer"), - [ABILITY_SCHOOLING] = _("Schooling"), - [ABILITY_DISGUISE] = _("Disguise"), - [ABILITY_BATTLE_BOND] = _("Battle Bond"), - [ABILITY_POWER_CONSTRUCT] = _("PwrConstruct"), - [ABILITY_CORROSION] = _("Corrosion"), - [ABILITY_COMATOSE] = _("Comatose"), - [ABILITY_QUEENLY_MAJESTY] = _("QueenlyMjsty"), - [ABILITY_INNARDS_OUT] = _("Innards Out"), - [ABILITY_DANCER] = _("Dancer"), - [ABILITY_BATTERY] = _("Battery"), - [ABILITY_FLUFFY] = _("Fluffy"), - [ABILITY_DAZZLING] = _("Dazzling"), - [ABILITY_SOUL_HEART] = _("Soul-Heart"), - [ABILITY_TANGLING_HAIR] = _("TanglingHair"), - [ABILITY_RECEIVER] = _("Receiver"), - [ABILITY_POWER_OF_ALCHEMY] = _("PwrOfAlchemy"), - [ABILITY_BEAST_BOOST] = _("Beast Boost"), - [ABILITY_RKS_SYSTEM] = _("RKS System"), - [ABILITY_ELECTRIC_SURGE] = _("ElectrcSurge"), - [ABILITY_PSYCHIC_SURGE] = _("PsychicSurge"), - [ABILITY_MISTY_SURGE] = _("Misty Surge"), - [ABILITY_GRASSY_SURGE] = _("Grassy Surge"), - [ABILITY_FULL_METAL_BODY] = _("FullMetalBdy"), - [ABILITY_SHADOW_SHIELD] = _("ShadowShield"), - [ABILITY_PRISM_ARMOR] = _("Prism Armor"), - [ABILITY_NEUROFORCE] = _("Neuroforce"), - [ABILITY_INTREPID_SWORD] = _("IntrepidSwrd"), - [ABILITY_DAUNTLESS_SHIELD] = _("DauntlssShld"), - [ABILITY_LIBERO] = _("Libero"), - [ABILITY_BALL_FETCH] = _("Ball Fetch"), - [ABILITY_COTTON_DOWN] = _("Cotton Down"), - [ABILITY_PROPELLER_TAIL] = _("PropellrTail"), - [ABILITY_MIRROR_ARMOR] = _("Mirror Armor"), - [ABILITY_GULP_MISSILE] = _("Gulp Missile"), - [ABILITY_STALWART] = _("Stalwart"), - [ABILITY_STEAM_ENGINE] = _("Steam Engine"), - [ABILITY_PUNK_ROCK] = _("Punk Rock"), - [ABILITY_SAND_SPIT] = _("Sand Spit"), - [ABILITY_ICE_SCALES] = _("Ice Scales"), - [ABILITY_RIPEN] = _("Ripen"), - [ABILITY_ICE_FACE] = _("Ice Face"), - [ABILITY_POWER_SPOT] = _("Power Spot"), - [ABILITY_MIMICRY] = _("Mimicry"), - [ABILITY_SCREEN_CLEANER] = _("ScreenCleanr"), - [ABILITY_STEELY_SPIRIT] = _("SteelySpirit"), - [ABILITY_PERISH_BODY] = _("Perish Body"), - [ABILITY_WANDERING_SPIRIT] = _("WandrngSprit"), - [ABILITY_GORILLA_TACTICS] = _("GorillaTacti"), - [ABILITY_NEUTRALIZING_GAS] = _("NeutrlzngGas"), - [ABILITY_PASTEL_VEIL] = _("Pastel Veil"), - [ABILITY_HUNGER_SWITCH] = _("HungerSwitch"), - [ABILITY_QUICK_DRAW] = _("Quick Draw"), - [ABILITY_UNSEEN_FIST] = _("Unseen Fist"), - [ABILITY_CURIOUS_MEDICINE] = _("CuriusMedicn"), - [ABILITY_TRANSISTOR] = _("Transistor"), - [ABILITY_DRAGONS_MAW] = _("Dragon's Maw"), - [ABILITY_CHILLING_NEIGH] = _("ChillngNeigh"), - [ABILITY_GRIM_NEIGH] = _("Grim Neigh"), - [ABILITY_AS_ONE_ICE_RIDER] = _("As One"), - [ABILITY_AS_ONE_SHADOW_RIDER] = _("As One"), - [ABILITY_LINGERING_AROMA] = _("LngerngAroma"), - [ABILITY_SEED_SOWER] = _("Seed Sower"), - [ABILITY_THERMAL_EXCHANGE] = _("ThrmlExchnge"), - [ABILITY_ANGER_SHELL] = _("Anger Shell"), - [ABILITY_PURIFYING_SALT] = _("PurfyingSalt"), - [ABILITY_WELL_BAKED_BODY] = _("WellBakedBdy"), - [ABILITY_WIND_RIDER] = _("Wind Rider"), - [ABILITY_GUARD_DOG] = _("Guard Dog"), - [ABILITY_ROCKY_PAYLOAD] = _("RockyPayload"), - [ABILITY_WIND_POWER] = _("Wind Power"), - [ABILITY_ZERO_TO_HERO] = _("Zero to Hero"), - [ABILITY_COMMANDER] = _("Commander"), - [ABILITY_ELECTROMORPHOSIS] = _("Elecmrphosis"), - [ABILITY_PROTOSYNTHESIS] = _("Protosnthsis"), - [ABILITY_QUARK_DRIVE] = _("Quark Drive"), - [ABILITY_GOOD_AS_GOLD] = _("Good as Gold"), - [ABILITY_VESSEL_OF_RUIN] = _("VesselOfRuin"), - [ABILITY_SWORD_OF_RUIN] = _("SwordOfRuin"), - [ABILITY_TABLETS_OF_RUIN] = _("TabltsOfRuin"), - [ABILITY_BEADS_OF_RUIN] = _("BeadsOfRuin"), - [ABILITY_ORICHALCUM_PULSE] = _("OrchlcumPlse"), - [ABILITY_HADRON_ENGINE] = _("HadronEngine"), - [ABILITY_OPPORTUNIST] = _("Opportunist"), - [ABILITY_CUD_CHEW] = _("Cud Chew"), - [ABILITY_SHARPNESS] = _("Sharpness"), - [ABILITY_SUPREME_OVERLORD] = _("SuprmeOvrlrd"), - [ABILITY_COSTAR] = _("Costar"), - [ABILITY_TOXIC_DEBRIS] = _("Toxic Debris"), - [ABILITY_ARMOR_TAIL] = _("Armor Tail"), - [ABILITY_EARTH_EATER] = _("Earth Eater"), - [ABILITY_MYCELIUM_MIGHT] = _("MceliumMight"), - [ABILITY_HOSPITALITY] = _("Hospitality"), - [ABILITY_MINDS_EYE] = _("Mind's Eye"), - [ABILITY_EMBODY_ASPECT_TEAL] = _("EmbodyAspect"), - [ABILITY_EMBODY_ASPECT_HEARTHFLAME] = _("EmbodyAspect"), - [ABILITY_EMBODY_ASPECT_WELLSPRING] = _("EmbodyAspect"), - [ABILITY_EMBODY_ASPECT_CORNERSTONE] = _("EmbodyAspect"), - [ABILITY_TOXIC_CHAIN] = _("Toxic Chain"), - [ABILITY_SUPERSWEET_SYRUP] = _("SuprswtSyrup"), - [ABILITY_TERA_SHIFT] = _("Tera Shift"), - [ABILITY_TERA_SHELL] = _("Tera Shell"), - [ABILITY_TERAFORM_ZERO] = _("TeraformZero"), - [ABILITY_POISON_PUPPETEER] = _("PoisnPuppter"), -}; -#endif - -const u8 *const gAbilityDescriptionPointers[ABILITIES_COUNT] = -{ - [ABILITY_NONE] = sNoneDescription, - [ABILITY_STENCH] = sStenchDescription, - [ABILITY_DRIZZLE] = sDrizzleDescription, - [ABILITY_SPEED_BOOST] = sSpeedBoostDescription, - [ABILITY_BATTLE_ARMOR] = sBattleArmorDescription, - [ABILITY_STURDY] = sSturdyDescription, - [ABILITY_DAMP] = sDampDescription, - [ABILITY_LIMBER] = sLimberDescription, - [ABILITY_SAND_VEIL] = sSandVeilDescription, - [ABILITY_STATIC] = sStaticDescription, - [ABILITY_VOLT_ABSORB] = sVoltAbsorbDescription, - [ABILITY_WATER_ABSORB] = sWaterAbsorbDescription, - [ABILITY_OBLIVIOUS] = sObliviousDescription, - [ABILITY_CLOUD_NINE] = sCloudNineDescription, - [ABILITY_COMPOUND_EYES] = sCompoundEyesDescription, - [ABILITY_INSOMNIA] = sInsomniaDescription, - [ABILITY_COLOR_CHANGE] = sColorChangeDescription, - [ABILITY_IMMUNITY] = sImmunityDescription, - [ABILITY_FLASH_FIRE] = sFlashFireDescription, - [ABILITY_SHIELD_DUST] = sShieldDustDescription, - [ABILITY_OWN_TEMPO] = sOwnTempoDescription, - [ABILITY_SUCTION_CUPS] = sSuctionCupsDescription, - [ABILITY_INTIMIDATE] = sIntimidateDescription, - [ABILITY_SHADOW_TAG] = sShadowTagDescription, - [ABILITY_ROUGH_SKIN] = sRoughSkinDescription, - [ABILITY_WONDER_GUARD] = sWonderGuardDescription, - [ABILITY_LEVITATE] = sLevitateDescription, - [ABILITY_EFFECT_SPORE] = sEffectSporeDescription, - [ABILITY_SYNCHRONIZE] = sSynchronizeDescription, - [ABILITY_CLEAR_BODY] = sClearBodyDescription, - [ABILITY_NATURAL_CURE] = sNaturalCureDescription, - [ABILITY_LIGHTNING_ROD] = sLightningRodDescription, - [ABILITY_SERENE_GRACE] = sSereneGraceDescription, - [ABILITY_SWIFT_SWIM] = sSwiftSwimDescription, - [ABILITY_CHLOROPHYLL] = sChlorophyllDescription, - [ABILITY_ILLUMINATE] = sIlluminateDescription, - [ABILITY_TRACE] = sTraceDescription, - [ABILITY_HUGE_POWER] = sHugePowerDescription, - [ABILITY_POISON_POINT] = sPoisonPointDescription, - [ABILITY_INNER_FOCUS] = sInnerFocusDescription, - [ABILITY_MAGMA_ARMOR] = sMagmaArmorDescription, - [ABILITY_WATER_VEIL] = sWaterVeilDescription, - [ABILITY_MAGNET_PULL] = sMagnetPullDescription, - [ABILITY_SOUNDPROOF] = sSoundproofDescription, - [ABILITY_RAIN_DISH] = sRainDishDescription, - [ABILITY_SAND_STREAM] = sSandStreamDescription, - [ABILITY_PRESSURE] = sPressureDescription, - [ABILITY_THICK_FAT] = sThickFatDescription, - [ABILITY_EARLY_BIRD] = sEarlyBirdDescription, - [ABILITY_FLAME_BODY] = sFlameBodyDescription, - [ABILITY_RUN_AWAY] = sRunAwayDescription, - [ABILITY_KEEN_EYE] = sKeenEyeDescription, - [ABILITY_HYPER_CUTTER] = sHyperCutterDescription, - [ABILITY_PICKUP] = sPickupDescription, - [ABILITY_TRUANT] = sTruantDescription, - [ABILITY_HUSTLE] = sHustleDescription, - [ABILITY_CUTE_CHARM] = sCuteCharmDescription, - [ABILITY_PLUS] = sPlusDescription, - [ABILITY_MINUS] = sMinusDescription, - [ABILITY_FORECAST] = sForecastDescription, - [ABILITY_STICKY_HOLD] = sStickyHoldDescription, - [ABILITY_SHED_SKIN] = sShedSkinDescription, - [ABILITY_GUTS] = sGutsDescription, - [ABILITY_MARVEL_SCALE] = sMarvelScaleDescription, - [ABILITY_LIQUID_OOZE] = sLiquidOozeDescription, - [ABILITY_OVERGROW] = sOvergrowDescription, - [ABILITY_BLAZE] = sBlazeDescription, - [ABILITY_TORRENT] = sTorrentDescription, - [ABILITY_SWARM] = sSwarmDescription, - [ABILITY_ROCK_HEAD] = sRockHeadDescription, - [ABILITY_DROUGHT] = sDroughtDescription, - [ABILITY_ARENA_TRAP] = sArenaTrapDescription, - [ABILITY_VITAL_SPIRIT] = sVitalSpiritDescription, - [ABILITY_WHITE_SMOKE] = sWhiteSmokeDescription, - [ABILITY_PURE_POWER] = sPurePowerDescription, - [ABILITY_SHELL_ARMOR] = sShellArmorDescription, - [ABILITY_AIR_LOCK] = sAirLockDescription, - [ABILITY_TANGLED_FEET] = sTangledFeetDescription, - [ABILITY_MOTOR_DRIVE] = sMotorDriveDescription, - [ABILITY_RIVALRY] = sRivalryDescription, - [ABILITY_STEADFAST] = sSteadfastDescription, - [ABILITY_SNOW_CLOAK] = sSnowCloakDescription, - [ABILITY_GLUTTONY] = sGluttonyDescription, - [ABILITY_ANGER_POINT] = sAngerPointDescription, - [ABILITY_UNBURDEN] = sUnburdenDescription, - [ABILITY_HEATPROOF] = sHeatproofDescription, - [ABILITY_SIMPLE] = sSimpleDescription, - [ABILITY_DRY_SKIN] = sDrySkinDescription, - [ABILITY_DOWNLOAD] = sDownloadDescription, - [ABILITY_IRON_FIST] = sIronFistDescription, - [ABILITY_POISON_HEAL] = sPoisonHealDescription, - [ABILITY_ADAPTABILITY] = sAdaptabilityDescription, - [ABILITY_SKILL_LINK] = sSkillLinkDescription, - [ABILITY_HYDRATION] = sHydrationDescription, - [ABILITY_SOLAR_POWER] = sSolarPowerDescription, - [ABILITY_QUICK_FEET] = sQuickFeetDescription, - [ABILITY_NORMALIZE] = sNormalizeDescription, - [ABILITY_SNIPER] = sSniperDescription, - [ABILITY_MAGIC_GUARD] = sMagicGuardDescription, - [ABILITY_NO_GUARD] = sNoGuardDescription, - [ABILITY_STALL] = sStallDescription, - [ABILITY_TECHNICIAN] = sTechnicianDescription, - [ABILITY_LEAF_GUARD] = sLeafGuardDescription, - [ABILITY_KLUTZ] = sKlutzDescription, - [ABILITY_MOLD_BREAKER] = sMoldBreakerDescription, - [ABILITY_SUPER_LUCK] = sSuperLuckDescription, - [ABILITY_AFTERMATH] = sAftermathDescription, - [ABILITY_ANTICIPATION] = sAnticipationDescription, - [ABILITY_FOREWARN] = sForewarnDescription, - [ABILITY_UNAWARE] = sUnawareDescription, - [ABILITY_TINTED_LENS] = sTintedLensDescription, - [ABILITY_FILTER] = sFilterDescription, - [ABILITY_SLOW_START] = sSlowStartDescription, - [ABILITY_SCRAPPY] = sScrappyDescription, - [ABILITY_STORM_DRAIN] = sStormDrainDescription, - [ABILITY_ICE_BODY] = sIceBodyDescription, - [ABILITY_SOLID_ROCK] = sFilterDescription, - [ABILITY_SNOW_WARNING] = sSnowWarningDescription, - [ABILITY_HONEY_GATHER] = sHoneyGatherDescription, - [ABILITY_FRISK] = sFriskDescription, - [ABILITY_RECKLESS] = sRecklessDescription, - [ABILITY_MULTITYPE] = sMultitypeDescription, - [ABILITY_FLOWER_GIFT] = sFlowerGiftDescription, - [ABILITY_BAD_DREAMS] = sBadDreamsDescription, - [ABILITY_PICKPOCKET] = sPickpocketDescription, - [ABILITY_SHEER_FORCE] = sSheerForceDescription, - [ABILITY_CONTRARY] = sContraryDescription, - [ABILITY_UNNERVE] = sUnnerveDescription, - [ABILITY_DEFIANT] = sDefiantDescription, - [ABILITY_DEFEATIST] = sDefeatistDescription, - [ABILITY_CURSED_BODY] = sCursedBodyDescription, - [ABILITY_HEALER] = sHealerDescription, - [ABILITY_FRIEND_GUARD] = sFriendGuardDescription, - [ABILITY_WEAK_ARMOR] = sWeakArmorDescription, - [ABILITY_HEAVY_METAL] = sHeavyMetalDescription, - [ABILITY_LIGHT_METAL] = sLightMetalDescription, - [ABILITY_MULTISCALE] = sMultiscaleDescription, - [ABILITY_TOXIC_BOOST] = sToxicBoostDescription, - [ABILITY_FLARE_BOOST] = sFlareBoostDescription, - [ABILITY_HARVEST] = sHarvestDescription, - [ABILITY_TELEPATHY] = sTelepathyDescription, - [ABILITY_MOODY] = sMoodyDescription, - [ABILITY_OVERCOAT] = sOvercoatDescription, - [ABILITY_POISON_TOUCH] = sPoisonPointDescription, - [ABILITY_REGENERATOR] = sNaturalCureDescription, - [ABILITY_BIG_PECKS] = sBigPecksDescription, - [ABILITY_SAND_RUSH] = sSandRushDescription, - [ABILITY_WONDER_SKIN] = sWonderSkinDescription, - [ABILITY_ANALYTIC] = sAnalyticDescription, - [ABILITY_ILLUSION] = sIllusionDescription, - [ABILITY_IMPOSTER] = sImposterDescription, - [ABILITY_INFILTRATOR] = sInfiltratorDescription, - [ABILITY_MUMMY] = sMummyDescription, - [ABILITY_MOXIE] = sMoxieDescription, - [ABILITY_JUSTIFIED] = sJustifiedDescription, - [ABILITY_RATTLED] = sRattledDescription, - [ABILITY_MAGIC_BOUNCE] = sMagicBounceDescription, - [ABILITY_SAP_SIPPER] = sSapSipperDescription, - [ABILITY_PRANKSTER] = sPranksterDescription, - [ABILITY_SAND_FORCE] = sSandForceDescription, - [ABILITY_IRON_BARBS] = sRoughSkinDescription, - [ABILITY_ZEN_MODE] = sZenModeDescription, - [ABILITY_VICTORY_STAR] = sVictoryStarDescription, - [ABILITY_TURBOBLAZE] = sMoldBreakerDescription, - [ABILITY_TERAVOLT] = sMoldBreakerDescription, - [ABILITY_AROMA_VEIL] = sAromaVeilDescription, - [ABILITY_FLOWER_VEIL] = sFlowerVeilDescription, - [ABILITY_CHEEK_POUCH] = sCheekPouchDescription, - [ABILITY_PROTEAN] = sProteanDescription, - [ABILITY_FUR_COAT] = sFurCoatDescription, - [ABILITY_MAGICIAN] = sPickpocketDescription, - [ABILITY_BULLETPROOF] = sBulletproofDescription, - [ABILITY_COMPETITIVE] = sCompetitiveDescription, - [ABILITY_STRONG_JAW] = sStrongJawDescription, - [ABILITY_REFRIGERATE] = sRefrigerateDescription, - [ABILITY_SWEET_VEIL] = sSweetVeilDescription, - [ABILITY_STANCE_CHANGE] = sStanceChangeDescription, - [ABILITY_GALE_WINGS] = sGaleWingsDescription, - [ABILITY_MEGA_LAUNCHER] = sMegaLauncherDescription, - [ABILITY_GRASS_PELT] = sGrassPeltDescription, - [ABILITY_SYMBIOSIS] = sSymbiosisDescription, - [ABILITY_TOUGH_CLAWS] = sToughClawsDescription, - [ABILITY_PIXILATE] = sPixilateDescription, - [ABILITY_GOOEY] = sGooeyDescription, - [ABILITY_AERILATE] = sAerilateDescription, - [ABILITY_PARENTAL_BOND] = sParentalBondDescription, - [ABILITY_DARK_AURA] = sDarkAuraDescription, - [ABILITY_FAIRY_AURA] = sFairyAuraDescription, - [ABILITY_AURA_BREAK] = sAuraBreakDescription, - [ABILITY_PRIMORDIAL_SEA] = sPrimordialSeaDescription, - [ABILITY_DESOLATE_LAND] = sDesolateLandDescription, - [ABILITY_DELTA_STREAM] = sDeltaStreamDescription, - [ABILITY_STAMINA] = sStaminaDescription, - [ABILITY_WIMP_OUT] = sWimpOutDescription, - [ABILITY_EMERGENCY_EXIT] = sWimpOutDescription, - [ABILITY_WATER_COMPACTION] = sWaterCompactionDescription, - [ABILITY_MERCILESS] = sMercilessDescription, - [ABILITY_SHIELDS_DOWN] = sShieldsDownDescription, - [ABILITY_STAKEOUT] = sStakeoutDescription, - [ABILITY_WATER_BUBBLE] = sWaterBubbleDescription, - [ABILITY_STEELWORKER] = sSteelworkerDescription, - [ABILITY_BERSERK] = sBerserkDescription, - [ABILITY_SLUSH_RUSH] = sSlushRushDescription, - [ABILITY_LONG_REACH] = sLongReachDescription, - [ABILITY_LIQUID_VOICE] = sLiquidVoiceDescription, - [ABILITY_TRIAGE] = sTriageDescription, - [ABILITY_GALVANIZE] = sGalvanizeDescription, - [ABILITY_SURGE_SURFER] = sSurgeSurferDescription, - [ABILITY_SCHOOLING] = sSchoolingDescription, - [ABILITY_DISGUISE] = sDisguiseDescription, - [ABILITY_BATTLE_BOND] = sBattleBondDescription, - [ABILITY_POWER_CONSTRUCT] = sPowerConstructDescription, - [ABILITY_CORROSION] = sCorrosionDescription, - [ABILITY_COMATOSE] = sComatoseDescription, - [ABILITY_QUEENLY_MAJESTY] = sQueenlyMajestyDescription, - [ABILITY_INNARDS_OUT] = sInnardsOutDescription, - [ABILITY_DANCER] = sDancerDescription, - [ABILITY_BATTERY] = sBatteryDescription, - [ABILITY_FLUFFY] = sFluffyDescription, - [ABILITY_DAZZLING] = sQueenlyMajestyDescription, - [ABILITY_SOUL_HEART] = sSoulHeartDescription, - [ABILITY_TANGLING_HAIR] = sGooeyDescription, - [ABILITY_RECEIVER] = sReceiverDescription, - [ABILITY_POWER_OF_ALCHEMY] = sReceiverDescription, - [ABILITY_BEAST_BOOST] = sBeastBoostDescription, - [ABILITY_RKS_SYSTEM] = sRKSSystemDescription, - [ABILITY_ELECTRIC_SURGE] = sElectricSurgeDescription, - [ABILITY_PSYCHIC_SURGE] = sPsychicSurgeDescription, - [ABILITY_MISTY_SURGE] = sMistySurgeDescription, - [ABILITY_GRASSY_SURGE] = sGrassySurgeDescription, - [ABILITY_FULL_METAL_BODY] = sFullMetalBodyDescription, - [ABILITY_SHADOW_SHIELD] = sMultiscaleDescription, - [ABILITY_PRISM_ARMOR] = sFilterDescription, - [ABILITY_NEUROFORCE] = sNeuroforceDescription, - [ABILITY_INTREPID_SWORD] = sIntrepidSwordDescription, - [ABILITY_DAUNTLESS_SHIELD] = sDauntlessShieldDescription, - [ABILITY_LIBERO] = sLiberoDescription, - [ABILITY_BALL_FETCH] = sBallFetchDescription, - [ABILITY_COTTON_DOWN] = sCottonDownDescription, - [ABILITY_PROPELLER_TAIL] = sPropellerTailDescription, - [ABILITY_MIRROR_ARMOR] = sMirrorArmorDescription, - [ABILITY_GULP_MISSILE] = sGulpMissileDescription, - [ABILITY_STALWART] = sStalwartDescription, - [ABILITY_STEAM_ENGINE] = sSteamEngineDescription, - [ABILITY_PUNK_ROCK] = sPunkRockDescription, - [ABILITY_SAND_SPIT] = sSandSpitDescription, - [ABILITY_ICE_SCALES] = sIceScalesDescription, - [ABILITY_RIPEN] = sRipenDescription, - [ABILITY_ICE_FACE] = sIceFaceDescription, - [ABILITY_POWER_SPOT] = sPowerSpotDescription, - [ABILITY_MIMICRY] = sMimicryDescription, - [ABILITY_SCREEN_CLEANER] = sScreenCleanerDescription, - [ABILITY_STEELY_SPIRIT] = sSteelySpiritDescription, - [ABILITY_PERISH_BODY] = sPerishBodyDescription, - [ABILITY_WANDERING_SPIRIT] = sWanderingSpiritDescription, - [ABILITY_GORILLA_TACTICS] = sGorillaTacticsDescription, - [ABILITY_NEUTRALIZING_GAS] = sNeutralizingGasDescription, - [ABILITY_PASTEL_VEIL] = sPastelVeilDescription, - [ABILITY_HUNGER_SWITCH] = sHungerSwitchDescription, - [ABILITY_QUICK_DRAW] = sQuickDrawDescription, - [ABILITY_UNSEEN_FIST] = sUnseenFistDescription, - [ABILITY_CURIOUS_MEDICINE] = sCuriousMedicineDescription, - [ABILITY_TRANSISTOR] = sTransistorDescription, - [ABILITY_DRAGONS_MAW] = sDragonsMawDescription, - [ABILITY_CHILLING_NEIGH] = sChillingNeighDescription, - [ABILITY_GRIM_NEIGH] = sGrimNeighDescription, - [ABILITY_AS_ONE_ICE_RIDER] = sAsOneIceRiderDescription, - [ABILITY_AS_ONE_SHADOW_RIDER] = sAsOneShadowRiderDescription, - [ABILITY_LINGERING_AROMA] = sLingeringAromaDescription, - [ABILITY_SEED_SOWER] = sSeedSowerDescription, - [ABILITY_THERMAL_EXCHANGE] = sThermalExchangeDescription, - [ABILITY_ANGER_SHELL] = sAngerShellDescription, - [ABILITY_PURIFYING_SALT] = sPurifyingSaltDescription, - [ABILITY_WELL_BAKED_BODY] = sWellBakedBodyDescription, - [ABILITY_WIND_RIDER] = sWindRiderDescription, - [ABILITY_GUARD_DOG] = sGuardDogDescription, - [ABILITY_ROCKY_PAYLOAD] = sRockyPayloadDescription, - [ABILITY_WIND_POWER] = sWindPowerDescription, - [ABILITY_ZERO_TO_HERO] = sZeroToHeroDescription, - [ABILITY_COMMANDER] = sCommanderDescription, - [ABILITY_ELECTROMORPHOSIS] = sElectromorphosisDescription, - [ABILITY_PROTOSYNTHESIS] = sProtosynthesisDescription, - [ABILITY_QUARK_DRIVE] = sQuarkDriveDescription, - [ABILITY_GOOD_AS_GOLD] = sGoodAsGoldDescription, - [ABILITY_VESSEL_OF_RUIN] = sVesselOfRuinDescription, - [ABILITY_SWORD_OF_RUIN] = sSwordOfRuinDescription, - [ABILITY_TABLETS_OF_RUIN] = sTabletsOfRuinDescription, - [ABILITY_BEADS_OF_RUIN] = sBeadsOfRuinDescription, - [ABILITY_ORICHALCUM_PULSE] = sOrichalcumPulseDescription, - [ABILITY_HADRON_ENGINE] = sHadronEngineDescription, - [ABILITY_OPPORTUNIST] = sOpportunistDescription, - [ABILITY_CUD_CHEW] = sCudChewDescription, - [ABILITY_SHARPNESS] = sSharpnessDescription, - [ABILITY_SUPREME_OVERLORD] = sSupremeOverlordDescription, - [ABILITY_COSTAR] = sCostarDescription, - [ABILITY_TOXIC_DEBRIS] = sToxicDebrisDescription, - [ABILITY_ARMOR_TAIL] = sArmorTailDescription, - [ABILITY_EARTH_EATER] = sEarthEaterDescription, - [ABILITY_MYCELIUM_MIGHT] = sMyceliumMightDescription, - [ABILITY_HOSPITALITY] = sHospitalityDescription, - [ABILITY_MINDS_EYE] = sMindsEyeDescription, - [ABILITY_EMBODY_ASPECT_TEAL] = sEmbodyAspectTealDescription, - [ABILITY_EMBODY_ASPECT_HEARTHFLAME] = sEmbodyAspectHearthflameDescription, - [ABILITY_EMBODY_ASPECT_WELLSPRING] = sEmbodyAspectWellspringDescription, - [ABILITY_EMBODY_ASPECT_CORNERSTONE] = sEmbodyAspectCornerstoneDescription, - [ABILITY_TOXIC_CHAIN] = sToxicChainDescription, - [ABILITY_SUPERSWEET_SYRUP] = sSupersweetSyrupDescription, - [ABILITY_TERA_SHIFT] = sTeraShiftDescription, - [ABILITY_TERA_SHELL] = sTeraShellDescription, - [ABILITY_TERAFORM_ZERO] = sTeraformZeroDescription, - [ABILITY_POISON_PUPPETEER] = sPoisonPuppeteerDescription, -}; diff --git a/src/debug.c b/src/debug.c index e68d65cbd6..35b4a6432f 100644 --- a/src/debug.c +++ b/src/debug.c @@ -3264,7 +3264,7 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); abilityId = GetAbilityBySpecies(sDebugMonData->species, 0); - StringCopy(gStringVar1, gAbilityNames[abilityId]); + StringCopy(gStringVar1, gAbilities[abilityId].name); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility); AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); @@ -3309,7 +3309,7 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); - StringCopy(gStringVar1, gAbilityNames[abilityId]); + StringCopy(gStringVar1, gAbilities[abilityId].name); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility); AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); } diff --git a/src/party_menu.c b/src/party_menu.c index eb276b30c6..e5d59e26a8 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -4691,7 +4691,7 @@ void Task_AbilityCapsule(u8 taskId) } gPartyMenuUseExitCallback = TRUE; GetMonNickname(&gPlayerParty[tMonId], gStringVar1); - StringCopy(gStringVar2, gAbilityNames[GetAbilityBySpecies(tSpecies, tAbilityNum)]); + StringCopy(gStringVar2, gAbilities[GetAbilityBySpecies(tSpecies, tAbilityNum)].name); StringExpandPlaceholders(gStringVar4, askText); PlaySE(SE_SELECT); DisplayPartyMenuMessage(gStringVar4, 1); @@ -4778,7 +4778,7 @@ void Task_AbilityPatch(u8 taskId) } gPartyMenuUseExitCallback = TRUE; GetMonNickname(&gPlayerParty[tMonId], gStringVar1); - StringCopy(gStringVar2, gAbilityNames[GetAbilityBySpecies(tSpecies, tAbilityNum)]); + StringCopy(gStringVar2, gAbilities[GetAbilityBySpecies(tSpecies, tAbilityNum)].name); StringExpandPlaceholders(gStringVar4, askText); PlaySE(SE_SELECT); DisplayPartyMenuMessage(gStringVar4, 1); diff --git a/src/pokedex_plus_hgss.c b/src/pokedex_plus_hgss.c index 95c899edc4..6526af075d 100644 --- a/src/pokedex_plus_hgss.c +++ b/src/pokedex_plus_hgss.c @@ -6043,21 +6043,21 @@ static void PrintStatsScreen_Abilities(u8 taskId) if (gTasks[taskId].data[5] == 0) { ability0 = sPokedexView->sPokemonStats.ability0; - PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilityNames[ability0], abilities_x, abilities_y); - PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilityDescriptionPointers[ability0], abilities_x, abilities_y + 14); + PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilities[ability0].name, abilities_x, abilities_y); + PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilities[ability0].description, abilities_x, abilities_y + 14); ability1 = sPokedexView->sPokemonStats.ability1; if (ability1 != ABILITY_NONE && ability1 != ability0) { - PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilityNames[ability1], abilities_x, abilities_y + 30); - PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilityDescriptionPointers[ability1], abilities_x, abilities_y + 44); + PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilities[ability1].name, abilities_x, abilities_y + 30); + PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilities[ability1].description, abilities_x, abilities_y + 44); } } else //Hidden abilities { abilityHidden = sPokedexView->sPokemonStats.abilityHidden; - PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilityNames[abilityHidden], abilities_x, abilities_y); - PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilityDescriptionPointers[abilityHidden], abilities_x, abilities_y + 14); + PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilities[abilityHidden].name, abilities_x, abilities_y); + PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilities[abilityHidden].description, abilities_x, abilities_y + 14); } } diff --git a/src/pokemon.c b/src/pokemon.c index 89e3f59a45..a2e357f134 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -87,6 +87,7 @@ EWRAM_DATA static struct MonSpritesGfxManager *sMonSpritesGfxManagers[MON_SPR_GF EWRAM_DATA static u8 sTriedEvolving = 0; #include "data/battle_moves.h" +#include "data/abilities.h" // Used in an unreferenced function in RS. // Unreferenced here and in FRLG. diff --git a/src/pokemon_summary_screen.c b/src/pokemon_summary_screen.c index 7ccc605b68..a9a70f1279 100644 --- a/src/pokemon_summary_screen.c +++ b/src/pokemon_summary_screen.c @@ -3193,13 +3193,13 @@ static void PrintMonOTID(void) static void PrintMonAbilityName(void) { u16 ability = GetAbilityBySpecies(sMonSummaryScreen->summary.species, sMonSummaryScreen->summary.abilityNum); - PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilityNames[ability], 0, 1, 0, 1); + PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilities[ability].name, 0, 1, 0, 1); } static void PrintMonAbilityDescription(void) { u16 ability = GetAbilityBySpecies(sMonSummaryScreen->summary.species, sMonSummaryScreen->summary.abilityNum); - PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilityDescriptionPointers[ability], 0, 17, 0, 0); + PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilities[ability].description, 0, 17, 0, 0); } static void BufferMonTrainerMemo(void) diff --git a/src/rom_header_gf.c b/src/rom_header_gf.c index 919c8c5419..022eb95017 100644 --- a/src/rom_header_gf.c +++ b/src/rom_header_gf.c @@ -151,8 +151,8 @@ static const struct GFRomHeader sGFRomHeader = { .externalEventDataOffset = offsetof(struct SaveBlock1, externalEventData), .unk18 = 0x00000000, .speciesInfo = gSpeciesInfo, - .abilityNames = gAbilityNames, - .abilityDescriptions = gAbilityDescriptionPointers, + //.abilityNames = gAbilityNames, //handled in gAbilities + //.abilityDescriptions = gAbilityDescriptionPointers, //handled in gAbilities .items = gItems, .moves = gBattleMoves, .ballGfx = gBallSpriteSheets, diff --git a/src/rom_header_rhh.c b/src/rom_header_rhh.c index f1e16f385e..40c05e4372 100644 --- a/src/rom_header_rhh.c +++ b/src/rom_header_rhh.c @@ -1,4 +1,5 @@ #include "global.h" +#include "constants/abilities.h" #include "constants/expansion.h" #include "constants/moves.h" #include "constants/species.h" @@ -18,6 +19,8 @@ struct RHHRomHeader /*0x09*/ u8 expansionVersionFlags; /*0x0C*/ u32 movesCount; /*0x10*/ u32 numSpecies; + /*0x14*/ u32 abilitiesCount; + /*0x18*/ const struct Ability *abilities; }; static const struct RHHRomHeader sRHHRomHeader = @@ -29,4 +32,6 @@ static const struct RHHRomHeader sRHHRomHeader = .expansionVersionFlags = (EXPANSION_TAGGED_RELEASE << 0), .movesCount = MOVES_COUNT, .numSpecies = NUM_SPECIES, + .abilitiesCount = ABILITIES_COUNT, + .abilities = gAbilities, };