diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 49e0109451..43b9417860 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -986,7 +986,7 @@ @ Gives the player a Pokémon of the specified species and level, and allows to customize extra parameters. @ VAR_RESULT will be set to MON_GIVEN_TO_PARTY, MON_GIVEN_TO_PC, or MON_CANT_GIVE depending on the outcome. - .macro givemon species:req, level:req, item, ball, nature, abilityNum, gender, hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv, hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv, move1, move2, move3, move4, isShiny, gmaxFactor, teraType, dmaxLevel + .macro givemon species:req, level:req, item, ball, nature, abilityNum, gender, hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv, hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv, move1, move2, move3, move4, shinyMode, gmaxFactor, teraType, dmaxLevel callnative ScrCmd_createmon, requests_effects=1 .byte 0 .byte PARTY_SIZE @ assign to first empty slot @@ -1014,7 +1014,7 @@ .ifnb \move2; .set givemon_flags, givemon_flags | (1 << 18); .endif .ifnb \move3; .set givemon_flags, givemon_flags | (1 << 19); .endif .ifnb \move4; .set givemon_flags, givemon_flags | (1 << 20); .endif - .ifnb \isShiny; .set givemon_flags, givemon_flags | (1 << 21); .endif + .ifnb \shinyMode; .set givemon_flags, givemon_flags | (1 << 21); .endif .ifnb \gmaxFactor; .set givemon_flags, givemon_flags | (1 << 22); .endif .ifnb \teraType; .set givemon_flags, givemon_flags | (1 << 23); .endif .ifnb \dmaxLevel; .set givemon_flags, givemon_flags | (1 << 24); .endif @@ -1040,7 +1040,7 @@ .ifnb \move2; .2byte \move2; .endif .ifnb \move3; .2byte \move3; .endif .ifnb \move4; .2byte \move4; .endif - .ifnb \isShiny; .2byte \isShiny; .endif + .ifnb \shinyMode; .2byte \shinyMode; .endif .ifnb \gmaxFactor; .2byte \gmaxFactor; .endif .ifnb \teraType; .2byte \teraType; .endif .ifnb \dmaxLevel; .2byte \dmaxLevel; .endif @@ -1048,7 +1048,7 @@ @ creates a mon for a given party and slot @ otherwise - .macro createmon side:req, slot:req, species:req, level:req, item, ball, nature, abilityNum, gender, hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv, hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv, move1, move2, move3, move4, isShiny, gmaxFactor, teraType, dmaxLevel + .macro createmon side:req, slot:req, species:req, level:req, item, ball, nature, abilityNum, gender, hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv, hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv, move1, move2, move3, move4, shinyMode, gmaxFactor, teraType, dmaxLevel callnative ScrCmd_createmon, requests_effects=1 .byte \side @ 0 - player, 1 - opponent .byte \slot @ 0-5 @@ -1076,7 +1076,7 @@ .ifnb \move2; .set givemon_flags, givemon_flags | (1 << 18); .endif .ifnb \move3; .set givemon_flags, givemon_flags | (1 << 19); .endif .ifnb \move4; .set givemon_flags, givemon_flags | (1 << 20); .endif - .ifnb \isShiny; .set givemon_flags, givemon_flags | (1 << 21); .endif + .ifnb \shinyMode; .set givemon_flags, givemon_flags | (1 << 21); .endif .ifnb \gmaxFactor; .set givemon_flags, givemon_flags | (1 << 22); .endif .ifnb \teraType; .set givemon_flags, givemon_flags | (1 << 23); .endif .ifnb \dmaxLevel; .set givemon_flags, givemon_flags | (1 << 24); .endif @@ -1102,7 +1102,7 @@ .ifnb \move2; .2byte \move2; .endif .ifnb \move3; .2byte \move3; .endif .ifnb \move4; .2byte \move4; .endif - .ifnb \isShiny; .2byte \isShiny; .endif + .ifnb \shinyMode; .2byte \shinyMode; .endif .ifnb \gmaxFactor; .2byte \gmaxFactor; .endif .ifnb \teraType; .2byte \teraType; .endif .ifnb \dmaxLevel; .2byte \dmaxLevel; .endif diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index 20cff8a30f..b2e6b23ead 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -347,6 +347,12 @@ enum EvoSpinDirections { SPIN_EITHER, // Player spins either clockwise or counter-clockwise }; +enum ShinyMode { + SHINY_MODE_ALWAYS, + SHINY_MODE_RANDOM, + SHINY_MODE_NEVER +}; + #define MON_PIC_WIDTH 64 #define MON_PIC_HEIGHT 64 #define MON_PIC_SIZE (MON_PIC_WIDTH * MON_PIC_HEIGHT / 2) diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index 359ab75e41..d4fba87859 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -332,7 +332,7 @@ void SetTeraType(struct ScriptContext *ctx) * if side/slot are assigned, it will create the mon at the assigned party location * if slot == PARTY_SIZE, it will give the mon to first available party or storage slot */ -static u32 ScriptGiveMonParameterized(u8 side, u8 slot, u16 species, u8 level, u16 item, enum PokeBall ball, u8 nature, u8 abilityNum, u8 gender, u8 *evs, u8 *ivs, u16 *moves, bool8 isShiny, bool8 gmaxFactor, u8 teraType, u8 dmaxLevel) +static u32 ScriptGiveMonParameterized(u8 side, u8 slot, u16 species, u8 level, u16 item, enum PokeBall ball, u8 nature, u8 abilityNum, u8 gender, u8 *evs, u8 *ivs, u16 *moves, enum ShinyMode shinyMode, bool8 gmaxFactor, u8 teraType, u8 dmaxLevel) { enum NationalDexOrder nationalDexNum; int sentToPc; @@ -340,6 +340,7 @@ static u32 ScriptGiveMonParameterized(u8 side, u8 slot, u16 species, u8 level, u u32 i; u8 genderRatio = gSpeciesInfo[species].genderRatio; u16 targetSpecies; + bool32 isShiny; // check whether to use a specific nature or a random one if (nature >= NUM_NATURES) @@ -360,10 +361,13 @@ static u32 ScriptGiveMonParameterized(u8 side, u8 slot, u16 species, u8 level, u CreateMonWithNature(&mon, species, level, 32, nature); // shininess - if (P_FLAG_FORCE_SHINY != 0 && FlagGet(P_FLAG_FORCE_SHINY)) + if (shinyMode == SHINY_MODE_ALWAYS || (P_FLAG_FORCE_SHINY != 0 && FlagGet(P_FLAG_FORCE_SHINY))) isShiny = TRUE; - else if (P_FLAG_FORCE_NO_SHINY != 0 && FlagGet(P_FLAG_FORCE_NO_SHINY)) + else if (shinyMode == SHINY_MODE_NEVER || (P_FLAG_FORCE_NO_SHINY != 0 && FlagGet(P_FLAG_FORCE_NO_SHINY))) isShiny = FALSE; + else + isShiny = GetMonData(&mon, MON_DATA_IS_SHINY); + SetMonData(&mon, MON_DATA_IS_SHINY, &isShiny); // gigantamax factor @@ -479,7 +483,7 @@ u32 ScriptGiveMon(u16 species, u8 level, u16 item) MAX_PER_STAT_IVS + 1, MAX_PER_STAT_IVS + 1, MAX_PER_STAT_IVS + 1}; // ScriptGiveMonParameterized won't touch the stats' IV. u16 moves[MAX_MON_MOVES] = {MOVE_NONE, MOVE_NONE, MOVE_NONE, MOVE_NONE}; - return ScriptGiveMonParameterized(0, PARTY_SIZE, species, level, item, ITEM_POKE_BALL, NUM_NATURES, NUM_ABILITY_PERSONALITY, MON_GENDERLESS, evs, ivs, moves, FALSE, FALSE, NUMBER_OF_MON_TYPES, 0); + return ScriptGiveMonParameterized(0, PARTY_SIZE, species, level, item, ITEM_POKE_BALL, NUM_NATURES, NUM_ABILITY_PERSONALITY, MON_GENDERLESS, evs, ivs, moves, SHINY_MODE_RANDOM, FALSE, NUMBER_OF_MON_TYPES, 0); } #define PARSE_FLAG(n, default_) (flags & (1 << (n))) ? VarGet(ScriptReadHalfword(ctx)) : (default_) @@ -542,20 +546,20 @@ void ScrCmd_createmon(struct ScriptContext *ctx) } } } - hpIv = PARSE_FLAG(11, hpIv); - atkIv = PARSE_FLAG(12, atkIv); - defIv = PARSE_FLAG(13, defIv); - speedIv = PARSE_FLAG(14, speedIv); - spAtkIv = PARSE_FLAG(15, spAtkIv); - spDefIv = PARSE_FLAG(16, spDefIv); - u16 move1 = PARSE_FLAG(17, MOVE_NONE); - u16 move2 = PARSE_FLAG(18, MOVE_NONE); - u16 move3 = PARSE_FLAG(19, MOVE_NONE); - u16 move4 = PARSE_FLAG(20, MOVE_NONE); - bool8 isShiny = PARSE_FLAG(21, FALSE); - bool8 gmaxFactor = PARSE_FLAG(22, FALSE); - u8 teraType = PARSE_FLAG(23, NUMBER_OF_MON_TYPES); - u8 dmaxLevel = PARSE_FLAG(24, 0); + hpIv = PARSE_FLAG(11, hpIv); + atkIv = PARSE_FLAG(12, atkIv); + defIv = PARSE_FLAG(13, defIv); + speedIv = PARSE_FLAG(14, speedIv); + spAtkIv = PARSE_FLAG(15, spAtkIv); + spDefIv = PARSE_FLAG(16, spDefIv); + u16 move1 = PARSE_FLAG(17, MOVE_NONE); + u16 move2 = PARSE_FLAG(18, MOVE_NONE); + u16 move3 = PARSE_FLAG(19, MOVE_NONE); + u16 move4 = PARSE_FLAG(20, MOVE_NONE); + enum ShinyMode shinyMode = PARSE_FLAG(21, SHINY_MODE_RANDOM); + bool8 gmaxFactor = PARSE_FLAG(22, FALSE); + u8 teraType = PARSE_FLAG(23, NUMBER_OF_MON_TYPES); + u8 dmaxLevel = PARSE_FLAG(24, 0); u8 evs[NUM_STATS] = {hpEv, atkEv, defEv, speedEv, spAtkEv, spDefEv}; u8 ivs[NUM_STATS] = {hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv}; @@ -566,7 +570,7 @@ void ScrCmd_createmon(struct ScriptContext *ctx) else Script_RequestEffects(SCREFF_V1); - gSpecialVar_Result = ScriptGiveMonParameterized(side, slot, species, level, item, ball, nature, abilityNum, gender, evs, ivs, moves, isShiny, gmaxFactor, teraType, dmaxLevel); + gSpecialVar_Result = ScriptGiveMonParameterized(side, slot, species, level, item, ball, nature, abilityNum, gender, evs, ivs, moves, shinyMode, gmaxFactor, teraType, dmaxLevel); } #undef PARSE_FLAG diff --git a/test/pokemon.c b/test/pokemon.c index 61c9e86c04..6079bd28bd 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -304,7 +304,7 @@ TEST("givemon [all]") ZeroPlayerPartyMons(); RUN_OVERWORLD_SCRIPT( - givemon SPECIES_WOBBUFFET, 100, item=ITEM_LEFTOVERS, ball=ITEM_MASTER_BALL, nature=NATURE_BOLD, abilityNum=2, gender=MON_MALE, hpEv=1, atkEv=2, defEv=3, speedEv=4, spAtkEv=5, spDefEv=6, hpIv=7, atkIv=8, defIv=9, speedIv=10, spAtkIv=11, spDefIv=12, move1=MOVE_SCRATCH, move2=MOVE_SPLASH, move3=MOVE_CELEBRATE, move4=MOVE_EXPLOSION, isShiny=TRUE, gmaxFactor=TRUE, teraType=TYPE_FIRE, dmaxLevel=7; + givemon SPECIES_WOBBUFFET, 100, item=ITEM_LEFTOVERS, ball=ITEM_MASTER_BALL, nature=NATURE_BOLD, abilityNum=2, gender=MON_MALE, hpEv=1, atkEv=2, defEv=3, speedEv=4, spAtkEv=5, spDefEv=6, hpIv=7, atkIv=8, defIv=9, speedIv=10, spAtkIv=11, spDefIv=12, move1=MOVE_SCRATCH, move2=MOVE_SPLASH, move3=MOVE_CELEBRATE, move4=MOVE_EXPLOSION, shinyMode=SHINY_MODE_ALWAYS, gmaxFactor=TRUE, teraType=TYPE_FIRE, dmaxLevel=7; ); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_WOBBUFFET); @@ -363,13 +363,13 @@ TEST("givemon [vars]") VarSet(VAR_TEMP_6, MOVE_SPLASH); VarSet(VAR_TEMP_7, MOVE_CELEBRATE); VarSet(VAR_TEMP_8, MOVE_EXPLOSION); - VarSet(VAR_TEMP_9, TRUE); + VarSet(VAR_TEMP_9, SHINY_MODE_ALWAYS); VarSet(VAR_TEMP_A, TRUE); VarSet(VAR_TEMP_B, TYPE_FIRE); VarSet(VAR_TEMP_E, 7); RUN_OVERWORLD_SCRIPT( - givemon VAR_TEMP_C, VAR_TEMP_D, item=VAR_0x8000, ball=VAR_0x8001, nature=VAR_0x8002, abilityNum=VAR_0x8003, gender=VAR_0x8004, hpEv=VAR_0x8005, atkEv=VAR_0x8006, defEv=VAR_0x8007, speedEv=VAR_0x8008, spAtkEv=VAR_0x8009, spDefEv=VAR_0x800A, hpIv=VAR_0x800B, atkIv=VAR_TEMP_0, defIv=VAR_TEMP_1, speedIv=VAR_TEMP_2, spAtkIv=VAR_TEMP_3, spDefIv=VAR_TEMP_4, move1=VAR_TEMP_5, move2=VAR_TEMP_6, move3=VAR_TEMP_7, move4=VAR_TEMP_8, isShiny=VAR_TEMP_9, gmaxFactor=VAR_TEMP_A, teraType=VAR_TEMP_B, dmaxLevel=VAR_TEMP_E; + givemon VAR_TEMP_C, VAR_TEMP_D, item=VAR_0x8000, ball=VAR_0x8001, nature=VAR_0x8002, abilityNum=VAR_0x8003, gender=VAR_0x8004, hpEv=VAR_0x8005, atkEv=VAR_0x8006, defEv=VAR_0x8007, speedEv=VAR_0x8008, spAtkEv=VAR_0x8009, spDefEv=VAR_0x800A, hpIv=VAR_0x800B, atkIv=VAR_TEMP_0, defIv=VAR_TEMP_1, speedIv=VAR_TEMP_2, spAtkIv=VAR_TEMP_3, spDefIv=VAR_TEMP_4, move1=VAR_TEMP_5, move2=VAR_TEMP_6, move3=VAR_TEMP_7, move4=VAR_TEMP_8, shinyMode=VAR_TEMP_9, gmaxFactor=VAR_TEMP_A, teraType=VAR_TEMP_B, dmaxLevel=VAR_TEMP_E; ); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_WOBBUFFET);