Add day limit for forms support (#4778)

* Add day limit for forms support

* Add missing newline

* Incorporate review suggestions
This commit is contained in:
Bassoonian 2024-06-26 10:36:44 +02:00 committed by GitHub
parent 6c9dcd60bc
commit 81bd14818e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
7 changed files with 82 additions and 3 deletions

View File

@ -129,4 +129,9 @@
// param1: tera type
#define FORM_CHANGE_BATTLE_TERASTALLIZATION 22
// Form change that activates at midnight after a certain amount of days has passed.
// Adding this form change will automatically make the countdown start as soon the Pokémon changes into a species other than the one specified for this form change.
// param1: amount of days
#define FORM_CHANGE_DAYS_PASSED 23
#endif // GUARD_CONSTANTS_FORM_CHANGE_TYPES_H

View File

@ -26,6 +26,7 @@ enum {
MON_DATA_IS_SHINY,
MON_DATA_HIDDEN_NATURE,
MON_DATA_HP_LOST,
MON_DATA_DAYS_SINCE_FORM_CHANGE,
MON_DATA_ENCRYPT_SEPARATOR,
MON_DATA_NICKNAME,
MON_DATA_NICKNAME10,
@ -246,7 +247,8 @@ struct BoxPokemon
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_13:4;
u8 daysSinceFormChange:3; // 7 days.
u8 unused_13:1;
u8 otName[PLAYER_NAME_LENGTH];
u8 markings:4;
u8 compressedStatus:4;
@ -877,5 +879,7 @@ void HealPokemon(struct Pokemon *mon);
void HealBoxPokemon(struct BoxPokemon *boxMon);
const u8 *GetMoveName(u16 moveId);
const u8 *GetMoveAnimationScript(u16 moveId);
void UpdateDaysPassedSinceFormChange(u16 days);
void TrySetDayLimitToFormChange(struct Pokemon *mon);
#endif // GUARD_POKEMON_H

View File

@ -54,6 +54,7 @@ static void UpdatePerDay(struct Time *localTime)
UpdateFrontierGambler(daysSince);
SetShoalItemFlag(daysSince);
SetRandomLotteryNumber(daysSince);
UpdateDaysPassedSinceFormChange(daysSince);
*days = localTime->days;
}
}

View File

@ -779,6 +779,14 @@ static const struct FormChange sGreninjaBattleBondFormChangeTable[] = {
};
#endif //P_FAMILY_FROAKIE
#if P_FAMILY_FURFROU
static const struct FormChange sFurfrouFormChangeTable[] = {
{FORM_CHANGE_WITHDRAW, SPECIES_FURFROU_NATURAL},
{FORM_CHANGE_DAYS_PASSED, SPECIES_FURFROU_NATURAL, 5},
{FORM_CHANGE_TERMINATOR},
};
#endif //P_FAMILY_FURFROU
#if P_FAMILY_HONEDGE
static const struct FormChange sAegislashFormChangeTable[] = {
{FORM_CHANGE_BATTLE_SWITCH, SPECIES_AEGISLASH_SHIELD},
@ -841,8 +849,9 @@ static const struct FormChange sDiancieFormChangeTable[] = {
#if P_FAMILY_HOOPA
static const struct FormChange sHoopaFormChangeTable[] = {
{FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA_CONFINED},
{FORM_CHANGE_WITHDRAW, SPECIES_HOOPA_CONFINED},
{FORM_CHANGE_ITEM_USE, SPECIES_HOOPA_UNBOUND, ITEM_PRISON_BOTTLE, SPECIES_HOOPA_CONFINED},
{FORM_CHANGE_WITHDRAW, SPECIES_HOOPA_CONFINED},
{FORM_CHANGE_DAYS_PASSED, SPECIES_HOOPA_CONFINED, 3},
{FORM_CHANGE_TERMINATOR},
};
#endif //P_FAMILY_HOOPA

View File

@ -2156,6 +2156,7 @@ const struct SpeciesInfo gSpeciesInfoGen6[] =
.teachableLearnset = sFurfrouTeachableLearnset, \
.eggMoveLearnset = sFurfrouEggMoveLearnset, \
.formSpeciesIdTable = sFurfrouFormSpeciesIdTable, \
.formChangeTable = sFurfrouFormChangeTable, \
}
[SPECIES_FURFROU_NATURAL] = FURFROU_MISC_INFO(Natural, FALSE, 48, 3, 56, 0, 0),

View File

@ -6361,6 +6361,7 @@ static void Task_TryItemUseFormChange(u8 taskId)
case 0:
targetSpecies = gTasks[taskId].tTargetSpecies;
SetMonData(mon, MON_DATA_SPECIES, &targetSpecies);
TrySetDayLimitToFormChange(mon);
CalculateMonStats(mon);
gTasks[taskId].tState++;
break;

View File

@ -2856,6 +2856,9 @@ u32 GetBoxMonData3(struct BoxPokemon *boxMon, s32 field, u8 *data)
retVal = nature ^ boxMon->hiddenNatureModifier;
break;
}
case MON_DATA_DAYS_SINCE_FORM_CHANGE:
retVal = boxMon->daysSinceFormChange;
break;
default:
break;
}
@ -3290,6 +3293,9 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
boxMon->hiddenNatureModifier = nature ^ hiddenNature;
break;
}
case MON_DATA_DAYS_SINCE_FORM_CHANGE:
SET8(boxMon->daysSinceFormChange);
break;
}
}
@ -6523,6 +6529,7 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32
break;
case FORM_CHANGE_WITHDRAW:
case FORM_CHANGE_FAINT:
case FORM_CHANGE_DAYS_PASSED:
targetSpecies = formChanges[i].targetSpecies;
break;
case FORM_CHANGE_STATUS:
@ -6550,6 +6557,22 @@ u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32
return targetSpecies;
}
void TrySetDayLimitToFormChange(struct Pokemon *mon)
{
u32 i;
u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
const struct FormChange *formChanges = GetSpeciesFormChanges(species);
for (i = 0; formChanges[i].method != FORM_CHANGE_TERMINATOR; i++)
{
if (formChanges[i].method == FORM_CHANGE_DAYS_PASSED && species != formChanges[i].targetSpecies)
{
SetMonData(mon, MON_DATA_DAYS_SINCE_FORM_CHANGE, &formChanges[i].param1);
break;
}
}
}
bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method)
{
u32 i;
@ -6866,3 +6889,38 @@ const u8 *GetMoveAnimationScript(u16 moveId)
}
return gMovesInfo[moveId].battleAnimScript;
}
void UpdateDaysPassedSinceFormChange(u16 days)
{
u32 i;
for (i = 0; i < PARTY_SIZE; i++)
{
struct Pokemon *mon = &gPlayerParty[i];
u8 daysSinceFormChange;
if (!GetMonData(mon, MON_DATA_SPECIES, 0))
continue;
daysSinceFormChange = GetMonData(mon, MON_DATA_DAYS_SINCE_FORM_CHANGE, 0);
if (daysSinceFormChange == 0)
continue;
if (daysSinceFormChange > days)
daysSinceFormChange -= days;
else
daysSinceFormChange = 0;
SetMonData(mon, MON_DATA_DAYS_SINCE_FORM_CHANGE, &daysSinceFormChange);
if (daysSinceFormChange == 0)
{
u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_DAYS_PASSED, 0);
if (targetSpecies != SPECIES_NONE)
{
SetMonData(mon, MON_DATA_SPECIES, &targetSpecies);
CalculateMonStats(mon);
}
}
}
}