Backwards-compatible BoxPokémon Refactor (#3438)
* 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
This commit is contained in:
parent
a9d6832908
commit
3ad66028e9
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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.
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
};
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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
|
||||
|
||||
48
include/test/overworld_script.h
Normal file
48
include/test/overworld_script.h
Normal file
@ -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
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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,
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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]);
|
||||
|
||||
|
||||
@ -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
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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)
|
||||
{
|
||||
|
||||
@ -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);
|
||||
|
||||
109
src/data/items.h
109
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,
|
||||
},
|
||||
|
||||
|
||||
@ -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();
|
||||
|
||||
24
src/debug.c
24
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++)
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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++;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
162
src/party_menu.c
162
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]
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
523
src/pokemon.c
523
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)
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@ -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;
|
||||
}
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
182
test/pokemon.c
Normal file
182
test/pokemon.c
Normal file
@ -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));
|
||||
}
|
||||
@ -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])
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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",
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user