Merge branch 'upcoming' into berryexpansion

This commit is contained in:
Bassoonian 2023-12-29 14:32:10 +01:00 committed by GitHub
commit 1662dc3478
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
109 changed files with 4723 additions and 2325 deletions

View File

@ -980,7 +980,7 @@
.byte 0xbb
.endm
.macro maxattackhalvehp failInstr:req
.macro halvehp failInstr:req
.byte 0xbc
.4byte \failInstr
.endm

View File

@ -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

View File

@ -860,21 +860,21 @@ gBattleAnims_Moves::
.4byte Move_MATCHA_GOTCHA
.4byte Move_SYRUP_BOMB
.4byte Move_IVY_CUDGEL
.4byte Move_833
.4byte Move_834
.4byte Move_835
.4byte Move_836
.4byte Move_837
.4byte Move_838
.4byte Move_839
.4byte Move_840
.4byte Move_841
.4byte Move_842
.4byte Move_843
.4byte Move_844
.4byte Move_845
.4byte Move_846
.4byte Move_847
.4byte Move_ELECTRO_SHOT
.4byte Move_TERA_STARSTORM
.4byte Move_FICKLE_BEAM
.4byte Move_BURNING_BULWARK
.4byte Move_THUNDERCLAP
.4byte Move_MIGHTY_CLEAVE
.4byte Move_TACHYON_CUTTER
.4byte Move_HARD_PRESS
.4byte Move_DRAGON_CHEER
.4byte Move_ALLURING_VOICE
.4byte Move_TEMPER_FLARE
.4byte Move_SUPERCELL_SLAM
.4byte Move_PSYCHIC_NOISE
.4byte Move_UPPER_HAND
.4byte Move_MALIGNANT_CHAIN
@@@@ Z MOVES
.4byte Move_BREAKNECK_BLITZ
.4byte Move_ALL_OUT_PUMMELING
@ -16977,6 +16977,21 @@ Move_HYDRO_STEAM::
Move_BLOOD_MOON::
Move_MATCHA_GOTCHA::
Move_IVY_CUDGEL::
Move_ELECTRO_SHOT::
Move_TERA_STARSTORM::
Move_FICKLE_BEAM::
Move_BURNING_BULWARK::
Move_THUNDERCLAP::
Move_MIGHTY_CLEAVE::
Move_TACHYON_CUTTER::
Move_HARD_PRESS::
Move_DRAGON_CHEER::
Move_ALLURING_VOICE::
Move_TEMPER_FLARE::
Move_SUPERCELL_SLAM::
Move_PSYCHIC_NOISE::
Move_UPPER_HAND::
Move_MALIGNANT_CHAIN::
end @to do
@@@@@@@@@@@@@@@@@@@@@@@ GEN 1-3 @@@@@@@@@@@@@@@@@@@@@@@

View File

@ -440,6 +440,41 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectBrickBreak @ EFFECT_RAGING_BULL
.4byte BattleScript_EffectHit @ EFFECT_RAGE_FIST
.4byte BattleScript_EffectDoodle @ EFFECT_DOODLE
.4byte BattleScript_EffectFilletAway @ EFFECT_FILLET_AWAY
BattleScript_EffectFilletAway:
attackcanceler
attackstring
ppreduce
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_ATK, MAX_STAT_STAGE, BattleScript_FilletAwayTryAttack
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_FilletAwayTryAttack
jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_SPEED, MAX_STAT_STAGE, BattleScript_ButItFailed
BattleScript_FilletAwayTryAttack::
halvehp BattleScript_ButItFailed
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
attackanimation
waitanimation
setbyte sSTAT_ANIM_PLAYED, FALSE
playstatchangeanimation BS_ATTACKER, BIT_ATK | BIT_SPATK | BIT_SPEED, STAT_CHANGE_BY_TWO
setstatchanger STAT_ATK, 2, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_FilletAwayTrySpAtk
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_FilletAwayTrySpAtk::
setstatchanger STAT_SPATK, 2, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_FilletAwayTrySpeed
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_FilletAwayTrySpeed::
setstatchanger STAT_SPEED, 2, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_FilletAwayEnd
printfromtable gStatUpStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_FilletAwayEnd::
bichalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
goto BattleScript_MoveEnd
BattleScript_EffectDoodle:
attackcanceler
@ -5343,12 +5378,16 @@ BattleScript_EffectBellyDrum::
attackcanceler
attackstring
ppreduce
maxattackhalvehp BattleScript_ButItFailed
jumpifstat BS_ATTACKER, CMP_EQUAL, STAT_ATK, MAX_STAT_STAGE, BattleScript_ButItFailed
halvehp BattleScript_ButItFailed
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE
attackanimation
waitanimation
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
playstatchangeanimation BS_ATTACKER, BIT_ATK, STAT_CHANGE_BY_TWO
setstatchanger STAT_ATK, MAX_STAT_STAGE, FALSE
statbuffchange MOVE_EFFECT_AFFECTS_USER | STAT_CHANGE_ALLOW_PTR, BattleScript_MoveEnd
printstring STRINGID_PKMNCUTHPMAXEDATTACK
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd

View File

@ -64,3 +64,11 @@ EventScript_AccessHallOfFame::
waitstate
goto EventScript_AccessPC
end
EventScript_AccessPokemonBoxLink::
playse SE_PC_LOGIN
msgbox gText_StorageSystemOpened, MSGBOX_DEFAULT
special ShowPokemonStorageSystemPC
waitstate
goto EventScript_TurnOffPC
end

View File

@ -0,0 +1,18 @@
JASC-PAL
0100
15
0 0 0
249 253 255
224 232 243
169 163 177
136 130 156
178 194 220
123 146 180
162 164 202
153 208 247
85 96 152
136 150 213
186 212 247
90 118 181
154 195 255
49 49 49

Binary file not shown.

After

Width:  |  Height:  |  Size: 299 B

View File

@ -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;

View File

@ -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);

View File

@ -84,8 +84,6 @@ extern const struct OamData gOamData_BattleSpriteOpponentSide;
extern const struct OamData gOamData_BattleSpritePlayerSide;
extern const u8 gTypeNames[NUMBER_OF_MON_TYPES][TYPE_NAME_LENGTH + 1];
extern const struct TrainerMoney gTrainerMoneyTable[];
extern const u8 gAbilityNames[][ABILITY_NAME_LENGTH + 1];
extern const u8 *const gAbilityDescriptionPointers[];
extern const u8 gStatusConditionString_PoisonJpn[8];
extern const u8 gStatusConditionString_SleepJpn[8];

View File

@ -113,6 +113,7 @@
#define B_QUICK_GUARD GEN_LATEST // In Gen5 only, Wide Guard has a chance to fail if used consecutively.
#define B_IMPRISON GEN_LATEST // In Gen5+, Imprison doesn't fail if opposing pokemon don't have any moves the user knows.
#define B_ALLY_SWITCH_FAIL_CHANCE GEN_LATEST // In Gen9, using Ally Switch consecutively decreases the chance of success for each consecutive use.
#define B_SKETCH_BANS GEN_LATEST // In Gen9+, Sketch is unable to copy more moves than in previous generations.
// Ability settings
#define B_EXPANDED_ABILITY_NAMES TRUE // If TRUE, ability names are increased from 12 characters to 16 characters.

View File

@ -14,6 +14,8 @@
#define I_USE_EVO_HELD_ITEMS_FROM_BAG FALSE // If TRUE, items such as Razor Claw or Electirizer will be usable from the bag to evolve a Pokémon just like in LA.
#define I_TYPE_BOOST_POWER GEN_LATEST // In Gen4+, all regular type boosting held items had their power increased from 10% to 20%. eg. Charcoal
#define I_SELL_VALUE_FRACTION GEN_LATEST // In Gen9+, items sell for 1/4 of their value instead of 1/2.
#define I_PRICE GEN_LATEST // Some items have varied in value across generations.
#define I_BERRY_PRICE GEN_7 // Since Berries have become unplantable (Gen8+), their price has gone up.
// TM config
#define I_REUSABLE_TMS FALSE // In Gen5-8, TMs are reusable. Setting this to TRUE will make all vanilla TMs reusable, though they can also be cherry-picked by setting their importance to 1.

View File

@ -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.
// Berry settings
// These generational defines only make a distinction for Berries!

View File

@ -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.

View File

@ -332,10 +332,10 @@
#define ABILITY_EMBODY_ASPECT_CORNERSTONE 304
#define ABILITY_TOXIC_CHAIN 305
#define ABILITY_SUPERSWEET_SYRUP 306
#define ABILITY_307 307
#define ABILITY_308 308
#define ABILITY_309 309
#define ABILITY_310 310
#define ABILITY_TERA_SHIFT 307
#define ABILITY_TERA_SHELL 308
#define ABILITY_TERAFORM_ZERO 309
#define ABILITY_POISON_PUPPETEER 310
#define ABILITIES_COUNT_GEN9 311

View File

@ -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)

View File

@ -417,7 +417,8 @@
#define EFFECT_RAGING_BULL 411
#define EFFECT_RAGE_FIST 412
#define EFFECT_DOODLE 413
#define EFFECT_FILLET_AWAY 414
#define NUM_BATTLE_MOVE_EFFECTS 414
#define NUM_BATTLE_MOVE_EFFECTS 415
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H

View File

@ -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

View File

@ -986,8 +986,8 @@
#define ITEM_SWIFT_MOCHI 811
#define ITEM_FRESH_START_MOCHI 812
#define ITEM_GLIMMERING_CHARM 813
#define ITEM_814 814 // TWV0YWwgQWxsb3k=
#define ITEM_815 815 // U3RlbGxhciBUZXJhIFNoYXJk
#define ITEM_METAL_ALLOY 814
#define ITEM_STELLAR_TERA_SHARD 815
#define ITEMS_COUNT 816
#define ITEM_FIELD_ARROW ITEMS_COUNT

View File

@ -886,25 +886,27 @@
#define MOVE_MAGICAL_TORQUE 826
#define MOVE_PSYBLADE 827
#define MOVE_HYDRO_STEAM 828
// The Teal Mask Moves
#define MOVE_BLOOD_MOON 829
#define MOVE_MATCHA_GOTCHA 830
#define MOVE_SYRUP_BOMB 831
#define MOVE_IVY_CUDGEL 832
#define MOVE_833 833
#define MOVE_834 834
#define MOVE_835 835
#define MOVE_836 836
#define MOVE_837 837
#define MOVE_838 838
#define MOVE_839 839
#define MOVE_840 840
#define MOVE_841 841
#define MOVE_842 842
#define MOVE_843 843
#define MOVE_844 844
#define MOVE_845 845
#define MOVE_846 846
#define MOVE_847 847
// The Indigo Disk Moves
#define MOVE_ELECTRO_SHOT 833
#define MOVE_TERA_STARSTORM 834
#define MOVE_FICKLE_BEAM 835
#define MOVE_BURNING_BULWARK 836
#define MOVE_THUNDERCLAP 837
#define MOVE_MIGHTY_CLEAVE 838
#define MOVE_TACHYON_CUTTER 839
#define MOVE_HARD_PRESS 840
#define MOVE_DRAGON_CHEER 841
#define MOVE_ALLURING_VOICE 842
#define MOVE_TEMPER_FLARE 843
#define MOVE_SUPERCELL_SLAM 844
#define MOVE_PSYCHIC_NOISE 845
#define MOVE_UPPER_HAND 846
#define MOVE_MALIGNANT_CHAIN 847
#define MOVES_COUNT_GEN9 848
@ -1014,6 +1016,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

View File

@ -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

View File

@ -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;

View File

@ -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)

View File

@ -515,6 +515,7 @@ extern const u8 MauvilleCity_PokemonCenter_1F_Text_HotSpringsStory[];
extern const u8 LittlerootTown_BrendansHouse_2F_EventScript_PC[];
extern const u8 LittlerootTown_MaysHouse_2F_EventScript_PC[];
extern const u8 EventScript_PC[];
extern const u8 EventScript_AccessPokemonBoxLink[];
extern const u8 EventScript_TestSignpostMsg[];
extern const u8 EventScript_HiddenItemScript[];
extern const u8 EventScript_TV[];

View File

@ -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;
};

View File

@ -785,6 +785,8 @@ extern const u32 gItemIcon_UnremarkableTeacup[];
extern const u32 gItemIconPalette_UnremarkableTeacup[];
extern const u32 gItemIcon_MasterpieceTeacup[];
extern const u32 gItemIconPalette_MasterpieceTeacup[];
extern const u32 gItemIcon_MetalAlloy[];
extern const u32 gItemIconPalette_MetalAlloy[];
// Nectars
extern const u32 gItemIcon_RedNectar[];
extern const u32 gItemIconPalette_RedNectar[];

View File

@ -62,7 +62,7 @@ u16 CountTotalItemQuantityInBag(u16 itemId);
bool8 AddPyramidBagItem(u16 itemId, u16 count);
bool8 RemovePyramidBagItem(u16 itemId, u16 count);
const u8 *ItemId_GetName(u16 itemId);
u16 ItemId_GetPrice(u16 itemId);
u32 ItemId_GetPrice(u16 itemId);
u32 ItemId_GetHoldEffect(u32 itemId);
u32 ItemId_GetHoldEffectParam(u32 itemId);
const u8 *ItemId_GetDescription(u16 itemId);

View File

@ -7,18 +7,21 @@ void ItemUseOutOfBattle_Rod(u8);
void ItemUseOutOfBattle_Itemfinder(u8);
void ItemUseOutOfBattle_PokeblockCase(u8);
void ItemUseOutOfBattle_CoinCase(u8);
void ItemUseOutOfBattle_PokemonBoxLink(u8);
void ItemUseOutOfBattle_PowderJar(u8);
void ItemUseOutOfBattle_SSTicket(u8);
void ItemUseOutOfBattle_WailmerPail(u8);
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);

View File

@ -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);

View File

@ -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);

View File

@ -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,79 +102,108 @@ 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;
/* 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;
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;
// The functionality of this bit changed in FRLG:
// In RS, this bit does nothing, is never set, & is accidentally unset when hatching Eggs.
@ -180,7 +211,7 @@ struct PokemonSubstruct3
// 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;
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
@ -468,10 +504,17 @@ struct BattleMove
u32 encoreBanned:1;
u32 parentalBondBanned:1;
u32 skyBattleBanned:1;
u32 sketchBanned:1;
u16 argument;
};
struct Ability
{
u8 name[ABILITY_NAME_LENGTH + 1];
const u8 *description;
};
#define SPINDA_SPOT_WIDTH 16
#define SPINDA_SPOT_HEIGHT 16
@ -540,6 +583,7 @@ extern const u16 gUnionRoomFacilityClasses[];
extern const struct SpriteTemplate gBattlerSpriteTemplates[];
extern const s8 gNatureStatTable[][5];
extern const u32 sExpCandyExperienceTable[];
extern const struct Ability gAbilities[];
void ZeroBoxMonData(struct BoxPokemon *boxMon);
void ZeroMonData(struct Pokemon *mon);
@ -673,7 +717,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 +729,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 +762,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

View File

@ -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

View 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

View File

@ -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;

View File

@ -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);

View File

@ -207,14 +207,7 @@ static void ShuffleApprenticeSpecies(void)
for (i = 0; i < ARRAY_COUNT(species); i++)
species[i] = i;
// Shuffle the possible species an arbitrary 50 times
for (i = 0; i < 50; i++)
{
u8 temp;
u8 rand1 = Random() % ARRAY_COUNT(species);
u8 rand2 = Random() % ARRAY_COUNT(species);
SWAP(species[rand1], species[rand2], temp);
}
Shuffle(species, APPRENTICE_SPECIES_COUNT, sizeof(species[0]));
for (i = 0; i < MULTI_PARTY_SIZE; i++)
PLAYER_APPRENTICE.speciesIds[i] = ((species[i * 2] & 0xF) << 4) | ((species[i * 2 + 1]) & 0xF);
@ -254,33 +247,19 @@ static void SetRandomQuestionData(void)
u8 questionOrder[APPRENTICE_MAX_QUESTIONS + 1];
u8 partyOrder[MULTI_PARTY_SIZE];
u8 partySlot;
u8 rand;
u8 i, j;
u8 rand1, rand2;
u8 id;
for (i = 0; i < ARRAY_COUNT(partyOrder); i++)
partyOrder[i] = i;
// Shuffle the party an arbitrary 10 times
for (i = 0; i < 10; i++)
{
u8 temp;
rand1 = Random() % ARRAY_COUNT(partyOrder);
rand2 = Random() % ARRAY_COUNT(partyOrder);
SWAP(partyOrder[rand1], partyOrder[rand2], temp);
}
Shuffle(partyOrder, MULTI_PARTY_SIZE, sizeof(partyOrder[0]));
for (i = 0; i < ARRAY_COUNT(questionOrder); i++)
questionOrder[i] = sQuestionPossibilities[i];
// Shuffle the questions an arbitrary 50 times
for (i = 0; i < 50; i++)
{
u8 temp;
rand1 = Random() % ARRAY_COUNT(questionOrder);
rand2 = Random() % ARRAY_COUNT(questionOrder);
SWAP(questionOrder[rand1], questionOrder[rand2], temp);
}
Shuffle(questionOrder, APPRENTICE_MAX_QUESTIONS + 1, sizeof(questionOrder[0]));
gApprenticePartyMovesData = AllocZeroed(sizeof(*gApprenticePartyMovesData));
gApprenticePartyMovesData->moveCounter = 0;
@ -302,16 +281,16 @@ static void SetRandomQuestionData(void)
{
do
{
rand1 = Random() % MAX_MON_MOVES;
rand = Random() % MAX_MON_MOVES;
for (j = 0; j < gApprenticePartyMovesData->moveCounter + 1; j++)
{
if (gApprenticePartyMovesData->moveSlots[id][j] == rand1)
if (gApprenticePartyMovesData->moveSlots[id][j] == rand)
break;
}
} while (j != gApprenticePartyMovesData->moveCounter + 1);
gApprenticePartyMovesData->moveSlots[id][gApprenticePartyMovesData->moveCounter] = rand1;
PLAYER_APPRENTICE.questions[i].moveSlot = rand1;
gApprenticePartyMovesData->moveSlots[id][gApprenticePartyMovesData->moveCounter] = rand;
PLAYER_APPRENTICE.questions[i].moveSlot = rand;
PLAYER_APPRENTICE.questions[i].data = GetRandomAlternateMove(PLAYER_APPRENTICE.questions[i].monId);
}
}

View File

@ -1699,6 +1699,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
ADJUST_SCORE(-6);
break;
case EFFECT_BELLY_DRUM:
case EFFECT_FILLET_AWAY:
if (aiData->abilities[battlerAtk] == ABILITY_CONTRARY)
ADJUST_SCORE(-10);
else if (aiData->hpPercents[battlerAtk] <= 60)
@ -5043,6 +5044,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_FOCUS_PUNCH:
case EFFECT_REVENGE:
case EFFECT_TEETER_DANCE:
case EFFECT_FILLET_AWAY:
if (Random() & 1)
ADJUST_SCORE(2);
break;
@ -5193,6 +5195,7 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_CONVERSION_2:
case EFFECT_SAFEGUARD:
case EFFECT_BELLY_DRUM:
case EFFECT_FILLET_AWAY:
ADJUST_SCORE(-2);
break;
default:
@ -5228,6 +5231,7 @@ static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score)
case EFFECT_HAIL:
case EFFECT_SNOWSCAPE:
case EFFECT_RAIN_DANCE:
case EFFECT_FILLET_AWAY:
ADJUST_SCORE(-2);
break;
default:

View File

@ -361,6 +361,7 @@ static const u16 sEncouragedEncoreEffects[] =
EFFECT_WATER_SPORT,
EFFECT_DRAGON_DANCE,
EFFECT_CAMOUFLAGE,
EFFECT_FILLET_AWAY,
};
// Functions
@ -2126,6 +2127,7 @@ bool32 IsAttackBoostMoveEffect(u32 effect)
case EFFECT_BELLY_DRUM:
case EFFECT_BULK_UP:
case EFFECT_GROWTH:
case EFFECT_FILLET_AWAY:
return TRUE;
default:
return FALSE;

View File

@ -6575,12 +6575,14 @@ static void AnimTask_AllySwitchDataSwap(u8 taskId)
SwapStructData(&gProtectStructs[battlerAtk], &gProtectStructs[battlerPartner], data, sizeof(struct ProtectStruct));
SwapStructData(&gBattleSpritesDataPtr->battlerData[battlerAtk], &gBattleSpritesDataPtr->battlerData[battlerPartner], data, sizeof(struct BattleSpriteInfo));
SWAP(gBattleSpritesDataPtr->battlerData[battlerAtk].invisible, gBattleSpritesDataPtr->battlerData[battlerPartner].invisible, temp);
SWAP(gTransformedPersonalities[battlerAtk], gTransformedPersonalities[battlerPartner], temp);
SWAP(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);
SWAP(gChosenMoveByBattler[battlerAtk], gChosenMoveByBattler[battlerPartner], temp);
SWAP(gLockedMoves[battlerAtk], gLockedMoves[battlerPartner], temp);
SWAP(gBattleStruct->moveTarget[battlerAtk], gBattleStruct->moveTarget[battlerPartner], temp);
SWAP(gMoveSelectionCursor[battlerAtk], gMoveSelectionCursor[battlerPartner], temp);
// Swap turn order, so that all the battlers take action
@ -6688,6 +6690,12 @@ void AnimTask_AllySwitchAttacker(u8 taskId)
PrepareDoubleTeamAnim(taskId, ANIM_ATTACKER, TRUE);
gSprites[gBattlerSpriteIds[gBattlerAttacker]].invisible = TRUE;
gSprites[gBattlerSpriteIds[BATTLE_PARTNER(gBattlerAttacker)]].invisible = TRUE;
// Edge case: Partner's sprite is invisible(i.e. after using Dig).
if (gBattleSpritesDataPtr->battlerData[BATTLE_PARTNER(gBattlerAttacker)].invisible)
{
gBattleSpritesDataPtr->battlerData[BATTLE_PARTNER(gBattlerAttacker)].invisible = FALSE;
gBattleSpritesDataPtr->battlerData[gBattlerAttacker].invisible = TRUE;
}
}
void AnimTask_AllySwitchPartner(u8 taskId)

View File

@ -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);

View File

@ -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,

View File

@ -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)

View File

@ -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)

View File

@ -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);
@ -864,7 +864,7 @@ static void PutAiInfoText(struct BattleDebugMenu *data)
u16 holdEffect = AI_DATA->holdEffects[i];
u16 item = AI_DATA->items[i];
u8 x = (i == B_POSITION_PLAYER_LEFT) ? 83 + (i) * 75 : 83 + (i-1) * 75;
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, gAbilityNames[ability], x, 0, 0, NULL);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, gAbilities[ability].name, x, 0, 0, NULL);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, ItemId_GetName(item), x, 15, 0, NULL);
AddTextPrinterParameterized(data->aiMovesWindowId, FONT_SMALL, GetHoldEffectName(holdEffect), x, 30, 0, NULL);
}
@ -897,7 +897,7 @@ static void PutAiPartyText(struct BattleDebugMenu *data)
AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL_NARROW, text, i * 41, 0, 0, NULL, 0, 0);
}
txtPtr = StringCopyN(text, gAbilityNames[aiMons[i].ability], 7); // The screen is too small to fit the whole string, so we need to drop the last letters.
txtPtr = StringCopyN(text, gAbilities[aiMons[i].ability].name, 7); // The screen is too small to fit the whole string, so we need to drop the last letters.
*txtPtr = EOS;
AddTextPrinterParameterized5(data->aiMovesWindowId, FONT_SMALL_NARROW, text, i * 41, 15, 0, NULL, 0, 0);
@ -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);
@ -1433,7 +1433,7 @@ static void PrintSecondaryEntries(struct BattleDebugMenu *data)
}
break;
case LIST_ITEM_ABILITY:
PadString(gAbilityNames[gBattleMons[data->battlerId].ability], text);
PadString(gAbilities[gBattleMons[data->battlerId].ability].name, text);
printer.currentY = printer.y = sSecondaryListTemplate.upText_Y;
AddTextPrinter(&printer, 0, NULL);
break;

View File

@ -4152,6 +4152,7 @@ static bool32 IsDomeComboMoveEffect(u32 effect)
case EFFECT_CHARGE:
case EFFECT_BULK_UP:
case EFFECT_ATTACK_ACCURACY_UP:
case EFFECT_FILLET_AWAY:
// Others
case EFFECT_FOCUS_ENERGY:
case EFFECT_LOCK_ON:

View File

@ -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);
}

View File

@ -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;

View File

@ -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);

View File

@ -3113,7 +3113,7 @@ static void PrintBattlerOnAbilityPopUp(u8 battlerId, u8 spriteId1, u8 spriteId2)
static void PrintAbilityOnAbilityPopUp(u32 ability, u8 spriteId1, u8 spriteId2)
{
PrintOnAbilityPopUp(gAbilityNames[ability],
PrintOnAbilityPopUp(gAbilities[ability].name,
(void*)(OBJ_VRAM0) + (gSprites[spriteId1].oam.tileNum * 32) + 256,
(void*)(OBJ_VRAM0) + (gSprites[spriteId2].oam.tileNum * 32) + 256,
5, 12,

View File

@ -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;
@ -409,8 +409,6 @@ static const u16 sTrainerBallTable[TRAINER_CLASS_COUNT] =
};
#endif
#include "data/text/abilities.h"
static void (* const sTurnActionsFuncsTable[])(void) =
{
[B_ACTION_USE_MOVE] = HandleAction_UseMove,
@ -2018,6 +2016,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

View File

@ -3407,19 +3407,19 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst)
}
break;
case B_TXT_LAST_ABILITY: // last used ability
toCpy = gAbilityNames[gLastUsedAbility];
toCpy = gAbilities[gLastUsedAbility].name;
break;
case B_TXT_ATK_ABILITY: // attacker ability
toCpy = gAbilityNames[sBattlerAbilities[gBattlerAttacker]];
toCpy = gAbilities[sBattlerAbilities[gBattlerAttacker]].name;
break;
case B_TXT_DEF_ABILITY: // target ability
toCpy = gAbilityNames[sBattlerAbilities[gBattlerTarget]];
toCpy = gAbilities[sBattlerAbilities[gBattlerTarget]].name;
break;
case B_TXT_SCR_ACTIVE_ABILITY: // scripting active ability
toCpy = gAbilityNames[sBattlerAbilities[gBattleScripting.battler]];
toCpy = gAbilities[sBattlerAbilities[gBattleScripting.battler]].name;
break;
case B_TXT_EFF_ABILITY: // effect battler ability
toCpy = gAbilityNames[sBattlerAbilities[gEffectBattler]];
toCpy = gAbilities[sBattlerAbilities[gEffectBattler]].name;
break;
case B_TXT_TRAINER1_CLASS: // trainer class name
toCpy = BattleStringGetOpponentClassByTrainerId(gTrainerBattleOpponent_A);
@ -3781,7 +3781,7 @@ void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst)
srcID += 2;
break;
case B_BUFF_ABILITY: // ability names
StringAppend(dst, gAbilityNames[T1_READ_16(&src[srcID + 1])]);
StringAppend(dst, gAbilities[T1_READ_16(&src[srcID + 1])].name);
srcID += 3;
break;
case B_BUFF_ITEM: // item name

View File

@ -886,14 +886,8 @@ static bool8 TryInflictRandomStatus(void)
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
indices[i] = i;
for (j = 0; j < 10; j++)
{
u8 temp, id;
i = Random() % FRONTIER_PARTY_SIZE;
id = Random() % FRONTIER_PARTY_SIZE;
SWAP(indices[i], indices[id], temp);
}
Shuffle(indices, FRONTIER_PARTY_SIZE, sizeof(indices[0]));
if (gSaveBlock2Ptr->frontier.curChallengeBattleNum <= 4)
count = 1;
@ -1265,7 +1259,7 @@ static void Task_DoStatusInflictionScreenFlash(u8 taskId)
static void TryHealMons(u8 healCount)
{
u8 j, i, k;
u8 j, i;
u8 indices[FRONTIER_PARTY_SIZE];
if (healCount == 0)
@ -1276,15 +1270,7 @@ static void TryHealMons(u8 healCount)
// Only 'healCount' number of pokemon will be healed.
// The order in which they're (attempted to be) healed is random,
// and determined by performing 10 random swaps to this index array.
for (k = 0; k < 10; k++)
{
u8 temp;
i = Random() % FRONTIER_PARTY_SIZE;
j = Random() % FRONTIER_PARTY_SIZE;
SWAP(indices[i], indices[j], temp);
}
Shuffle(indices, FRONTIER_PARTY_SIZE, sizeof(indices[0]));
for (i = 0; i < FRONTIER_PARTY_SIZE; i++)
{

View File

@ -543,7 +543,7 @@ static void Cmd_setsafeguard(void);
static void Cmd_magnitudedamagecalculation(void);
static void Cmd_jumpifnopursuitswitchdmg(void);
static void Cmd_setsunny(void);
static void Cmd_maxattackhalvehp(void);
static void Cmd_halvehp(void);
static void Cmd_copyfoestats(void);
static void Cmd_rapidspinfree(void);
static void Cmd_setdefensecurlbit(void);
@ -802,7 +802,7 @@ void (* const gBattleScriptingCommandsTable[])(void) =
Cmd_magnitudedamagecalculation, //0xB9
Cmd_jumpifnopursuitswitchdmg, //0xBA
Cmd_setsunny, //0xBB
Cmd_maxattackhalvehp, //0xBC
Cmd_halvehp, //0xBC
Cmd_copyfoestats, //0xBD
Cmd_rapidspinfree, //0xBE
Cmd_setdefensecurlbit, //0xBF
@ -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;
@ -12693,10 +12693,8 @@ static void Cmd_copymovepermanently(void)
gChosenMove = MOVE_UNAVAILABLE;
if (!(gBattleMons[gBattlerAttacker].status2 & STATUS2_TRANSFORMED)
&& gLastPrintedMoves[gBattlerTarget] != MOVE_STRUGGLE
&& gLastPrintedMoves[gBattlerTarget] != MOVE_NONE
&& gLastPrintedMoves[gBattlerTarget] != MOVE_UNAVAILABLE
&& gLastPrintedMoves[gBattlerTarget] != MOVE_SKETCH)
&& !gBattleMoves[gLastPrintedMoves[gBattlerTarget]].sketchBanned)
{
s32 i;
@ -13324,8 +13322,8 @@ static void Cmd_setsunny(void)
gBattlescriptCurrInstr = cmd->nextInstr;
}
// Belly Drum
static void Cmd_maxattackhalvehp(void)
// Belly Drum, Fillet Away
static void Cmd_halvehp(void)
{
CMD_ARGS(const u8 *failInstr);
@ -13334,11 +13332,8 @@ static void Cmd_maxattackhalvehp(void)
if (!(GetNonDynamaxMaxHP(gBattlerAttacker) / 2))
halfHp = 1;
// Belly Drum fails if the user's current HP is less than half its maximum, or if the user's Attack is already at +6 (even if the user has Contrary).
if (gBattleMons[gBattlerAttacker].statStages[STAT_ATK] < MAX_STAT_STAGE
&& gBattleMons[gBattlerAttacker].hp > halfHp)
if (gBattleMons[gBattlerAttacker].hp > halfHp)
{
gBattleMons[gBattlerAttacker].statStages[STAT_ATK] = MAX_STAT_STAGE;
gBattleMoveDamage = GetNonDynamaxMaxHP(gBattlerAttacker) / 2;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
@ -15171,10 +15166,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;

View File

@ -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));
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]);

View File

@ -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,7 +10603,7 @@ u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method)
}
break;
case FORM_CHANGE_BATTLE_GIGANTAMAX:
// TODO: check Gigantamax factor
if (GetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR))
targetSpecies = formChanges[i].targetSpecies;
break;
case FORM_CHANGE_BATTLE_WEATHER:

View File

@ -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);

View File

@ -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)
{

View File

@ -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);

2068
src/data/abilities.h Normal file

File diff suppressed because it is too large Load Diff

View File

@ -13,6 +13,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.category = BATTLE_CATEGORY_PHYSICAL,
.metronomeBanned = TRUE,
.mirrorMoveBanned = TRUE,
.sketchBanned = TRUE,
},
[MOVE_POUND] =
@ -2844,6 +2845,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.encoreBanned = TRUE,
.assistBanned = TRUE,
.sketchBanned = TRUE,
},
[MOVE_SKETCH] =
@ -2868,6 +2870,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.encoreBanned = TRUE,
.assistBanned = TRUE,
.sketchBanned = TRUE,
},
[MOVE_TRIPLE_KICK] =
@ -3063,6 +3066,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_SPECIAL,
.windMove = TRUE,
},
[MOVE_COTTON_SPORE] =
@ -5117,7 +5121,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
[MOVE_LUSTER_PURGE] =
{
.effect = EFFECT_SPECIAL_DEFENSE_DOWN_HIT,
.power = 70,
.power = (B_UPDATED_MOVE_DATA >= GEN_9) ? 95 : 70,
.type = TYPE_PSYCHIC,
.accuracy = 100,
.pp = 5,
@ -5131,7 +5135,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
[MOVE_MIST_BALL] =
{
.effect = EFFECT_SPECIAL_ATTACK_DOWN_HIT,
.power = 70,
.power = (B_UPDATED_MOVE_DATA >= GEN_9) ? 95 : 70,
.type = TYPE_PSYCHIC,
.accuracy = 100,
.pp = 5,
@ -7900,6 +7904,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.category = BATTLE_CATEGORY_STATUS,
.zMove = { .effect = Z_EFFECT_RESET_STATS },
.magicCoatAffected = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_SEED_FLARE] =
@ -10463,6 +10468,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.ignoresProtect = TRUE,
.ignoresSubstitute = TRUE,
.metronomeBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_SHORE_UP] =
@ -13220,6 +13226,8 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.ignoresProtect = TRUE,
.mirrorMoveBanned = TRUE,
.metronomeBanned = TRUE,
.healBlockBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_SALT_CURE] =
@ -13285,7 +13293,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
[MOVE_FILLET_AWAY] =
{
.effect = EFFECT_PLACEHOLDER, // EFFECT_FILLET_AWAY
.effect = EFFECT_FILLET_AWAY,
.power = 0,
.type = TYPE_NORMAL,
.accuracy = 0,
@ -13620,7 +13628,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.category = BATTLE_CATEGORY_PHYSICAL,
.makesContact = TRUE,
.slicingMove = TRUE,
.healBlockBanned = B_EXTRAPOLATED_MOVE_FLAGS,
.healBlockBanned = TRUE,
},
[MOVE_DOUBLE_SHOCK] =
@ -13704,6 +13712,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.encoreBanned = TRUE,
.assistBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_WICKED_TORQUE] =
@ -13727,6 +13736,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.encoreBanned = TRUE,
.assistBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_NOXIOUS_TORQUE] =
@ -13750,6 +13760,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.encoreBanned = TRUE,
.assistBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_COMBAT_TORQUE] =
@ -13773,6 +13784,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.encoreBanned = TRUE,
.assistBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_MAGICAL_TORQUE] =
@ -13796,6 +13808,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.instructBanned = TRUE,
.encoreBanned = TRUE,
.assistBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_PSYBLADE] =
@ -13854,7 +13867,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.category = BATTLE_CATEGORY_SPECIAL,
.thawsUser = TRUE,
.metronomeBanned = TRUE,
.healBlockBanned = B_EXTRAPOLATED_MOVE_FLAGS,
.healBlockBanned = TRUE,
},
[MOVE_SYRUP_BOMB] =
@ -13888,6 +13901,226 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_DYNAMAX] =
.metronomeBanned = TRUE,
},
[MOVE_ELECTRO_SHOT] =
{
.effect = EFFECT_PLACEHOLDER, //EFFECT_ELECTRO_SHOT
.power = 130,
.type = TYPE_ELECTRIC,
.accuracy = 100,
.pp = 10,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_SPECIAL,
//.sheerForceBoost = TRUE, (uncomment when effect is implemented, otherwise it breaks the Sheer Force Test)
},
[MOVE_TERA_STARSTORM] =
{
.effect = EFFECT_PLACEHOLDER, //EFFECT_TERA_STARSTORM
.power = 120,
.type = TYPE_NORMAL, // Stellar type if used by Terapagos-Stellar
.accuracy = 100,
.pp = 5,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED, // MOVE_TARGET_BOTH if used by Terapagos-Stellar
.priority = 0,
.category = BATTLE_CATEGORY_SPECIAL,
.assistBanned = TRUE,
.copycatBanned = TRUE,
.mimicBanned = TRUE,
.sketchBanned = (B_SKETCH_BANS >= GEN_9),
},
[MOVE_FICKLE_BEAM] =
{
.effect = EFFECT_PLACEHOLDER, //EFFECT_FICKLE_BEAM
.power = 80,
.type = TYPE_DRAGON,
.accuracy = 100,
.pp = 5,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_SPECIAL,
},
[MOVE_BURNING_BULWARK] =
{
.effect = EFFECT_PROTECT, // NEEDS ACTUAL PROTECT SIDE EFFECT
.power = 0,
.type = TYPE_FIRE,
.accuracy = 0,
.pp = 10,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_USER,
.priority = 4,
.category = BATTLE_CATEGORY_STATUS,
.zMove = { .effect = Z_EFFECT_RESET_STATS },
.protectionMove = TRUE,
.ignoresProtect = TRUE,
.mirrorMoveBanned = TRUE,
.metronomeBanned = TRUE,
.copycatBanned = TRUE,
.assistBanned = TRUE,
},
[MOVE_THUNDERCLAP] =
{
.effect = EFFECT_SUCKER_PUNCH,
.power = 70,
.type = TYPE_ELECTRIC,
.accuracy = 100,
.pp = 5,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 1,
.category = BATTLE_CATEGORY_SPECIAL,
},
[MOVE_MIGHTY_CLEAVE] =
{
.effect = EFFECT_FEINT,
.power = 95,
.type = TYPE_ROCK,
.accuracy = 100,
.pp = 5,
.secondaryEffectChance = 100,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_PHYSICAL,
.makesContact = TRUE,
.slicingMove = TRUE,
},
[MOVE_TACHYON_CUTTER] =
{
.effect = EFFECT_HIT,
.power = 50,
.type = TYPE_STEEL,
.accuracy = 0,
.pp = 10,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_SPECIAL,
.strikeCount = 2,
.slicingMove = TRUE,
},
[MOVE_HARD_PRESS] =
{
.effect = EFFECT_WRING_OUT,
.power = 1,
.type = TYPE_STEEL,
.accuracy = 100,
.pp = 10,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_PHYSICAL,
.makesContact = TRUE,
},
[MOVE_DRAGON_CHEER] =
{
.effect = EFFECT_PLACEHOLDER, //EFFECT_DRAGON_CHEER
.power = 0,
.type = TYPE_DRAGON,
.accuracy = 0,
.pp = 15,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_ALLY,
.priority = 0,
.category = BATTLE_CATEGORY_STATUS,
.ignoresSubstitute = TRUE,
},
[MOVE_ALLURING_VOICE] =
{
.effect = EFFECT_PLACEHOLDER, //EFFECT_ALLURING_VOICE
.power = 80,
.type = TYPE_FAIRY,
.accuracy = 100,
.pp = 10,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_SPECIAL,
.soundMove = TRUE,
.ignoresSubstitute = TRUE,
},
[MOVE_TEMPER_FLARE] =
{
.effect = EFFECT_STOMPING_TANTRUM,
.power = 75,
.type = TYPE_FIRE,
.accuracy = 100,
.pp = 10,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_PHYSICAL,
.makesContact = TRUE,
},
[MOVE_SUPERCELL_SLAM] =
{
.effect = EFFECT_RECOIL_IF_MISS,
.power = 100,
.type = TYPE_ELECTRIC,
.accuracy = 95,
.pp = 15,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_PHYSICAL,
.makesContact = TRUE,
},
[MOVE_PSYCHIC_NOISE] =
{
.effect = EFFECT_PLACEHOLDER, //EFFECT_PSYCHIC_NOISE
.power = 75,
.type = TYPE_PSYCHIC,
.accuracy = 100,
.pp = 10,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_SPECIAL,
.soundMove = TRUE,
.ignoresSubstitute = TRUE,
},
[MOVE_UPPER_HAND] =
{
.effect = EFFECT_PLACEHOLDER, //EFFECT_UPPER_HAND
.power = 65,
.type = TYPE_FIGHTING,
.accuracy = 100,
.pp = 15,
.secondaryEffectChance = 0,
.target = MOVE_TARGET_SELECTED,
.priority = 3,
.category = BATTLE_CATEGORY_PHYSICAL,
.makesContact = TRUE,
},
[MOVE_MALIGNANT_CHAIN] =
{
.effect = EFFECT_POISON_FANG,
.power = 100,
.type = TYPE_POISON,
.accuracy = 100,
.pp = 5,
.secondaryEffectChance = 50,
.target = MOVE_TARGET_SELECTED,
.priority = 0,
.category = BATTLE_CATEGORY_SPECIAL,
},
// Z-Moves
[MOVE_BREAKNECK_BLITZ] =
{

View File

@ -6074,6 +6074,36 @@ const struct ContestMove gContestMoves[MOVES_COUNT] =
[MOVE_SYRUP_BOMB] = {0}, // TODO
[MOVE_IVY_CUDGEL] = {0}, // TODO
[MOVE_ELECTRO_SHOT] = {0}, // TODO
[MOVE_TERA_STARSTORM] = {0}, // TODO
[MOVE_FICKLE_BEAM] = {0}, // TODO
[MOVE_BURNING_BULWARK] = {0}, // TODO
[MOVE_THUNDERCLAP] = {0}, // TODO
[MOVE_MIGHTY_CLEAVE] = {0}, // TODO
[MOVE_TACHYON_CUTTER] = {0}, // TODO
[MOVE_HARD_PRESS] = {0}, // TODO
[MOVE_DRAGON_CHEER] = {0}, // TODO
[MOVE_ALLURING_VOICE] = {0}, // TODO
[MOVE_TEMPER_FLARE] = {0}, // TODO
[MOVE_SUPERCELL_SLAM] = {0}, // TODO
[MOVE_PSYCHIC_NOISE] = {0}, // TODO
[MOVE_UPPER_HAND] = {0}, // TODO
[MOVE_MALIGNANT_CHAIN] = {0}, // TODO
};
const struct ContestEffect gContestEffects[] =

View File

@ -663,6 +663,9 @@ const u32 gItemIconPalette_UnremarkableTeacup[] = INCBIN_U32("graphics/items/ico
const u32 gItemIcon_MasterpieceTeacup[] = INCBIN_U32("graphics/items/icons/masterpiece_teacup.4bpp.lz");
const u32 gItemIconPalette_MasterpieceTeacup[] = INCBIN_U32("graphics/items/icon_palettes/masterpiece_teacup.gbapal.lz");
const u32 gItemIcon_MetalAlloy[] = INCBIN_U32("graphics/items/icons/metal_alloy.4bpp.lz");
const u32 gItemIconPalette_MetalAlloy[] = INCBIN_U32("graphics/items/icon_palettes/metal_alloy.gbapal.lz");
// Nectars
const u32 gItemIcon_RedNectar[] = INCBIN_U32("graphics/items/icons/red_nectar.4bpp.lz");

View File

@ -859,6 +859,8 @@ const u32 *const gItemIconTable[ITEMS_COUNT + 1][2] =
[ITEM_SWIFT_MOCHI] = {gItemIcon_Mochi, gItemIconPalette_SwiftMochi},
[ITEM_FRESH_START_MOCHI] = {gItemIcon_Mochi, gItemIconPalette_FreshStartMochi},
[ITEM_GLIMMERING_CHARM] = {gItemIcon_GlimmeringCharm, gItemIconPalette_GlimmeringCharm},
[ITEM_METAL_ALLOY] = {gItemIcon_MetalAlloy, gItemIconPalette_MetalAlloy},
[ITEM_STELLAR_TERA_SHARD] = {gItemIcon_QuestionMark, gItemIconPalette_QuestionMark}, //{gItemIcon_TeraShard, gItemIconPalette_StellarTeraShard},
// Return to field arrow
[ITEMS_COUNT] = {gItemIcon_ReturnToFieldArrow, gItemIconPalette_ReturnToFieldArrow},
};

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -3284,6 +3284,54 @@ static const u8 sIvyCudgelDescription[] = _(
"Type changes with held mask.\n"
"High critical-hit ratio.");
static const u8 sElectroShotDescription[] = _(
"Absorbs electricity in one turn,\n"
"then attacks next turn.");
static const u8 sTeraStarstormDescription[] = _(
"Damages all opponents if user is\n"
"Stellar form Terapagos.");
static const u8 sFickleBeamDescription[] = _(
"Shoots a beam of light. Sometimes\n"
"twice as strong.");
static const u8 sBurningBulwarkDescription[] = _(
"Evades attack, and burns\n"
"the foe if struck.");
static const u8 sTachyonCutterDescription[] = _(
"Launches particle blades at\n"
"the target. Strikes twice.");
static const u8 sDragonCheerDescription[] = _(
"Increases allies' critical hit\n"
"ration, especially if Dragons.");
static const u8 sAlluringVoiceDescription[] = _(
"Confuses the target if their\n"
"stats were boosted this turn.");
static const u8 sTemperFlareDescription[] = _(
"A desperation attack. Power\n"
"doubles if last move failed.");
static const u8 sSupercellSlamDescription[] = _(
"An electrified slam. If it\n"
"misses, the user is hurt.");
static const u8 sPsychicNoiseDescription[] = _(
"Unpleasant sound waves that\n"
"damage and prevent healing.");
static const u8 sUpperHandDescription[] = _(
"Makes the target flinch if\n"
"readying a priority move.");
static const u8 sMalignantChainDescription[] = _(
"A corrosive chain attack\n"
"that may badly poison.");
const u8 gNotDoneYetDescription[] = _(
"This move can't be used. Its\n"
"effect is in development.");
@ -4127,4 +4175,19 @@ const u8 *const gMoveDescriptionPointers[MOVES_COUNT - 1] =
[MOVE_MATCHA_GOTCHA - 1] = sMatchaGotchaDescription,
[MOVE_SYRUP_BOMB - 1] = sSyrupBombDescription,
[MOVE_IVY_CUDGEL - 1] = sIvyCudgelDescription,
[MOVE_ELECTRO_SHOT - 1] = sElectroShotDescription,
[MOVE_TERA_STARSTORM - 1] = sTeraStarstormDescription,
[MOVE_FICKLE_BEAM - 1] = sFickleBeamDescription,
[MOVE_BURNING_BULWARK - 1] = sBurningBulwarkDescription,
[MOVE_THUNDERCLAP - 1] = sSuckerPunchDescription,
[MOVE_MIGHTY_CLEAVE - 1] = sFeintDescription,
[MOVE_TACHYON_CUTTER - 1] = sTachyonCutterDescription,
[MOVE_HARD_PRESS - 1] = sWringOutDescription,
[MOVE_DRAGON_CHEER - 1] = sDragonCheerDescription,
[MOVE_ALLURING_VOICE - 1] = sAlluringVoiceDescription,
[MOVE_TEMPER_FLARE - 1] = sTemperFlareDescription,
[MOVE_SUPERCELL_SLAM - 1] = sSupercellSlamDescription,
[MOVE_PSYCHIC_NOISE - 1] = sPsychicNoiseDescription,
[MOVE_UPPER_HAND - 1] = sUpperHandDescription,
[MOVE_MALIGNANT_CHAIN - 1] = sMalignantChainDescription,
};

View File

@ -835,6 +835,21 @@ const u8 gMoveNames[MOVES_COUNT_DYNAMAX][MOVE_NAME_LENGTH + 1] =
[MOVE_MATCHA_GOTCHA] = _("Matcha Gotcha"),
[MOVE_SYRUP_BOMB] = _("Syrup Bomb"),
[MOVE_IVY_CUDGEL] = _("Ivy Cudgel"),
[MOVE_ELECTRO_SHOT] = _("Electro Shot"),
[MOVE_TERA_STARSTORM] = _("Tera Starstorm"),
[MOVE_FICKLE_BEAM] = _("Fickle Beam"),
[MOVE_BURNING_BULWARK] = _("Burning Bulwark"),
[MOVE_THUNDERCLAP] = _("Thunderclap"),
[MOVE_MIGHTY_CLEAVE] = _("Mighty Cleave"),
[MOVE_TACHYON_CUTTER] = _("Tachyon Cutter"),
[MOVE_HARD_PRESS] = _("Hard Press"),
[MOVE_DRAGON_CHEER] = _("Dragon Cheer"),
[MOVE_ALLURING_VOICE] = _("Alluring Voice"),
[MOVE_TEMPER_FLARE] = _("Temper Flare"),
[MOVE_SUPERCELL_SLAM] = _("Supercell Slam"),
[MOVE_PSYCHIC_NOISE] = _("Psychic Noise"),
[MOVE_UPPER_HAND] = _("Upper Hand"),
[MOVE_MALIGNANT_CHAIN] = _("Malignant Chain"),
// Max Moves
[MOVE_MAX_GUARD] = _("Max Guard"),
[MOVE_MAX_STRIKE] = _("Max Strike"),
@ -1727,6 +1742,21 @@ const u8 gMoveNames[MOVES_COUNT_DYNAMAX][MOVE_NAME_LENGTH + 1] =
[MOVE_MATCHA_GOTCHA] = _("MatchaGotcha"),
[MOVE_SYRUP_BOMB] = _("Syrup Bomb"),
[MOVE_IVY_CUDGEL] = _("Ivy Cudgel"),
[MOVE_ELECTRO_SHOT] = _("Electro Shot"),
[MOVE_TERA_STARSTORM] = _("TeraStarstrm"),
[MOVE_FICKLE_BEAM] = _("Fickle Beam"),
[MOVE_BURNING_BULWARK] = _("BurnngBulwrk"),
[MOVE_THUNDERCLAP] = _("Thunderclap"),
[MOVE_MIGHTY_CLEAVE] = _("MightyCleave"),
[MOVE_TACHYON_CUTTER] = _("TachyonCuttr"),
[MOVE_HARD_PRESS] = _("Hard Press"),
[MOVE_DRAGON_CHEER] = _("Dragon Cheer"),
[MOVE_ALLURING_VOICE] = _("AllurngVoice"),
[MOVE_TEMPER_FLARE] = _("Temper Flare"),
[MOVE_SUPERCELL_SLAM] = _("SuprcellSlam"),
[MOVE_PSYCHIC_NOISE] = _("PsychicNoise"),
[MOVE_UPPER_HAND] = _("Upper Hand"),
[MOVE_MALIGNANT_CHAIN] = _("MalignntChan"),
// Max Moves
[MOVE_MAX_GUARD] = _("M-Guard"),
[MOVE_MAX_STRIKE] = _("M-Strike"),

View File

@ -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();

View File

@ -3017,7 +3017,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;
@ -3343,7 +3343,7 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId)
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2);
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
abilityId = GetAbilityBySpecies(sDebugMonData->species, 0);
StringCopy(gStringVar1, gAbilityNames[abilityId]);
StringCopy(gStringVar1, gAbilities[abilityId].name);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility);
AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
@ -3388,7 +3388,7 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId)
StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]);
ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2);
StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15);
StringCopy(gStringVar1, gAbilityNames[abilityId]);
StringCopy(gStringVar1, gAbilities[abilityId].name);
StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility);
AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL);
}
@ -3687,7 +3687,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;
@ -3704,26 +3704,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++)

View File

@ -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);

View File

@ -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;

View File

@ -2460,12 +2460,9 @@ void CreateFrontierBrainPokemon(void)
if (!(selectedMonBits & 1))
continue;
do
{
do
{
j = Random32(); //should just be one while loop, but that doesn't match
} while (IsShinyOtIdPersonality(FRONTIER_BRAIN_OTID, j));
} 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++;
}

View File

@ -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;
}

View File

@ -878,7 +878,7 @@ const u8 *ItemId_GetName(u16 itemId)
return gItems[SanitizeItemId(itemId)].name;
}
u16 ItemId_GetPrice(u16 itemId)
u32 ItemId_GetPrice(u16 itemId)
{
return gItems[SanitizeItemId(itemId)].price;
}

View File

@ -58,6 +58,7 @@ static u8 GetDirectionToHiddenItem(s16, s16);
static void PlayerFaceHiddenItem(u8);
static void CheckForHiddenItemsInMapConnection(u8);
static void Task_OpenRegisteredPokeblockCase(u8);
static void Task_AccessPokemonBoxLink(u8);
static void ItemUseOnFieldCB_Bike(u8);
static void ItemUseOnFieldCB_Rod(u8);
static void ItemUseOnFieldCB_Itemfinder(u8);
@ -680,6 +681,18 @@ static void Task_OpenRegisteredPokeblockCase(u8 taskId)
}
}
void ItemUseOutOfBattle_PokemonBoxLink(u8 taskId)
{
sItemUseOnFieldCB = Task_AccessPokemonBoxLink;
SetUpItemUseOnFieldCallback(taskId);
}
static void Task_AccessPokemonBoxLink(u8 taskId)
{
ScriptContext_SetupScript(EventScript_AccessPokemonBoxLink);
DestroyTask(taskId);
}
void ItemUseOutOfBattle_CoinCase(u8 taskId)
{
ConvertIntToDecimalStringN(gStringVar1, GetCoins(), STR_CONV_MODE_LEFT_ALIGN, 4);
@ -797,6 +810,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 +852,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)

View File

@ -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)

View File

@ -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)

View File

@ -320,11 +320,7 @@ static void InitGiddyTaleList(void)
// Shuffle question list
for (i = 0; i < GIDDY_MAX_QUESTIONS; i++)
giddy->questionList[i] = i;
for (i = 0; i < GIDDY_MAX_QUESTIONS; i++)
{
var = Random() % (i + 1);
SWAP(giddy->questionList[i], giddy->questionList[var], temp);
}
Shuffle(giddy->questionList, GIDDY_MAX_QUESTIONS, sizeof(giddy->questionList[0]));
// Count total number of words in above word groups
totalWords = 0;
@ -1265,27 +1261,12 @@ static void StorytellerRecordNewStat(u32 player, u32 stat)
sStorytellerPtr->language[player] = gGameLanguage;
}
static void ScrambleStatList(u8 *arr, s32 count)
{
s32 i;
for (i = 0; i < count; i++)
arr[i] = i;
for (i = 0; i < count; i++)
{
u32 a = Random() % count;
u32 b = Random() % count;
u8 temp;
SWAP(arr[a], arr[b], temp);
}
}
static bool8 StorytellerInitializeRandomStat(void)
{
u8 storyIds[sNumStories];
s32 i, j;
ScrambleStatList(storyIds, sNumStories);
Shuffle(storyIds, sNumStories, sizeof(storyIds[0]));
for (i = 0; i < sNumStories; i++)
{
u8 stat = sStorytellerStories[storyIds[i]].stat;
@ -1427,4 +1408,3 @@ bool8 Script_StorytellerInitializeRandomStat(void)
sStorytellerPtr = &gSaveBlock1Ptr->oldMan.storyteller;
return StorytellerInitializeRandomStat();
}

View File

@ -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);
}
}

View File

@ -598,13 +598,9 @@ static void DoMirageTowerDisintegration(u8 taskId)
sFallingTower[index].disintegrateRand[i] = i;
// Randomize disintegration pattern
for (i = 0; i <= (INNER_BUFFER_LENGTH - 1); i++)
{
u16 rand1, rand2, temp;
rand1 = Random() % INNER_BUFFER_LENGTH;
rand2 = Random() % INNER_BUFFER_LENGTH;
SWAP(sFallingTower[index].disintegrateRand[rand2], sFallingTower[index].disintegrateRand[rand1], temp);
}
Shuffle(sFallingTower[index].disintegrateRand, INNER_BUFFER_LENGTH,
sizeof(sFallingTower[index].disintegrateRand[0]));
if (gTasks[taskId].data[3] <= (OUTER_BUFFER_LENGTH - 1))
gTasks[taskId].data[3]++;
gTasks[taskId].data[1] = 0;
@ -702,13 +698,8 @@ static void Task_FossilFallAndSink(u8 taskId)
break;
case 6:
// Randomize disintegration pattern
for (i = 0; i < FOSSIL_DISINTEGRATE_LENGTH * sizeof(u16); i++)
{
u16 rand1, rand2, temp;
rand1 = Random() % FOSSIL_DISINTEGRATE_LENGTH;
rand2 = Random() % FOSSIL_DISINTEGRATE_LENGTH;
SWAP(sFallingFossil->disintegrateRand[rand2], sFallingFossil->disintegrateRand[rand1], temp);
}
Shuffle(sFallingFossil->disintegrateRand, FOSSIL_DISINTEGRATE_LENGTH,
sizeof(sFallingFossil->disintegrateRand[0]));
gSprites[sFallingFossil->spriteId].callback = SpriteCB_FallingFossil;
break;
case 7:

View File

@ -4691,7 +4691,7 @@ void Task_AbilityCapsule(u8 taskId)
}
gPartyMenuUseExitCallback = TRUE;
GetMonNickname(&gPlayerParty[tMonId], gStringVar1);
StringCopy(gStringVar2, gAbilityNames[GetAbilityBySpecies(tSpecies, tAbilityNum)]);
StringCopy(gStringVar2, gAbilities[GetAbilityBySpecies(tSpecies, tAbilityNum)].name);
StringExpandPlaceholders(gStringVar4, askText);
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gStringVar4, 1);
@ -4778,7 +4778,7 @@ void Task_AbilityPatch(u8 taskId)
}
gPartyMenuUseExitCallback = TRUE;
GetMonNickname(&gPlayerParty[tMonId], gStringVar1);
StringCopy(gStringVar2, gAbilityNames[GetAbilityBySpecies(tSpecies, tAbilityNum)]);
StringCopy(gStringVar2, gAbilities[GetAbilityBySpecies(tSpecies, tAbilityNum)].name);
StringExpandPlaceholders(gStringVar4, askText);
PlaySE(SE_SELECT);
DisplayPartyMenuMessage(gStringVar4, 1);
@ -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]

View File

@ -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;

View File

@ -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)

View File

@ -4738,7 +4738,7 @@ static u32 GetPokedexMonPersonality(u16 species)
static u16 CreateMonSpriteFromNationalDexNumberHGSS(u16 nationalNum, s16 x, s16 y, u16 paletteSlot)
{
nationalNum = NationalPokedexNumToSpeciesHGSS(nationalNum);
return CreateMonPicSprite(nationalNum, SHINY_ODDS, GetPokedexMonPersonality(nationalNum), TRUE, x, y, paletteSlot, TAG_NONE);
return CreateMonPicSprite(nationalNum, FALSE, GetPokedexMonPersonality(nationalNum), TRUE, x, y, paletteSlot, TAG_NONE);
}
static u16 GetPokemonScaleFromNationalDexNumber(u16 nationalNum)
@ -6043,21 +6043,21 @@ static void PrintStatsScreen_Abilities(u8 taskId)
if (gTasks[taskId].data[5] == 0)
{
ability0 = sPokedexView->sPokemonStats.ability0;
PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilityNames[ability0], abilities_x, abilities_y);
PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilityDescriptionPointers[ability0], abilities_x, abilities_y + 14);
PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilities[ability0].name, abilities_x, abilities_y);
PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilities[ability0].description, abilities_x, abilities_y + 14);
ability1 = sPokedexView->sPokemonStats.ability1;
if (ability1 != ABILITY_NONE && ability1 != ability0)
{
PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilityNames[ability1], abilities_x, abilities_y + 30);
PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilityDescriptionPointers[ability1], abilities_x, abilities_y + 44);
PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilities[ability1].name, abilities_x, abilities_y + 30);
PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilities[ability1].description, abilities_x, abilities_y + 44);
}
}
else //Hidden abilities
{
abilityHidden = sPokedexView->sPokemonStats.abilityHidden;
PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilityNames[abilityHidden], abilities_x, abilities_y);
PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilityDescriptionPointers[abilityHidden], abilities_x, abilities_y + 14);
PrintStatsScreenTextSmallWhite(WIN_STATS_ABILITIES, gAbilities[abilityHidden].name, abilities_x, abilities_y);
PrintStatsScreenTextSmall(WIN_STATS_ABILITIES, gAbilities[abilityHidden].description, abilities_x, abilities_y + 14);
}
}

View File

@ -87,6 +87,7 @@ EWRAM_DATA static struct MonSpritesGfxManager *sMonSpritesGfxManagers[MON_SPR_GF
EWRAM_DATA static u8 sTriedEvolving = 0;
#include "data/battle_moves.h"
#include "data/abilities.h"
// Used in an unreferenced function in RS.
// Unreferenced here and in FRLG.
@ -673,6 +674,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 +791,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 +803,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);
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 +818,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 +839,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 +850,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 +1429,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 +1439,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 +1513,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 +2095,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 +2181,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 +2333,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 +2358,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 +2413,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 +2461,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 +2504,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 +2544,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 +2623,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 +2656,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 +2818,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 +2832,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 +2874,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 +2915,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 +3995,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 +4019,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 +4092,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 +4279,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 +4300,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 +4390,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 +5323,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 +5531,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 +6314,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 +6337,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)

View File

@ -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;

View File

@ -6414,16 +6414,14 @@ 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);

View File

@ -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++;
@ -3188,13 +3193,13 @@ static void PrintMonOTID(void)
static void PrintMonAbilityName(void)
{
u16 ability = GetAbilityBySpecies(sMonSummaryScreen->summary.species, sMonSummaryScreen->summary.abilityNum);
PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilityNames[ability], 0, 1, 0, 1);
PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilities[ability].name, 0, 1, 0, 1);
}
static void PrintMonAbilityDescription(void)
{
u16 ability = GetAbilityBySpecies(sMonSummaryScreen->summary.species, sMonSummaryScreen->summary.abilityNum);
PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilityDescriptionPointers[ability], 0, 17, 0, 0);
PrintTextOnWindow(AddWindowFromTemplateList(sPageInfoTemplate, PSS_DATA_WINDOW_INFO_ABILITY), gAbilities[ability].description, 0, 17, 0, 0);
}
static void BufferMonTrainerMemo(void)
@ -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;

View File

@ -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)

View File

@ -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;
}

View File

@ -151,8 +151,8 @@ static const struct GFRomHeader sGFRomHeader = {
.externalEventDataOffset = offsetof(struct SaveBlock1, externalEventData),
.unk18 = 0x00000000,
.speciesInfo = gSpeciesInfo,
.abilityNames = gAbilityNames,
.abilityDescriptions = gAbilityDescriptionPointers,
//.abilityNames = gAbilityNames, //handled in gAbilities
//.abilityDescriptions = gAbilityDescriptionPointers, //handled in gAbilities
.items = gItems,
.moves = gBattleMoves,
.ballGfx = gBallSpriteSheets,

View File

@ -1,5 +1,8 @@
#include "global.h"
#include "constants/abilities.h"
#include "constants/expansion.h"
#include "constants/moves.h"
#include "constants/species.h"
// Similar to the GF ROM header, this struct allows external programs to
// detect details about Expansion.
@ -14,6 +17,10 @@ struct RHHRomHeader
/*0x07*/ u8 expansionVersionMinor;
/*0x08*/ u8 expansionVersionPatch;
/*0x09*/ u8 expansionVersionFlags;
/*0x0C*/ u32 movesCount;
/*0x10*/ u32 numSpecies;
/*0x14*/ u32 abilitiesCount;
/*0x18*/ const struct Ability *abilities;
};
static const struct RHHRomHeader sRHHRomHeader =
@ -23,4 +30,8 @@ static const struct RHHRomHeader sRHHRomHeader =
.expansionVersionMinor = EXPANSION_VERSION_MINOR,
.expansionVersionPatch = EXPANSION_VERSION_PATCH,
.expansionVersionFlags = (EXPANSION_TAGGED_RELEASE << 0),
.movesCount = MOVES_COUNT,
.numSpecies = NUM_SPECIES,
.abilitiesCount = ABILITIES_COUNT,
.abilities = gAbilities,
};

View File

@ -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];
// restore HP.
u32 i;
for (i = 0; i < gPlayerPartyCount; i++)
{
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++)
{
arg[0] = CalculatePPWithBonus(GetMonData(&gPlayerParty[i], MON_DATA_MOVE1 + j), ppBonuses, j);
SetMonData(&gPlayerParty[i], MON_DATA_PP1 + j, arg);
HealPokemon(&gPlayerParty[i]);
if (OW_PC_HEAL >= GEN_8)
HealPlayerBoxes();
}
// 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);
static void HealPlayerBoxes(void)
{
int boxId, boxPosition;
struct BoxPokemon *boxMon;
for (boxId = 0; boxId < TOTAL_BOXES_COUNT; boxId++)
{
for (boxPosition = 0; boxPosition < IN_BOX_COUNT; boxPosition++)
{
boxMon = &gPokemonStoragePtr->boxes[boxId][boxPosition];
if (GetBoxMonData(boxMon, MON_DATA_SANITY_HAS_SPECIES))
HealBoxPokemon(boxMon);
}
}
}
@ -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;
}
}

View File

@ -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;
}

View File

@ -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)

View File

@ -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)

View File

@ -1956,7 +1956,6 @@ void AlertTVThatPlayerPlayedRoulette(u16 nCoinsSpent)
static void SecretBaseVisit_CalculateDecorationData(TVShow *show)
{
u8 i, j;
u16 k;
u8 n;
u8 decoration;
@ -2002,12 +2001,7 @@ static void SecretBaseVisit_CalculateDecorationData(TVShow *show)
break;
default:
// More than 1 decoration, randomize the full list
for (k = 0; k < n * n; k++)
{
decoration = Random() % n;
j = Random() % n;
SWAP(sTV_DecorationsBuffer[decoration], sTV_DecorationsBuffer[j], i);
}
Shuffle(sTV_DecorationsBuffer, n, sizeof(sTV_DecorationsBuffer[0]));
// Pick the first decorations in the randomized list to talk about on the show
for (i = 0; i < show->secretBaseVisit.numDecorations; i++)

View File

@ -385,7 +385,6 @@ static u16 GetCurrentMapWildMonHeaderId(void)
u8 PickWildMonNature(void)
{
u8 i;
u8 j;
struct Pokeblock *safariPokeblock;
u8 natures[NUM_NATURES];
@ -396,17 +395,7 @@ u8 PickWildMonNature(void)
{
for (i = 0; i < NUM_NATURES; i++)
natures[i] = i;
for (i = 0; i < NUM_NATURES - 1; i++)
{
for (j = i + 1; j < NUM_NATURES; j++)
{
if (Random() & 1)
{
u8 temp;
SWAP(natures[i], natures[j], temp);
}
}
}
Shuffle(natures, NUM_NATURES, sizeof(natures[0]));
for (i = 0; i < NUM_NATURES; i++)
{
if (PokeblockGetGain(natures[i], safariPokeblock) > 0)

View File

@ -187,3 +187,37 @@ SINGLE_BATTLE_TEST("Contrary raises a stat after using a move which would normal
EXPECT_MUL_EQ(results[1].damage, Q_4_12(2.125), results[0].damage);
}
}
SINGLE_BATTLE_TEST("Contrary lowers a stat after using a move which would normally raise it: Belly Drum", s16 damageBefore, s16 damageAfter)
{
u32 ability;
PARAMETRIZE { ability = ABILITY_CONTRARY; }
PARAMETRIZE { ability = ABILITY_TANGLED_FEET; }
GIVEN {
ASSUME(gBattleMoves[MOVE_BELLY_DRUM].effect == EFFECT_BELLY_DRUM);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_SPINDA) { Ability(ability); }
} WHEN {
TURN { MOVE(opponent, MOVE_TACKLE); }
TURN { MOVE(opponent, MOVE_BELLY_DRUM); }
TURN { MOVE(opponent, MOVE_TACKLE); }
} SCENE {
MESSAGE("Foe Spinda used Tackle!");
HP_BAR(player, captureDamage: &results[i].damageBefore);
if (ability == ABILITY_CONTRARY) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda cut its own HP and maximized ATTACK!"); //Message stays the same
}
else {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
MESSAGE("Foe Spinda cut its own HP and maximized ATTACK!");
}
HP_BAR(player, captureDamage: &results[i].damageAfter);
}
FINALLY {
EXPECT_MUL_EQ(results[0].damageBefore, UQ_4_12(0.25), results[0].damageAfter);
EXPECT_MUL_EQ(results[1].damageBefore, UQ_4_12(4.0), results[1].damageAfter);
}
}

View File

@ -177,15 +177,15 @@ AI_SINGLE_BATTLE_TEST("AI chooses moves with secondary effect that have a 100% c
AI_LOG;
ASSUME(gBattleMoves[MOVE_SHADOW_BALL].effect == EFFECT_SPECIAL_DEFENSE_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_SHADOW_BALL].secondaryEffectChance == 20);
ASSUME(gBattleMoves[MOVE_LUSTER_PURGE].effect == EFFECT_SPECIAL_DEFENSE_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_LUSTER_PURGE].secondaryEffectChance == 50);
ASSUME(gBattleMoves[MOVE_OCTAZOOKA].effect == EFFECT_ACCURACY_DOWN_HIT);
ASSUME(gBattleMoves[MOVE_OCTAZOOKA].secondaryEffectChance == 50);
AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT);
PLAYER(SPECIES_REGICE);
OPPONENT(SPECIES_REGIROCK) { Ability(ability); Moves(MOVE_SHADOW_BALL, MOVE_LUSTER_PURGE); }
OPPONENT(SPECIES_REGIROCK) { Ability(ability); Moves(MOVE_SHADOW_BALL, MOVE_OCTAZOOKA); }
} WHEN {
if (ability == ABILITY_NONE)
TURN { EXPECT_MOVE(opponent, MOVE_SHADOW_BALL); }
else
TURN { EXPECT_MOVES(opponent, MOVE_LUSTER_PURGE); }
TURN { EXPECT_MOVES(opponent, MOVE_OCTAZOOKA); }
}
}

Some files were not shown because too many files have changed in this diff Show More