Primal Reversion in Form Change tables

This commit is contained in:
Eduardo Quezada 2022-10-21 02:08:37 -03:00
parent 861590f747
commit 0a79390ec0
13 changed files with 136 additions and 109 deletions

View File

@ -472,9 +472,6 @@ struct MegaEvolutionData
bool8 alreadyEvolved[4]; // Array id is used for mon position.
u16 evolvedSpecies[MAX_BATTLERS_COUNT];
u16 playerEvolvedSpecies;
u8 primalRevertedPartyIds[2]; // As flags using gBitTable;
u16 primalRevertedSpecies[MAX_BATTLERS_COUNT];
u16 playerPrimalRevertedSpecies;
u8 battlerId;
bool8 playerSelect;
u8 triggerSpriteId;

View File

@ -145,11 +145,12 @@ u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilit
u16 GetTypeModifier(u8 atkType, u8 defType);
s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId);
u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId);
u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId);
u16 GetPrimalReversionSpecies(u16 preSpecies, u16 heldItemId);
u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4);
bool32 CanMegaEvolve(u8 battlerId);
void UndoMegaEvolution(u32 monId);
void BattleFormChange(u32 monId, u32 side, u16 method);
bool32 IsBattlerPrimalReverted(u8 battlerId);
void TryBattleFormChange(u8 battlerId, u16 method);
bool32 DoBattlersShareType(u32 battler1, u32 battler2);
bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId);
struct Pokemon *GetIllusionMonPtr(u32 battlerId);
@ -186,6 +187,7 @@ void TryToRevertMimicry(void);
void RestoreBattlerOriginalTypes(u8 battlerId);
u32 GetBattlerMoveTargetType(u8 battlerId, u16 move);
bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move);
void RecalcBattlerStats(u32 battler, struct Pokemon *mon);
// Ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability);
bool32 IsRolePlayBannedAbility(u16 ability);

View File

@ -266,7 +266,6 @@
// Evolution types
#define EVO_MEGA_EVOLUTION 0xffff // Not an actual evolution, used to temporarily mega evolve in battle.
#define EVO_MOVE_MEGA_EVOLUTION 0xfffe // Mega Evolution that checks for a move instead of held item.
#define EVO_PRIMAL_REVERSION 0xfffd // Not an actual evolution, used to undergo primal reversion in battle.
#define EVO_FRIENDSHIP 1 // Pokémon levels up with friendship ≥ 220
#define EVO_FRIENDSHIP_DAY 2 // Pokémon levels up during the day with friendship ≥ 220
#define EVO_FRIENDSHIP_NIGHT 3 // Pokémon levels up at night with friendship ≥ 220
@ -317,15 +316,16 @@
#define EVO_MODE_OVERWORLD_SPECIAL 5
// Form change types
#define FORM_CHANGE_END 0
#define FORM_CHANGE_ITEM_HOLD 1
#define FORM_CHANGE_ITEM_USE 2
#define FORM_CHANGE_MOVE 3
#define FORM_CHANGE_WITHDRAW 4
#define FORM_CHANGE_BATTLE_BEGIN 5
#define FORM_CHANGE_BATTLE_SWITCH 6
#define FORM_CHANGE_BATTLE_FAINT 7
#define FORM_CHANGE_BATTLE_END 8
#define FORM_CHANGE_END 0 // Form table terminator
#define FORM_CHANGE_ITEM_HOLD 1
#define FORM_CHANGE_ITEM_USE 2
#define FORM_CHANGE_MOVE 3 // Todo
#define FORM_CHANGE_WITHDRAW 4 //
#define FORM_CHANGE_BATTLE_BEGIN 5
#define FORM_CHANGE_BATTLE_END 6
#define FORM_CHANGE_BATTLE_SWITCH 7
#define FORM_CHANGE_BATTLE_FAINT 8
#define FORM_CHANGE_PRIMAL_REVERSION 9
#define MON_PIC_WIDTH 64
#define MON_PIC_HEIGHT 64
@ -345,14 +345,15 @@
#define SPECIES_FLAG_LEGENDARY (1 << 0)
#define SPECIES_FLAG_MYTHICAL (1 << 1)
#define SPECIES_FLAG_MEGA_EVOLUTION (1 << 2)
#define SPECIES_FLAG_ULTRA_BEAST (1 << 3)
#define SPECIES_FLAG_ALOLAN_FORM (1 << 4)
#define SPECIES_FLAG_GALARIAN_FORM (1 << 5)
#define SPECIES_FLAG_HISUIAN_FORM (1 << 6)
#define SPECIES_FLAG_GENDER_DIFFERENCE (1 << 7)
#define SPECIES_FLAG_ALL_PERFECT_IVS (1 << 8)
#define SPECIES_FLAG_SHINY_LOCKED (1 << 9)
#define SPECIES_FLAG_CANNOT_BE_TRADED (1 << 10)
#define SPECIES_FLAG_PRIMAL_REVERSION (1 << 3)
#define SPECIES_FLAG_ULTRA_BEAST (1 << 4)
#define SPECIES_FLAG_ALOLAN_FORM (1 << 5)
#define SPECIES_FLAG_GALARIAN_FORM (1 << 6)
#define SPECIES_FLAG_HISUIAN_FORM (1 << 7)
#define SPECIES_FLAG_GENDER_DIFFERENCE (1 << 8)
#define SPECIES_FLAG_ALL_PERFECT_IVS (1 << 9)
#define SPECIES_FLAG_SHINY_LOCKED (1 << 10)
#define SPECIES_FLAG_CANNOT_BE_TRADED (1 << 11)
#define LEGENDARY_PERFECT_IV_COUNT 3

View File

@ -409,6 +409,7 @@ extern const u16 gUnionRoomFacilityClasses[];
extern const struct SpriteTemplate gBattlerSpriteTemplates[];
extern const s8 gNatureStatTable[][5];
extern const u16 *const gFormSpeciesIdTables[NUM_SPECIES];
extern const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES];
extern const u32 sExpCandyExperienceTable[];
void ZeroBoxMonData(struct BoxPokemon *boxMon);
@ -564,6 +565,7 @@ u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg);
u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *mon, u16 method, u32 arg);
u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove);
bool32 ShouldShowFemaleDifferences(u16 species, u32 personality);
void TryFormChange(u32 monId, u32 side, u16 method);
void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method);
u32 GetMonFriendshipScore(struct Pokemon *pokemon);

View File

@ -871,8 +871,8 @@ u8 CreateBattlerHealthboxSprites(u8 battlerId)
healthBarSpritePtr->invisible = TRUE;
// Create mega indicator sprite if is a mega evolved or a primal reverted mon.
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]
|| gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
|| IsBattlerPrimalReverted(battlerId))
{
megaIndicatorSpriteId = CreateMegaIndicatorSprite(battlerId, 0);
gSprites[megaIndicatorSpriteId].invisible = TRUE;
@ -979,8 +979,8 @@ void SetHealthboxSpriteVisible(u8 healthboxSpriteId)
gSprites[healthboxSpriteId].invisible = FALSE;
gSprites[gSprites[healthboxSpriteId].hMain_HealthBarSpriteId].invisible = FALSE;
gSprites[gSprites[healthboxSpriteId].oam.affineParam].invisible = FALSE;
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]]
|| gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
|| IsBattlerPrimalReverted(battlerId))
{
u8 spriteId = GetMegaIndicatorSpriteId(healthboxSpriteId);
if (spriteId != 0xFF)
@ -1104,8 +1104,8 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl)
u8 battler = gSprites[healthboxSpriteId].hMain_Battler;
// Don't print Lv char if mon is mega evolved or primal reverted.
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]]
|| gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])
if ((gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])
|| IsBattlerPrimalReverted(battler))
{
objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3);
xPos = 5 * (3 - (objVram - (text + 2))) - 1;
@ -1561,7 +1561,7 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which)
LoadSpritePalette(&sSpritePalette_MegaIndicator);
LoadSpriteSheet(&sSpriteSheet_MegaIndicator);
}
else if (gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
else if (IsBattlerPrimalReverted(battlerId))
{
if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_GROUDON)
{
@ -1590,7 +1590,7 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which)
{
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_MegaIndicator, x, y, 0);
}
else if (gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(battlerId)] & gBitTable[gBattlerPartyIndexes[battlerId]])
else if (IsBattlerPrimalReverted(battlerId))
{
if (GET_BASE_SPECIES_ID(gBattleMons[battlerId].species) == SPECIES_GROUDON)
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_OmegaIndicator, x, y, 0);

View File

@ -602,9 +602,9 @@ static void CB2_InitBattleInternal(void)
for (i = 0; i < PARTY_SIZE; i++)
{
// Player's side
BattleFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_BEGIN);
TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_BEGIN);
// Opponent's side
BattleFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BATTLE_BEGIN);
TryFormChange(i, B_SIDE_OPPONENT, FORM_CHANGE_BATTLE_BEGIN);
}
gBattleCommunication[MULTIUSE_STATE] = 0;
@ -3247,7 +3247,7 @@ void FaintClearSetData(void)
gBattleMons[gActiveBattler].type3 = TYPE_MYSTERY;
Ai_UpdateFaintData(gActiveBattler);
BattleFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FORM_CHANGE_BATTLE_FAINT);
TryFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FORM_CHANGE_BATTLE_FAINT);
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]);
@ -3682,18 +3682,12 @@ static void TryDoEventsBeforeFirstTurn(void)
// Primal Reversion
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB)
if (GetBattlerHoldEffect(i, TRUE) == HOLD_EFFECT_PRIMAL_ORB
&& GetPrimalReversionSpecies(gBattleMons[i].species, gBattleMons[i].item) != SPECIES_NONE)
{
for (j = 0; j < EVOS_PER_MON; j++)
{
if (gEvolutionTable[gBattleMons[i].species][j].targetSpecies != SPECIES_NONE
&& gEvolutionTable[gBattleMons[i].species][j].method == EVO_PRIMAL_REVERSION)
{
gBattlerAttacker = i;
BattleScriptExecute(BattleScript_PrimalReversion);
return;
}
}
gBattlerAttacker = i;
BattleScriptExecute(BattleScript_PrimalReversion);
return;
}
}
@ -5207,7 +5201,7 @@ static void HandleEndTurn_FinishBattle(void)
for (i = 0; i < PARTY_SIZE; i++)
{
UndoMegaEvolution(i);
BattleFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END);
TryFormChange(i, B_SIDE_PLAYER, FORM_CHANGE_BATTLE_END);
DoBurmyFormChange(i);
}
#if B_RECALCULATE_STATS >= GEN_5
@ -5221,6 +5215,13 @@ static void HandleEndTurn_FinishBattle(void)
}
}
#endif
// Clear battle mon species to avoid a bug on the next battle that causes
// healthboxes loading incorrectly due to it trying to create a Mega Indicator
// if the previous battler would've had.
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
gBattleMons[i].species = SPECIES_NONE;
}
gBattleMainFunc = FreeResetData_ReturnToOvOrDoEvolutions;
gCB2_AfterEvolution = BattleMainCB2;
}

View File

@ -7914,22 +7914,6 @@ u32 IsAbilityStatusProtected(u32 battler)
|| IsShieldsDownProtected(battler);
}
static void RecalcBattlerStats(u32 battler, struct Pokemon *mon)
{
CalculateMonStats(mon);
gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL);
gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP);
gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP);
gBattleMons[battler].attack = GetMonData(mon, MON_DATA_ATK);
gBattleMons[battler].defense = GetMonData(mon, MON_DATA_DEF);
gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED);
gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK);
gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF);
gBattleMons[battler].ability = GetMonAbility(mon);
gBattleMons[battler].type1 = gBaseStats[gBattleMons[battler].species].type1;
gBattleMons[battler].type2 = gBaseStats[gBattleMons[battler].species].type2;
}
static u32 GetHighestStatId(u32 battlerId)
{
u32 i, highestId = STAT_ATK, highestStat = gBattleMons[battlerId].attack;
@ -8870,17 +8854,7 @@ static void Cmd_various(void)
// Change species.
if (gBattlescriptCurrInstr[3] == 0)
{
u16 primalSpecies;
gBattleStruct->mega.primalRevertedSpecies[gActiveBattler] = gBattleMons[gActiveBattler].species;
if (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_LEFT
|| (GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT && !(gBattleTypeFlags & (BATTLE_TYPE_MULTI | BATTLE_TYPE_INGAME_PARTNER))))
{
gBattleStruct->mega.playerPrimalRevertedSpecies = gBattleStruct->mega.primalRevertedSpecies[gActiveBattler];
}
// Checks Primal Reversion
primalSpecies = GetPrimalReversionSpecies(gBattleStruct->mega.primalRevertedSpecies[gActiveBattler], gBattleMons[gActiveBattler].item);
gBattleMons[gActiveBattler].species = primalSpecies;
gBattleMons[gActiveBattler].species = GetPrimalReversionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].item);
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species);
BtlController_EmitSetMonData(BUFFER_A, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], sizeof(gBattleMons[gActiveBattler].species), &gBattleMons[gActiveBattler].species);
@ -8890,7 +8864,6 @@ static void Cmd_various(void)
else if (gBattlescriptCurrInstr[3] == 1)
{
RecalcBattlerStats(gActiveBattler, mon);
gBattleStruct->mega.primalRevertedPartyIds[GetBattlerSide(gActiveBattler)] |= gBitTable[gBattlerPartyIndexes[gActiveBattler]];
}
// Update healthbox and elevation.
else
@ -9606,15 +9579,7 @@ static void Cmd_various(void)
return;
case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL:
{
bool8 canDoPrimalReversion = FALSE;
for (i = 0; i < EVOS_PER_MON; i++)
{
if (gEvolutionTable[gBattleMons[gActiveBattler].species][i].method == EVO_PRIMAL_REVERSION
&& gEvolutionTable[gBattleMons[gActiveBattler].species][i].param == gBattleMons[gActiveBattler].item)
canDoPrimalReversion = TRUE;
}
if (!canDoPrimalReversion)
if (GetPrimalReversionSpecies(gBattleMons[gActiveBattler].species, gBattleMons[gActiveBattler].item) == SPECIES_NONE)
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
else
gBattlescriptCurrInstr += 7;
@ -14109,7 +14074,7 @@ static void Cmd_handleballthrow(void)
{
BtlController_EmitBallThrowAnim(BUFFER_A, BALL_3_SHAKES_SUCCESS);
MarkBattlerForControllerExec(gActiveBattler);
BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END),
TryFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END),
gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem);
@ -14163,7 +14128,7 @@ static void Cmd_handleballthrow(void)
if (IsCriticalCapture())
gBattleSpritesDataPtr->animationData->criticalCaptureSuccess = TRUE;
BattleFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END),
TryFormChange(gBattlerPartyIndexes[gBattlerTarget], GET_BATTLER_SIDE(gBattlerTarget), FORM_CHANGE_BATTLE_END),
gBattlescriptCurrInstr = BattleScript_SuccessBallThrow;
SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_POKEBALL, &gLastUsedItem);

View File

@ -518,7 +518,7 @@ void HandleAction_Switch(void)
if (gBattleResults.playerSwitchesCounter < 255)
gBattleResults.playerSwitchesCounter++;
BattleFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), FORM_CHANGE_BATTLE_SWITCH);
TryFormChange(gBattlerPartyIndexes[gBattlerAttacker], GetBattlerSide(gBattlerAttacker), FORM_CHANGE_BATTLE_SWITCH);
}
void HandleAction_UseItem(void)
@ -8955,8 +8955,7 @@ static bool32 CanEvolve(u32 species)
{
if (gEvolutionTable[species][i].method
&& gEvolutionTable[species][i].method != EVO_MEGA_EVOLUTION
&& gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION
&& gEvolutionTable[species][i].method != EVO_PRIMAL_REVERSION)
&& gEvolutionTable[species][i].method != EVO_MOVE_MEGA_EVOLUTION)
return TRUE;
}
return FALSE;
@ -9565,15 +9564,20 @@ u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId)
return SPECIES_NONE;
}
u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId)
u16 GetPrimalReversionSpecies(u16 preSpecies, u16 heldItemId)
{
u32 i;
const struct FormChange *formChanges = gFormChangeTablePointers[preSpecies];
for (i = 0; i < EVOS_PER_MON; i++)
if (formChanges != NULL)
{
if (gEvolutionTable[preEvoSpecies][i].method == EVO_PRIMAL_REVERSION
&& gEvolutionTable[preEvoSpecies][i].param == heldItemId)
return gEvolutionTable[preEvoSpecies][i].targetSpecies;
for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++)
{
if (formChanges[i].method == FORM_CHANGE_PRIMAL_REVERSION
&& formChanges[i].param1 == heldItemId
&& formChanges[i].targetSpecies != preSpecies)
return formChanges[i].targetSpecies;
}
}
return SPECIES_NONE;
}
@ -9675,12 +9679,6 @@ void UndoMegaEvolution(u32 monId)
SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &gBattleStruct->mega.playerEvolvedSpecies);
CalculateMonStats(&gPlayerParty[monId]);
}
else if (gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] & gBitTable[monId])
{
gBattleStruct->mega.primalRevertedPartyIds[B_SIDE_PLAYER] &= ~(gBitTable[monId]);
SetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, &baseSpecies);
CalculateMonStats(&gPlayerParty[monId]);
}
// While not exactly a mega evolution, Zygarde follows the same rules.
else if (GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES, NULL) == SPECIES_ZYGARDE_COMPLETE)
{
@ -9690,17 +9688,23 @@ void UndoMegaEvolution(u32 monId)
}
}
void BattleFormChange(u32 monId, u32 side, u16 method)
bool32 IsBattlerPrimalReverted(u8 battlerId)
{
u32 targetSpecies;
return (gBaseStats[gBattleMons[battlerId].species].flags & SPECIES_FLAG_PRIMAL_REVERSION);
}
void TryBattleFormChange(u8 battlerId, u16 method)
{
u16 targetSpecies;
u8 monId = gBattlerPartyIndexes[battlerId];
u8 side = GET_BATTLER_SIDE(battlerId);
struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0);
if (targetSpecies != SPECIES_NONE)
{
TryToSetBattleFormChangeMoves(&party[monId], method);
SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies);
CalculateMonStats(&party[monId]);
RecalcBattlerStats(battlerId, &party[monId]);
}
}
@ -10362,3 +10366,19 @@ bool32 CanTargetBattler(u8 battlerAtk, u8 battlerDef, u16 move)
return FALSE; // Pokémon affected by Heal Block cannot target allies with Pollen Puff
return TRUE;
}
void RecalcBattlerStats(u32 battler, struct Pokemon *mon)
{
CalculateMonStats(mon);
gBattleMons[battler].level = GetMonData(mon, MON_DATA_LEVEL);
gBattleMons[battler].hp = GetMonData(mon, MON_DATA_HP);
gBattleMons[battler].maxHP = GetMonData(mon, MON_DATA_MAX_HP);
gBattleMons[battler].attack = GetMonData(mon, MON_DATA_ATK);
gBattleMons[battler].defense = GetMonData(mon, MON_DATA_DEF);
gBattleMons[battler].speed = GetMonData(mon, MON_DATA_SPEED);
gBattleMons[battler].spAttack = GetMonData(mon, MON_DATA_SPATK);
gBattleMons[battler].spDefense = GetMonData(mon, MON_DATA_SPDEF);
gBattleMons[battler].ability = GetMonAbility(mon);
gBattleMons[battler].type1 = gBaseStats[gBattleMons[battler].species].type1;
gBattleMons[battler].type2 = gBaseStats[gBattleMons[battler].species].type2;
}

View File

@ -24117,7 +24117,7 @@ const struct BaseStats gBaseStats[] =
.abilities = {ABILITY_PRIMORDIAL_SEA, ABILITY_PRIMORDIAL_SEA},
.bodyColor = BODY_COLOR_BLUE,
.noFlip = FALSE,
.flags = SPECIES_FLAG_LEGENDARY,
.flags = SPECIES_FLAG_LEGENDARY | SPECIES_FLAG_PRIMAL_REVERSION,
},
[SPECIES_GROUDON_PRIMAL] =
@ -24142,7 +24142,7 @@ const struct BaseStats gBaseStats[] =
.abilities = {ABILITY_DESOLATE_LAND, ABILITY_DESOLATE_LAND},
.bodyColor = BODY_COLOR_RED,
.noFlip = FALSE,
.flags = SPECIES_FLAG_LEGENDARY,
.flags = SPECIES_FLAG_LEGENDARY | SPECIES_FLAG_PRIMAL_REVERSION,
},
[SPECIES_RATTATA_ALOLAN] =

View File

@ -293,8 +293,6 @@ const struct Evolution gEvolutionTable[NUM_SPECIES][EVOS_PER_MON] =
[SPECIES_METAGROSS] = {{EVO_MEGA_EVOLUTION, ITEM_METAGROSSITE, SPECIES_METAGROSS_MEGA}},
[SPECIES_LATIAS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIASITE, SPECIES_LATIAS_MEGA}},
[SPECIES_LATIOS] = {{EVO_MEGA_EVOLUTION, ITEM_LATIOSITE, SPECIES_LATIOS_MEGA}},
[SPECIES_KYOGRE] = {{EVO_PRIMAL_REVERSION, ITEM_BLUE_ORB, SPECIES_KYOGRE_PRIMAL}},
[SPECIES_GROUDON] = {{EVO_PRIMAL_REVERSION, ITEM_RED_ORB, SPECIES_GROUDON_PRIMAL}},
[SPECIES_RAYQUAZA] = {{EVO_MOVE_MEGA_EVOLUTION, MOVE_DRAGON_ASCENT, SPECIES_RAYQUAZA_MEGA}},
#if P_GEN_4_POKEMON == TRUE

View File

@ -1,5 +1,9 @@
const struct FormChange *const gFormChangeTablePointers[NUM_SPECIES] =
{
[SPECIES_KYOGRE] = sKyogreFormChangeTable,
[SPECIES_KYOGRE_PRIMAL] = sKyogreFormChangeTable,
[SPECIES_GROUDON] = sGroudonFormChangeTable,
[SPECIES_GROUDON_PRIMAL] = sGroudonFormChangeTable,
#if P_GEN_4_POKEMON == TRUE
[SPECIES_GIRATINA] = sGiratinaFormChangeTable,
[SPECIES_GIRATINA_ORIGIN] = sGiratinaFormChangeTable,

View File

@ -47,6 +47,18 @@ FORM_CHANGE_BATTLE_END:
#define DAY 1
#define NIGHT 2
static const struct FormChange sKyogreFormChangeTable[] = {
{FORM_CHANGE_PRIMAL_REVERSION, SPECIES_KYOGRE_PRIMAL, ITEM_BLUE_ORB},
{FORM_CHANGE_BATTLE_END, SPECIES_KYOGRE},
{FORM_CHANGE_END},
};
static const struct FormChange sGroudonFormChangeTable[] = {
{FORM_CHANGE_PRIMAL_REVERSION, SPECIES_GROUDON_PRIMAL, ITEM_RED_ORB},
{FORM_CHANGE_BATTLE_END, SPECIES_GROUDON},
{FORM_CHANGE_END},
};
#if P_GEN_4_POKEMON == TRUE
static const struct FormChange sGiratinaFormChangeTable[] = {
{FORM_CHANGE_ITEM_HOLD, SPECIES_GIRATINA, ITEM_NONE},
@ -178,7 +190,7 @@ static const struct FormChange sXerneasFormChangeTable[] = {
static const struct FormChange sHoopaFormChangeTable[] = {
{FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA},
// {FORM_CHANGE_WITHDRAW, SPECIES_HOOPA},
{FORM_CHANGE_WITHDRAW, SPECIES_HOOPA},
{FORM_CHANGE_END},
};
#endif

View File

@ -8397,6 +8397,16 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32
case FORM_CHANGE_BATTLE_END:
if (heldItem == formChanges[i].param1 || formChanges[i].param1 == ITEM_NONE)
targetSpecies = formChanges[i].targetSpecies;
break;
case FORM_CHANGE_PRIMAL_REVERSION:
if (arg == formChanges[i].param1)
targetSpecies = formChanges[i].targetSpecies;
break;
case FORM_CHANGE_WITHDRAW:
case FORM_CHANGE_BATTLE_SWITCH:
case FORM_CHANGE_BATTLE_FAINT:
targetSpecies = formChanges[i].targetSpecies;
break;
}
}
}
@ -8485,13 +8495,28 @@ bool32 ShouldShowFemaleDifferences(u16 species, u32 personality)
return (gBaseStats[species].flags & SPECIES_FLAG_GENDER_DIFFERENCE) && GetGenderFromSpeciesAndPersonality(species, personality) == MON_FEMALE;
}
void TryFormChange(u32 monId, u32 side, u16 method)
{
u32 targetSpecies;
struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty;
targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0);
if (targetSpecies != SPECIES_NONE)
{
TryToSetBattleFormChangeMoves(&party[monId], method);
SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies);
CalculateMonStats(&party[monId]);
}
}
void TryToSetBattleFormChangeMoves(struct Pokemon *mon, u16 method)
{
int i, j;
u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
const struct FormChange *formChanges = gFormChangeTablePointers[species];
if (formChanges == NULL || (method != FORM_CHANGE_BATTLE_BEGIN && method != FORM_CHANGE_BATTLE_END))
if (formChanges == NULL
|| (method != FORM_CHANGE_BATTLE_BEGIN && method != FORM_CHANGE_BATTLE_END))
return;
for (i = 0; formChanges[i].method != FORM_CHANGE_END; i++)