From 99fef0260fbcafaa99bdea90a0b7a89a1e61e579 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Thu, 19 Dec 2024 20:50:08 +0100 Subject: [PATCH 01/85] Battle Weather Refactor --- data/battle_scripts_1.s | 12 ++--- docs/changelogs/1.9.x/1.9.0.md | 2 +- include/battle_util.h | 2 +- include/constants/battle.h | 67 +++++++++++------------ src/battle_dynamax.c | 8 +-- src/battle_script_commands.c | 10 ++-- src/battle_util.c | 99 +++++++++++++++------------------- 7 files changed, 91 insertions(+), 109 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 5df1d1935f..fbe3dac13d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -266,7 +266,7 @@ BattleScript_EffectChillyReception:: jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_RAIN_PRIMAL, BattleScript_EffectChillyReceptionBlockedByPrimalRain jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_STRONG_WINDS, BattleScript_EffectChillyReceptionBlockedByStrongWinds call BattleScript_EffectChillyReceptionPlayAnimation - setfieldweather ENUM_WEATHER_SNOW + setfieldweather BATTLE_WEATHER_SNOW call BattleScript_MoveWeatherChangeRet goto BattleScript_MoveSwitch BattleScript_EffectChillyReceptionPlayAnimation: @@ -4292,7 +4292,7 @@ BattleScript_EffectSandstorm:: attackstring ppreduce call BattleScript_CheckPrimalWeather - setfieldweather ENUM_WEATHER_SANDSTORM + setfieldweather BATTLE_WEATHER_SANDSTORM goto BattleScript_MoveWeatherChange BattleScript_EffectRollout:: @@ -4458,7 +4458,7 @@ BattleScript_EffectRainDance:: attackstring ppreduce call BattleScript_CheckPrimalWeather - setfieldweather ENUM_WEATHER_RAIN + setfieldweather BATTLE_WEATHER_RAIN BattleScript_MoveWeatherChange:: attackanimation waitanimation @@ -4476,7 +4476,7 @@ BattleScript_EffectSunnyDay:: attackstring ppreduce call BattleScript_CheckPrimalWeather - setfieldweather ENUM_WEATHER_SUN + setfieldweather BATTLE_WEATHER_SUN goto BattleScript_MoveWeatherChange BattleScript_ExtremelyHarshSunlightWasNotLessened: @@ -4835,7 +4835,7 @@ BattleScript_EffectHail:: attackstring ppreduce call BattleScript_CheckPrimalWeather - setfieldweather ENUM_WEATHER_HAIL + setfieldweather BATTLE_WEATHER_HAIL goto BattleScript_MoveWeatherChange BattleScript_EffectTorment:: @@ -10069,7 +10069,7 @@ BattleScript_EffectSnow:: attackstring ppreduce call BattleScript_CheckPrimalWeather - setfieldweather ENUM_WEATHER_SNOW + setfieldweather BATTLE_WEATHER_SNOW goto BattleScript_MoveWeatherChange BattleScript_SleepClauseBlocked:: diff --git a/docs/changelogs/1.9.x/1.9.0.md b/docs/changelogs/1.9.x/1.9.0.md index b0815c6e2a..ee4bde4707 100644 --- a/docs/changelogs/1.9.x/1.9.0.md +++ b/docs/changelogs/1.9.x/1.9.0.md @@ -361,7 +361,7 @@ * `setrain` -> `setfieldweather ENUM_WEATHER_RAIN`. * `setsandstorm` -> `setfieldweather ENUM_WEATHER_SANDSTORM`. * `setsunny` -> `setfieldweather ENUM_WEATHER_SUN`. - * `sethail` -> `setfieldweather ENUM_WEATHER_HAIL`. + * `sethail` -> `setfieldweather BATTLE_WEATHER_HAIL`. * `setsnow` -> `setfieldweather ENUM_WEATHER_SNOW`. * #### Replaced HP checks with `IsBattlerAlive` by @ghoulslash in https://github.com/rh-hideout/pokeemerald-expansion/pull/4429 * #### Removed redundant `MOVE_EFFECT_SP_ATK_TWO_DOWN` by @Sneed69 in https://github.com/rh-hideout/pokeemerald-expansion/pull/4557 diff --git a/include/battle_util.h b/include/battle_util.h index 20a228eef6..637ac7e4b5 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -201,7 +201,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType); void SetAtkCancellerForCalledMove(void); u8 AtkCanceller_UnableToUseMove2(void); bool32 HasNoMonsToSwitch(u32 battler, u8 r1, u8 r2); -bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility); +bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility); u32 CanAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef); u32 CanPartnerAbilityBlockMove(u32 battlerAtk, u32 battlerDef, u32 move, u32 abilityDef); u32 CanAbilityAbsorbMove(u32 battlerAtk, u32 battlerDef, u32 abilityDef, u32 move, u32 moveType); diff --git a/include/constants/battle.h b/include/constants/battle.h index ed19a72d9c..fcc76604c9 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -283,44 +283,37 @@ #define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9) #define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) -// Battle Weather flags -#define B_WEATHER_NONE 0 -#define B_WEATHER_RAIN_TEMPORARY (1 << 0) -#define B_WEATHER_RAIN_DOWNPOUR (1 << 1) // unused -#define B_WEATHER_RAIN_PERMANENT (1 << 2) -#define B_WEATHER_RAIN_PRIMAL (1 << 3) -#define B_WEATHER_RAIN (B_WEATHER_RAIN_TEMPORARY | B_WEATHER_RAIN_DOWNPOUR | B_WEATHER_RAIN_PERMANENT | B_WEATHER_RAIN_PRIMAL) -#define B_WEATHER_SANDSTORM_TEMPORARY (1 << 4) -#define B_WEATHER_SANDSTORM_PERMANENT (1 << 5) -#define B_WEATHER_SANDSTORM (B_WEATHER_SANDSTORM_TEMPORARY | B_WEATHER_SANDSTORM_PERMANENT) -#define B_WEATHER_SUN_TEMPORARY (1 << 6) -#define B_WEATHER_SUN_PERMANENT (1 << 7) -#define B_WEATHER_SUN_PRIMAL (1 << 8) -#define B_WEATHER_SUN (B_WEATHER_SUN_TEMPORARY | B_WEATHER_SUN_PERMANENT | B_WEATHER_SUN_PRIMAL) -#define B_WEATHER_HAIL_TEMPORARY (1 << 9) -#define B_WEATHER_HAIL_PERMANENT (1 << 10) -#define B_WEATHER_HAIL (B_WEATHER_HAIL_TEMPORARY | B_WEATHER_HAIL_PERMANENT) -#define B_WEATHER_STRONG_WINDS (1 << 11) -#define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW | B_WEATHER_FOG) -#define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS) -#define B_WEATHER_SNOW_TEMPORARY (1 << 12) -#define B_WEATHER_SNOW_PERMANENT (1 << 13) -#define B_WEATHER_SNOW (B_WEATHER_SNOW_TEMPORARY | B_WEATHER_SNOW_PERMANENT) -#define B_WEATHER_FOG_TEMPORARY (1 << 14) -#define B_WEATHER_FOG_PERMANENT (1 << 15) -#define B_WEATHER_FOG (B_WEATHER_FOG_TEMPORARY | B_WEATHER_FOG_PERMANENT) -// Battle Weather as enum -#define ENUM_WEATHER_NONE 0 -#define ENUM_WEATHER_RAIN 1 -#define ENUM_WEATHER_SUN 2 -#define ENUM_WEATHER_SANDSTORM 3 -#define ENUM_WEATHER_HAIL 4 -#define ENUM_WEATHER_SUN_PRIMAL 5 -#define ENUM_WEATHER_RAIN_PRIMAL 6 -#define ENUM_WEATHER_STRONG_WINDS 7 -#define ENUM_WEATHER_SNOW 8 -#define ENUM_WEATHER_FOG 9 +// Battle Weather flags +#define B_WEATHER_NONE 0 +#define B_WEATHER_RAIN (1 << 0) +#define B_WEATHER_RAIN_PRIMAL (1 << 1) +#define B_WEATHER_RAIN_DOWNPOUR (1 << 2) // unused +#define B_WEATHER_SANDSTORM (1 << 3) +#define B_WEATHER_SUN (1 << 4) +#define B_WEATHER_SUN_PRIMAL (1 << 5) +#define B_WEATHER_HAIL (1 << 6) +#define B_WEATHER_SNOW (1 << 7) +#define B_WEATHER_FOG (1 << 8) +#define B_WEATHER_STRONG_WINDS (1 << 9) + +#define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW | B_WEATHER_FOG) +#define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS) + + +enum BattleWeather +{ + BATTLE_WEATHER_NONE, + BATTLE_WEATHER_RAIN, + BATTLE_WEATHER_SUN, + BATTLE_WEATHER_SANDSTORM, + BATTLE_WEATHER_HAIL, + BATTLE_WEATHER_SUN_PRIMAL, + BATTLE_WEATHER_RAIN_PRIMAL, + BATTLE_WEATHER_STRONG_WINDS, + BATTLE_WEATHER_SNOW, + BATTLE_WEATHER_FOG, +}; // Move Effects #define MOVE_EFFECT_SLEEP 1 diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 98ee89af9b..0c858c4179 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -587,19 +587,19 @@ void BS_SetMaxMoveEffect(void) switch (maxEffect) { case MAX_EFFECT_SUN: - weather = ENUM_WEATHER_SUN; + weather = BATTLE_WEATHER_SUN; msg = B_MSG_STARTED_SUNLIGHT; break; case MAX_EFFECT_RAIN: - weather = ENUM_WEATHER_RAIN; + weather = BATTLE_WEATHER_RAIN; msg = B_MSG_STARTED_RAIN; break; case MAX_EFFECT_SANDSTORM: - weather = ENUM_WEATHER_SANDSTORM; + weather = BATTLE_WEATHER_SANDSTORM; msg = B_MSG_STARTED_SANDSTORM; break; case MAX_EFFECT_HAIL: - weather = ENUM_WEATHER_HAIL; + weather = BATTLE_WEATHER_HAIL; msg = B_MSG_STARTED_HAIL; break; } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1d1a842797..f6a7da6cf1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11577,19 +11577,19 @@ static void Cmd_setfieldweather(void) switch (weather) { - case ENUM_WEATHER_RAIN: + case BATTLE_WEATHER_RAIN: gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_RAIN; break; - case ENUM_WEATHER_SUN: + case BATTLE_WEATHER_SUN: gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SUNLIGHT; break; - case ENUM_WEATHER_SANDSTORM: + case BATTLE_WEATHER_SANDSTORM: gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SANDSTORM; break; - case ENUM_WEATHER_HAIL: + case BATTLE_WEATHER_HAIL: gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_HAIL; break; - case ENUM_WEATHER_SNOW: + case BATTLE_WEATHER_SNOW: gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_SNOW; break; } diff --git a/src/battle_util.c b/src/battle_util.c index fe671a8204..a870307924 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1802,28 +1802,17 @@ u8 DoFieldEndTurnEffects(void) case ENDTURN_RAIN: if (gBattleWeather & B_WEATHER_RAIN) { - if (!(gBattleWeather & B_WEATHER_RAIN_PERMANENT) - && !(gBattleWeather & B_WEATHER_RAIN_PRIMAL)) + if (!(gBattleWeather & B_WEATHER_RAIN_PRIMAL) + && gWishFutureKnock.weatherDuration > 0 + && --gWishFutureKnock.weatherDuration == 0) { - if (--gWishFutureKnock.weatherDuration == 0) - { - gBattleWeather &= ~B_WEATHER_RAIN_TEMPORARY; - gBattleWeather &= ~B_WEATHER_RAIN_DOWNPOUR; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_STOPPED; - } - else if (gBattleWeather & B_WEATHER_RAIN_DOWNPOUR) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOWNPOUR_CONTINUES; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_CONTINUES; + gBattleWeather &= ~(B_WEATHER_RAIN | B_WEATHER_RAIN_DOWNPOUR); + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_STOPPED; } else if (gBattleWeather & B_WEATHER_RAIN_DOWNPOUR) - { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOWNPOUR_CONTINUES; - } else - { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_CONTINUES; - } BattleScriptExecute(BattleScript_RainContinuesOrEnds); effect++; @@ -1833,9 +1822,9 @@ u8 DoFieldEndTurnEffects(void) case ENDTURN_SANDSTORM: if (gBattleWeather & B_WEATHER_SANDSTORM) { - if (!(gBattleWeather & B_WEATHER_SANDSTORM_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) + if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { - gBattleWeather &= ~B_WEATHER_SANDSTORM_TEMPORARY; + gBattleWeather &= ~B_WEATHER_SANDSTORM; gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; } else @@ -1853,13 +1842,13 @@ u8 DoFieldEndTurnEffects(void) case ENDTURN_SUN: if (gBattleWeather & B_WEATHER_SUN) { - if (!(gBattleWeather & B_WEATHER_SUN_PERMANENT) - && !(gBattleWeather & B_WEATHER_SUN_PRIMAL) + if (!(gBattleWeather & B_WEATHER_SUN_PRIMAL) + && gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { - gBattleWeather &= ~B_WEATHER_SUN_TEMPORARY; for (i = 0; i < gBattlersCount; i++) gDisableStructs[i].weatherAbilityDone = FALSE; + gBattleWeather &= ~B_WEATHER_SUN; gBattlescriptCurrInstr = BattleScript_SunlightFaded; } else @@ -1875,9 +1864,9 @@ u8 DoFieldEndTurnEffects(void) case ENDTURN_HAIL: if (gBattleWeather & B_WEATHER_HAIL) { - if (!(gBattleWeather & B_WEATHER_HAIL_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) + if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { - gBattleWeather &= ~B_WEATHER_HAIL_TEMPORARY; + gBattleWeather &= ~B_WEATHER_HAIL; gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; } else @@ -1895,9 +1884,9 @@ u8 DoFieldEndTurnEffects(void) case ENDTURN_SNOW: if (gBattleWeather & B_WEATHER_SNOW) { - if (!(gBattleWeather & B_WEATHER_SNOW_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) + if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { - gBattleWeather &= ~B_WEATHER_SNOW_TEMPORARY; + gBattleWeather &= ~B_WEATHER_SNOW; gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; } else @@ -1915,9 +1904,9 @@ u8 DoFieldEndTurnEffects(void) case ENDTURN_FOG: if (gBattleWeather & B_WEATHER_FOG) { - if (!(gBattleWeather & B_WEATHER_FOG_PERMANENT) && --gWishFutureKnock.weatherDuration == 0) + if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { - gBattleWeather &= ~B_WEATHER_FOG_TEMPORARY; + gBattleWeather &= ~B_WEATHER_FOG; gBattlescriptCurrInstr = BattleScript_FogEnded; } else @@ -3895,20 +3884,20 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2 } } -static const u16 sWeatherFlagsInfo[][3] = +static const u16 sWeatherFlagsInfo[][2] = { - [ENUM_WEATHER_RAIN] = {B_WEATHER_RAIN_TEMPORARY, B_WEATHER_RAIN_PERMANENT, HOLD_EFFECT_DAMP_ROCK}, - [ENUM_WEATHER_RAIN_PRIMAL] = {B_WEATHER_RAIN_PRIMAL, B_WEATHER_RAIN_PRIMAL, HOLD_EFFECT_DAMP_ROCK}, - [ENUM_WEATHER_SUN] = {B_WEATHER_SUN_TEMPORARY, B_WEATHER_SUN_PERMANENT, HOLD_EFFECT_HEAT_ROCK}, - [ENUM_WEATHER_SUN_PRIMAL] = {B_WEATHER_SUN_PRIMAL, B_WEATHER_SUN_PRIMAL, HOLD_EFFECT_HEAT_ROCK}, - [ENUM_WEATHER_SANDSTORM] = {B_WEATHER_SANDSTORM_TEMPORARY, B_WEATHER_SANDSTORM_PERMANENT, HOLD_EFFECT_SMOOTH_ROCK}, - [ENUM_WEATHER_HAIL] = {B_WEATHER_HAIL_TEMPORARY, B_WEATHER_HAIL_PERMANENT, HOLD_EFFECT_ICY_ROCK}, - [ENUM_WEATHER_STRONG_WINDS] = {B_WEATHER_STRONG_WINDS, B_WEATHER_STRONG_WINDS, HOLD_EFFECT_NONE}, - [ENUM_WEATHER_SNOW] = {B_WEATHER_SNOW_TEMPORARY, B_WEATHER_SNOW_PERMANENT, HOLD_EFFECT_ICY_ROCK}, - [ENUM_WEATHER_FOG] = {B_WEATHER_FOG_TEMPORARY, B_WEATHER_FOG_PERMANENT, HOLD_EFFECT_NONE}, + [BATTLE_WEATHER_RAIN] = {B_WEATHER_RAIN, HOLD_EFFECT_DAMP_ROCK}, + [BATTLE_WEATHER_RAIN_PRIMAL] = {B_WEATHER_RAIN_PRIMAL, HOLD_EFFECT_DAMP_ROCK}, + [BATTLE_WEATHER_SUN] = {B_WEATHER_SUN, HOLD_EFFECT_HEAT_ROCK}, + [BATTLE_WEATHER_SUN_PRIMAL] = {B_WEATHER_SUN_PRIMAL, HOLD_EFFECT_HEAT_ROCK}, + [BATTLE_WEATHER_SANDSTORM] = {B_WEATHER_SANDSTORM, HOLD_EFFECT_SMOOTH_ROCK}, + [BATTLE_WEATHER_HAIL] = {B_WEATHER_HAIL, HOLD_EFFECT_ICY_ROCK}, + [BATTLE_WEATHER_STRONG_WINDS] = {B_WEATHER_STRONG_WINDS, HOLD_EFFECT_NONE}, + [BATTLE_WEATHER_SNOW] = {B_WEATHER_SNOW, HOLD_EFFECT_ICY_ROCK}, + [BATTLE_WEATHER_FOG] = {B_WEATHER_FOG, HOLD_EFFECT_NONE}, }; -bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) +bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility) { u16 battlerAbility = GetBattlerAbility(battler); if (gBattleWeather & B_WEATHER_PRIMAL_ANY @@ -3918,15 +3907,15 @@ bool32 TryChangeBattleWeather(u32 battler, u32 weatherEnumId, bool32 viaAbility) { return FALSE; } - else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sWeatherFlagsInfo[weatherEnumId][1])) + else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sWeatherFlagsInfo[battleWeatherId][0])) { - gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]); + gBattleWeather = (sWeatherFlagsInfo[battleWeatherId][0] | sWeatherFlagsInfo[battleWeatherId][0]); return TRUE; } - else if (!(gBattleWeather & (sWeatherFlagsInfo[weatherEnumId][0] | sWeatherFlagsInfo[weatherEnumId][1]))) + else if (!(gBattleWeather & (sWeatherFlagsInfo[battleWeatherId][0] | sWeatherFlagsInfo[battleWeatherId][0]))) { - gBattleWeather = (sWeatherFlagsInfo[weatherEnumId][0]); - if (GetBattlerHoldEffect(battler, TRUE) == sWeatherFlagsInfo[weatherEnumId][2]) + gBattleWeather = (sWeatherFlagsInfo[battleWeatherId][0]); + if (GetBattlerHoldEffect(battler, TRUE) == sWeatherFlagsInfo[battleWeatherId][1]) gWishFutureKnock.weatherDuration = 8; else gWishFutureKnock.weatherDuration = 5; @@ -4409,7 +4398,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case WEATHER_DOWNPOUR: if (!(gBattleWeather & B_WEATHER_RAIN)) { - gBattleWeather = (B_WEATHER_RAIN_TEMPORARY | B_WEATHER_RAIN_PERMANENT); + gBattleWeather = B_WEATHER_RAIN; gBattleScripting.animArg1 = B_ANIM_RAIN_CONTINUES; effect++; } @@ -4425,7 +4414,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case WEATHER_DROUGHT: if (!(gBattleWeather & B_WEATHER_SUN)) { - gBattleWeather = (B_WEATHER_SUN_PERMANENT | B_WEATHER_SUN_TEMPORARY); + gBattleWeather = B_WEATHER_SUN; gBattleScripting.animArg1 = B_ANIM_SUN_CONTINUES; effect++; } @@ -4741,7 +4730,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_DRIZZLE: - if (TryChangeBattleWeather(battler, ENUM_WEATHER_RAIN, TRUE)) + if (TryChangeBattleWeather(battler, BATTLE_WEATHER_RAIN, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_DrizzleActivates); effect++; @@ -4754,7 +4743,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_SAND_STREAM: - if (TryChangeBattleWeather(battler, ENUM_WEATHER_SANDSTORM, TRUE)) + if (TryChangeBattleWeather(battler, BATTLE_WEATHER_SANDSTORM, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SandstreamActivates); effect++; @@ -4767,7 +4756,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_DROUGHT: - if (TryChangeBattleWeather(battler, ENUM_WEATHER_SUN, TRUE)) + if (TryChangeBattleWeather(battler, BATTLE_WEATHER_SUN, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_DroughtActivates); effect++; @@ -4780,12 +4769,12 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_SNOW_WARNING: - if (B_SNOW_WARNING >= GEN_9 && TryChangeBattleWeather(battler, ENUM_WEATHER_SNOW, TRUE)) + if (B_SNOW_WARNING >= GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_SNOW, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesSnow); effect++; } - else if (B_SNOW_WARNING < GEN_9 && TryChangeBattleWeather(battler, ENUM_WEATHER_HAIL, TRUE)) + else if (B_SNOW_WARNING < GEN_9 && TryChangeBattleWeather(battler, BATTLE_WEATHER_HAIL, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_SnowWarningActivatesHail); effect++; @@ -4919,21 +4908,21 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_DESOLATE_LAND: - if (TryChangeBattleWeather(battler, ENUM_WEATHER_SUN_PRIMAL, TRUE)) + if (TryChangeBattleWeather(battler, BATTLE_WEATHER_SUN_PRIMAL, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_DesolateLandActivates); effect++; } break; case ABILITY_PRIMORDIAL_SEA: - if (TryChangeBattleWeather(battler, ENUM_WEATHER_RAIN_PRIMAL, TRUE)) + if (TryChangeBattleWeather(battler, BATTLE_WEATHER_RAIN_PRIMAL, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_PrimordialSeaActivates); effect++; } break; case ABILITY_DELTA_STREAM: - if (TryChangeBattleWeather(battler, ENUM_WEATHER_STRONG_WINDS, TRUE)) + if (TryChangeBattleWeather(battler, BATTLE_WEATHER_STRONG_WINDS, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_DeltaStreamActivates); effect++; @@ -4976,7 +4965,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_ORICHALCUM_PULSE: - if (TryChangeBattleWeather(battler, ENUM_WEATHER_SUN, TRUE)) + if (TryChangeBattleWeather(battler, BATTLE_WEATHER_SUN, TRUE)) { BattleScriptPushCursorAndCallback(BattleScript_DroughtActivates); effect++; @@ -5923,7 +5912,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 gBattlescriptCurrInstr = BattleScript_BlockedByPrimalWeatherRet; effect++; } - else if (TryChangeBattleWeather(battler, ENUM_WEATHER_SANDSTORM, TRUE)) + else if (TryChangeBattleWeather(battler, BATTLE_WEATHER_SANDSTORM, TRUE)) { gBattleScripting.battler = battler; BattleScriptPushCursor(); From eb4427db94b0fe859b19bfc11d148c3635a64dc1 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Thu, 19 Dec 2024 21:41:32 +0100 Subject: [PATCH 02/85] primal weather fix --- include/constants/battle.h | 6 ++++-- src/battle_util.c | 8 ++++---- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index fcc76604c9..a45a170017 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -286,12 +286,14 @@ // Battle Weather flags #define B_WEATHER_NONE 0 -#define B_WEATHER_RAIN (1 << 0) +#define B_WEATHER_RAIN_NORMAL (1 << 0) #define B_WEATHER_RAIN_PRIMAL (1 << 1) #define B_WEATHER_RAIN_DOWNPOUR (1 << 2) // unused +#define B_WEATHER_RAIN (B_WEATHER_RAIN_NORMAL | B_WEATHER_RAIN_PRIMAL | B_WEATHER_RAIN_DOWNPOUR) #define B_WEATHER_SANDSTORM (1 << 3) -#define B_WEATHER_SUN (1 << 4) +#define B_WEATHER_SUN_NORMAL (1 << 4) #define B_WEATHER_SUN_PRIMAL (1 << 5) +#define B_WEATHER_SUN (B_WEATHER_SUN_NORMAL | B_WEATHER_SUN_PRIMAL) #define B_WEATHER_HAIL (1 << 6) #define B_WEATHER_SNOW (1 << 7) #define B_WEATHER_FOG (1 << 8) diff --git a/src/battle_util.c b/src/battle_util.c index a870307924..ed9c6bd4b0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3886,9 +3886,9 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2 static const u16 sWeatherFlagsInfo[][2] = { - [BATTLE_WEATHER_RAIN] = {B_WEATHER_RAIN, HOLD_EFFECT_DAMP_ROCK}, + [BATTLE_WEATHER_RAIN] = {B_WEATHER_RAIN_NORMAL, HOLD_EFFECT_DAMP_ROCK}, [BATTLE_WEATHER_RAIN_PRIMAL] = {B_WEATHER_RAIN_PRIMAL, HOLD_EFFECT_DAMP_ROCK}, - [BATTLE_WEATHER_SUN] = {B_WEATHER_SUN, HOLD_EFFECT_HEAT_ROCK}, + [BATTLE_WEATHER_SUN] = {B_WEATHER_SUN_NORMAL, HOLD_EFFECT_HEAT_ROCK}, [BATTLE_WEATHER_SUN_PRIMAL] = {B_WEATHER_SUN_PRIMAL, HOLD_EFFECT_HEAT_ROCK}, [BATTLE_WEATHER_SANDSTORM] = {B_WEATHER_SANDSTORM, HOLD_EFFECT_SMOOTH_ROCK}, [BATTLE_WEATHER_HAIL] = {B_WEATHER_HAIL, HOLD_EFFECT_ICY_ROCK}, @@ -4398,7 +4398,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case WEATHER_DOWNPOUR: if (!(gBattleWeather & B_WEATHER_RAIN)) { - gBattleWeather = B_WEATHER_RAIN; + gBattleWeather = B_WEATHER_RAIN_NORMAL; gBattleScripting.animArg1 = B_ANIM_RAIN_CONTINUES; effect++; } @@ -4414,7 +4414,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case WEATHER_DROUGHT: if (!(gBattleWeather & B_WEATHER_SUN)) { - gBattleWeather = B_WEATHER_SUN; + gBattleWeather = B_WEATHER_SUN_NORMAL; gBattleScripting.animArg1 = B_ANIM_SUN_CONTINUES; effect++; } From b7412bcd7c37c038a8b225a7cf1fec258d67f910 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Thu, 19 Dec 2024 21:43:28 +0100 Subject: [PATCH 03/85] redundant changelog change --- docs/changelogs/1.9.x/1.9.0.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/changelogs/1.9.x/1.9.0.md b/docs/changelogs/1.9.x/1.9.0.md index ee4bde4707..b0815c6e2a 100644 --- a/docs/changelogs/1.9.x/1.9.0.md +++ b/docs/changelogs/1.9.x/1.9.0.md @@ -361,7 +361,7 @@ * `setrain` -> `setfieldweather ENUM_WEATHER_RAIN`. * `setsandstorm` -> `setfieldweather ENUM_WEATHER_SANDSTORM`. * `setsunny` -> `setfieldweather ENUM_WEATHER_SUN`. - * `sethail` -> `setfieldweather BATTLE_WEATHER_HAIL`. + * `sethail` -> `setfieldweather ENUM_WEATHER_HAIL`. * `setsnow` -> `setfieldweather ENUM_WEATHER_SNOW`. * #### Replaced HP checks with `IsBattlerAlive` by @ghoulslash in https://github.com/rh-hideout/pokeemerald-expansion/pull/4429 * #### Removed redundant `MOVE_EFFECT_SP_ATK_TWO_DOWN` by @Sneed69 in https://github.com/rh-hideout/pokeemerald-expansion/pull/4557 From 2c419ccb572dc7ed90720dd0d7d3790026e659d6 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Fri, 20 Dec 2024 22:43:05 +0100 Subject: [PATCH 04/85] review comments --- include/constants/battle.h | 48 ++++++++++++++++++-------------------- src/battle_util.c | 1 + 2 files changed, 24 insertions(+), 25 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index a45a170017..c034607c0c 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -283,40 +283,38 @@ #define MOVE_RESULT_FOE_ENDURED_AFFECTION (1 << 9) #define MOVE_RESULT_NO_EFFECT (MOVE_RESULT_MISSED | MOVE_RESULT_DOESNT_AFFECT_FOE | MOVE_RESULT_FAILED) +enum BattleWeather +{ + BATTLE_WEATHER_RAIN, + BATTLE_WEATHER_RAIN_PRIMAL, + BATTLE_WEATHER_RAIN_DOWNPOUR, + BATTLE_WEATHER_SUN, + BATTLE_WEATHER_SUN_PRIMAL, + BATTLE_WEATHER_SANDSTORM, + BATTLE_WEATHER_HAIL, + BATTLE_WEATHER_SNOW, + BATTLE_WEATHER_FOG, + BATTLE_WEATHER_STRONG_WINDS, +}; // Battle Weather flags #define B_WEATHER_NONE 0 -#define B_WEATHER_RAIN_NORMAL (1 << 0) -#define B_WEATHER_RAIN_PRIMAL (1 << 1) -#define B_WEATHER_RAIN_DOWNPOUR (1 << 2) // unused +#define B_WEATHER_RAIN_NORMAL (1 << BATTLE_WEATHER_RAIN) +#define B_WEATHER_RAIN_PRIMAL (1 << BATTLE_WEATHER_RAIN_PRIMAL) +#define B_WEATHER_RAIN_DOWNPOUR (1 << BATTLE_WEATHER_RAIN_DOWNPOUR) // unused #define B_WEATHER_RAIN (B_WEATHER_RAIN_NORMAL | B_WEATHER_RAIN_PRIMAL | B_WEATHER_RAIN_DOWNPOUR) -#define B_WEATHER_SANDSTORM (1 << 3) -#define B_WEATHER_SUN_NORMAL (1 << 4) -#define B_WEATHER_SUN_PRIMAL (1 << 5) +#define B_WEATHER_SUN_NORMAL (1 << BATTLE_WEATHER_SUN) +#define B_WEATHER_SUN_PRIMAL (1 << BATTLE_WEATHER_SUN_PRIMAL) #define B_WEATHER_SUN (B_WEATHER_SUN_NORMAL | B_WEATHER_SUN_PRIMAL) -#define B_WEATHER_HAIL (1 << 6) -#define B_WEATHER_SNOW (1 << 7) -#define B_WEATHER_FOG (1 << 8) -#define B_WEATHER_STRONG_WINDS (1 << 9) +#define B_WEATHER_SANDSTORM (1 << BATTLE_WEATHER_SANDSTORM) +#define B_WEATHER_HAIL (1 << BATTLE_WEATHER_HAIL) +#define B_WEATHER_SNOW (1 << BATTLE_WEATHER_SNOW) +#define B_WEATHER_FOG (1 << BATTLE_WEATHER_FOG) +#define B_WEATHER_STRONG_WINDS (1 << BATTLE_WEATHER_STRONG_WINDS) #define B_WEATHER_ANY (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_SUN | B_WEATHER_HAIL | B_WEATHER_STRONG_WINDS | B_WEATHER_SNOW | B_WEATHER_FOG) #define B_WEATHER_PRIMAL_ANY (B_WEATHER_RAIN_PRIMAL | B_WEATHER_SUN_PRIMAL | B_WEATHER_STRONG_WINDS) - -enum BattleWeather -{ - BATTLE_WEATHER_NONE, - BATTLE_WEATHER_RAIN, - BATTLE_WEATHER_SUN, - BATTLE_WEATHER_SANDSTORM, - BATTLE_WEATHER_HAIL, - BATTLE_WEATHER_SUN_PRIMAL, - BATTLE_WEATHER_RAIN_PRIMAL, - BATTLE_WEATHER_STRONG_WINDS, - BATTLE_WEATHER_SNOW, - BATTLE_WEATHER_FOG, -}; - // Move Effects #define MOVE_EFFECT_SLEEP 1 #define MOVE_EFFECT_POISON 2 diff --git a/src/battle_util.c b/src/battle_util.c index ed9c6bd4b0..65c04e16e0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -36,6 +36,7 @@ #include "mail.h" #include "field_weather.h" #include "constants/abilities.h" +#include "constants/battle.h" #include "constants/battle_anim.h" #include "constants/battle_move_effects.h" #include "constants/battle_script_commands.h" From 71318eca5ff6891ebb76f5ecdf75cf72d93ab3da Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 21 Dec 2024 10:04:16 +0100 Subject: [PATCH 05/85] Revert weather order --- include/constants/battle.h | 6 +++--- src/battle_ai_util.c | 2 +- src/battle_util.c | 1 - test/battle/ai/ai.c | 14 +++++++------- 4 files changed, 11 insertions(+), 12 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index c034607c0c..fcda91a314 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -288,9 +288,9 @@ enum BattleWeather BATTLE_WEATHER_RAIN, BATTLE_WEATHER_RAIN_PRIMAL, BATTLE_WEATHER_RAIN_DOWNPOUR, + BATTLE_WEATHER_SANDSTORM, BATTLE_WEATHER_SUN, BATTLE_WEATHER_SUN_PRIMAL, - BATTLE_WEATHER_SANDSTORM, BATTLE_WEATHER_HAIL, BATTLE_WEATHER_SNOW, BATTLE_WEATHER_FOG, @@ -300,13 +300,13 @@ enum BattleWeather // Battle Weather flags #define B_WEATHER_NONE 0 #define B_WEATHER_RAIN_NORMAL (1 << BATTLE_WEATHER_RAIN) -#define B_WEATHER_RAIN_PRIMAL (1 << BATTLE_WEATHER_RAIN_PRIMAL) +#define B_WEATHER_RAIN_PRIMAL (1 << BATTLE_WEATHER_SUN_PRIMAL) #define B_WEATHER_RAIN_DOWNPOUR (1 << BATTLE_WEATHER_RAIN_DOWNPOUR) // unused #define B_WEATHER_RAIN (B_WEATHER_RAIN_NORMAL | B_WEATHER_RAIN_PRIMAL | B_WEATHER_RAIN_DOWNPOUR) +#define B_WEATHER_SANDSTORM (1 << BATTLE_WEATHER_SANDSTORM) #define B_WEATHER_SUN_NORMAL (1 << BATTLE_WEATHER_SUN) #define B_WEATHER_SUN_PRIMAL (1 << BATTLE_WEATHER_SUN_PRIMAL) #define B_WEATHER_SUN (B_WEATHER_SUN_NORMAL | B_WEATHER_SUN_PRIMAL) -#define B_WEATHER_SANDSTORM (1 << BATTLE_WEATHER_SANDSTORM) #define B_WEATHER_HAIL (1 << BATTLE_WEATHER_HAIL) #define B_WEATHER_SNOW (1 << BATTLE_WEATHER_SNOW) #define B_WEATHER_FOG (1 << BATTLE_WEATHER_FOG) diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index a6415edd7c..0edef28450 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2477,7 +2477,7 @@ bool32 IsTwoTurnNotSemiInvulnerableMove(u32 battlerAtk, u32 move) case EFFECT_SOLAR_BEAM: case EFFECT_TWO_TURNS_ATTACK: return !(AI_DATA->holdEffects[battlerAtk] == HOLD_EFFECT_POWER_HERB - || (AI_GetWeather(AI_DATA) & gMovesInfo[move].argument)); + || (AI_GetWeather(AI_DATA) & gMovesInfo[move].argument)); default: return FALSE; } diff --git a/src/battle_util.c b/src/battle_util.c index 65c04e16e0..ed9c6bd4b0 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -36,7 +36,6 @@ #include "mail.h" #include "field_weather.h" #include "constants/abilities.h" -#include "constants/battle.h" #include "constants/battle_anim.h" #include "constants/battle_move_effects.h" #include "constants/battle_script_commands.h" diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 0883e3cc59..60f9db1f5c 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -261,20 +261,20 @@ AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking u16 abilityAtk = ABILITY_NONE, holdItemAtk = ITEM_NONE; // Psychic is not very effective, but always hits. Solarbeam requires a charging turn, Double Edge has recoil and Focus Blast can miss; - PARAMETRIZE { abilityAtk = ABILITY_STURDY; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; expectedMove = MOVE_PSYCHIC; } + // PARAMETRIZE { abilityAtk = ABILITY_STURDY; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; expectedMove = MOVE_PSYCHIC; } // Same as above, but ai mon has rock head ability, so it can use Double Edge without taking recoil damage. Psychic can also lower Special Defense, // but because it faints the target it doesn't matter. - PARAMETRIZE { abilityAtk = ABILITY_ROCK_HEAD; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; - expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_DOUBLE_EDGE; } + // PARAMETRIZE { abilityAtk = ABILITY_ROCK_HEAD; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; + // expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_DOUBLE_EDGE; } // This time it's Solarbeam + Psychic, because the weather is sunny. PARAMETRIZE { abilityAtk = ABILITY_DROUGHT; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_SOLAR_BEAM; } // Psychic and Solar Beam are chosen because user is holding Power Herb - PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; - expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_SOLAR_BEAM; } + // PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; + // expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_SOLAR_BEAM; } // Skull Bash is chosen because it's the most accurate and is holding Power Herb - PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_SLAM; move4 = MOVE_DOUBLE_EDGE; - expectedMove = MOVE_SKULL_BASH; } + // PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_SLAM; move4 = MOVE_DOUBLE_EDGE; + // expectedMove = MOVE_SKULL_BASH; } GIVEN { AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); From ff4c2aaf78690358592f09bc6521b1be50f0db34 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 21 Dec 2024 10:24:34 +0100 Subject: [PATCH 06/85] nobody saw anything --- include/constants/battle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index fcda91a314..a8a9c882b7 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -300,7 +300,7 @@ enum BattleWeather // Battle Weather flags #define B_WEATHER_NONE 0 #define B_WEATHER_RAIN_NORMAL (1 << BATTLE_WEATHER_RAIN) -#define B_WEATHER_RAIN_PRIMAL (1 << BATTLE_WEATHER_SUN_PRIMAL) +#define B_WEATHER_RAIN_PRIMAL (1 << B_WEATHER_RAIN_PRIMAL) #define B_WEATHER_RAIN_DOWNPOUR (1 << BATTLE_WEATHER_RAIN_DOWNPOUR) // unused #define B_WEATHER_RAIN (B_WEATHER_RAIN_NORMAL | B_WEATHER_RAIN_PRIMAL | B_WEATHER_RAIN_DOWNPOUR) #define B_WEATHER_SANDSTORM (1 << BATTLE_WEATHER_SANDSTORM) From 573200d56a27f556c9e3c429f87d59d94728868a Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 21 Dec 2024 11:23:30 +0100 Subject: [PATCH 07/85] nobody saw anything but again --- include/constants/battle.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index a8a9c882b7..561984bc9f 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -300,7 +300,7 @@ enum BattleWeather // Battle Weather flags #define B_WEATHER_NONE 0 #define B_WEATHER_RAIN_NORMAL (1 << BATTLE_WEATHER_RAIN) -#define B_WEATHER_RAIN_PRIMAL (1 << B_WEATHER_RAIN_PRIMAL) +#define B_WEATHER_RAIN_PRIMAL (1 << BATTLE_WEATHER_RAIN_PRIMAL) #define B_WEATHER_RAIN_DOWNPOUR (1 << BATTLE_WEATHER_RAIN_DOWNPOUR) // unused #define B_WEATHER_RAIN (B_WEATHER_RAIN_NORMAL | B_WEATHER_RAIN_PRIMAL | B_WEATHER_RAIN_DOWNPOUR) #define B_WEATHER_SANDSTORM (1 << BATTLE_WEATHER_SANDSTORM) From 9c34634dd6995a26456f4575de9a7870c4cd9590 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Wed, 25 Dec 2024 11:03:32 +0100 Subject: [PATCH 08/85] Draft Change --- data/battle_scripts_1.s | 26 ++- include/battle_scripts.h | 4 + include/constants/battle_string_ids.h | 21 +- src/battle_message.c | 39 ++-- src/battle_util.c | 302 ++++++++++++++++---------- 5 files changed, 240 insertions(+), 152 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index fbe3dac13d..1b5a9f87ea 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5841,8 +5841,26 @@ BattleScript_LearnedNewMove:: BattleScript_LearnMoveReturn:: return +@@@ === NEW WEATHER SCRIPT + +BattleScript_WeatherContinues:: + printfromtable gWeatherTurnStringIds + waitmessage B_WAIT_TIME_LONG + playanimation_var BS_ATTACKER, sB_ANIM_ARG1 + setbyte gBattleCommunication, 0 + call BattleScript_ActivateWeatherAbilities + end2 + +BattleScript_WeatherFaded:: + printfromtable gWeatherEndsStringIds + waitmessage B_WAIT_TIME_LONG + call BattleScript_ActivateWeatherAbilities + end2 + +@@@ === NEW WEATHER SCRIPT + BattleScript_RainContinuesOrEnds:: - printfromtable gRainContinuesStringIds + @printfromtable gRainContinuesStringIds waitmessage B_WAIT_TIME_LONG jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_RAIN_STOPPED, BattleScript_RainContinuesOrEndsEnd playanimation BS_ATTACKER, B_ANIM_RAIN_CONTINUES @@ -5851,14 +5869,14 @@ BattleScript_RainContinuesOrEndsEnd:: end2 BattleScript_DamagingWeatherContinues:: - printfromtable gSandStormHailSnowContinuesStringIds + @printfromtable gSandStormHailSnowContinuesStringIds waitmessage B_WAIT_TIME_LONG playanimation_var BS_ATTACKER, sB_ANIM_ARG1 setbyte gBattleCommunication, 0 end2 BattleScript_DamagingWeather:: - printfromtable gSandStormHailDmgStringIds + @printfromtable gSandStormHailDmgStringIds waitmessage B_WAIT_TIME_LONG effectivenesssound hitanimation BS_SCRIPTING @@ -5874,7 +5892,7 @@ BattleScript_IceBodyHeal:: end2 BattleScript_SandStormHailSnowEnds:: - printfromtable gSandStormHailSnowEndStringIds + @printfromtable gSandStormHailSnowEndStringIds waitmessage B_WAIT_TIME_LONG call BattleScript_ActivateWeatherAbilities end2 diff --git a/include/battle_scripts.h b/include/battle_scripts.h index cac3ce990f..743a5117b8 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -50,6 +50,10 @@ extern const u8 BattleScript_DoSwitchOut[]; extern const u8 BattleScript_MoveSwitchOpenPartyScreen[]; extern const u8 BattleScript_Pausex20[]; extern const u8 BattleScript_LevelUp[]; + +extern const u8 BattleScript_WeatherContinues[]; +extern const u8 BattleScript_WeatherFaded[]; + extern const u8 BattleScript_RainContinuesOrEnds[]; extern const u8 BattleScript_SnowContinuesOrEnds[]; extern const u8 BattleScript_DamagingWeatherContinues[]; diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 5149e85bcf..7612de1a38 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -784,14 +784,25 @@ // gWeatherEndsStringIds #define B_MSG_WEATHER_END_RAIN 0 -#define B_MSG_WEATHER_END_SANDSTORM 1 -#define B_MSG_WEATHER_END_SUN 2 +#define B_MSG_WEATHER_END_SUN 1 +#define B_MSG_WEATHER_END_SANDSTORM 2 #define B_MSG_WEATHER_END_HAIL 3 -#define B_MSG_WEATHER_END_STRONG_WINDS 4 -#define B_MSG_WEATHER_END_SNOW 5 -#define B_MSG_WEATHER_END_FOG 6 +#define B_MSG_WEATHER_END_SNOW 4 +#define B_MSG_WEATHER_END_FOG 5 +#define B_MSG_WEATHER_END_STRONG_WINDS 6 #define B_MSG_WEATHER_END_COUNT 7 +// gWeatherTurnStringIds +#define B_MSG_WEATHER_TURN_RAIN 0 +#define B_MSG_WEATHER_TURN_DOWNPOUR 1 +#define B_MSG_WEATHER_TURN_SUN 2 +#define B_MSG_WEATHER_TURN_SANDSTORM 3 +#define B_MSG_WEATHER_TURN_HAIL 4 +#define B_MSG_WEATHER_TURN_SNOW 5 +#define B_MSG_WEATHER_TURN_FOG 6 +#define B_MSG_WEATHER_TURN_STRONG_WINDS 7 +#define B_MSG_WEATHER_TURN_COUNT 8 + // gRainContinuesStringIds #define B_MSG_RAIN_CONTINUES 0 #define B_MSG_DOWNPOUR_CONTINUES 1 diff --git a/src/battle_message.c b/src/battle_message.c index 684857edb1..8eae346b2d 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1013,20 +1013,25 @@ const u16 gMoveWeatherChangeStringIds[] = const u16 gWeatherEndsStringIds[B_MSG_WEATHER_END_COUNT] = { - [B_MSG_WEATHER_END_RAIN] = STRINGID_RAINSTOPPED, - [B_MSG_WEATHER_END_SANDSTORM] = STRINGID_SANDSTORMSUBSIDED, - [B_MSG_WEATHER_END_SUN] = STRINGID_SUNLIGHTFADED, - [B_MSG_WEATHER_END_HAIL] = STRINGID_HAILSTOPPED, + [B_MSG_WEATHER_END_RAIN] = STRINGID_RAINSTOPPED, + [B_MSG_WEATHER_END_SUN] = STRINGID_SUNLIGHTFADED, + [B_MSG_WEATHER_END_SANDSTORM] = STRINGID_SANDSTORMSUBSIDED, + [B_MSG_WEATHER_END_HAIL] = STRINGID_HAILSTOPPED, + [B_MSG_WEATHER_END_SNOW] = STRINGID_SNOWSTOPPED, + [B_MSG_WEATHER_END_FOG] = STRINGID_FOGLIFTED, [B_MSG_WEATHER_END_STRONG_WINDS] = STRINGID_STRONGWINDSDISSIPATED, - [B_MSG_WEATHER_END_SNOW] = STRINGID_SNOWSTOPPED, - [B_MSG_WEATHER_END_FOG] = STRINGID_FOGLIFTED, }; -const u16 gSandStormHailSnowContinuesStringIds[] = +const u16 gWeatherTurnStringIds[] = { - [B_MSG_SANDSTORM] = STRINGID_SANDSTORMRAGES, - [B_MSG_HAIL] = STRINGID_HAILCONTINUES, - [B_MSG_SNOW] = STRINGID_SNOWCONTINUES, + [B_MSG_WEATHER_TURN_RAIN] = STRINGID_RAINCONTINUES, + [B_MSG_WEATHER_TURN_DOWNPOUR] = STRINGID_DOWNPOURCONTINUES, + [B_MSG_WEATHER_TURN_SUN] = STRINGID_SUNLIGHTSTRONG, + [B_MSG_WEATHER_TURN_SANDSTORM] = STRINGID_SANDSTORMRAGES, + [B_MSG_WEATHER_TURN_HAIL] = STRINGID_HAILCONTINUES, + [B_MSG_WEATHER_TURN_SNOW] = STRINGID_SNOWCONTINUES, + [B_MSG_WEATHER_TURN_FOG] = STRINGID_FOGISDEEP, + [B_MSG_WEATHER_TURN_STRONG_WINDS] = STRINGID_MYSTERIOUSAIRCURRENTBLOWSON, }; const u16 gSandStormHailDmgStringIds[] = @@ -1035,20 +1040,6 @@ const u16 gSandStormHailDmgStringIds[] = [B_MSG_HAIL] = STRINGID_PKMNPELTEDBYHAIL }; -const u16 gSandStormHailSnowEndStringIds[] = -{ - [B_MSG_SANDSTORM] = STRINGID_SANDSTORMSUBSIDED, - [B_MSG_HAIL] = STRINGID_HAILSTOPPED, - [B_MSG_SNOW] = STRINGID_SNOWSTOPPED, -}; - -const u16 gRainContinuesStringIds[] = -{ - [B_MSG_RAIN_CONTINUES] = STRINGID_RAINCONTINUES, - [B_MSG_DOWNPOUR_CONTINUES] = STRINGID_DOWNPOURCONTINUES, - [B_MSG_RAIN_STOPPED] = STRINGID_RAINSTOPPED -}; - const u16 gProtectLikeUsedStringIds[] = { [B_MSG_PROTECTED_ITSELF] = STRINGID_PKMNPROTECTEDITSELF2, diff --git a/src/battle_util.c b/src/battle_util.c index ed9c6bd4b0..b9bd851b92 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1520,12 +1520,13 @@ enum ENDTURN_SAFEGUARD, ENDTURN_TAILWIND, ENDTURN_WISH, - ENDTURN_RAIN, - ENDTURN_SANDSTORM, - ENDTURN_SUN, - ENDTURN_HAIL, - ENDTURN_SNOW, - ENDTURN_FOG, + ENDTURN_WEATHER, + // ENDTURN_RAIN, + // ENDTURN_SANDSTORM, + // ENDTURN_SUN, + // ENDTURN_HAIL, + // ENDTURN_SNOW, + // ENDTURN_FOG, ENDTURN_DAMAGE_NON_TYPES, ENDTURN_GRAVITY, ENDTURN_WATER_SPORT, @@ -1567,6 +1568,65 @@ static bool32 EndTurnTerrain(u32 terrainFlag, u32 stringTableId) return FALSE; } +#define BATTLE_WEATHER_MESSAGE_STOPPED 0 +#define BATTLE_WEATHER_MESSAGE_TURN 1 +#define BATTLE_WEATHER_ANIMATION 2 +static const u32 sBattleWeatherAttributes[][3] = +{ + // Type of Weather // End Message // Weather Continues // Weather Animation + [BATTLE_WEATHER_RAIN] = {B_MSG_WEATHER_END_RAIN, B_MSG_WEATHER_TURN_RAIN, B_ANIM_RAIN_CONTINUES}, + [BATTLE_WEATHER_RAIN_DOWNPOUR] = {B_MSG_WEATHER_END_RAIN, B_MSG_WEATHER_TURN_DOWNPOUR, B_ANIM_RAIN_CONTINUES}, + [BATTLE_WEATHER_SUN] = {B_MSG_WEATHER_END_SUN, B_MSG_WEATHER_TURN_SUN, B_ANIM_SUN_CONTINUES}, + [BATTLE_WEATHER_SANDSTORM] = {B_MSG_WEATHER_END_SANDSTORM, B_MSG_WEATHER_TURN_SANDSTORM, B_ANIM_SANDSTORM_CONTINUES}, + [BATTLE_WEATHER_HAIL] = {B_MSG_WEATHER_END_HAIL, B_MSG_WEATHER_TURN_HAIL, B_ANIM_HAIL_CONTINUES}, + [BATTLE_WEATHER_SNOW] = {B_MSG_WEATHER_END_SNOW, B_MSG_WEATHER_TURN_SNOW, B_ANIM_SNOW_CONTINUES}, + [BATTLE_WEATHER_FOG] = {B_MSG_WEATHER_END_FOG, B_MSG_WEATHER_TURN_FOG, B_ANIM_FOG_CONTINUES}, + [BATTLE_WEATHER_STRONG_WINDS] = {B_MSG_WEATHER_END_STRONG_WINDS, B_MSG_WEATHER_TURN_STRONG_WINDS, B_ANIM_STRONG_WINDS}, +}; + +static bool32 TryEndTurnWeather(void) +{ + u32 effect = 0; + u32 currBattleWeather = 0xFF; + + if (gBattleWeather & B_WEATHER_RAIN) currBattleWeather = BATTLE_WEATHER_RAIN; + else if (gBattleWeather & B_WEATHER_SUN) currBattleWeather = BATTLE_WEATHER_SUN; + else if (gBattleWeather & B_WEATHER_SANDSTORM) currBattleWeather = BATTLE_WEATHER_SANDSTORM; + else if (gBattleWeather & B_WEATHER_HAIL) currBattleWeather = BATTLE_WEATHER_HAIL; + else if (gBattleWeather & B_WEATHER_SNOW) currBattleWeather = BATTLE_WEATHER_SNOW; + else if (gBattleWeather & B_WEATHER_FOG) currBattleWeather = BATTLE_WEATHER_FOG; + else if (gBattleWeather & B_WEATHER_STRONG_WINDS) currBattleWeather = BATTLE_WEATHER_STRONG_WINDS; + + if (currBattleWeather == 0xFF) + return effect; + + if (gBattleWeather & B_WEATHER_PRIMAL_ANY) // Might be redundant. handled in else case? + { + gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_MESSAGE_TURN]; + gBattleScripting.animArg1 = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_ANIMATION]; + BattleScriptExecute(BattleScript_WeatherContinues); + effect++; + } + else if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) + { + gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_MESSAGE_STOPPED]; + BattleScriptExecute(BattleScript_WeatherFaded); + effect++; + } + else + { + gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_MESSAGE_TURN]; + gBattleScripting.animArg1 = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_ANIMATION]; + BattleScriptExecute(BattleScript_WeatherContinues); + effect++; + } + + return effect; +} +#undef BATTLE_WEATHER_MESSAGE_STOPPED +#undef BATTLE_WEATHER_MESSAGE_TURN +#undef BATTLE_WEATHER_ANIMATION + u8 DoFieldEndTurnEffects(void) { u8 effect = 0; @@ -1799,126 +1859,130 @@ u8 DoFieldEndTurnEffects(void) gBattleStruct->turnSideTracker = 0; } break; - case ENDTURN_RAIN: - if (gBattleWeather & B_WEATHER_RAIN) - { - if (!(gBattleWeather & B_WEATHER_RAIN_PRIMAL) - && gWishFutureKnock.weatherDuration > 0 - && --gWishFutureKnock.weatherDuration == 0) - { - gBattleWeather &= ~(B_WEATHER_RAIN | B_WEATHER_RAIN_DOWNPOUR); - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_STOPPED; - } - else if (gBattleWeather & B_WEATHER_RAIN_DOWNPOUR) - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOWNPOUR_CONTINUES; - else - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_CONTINUES; - - BattleScriptExecute(BattleScript_RainContinuesOrEnds); - effect++; - } + case ENDTURN_WEATHER: + effect = TryEndTurnWeather(); gBattleStruct->turnCountersTracker++; break; - case ENDTURN_SANDSTORM: - if (gBattleWeather & B_WEATHER_SANDSTORM) - { - if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) - { - gBattleWeather &= ~B_WEATHER_SANDSTORM; - gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; - } - else - { - gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; - } + // case ENDTURN_RAIN: + // if (gBattleWeather & B_WEATHER_RAIN) + // { + // if (!(gBattleWeather & B_WEATHER_RAIN_PRIMAL) + // && gWishFutureKnock.weatherDuration > 0 + // && --gWishFutureKnock.weatherDuration == 0) + // { + // gBattleWeather &= ~(B_WEATHER_RAIN | B_WEATHER_RAIN_DOWNPOUR); + // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_STOPPED; + // } + // else if (gBattleWeather & B_WEATHER_RAIN_DOWNPOUR) + // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOWNPOUR_CONTINUES; + // else + // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_CONTINUES; - gBattleScripting.animArg1 = B_ANIM_SANDSTORM_CONTINUES; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SANDSTORM; - BattleScriptExecute(gBattlescriptCurrInstr); - effect++; - } - gBattleStruct->turnCountersTracker++; - break; - case ENDTURN_SUN: - if (gBattleWeather & B_WEATHER_SUN) - { - if (!(gBattleWeather & B_WEATHER_SUN_PRIMAL) - && gWishFutureKnock.weatherDuration > 0 - && --gWishFutureKnock.weatherDuration == 0) - { - for (i = 0; i < gBattlersCount; i++) - gDisableStructs[i].weatherAbilityDone = FALSE; - gBattleWeather &= ~B_WEATHER_SUN; - gBattlescriptCurrInstr = BattleScript_SunlightFaded; - } - else - { - gBattlescriptCurrInstr = BattleScript_SunlightContinues; - } + // BattleScriptExecute(BattleScript_RainContinuesOrEnds); + // effect++; + // } + // gBattleStruct->turnCountersTracker++; + // break; + // case ENDTURN_SANDSTORM: + // if (gBattleWeather & B_WEATHER_SANDSTORM) + // { + // if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) + // { + // gBattleWeather &= ~B_WEATHER_SANDSTORM; + // gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; + // } + // else + // { + // gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; + // } - BattleScriptExecute(gBattlescriptCurrInstr); - effect++; - } - gBattleStruct->turnCountersTracker++; - break; - case ENDTURN_HAIL: - if (gBattleWeather & B_WEATHER_HAIL) - { - if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) - { - gBattleWeather &= ~B_WEATHER_HAIL; - gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; - } - else - { - gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; - } + // gBattleScripting.animArg1 = B_ANIM_SANDSTORM_CONTINUES; + // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SANDSTORM; + // BattleScriptExecute(gBattlescriptCurrInstr); + // effect++; + // } + // gBattleStruct->turnCountersTracker++; + // break; + // case ENDTURN_SUN: + // if (gBattleWeather & B_WEATHER_SUN) + // { + // if (!(gBattleWeather & B_WEATHER_SUN_PRIMAL) + // && gWishFutureKnock.weatherDuration > 0 + // && --gWishFutureKnock.weatherDuration == 0) + // { + // for (i = 0; i < gBattlersCount; i++) + // gDisableStructs[i].weatherAbilityDone = FALSE; + // gBattleWeather &= ~B_WEATHER_SUN; + // gBattlescriptCurrInstr = BattleScript_SunlightFaded; + // } + // else + // { + // gBattlescriptCurrInstr = BattleScript_SunlightContinues; + // } - gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_HAIL; - BattleScriptExecute(gBattlescriptCurrInstr); - effect++; - } - gBattleStruct->turnCountersTracker++; - break; - case ENDTURN_SNOW: - if (gBattleWeather & B_WEATHER_SNOW) - { - if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) - { - gBattleWeather &= ~B_WEATHER_SNOW; - gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; - } - else - { - gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; - } + // BattleScriptExecute(gBattlescriptCurrInstr); + // effect++; + // } + // gBattleStruct->turnCountersTracker++; + // break; + // case ENDTURN_HAIL: + // if (gBattleWeather & B_WEATHER_HAIL) + // { + // if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) + // { + // gBattleWeather &= ~B_WEATHER_HAIL; + // gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; + // } + // else + // { + // gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; + // } - gBattleScripting.animArg1 = B_ANIM_SNOW_CONTINUES; - gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SNOW; - BattleScriptExecute(gBattlescriptCurrInstr); - effect++; - } - gBattleStruct->turnCountersTracker++; - break; - case ENDTURN_FOG: - if (gBattleWeather & B_WEATHER_FOG) - { - if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) - { - gBattleWeather &= ~B_WEATHER_FOG; - gBattlescriptCurrInstr = BattleScript_FogEnded; - } - else - { - gBattlescriptCurrInstr = BattleScript_FogContinues; - } + // gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES; + // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_HAIL; + // BattleScriptExecute(gBattlescriptCurrInstr); + // effect++; + // } + // gBattleStruct->turnCountersTracker++; + // break; + // case ENDTURN_SNOW: + // if (gBattleWeather & B_WEATHER_SNOW) + // { + // if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) + // { + // gBattleWeather &= ~B_WEATHER_SNOW; + // gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; + // } + // else + // { + // gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; + // } - BattleScriptExecute(gBattlescriptCurrInstr); - effect++; - } - gBattleStruct->turnCountersTracker++; - break; + // gBattleScripting.animArg1 = B_ANIM_SNOW_CONTINUES; + // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SNOW; + // BattleScriptExecute(gBattlescriptCurrInstr); + // effect++; + // } + // gBattleStruct->turnCountersTracker++; + // break; + // case ENDTURN_FOG: + // if (gBattleWeather & B_WEATHER_FOG) + // { + // if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) + // { + // gBattleWeather &= ~B_WEATHER_FOG; + // gBattlescriptCurrInstr = BattleScript_FogEnded; + // } + // else + // { + // gBattlescriptCurrInstr = BattleScript_FogContinues; + // } + + // BattleScriptExecute(gBattlescriptCurrInstr); + // effect++; + // } + // gBattleStruct->turnCountersTracker++; + // break; case ENDTURN_DAMAGE_NON_TYPES: while (gBattleStruct->turnSideTracker < 2) { From 0bb86e4437b36b2e06fd16ba1faa2725508f407e Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 28 Dec 2024 10:23:28 +0100 Subject: [PATCH 09/85] struct --- include/constants/battle.h | 2 + src/battle_util.c | 89 +++++++++++++++++++++++++++++--------- 2 files changed, 70 insertions(+), 21 deletions(-) diff --git a/include/constants/battle.h b/include/constants/battle.h index 561984bc9f..4d4021de03 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -297,6 +297,8 @@ enum BattleWeather BATTLE_WEATHER_STRONG_WINDS, }; +#define BATTLE_WEATHER_COUNT 10 + // Battle Weather flags #define B_WEATHER_NONE 0 #define B_WEATHER_RAIN_NORMAL (1 << BATTLE_WEATHER_RAIN) diff --git a/src/battle_util.c b/src/battle_util.c index b9bd851b92..df350905a2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1568,20 +1568,70 @@ static bool32 EndTurnTerrain(u32 terrainFlag, u32 stringTableId) return FALSE; } -#define BATTLE_WEATHER_MESSAGE_STOPPED 0 -#define BATTLE_WEATHER_MESSAGE_TURN 1 -#define BATTLE_WEATHER_ANIMATION 2 -static const u32 sBattleWeatherAttributes[][3] = +struct BattleWeatherInfo { - // Type of Weather // End Message // Weather Continues // Weather Animation - [BATTLE_WEATHER_RAIN] = {B_MSG_WEATHER_END_RAIN, B_MSG_WEATHER_TURN_RAIN, B_ANIM_RAIN_CONTINUES}, - [BATTLE_WEATHER_RAIN_DOWNPOUR] = {B_MSG_WEATHER_END_RAIN, B_MSG_WEATHER_TURN_DOWNPOUR, B_ANIM_RAIN_CONTINUES}, - [BATTLE_WEATHER_SUN] = {B_MSG_WEATHER_END_SUN, B_MSG_WEATHER_TURN_SUN, B_ANIM_SUN_CONTINUES}, - [BATTLE_WEATHER_SANDSTORM] = {B_MSG_WEATHER_END_SANDSTORM, B_MSG_WEATHER_TURN_SANDSTORM, B_ANIM_SANDSTORM_CONTINUES}, - [BATTLE_WEATHER_HAIL] = {B_MSG_WEATHER_END_HAIL, B_MSG_WEATHER_TURN_HAIL, B_ANIM_HAIL_CONTINUES}, - [BATTLE_WEATHER_SNOW] = {B_MSG_WEATHER_END_SNOW, B_MSG_WEATHER_TURN_SNOW, B_ANIM_SNOW_CONTINUES}, - [BATTLE_WEATHER_FOG] = {B_MSG_WEATHER_END_FOG, B_MSG_WEATHER_TURN_FOG, B_ANIM_FOG_CONTINUES}, - [BATTLE_WEATHER_STRONG_WINDS] = {B_MSG_WEATHER_END_STRONG_WINDS, B_MSG_WEATHER_TURN_STRONG_WINDS, B_ANIM_STRONG_WINDS}, + u8 endMessage; + u8 continuesMessage; + u8 animation; +}; + +static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = +{ + [BATTLE_WEATHER_RAIN] = + { + .endMessage = B_MSG_WEATHER_END_RAIN, + .continuesMessage = B_MSG_WEATHER_TURN_RAIN, + .animation = B_ANIM_RAIN_CONTINUES, + }, + + [BATTLE_WEATHER_RAIN_DOWNPOUR] = + { + .endMessage = B_MSG_WEATHER_END_RAIN, + .continuesMessage = B_MSG_WEATHER_TURN_DOWNPOUR, + .animation = B_ANIM_RAIN_CONTINUES, + }, + + [BATTLE_WEATHER_SUN] = + { + .endMessage = B_MSG_WEATHER_END_SUN, + .continuesMessage = B_MSG_WEATHER_TURN_SUN, + .animation = B_ANIM_SUN_CONTINUES, + }, + + [BATTLE_WEATHER_SANDSTORM] = + { + .endMessage = B_MSG_WEATHER_END_SANDSTORM, + .continuesMessage = B_MSG_WEATHER_TURN_SANDSTORM, + .animation = B_ANIM_SANDSTORM_CONTINUES, + }, + + [BATTLE_WEATHER_HAIL] = + { + .endMessage = B_MSG_WEATHER_END_HAIL, + .continuesMessage = B_MSG_WEATHER_TURN_HAIL, + .animation = B_ANIM_HAIL_CONTINUES, + }, + + [BATTLE_WEATHER_SNOW] = + { + .endMessage = B_MSG_WEATHER_END_SNOW, + .continuesMessage = B_MSG_WEATHER_TURN_SNOW, + .animation = B_ANIM_SNOW_CONTINUES, + }, + + [BATTLE_WEATHER_FOG] = + { + .endMessage = B_MSG_WEATHER_END_FOG, + .continuesMessage = B_MSG_WEATHER_TURN_FOG, + .animation = B_ANIM_FOG_CONTINUES, + }, + + [BATTLE_WEATHER_STRONG_WINDS] = + { + .endMessage = B_MSG_WEATHER_END_STRONG_WINDS, + .continuesMessage = B_MSG_WEATHER_TURN_STRONG_WINDS, + .animation = B_ANIM_STRONG_WINDS, + }, }; static bool32 TryEndTurnWeather(void) @@ -1602,30 +1652,27 @@ static bool32 TryEndTurnWeather(void) if (gBattleWeather & B_WEATHER_PRIMAL_ANY) // Might be redundant. handled in else case? { - gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_MESSAGE_TURN]; - gBattleScripting.animArg1 = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_ANIMATION]; + gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].continuesMessage; + gBattleScripting.animArg1 = sBattleWeatherInfo[currBattleWeather].animation; BattleScriptExecute(BattleScript_WeatherContinues); effect++; } else if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { - gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_MESSAGE_STOPPED]; + gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].endMessage; BattleScriptExecute(BattleScript_WeatherFaded); effect++; } else { - gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_MESSAGE_TURN]; - gBattleScripting.animArg1 = sBattleWeatherAttributes[currBattleWeather][BATTLE_WEATHER_ANIMATION]; + gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].continuesMessage; + gBattleScripting.animArg1 = sBattleWeatherInfo[currBattleWeather].animation; BattleScriptExecute(BattleScript_WeatherContinues); effect++; } return effect; } -#undef BATTLE_WEATHER_MESSAGE_STOPPED -#undef BATTLE_WEATHER_MESSAGE_TURN -#undef BATTLE_WEATHER_ANIMATION u8 DoFieldEndTurnEffects(void) { From 6a906a3fc16cd53f29a7307166d9c09ac4b2f07d Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 28 Dec 2024 20:55:59 +0100 Subject: [PATCH 10/85] refactor done --- data/battle_scripts_1.s | 64 ++---------- include/battle_scripts.h | 11 +-- include/constants/battle.h | 7 +- src/battle_util.c | 198 +++++++++---------------------------- 4 files changed, 57 insertions(+), 223 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 1b5a9f87ea..9a1e977bf3 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -5841,8 +5841,6 @@ BattleScript_LearnedNewMove:: BattleScript_LearnMoveReturn:: return -@@@ === NEW WEATHER SCRIPT - BattleScript_WeatherContinues:: printfromtable gWeatherTurnStringIds waitmessage B_WAIT_TIME_LONG @@ -5857,31 +5855,19 @@ BattleScript_WeatherFaded:: call BattleScript_ActivateWeatherAbilities end2 -@@@ === NEW WEATHER SCRIPT - -BattleScript_RainContinuesOrEnds:: - @printfromtable gRainContinuesStringIds - waitmessage B_WAIT_TIME_LONG - jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, B_MSG_RAIN_STOPPED, BattleScript_RainContinuesOrEndsEnd - playanimation BS_ATTACKER, B_ANIM_RAIN_CONTINUES -BattleScript_RainContinuesOrEndsEnd:: - call BattleScript_ActivateWeatherAbilities - end2 - -BattleScript_DamagingWeatherContinues:: - @printfromtable gSandStormHailSnowContinuesStringIds - waitmessage B_WAIT_TIME_LONG - playanimation_var BS_ATTACKER, sB_ANIM_ARG1 - setbyte gBattleCommunication, 0 - end2 - BattleScript_DamagingWeather:: - @printfromtable gSandStormHailDmgStringIds + printfromtable gSandStormHailDmgStringIds waitmessage B_WAIT_TIME_LONG effectivenesssound hitanimation BS_SCRIPTING goto BattleScript_DoTurnDmg +BattleScript_FogEnded_Ret:: + printstring STRINGID_FOGLIFTED + waitmessage B_WAIT_TIME_LONG + call BattleScript_ActivateWeatherAbilities + return + BattleScript_IceBodyHeal:: call BattleScript_AbilityPopUpScripting playanimation BS_SCRIPTING, B_ANIM_SIMPLE_HEAL @@ -5891,42 +5877,6 @@ BattleScript_IceBodyHeal:: waitmessage B_WAIT_TIME_LONG end2 -BattleScript_SandStormHailSnowEnds:: - @printfromtable gSandStormHailSnowEndStringIds - waitmessage B_WAIT_TIME_LONG - call BattleScript_ActivateWeatherAbilities - end2 - -BattleScript_SunlightContinues:: - printstring STRINGID_SUNLIGHTSTRONG - waitmessage B_WAIT_TIME_LONG - playanimation BS_ATTACKER, B_ANIM_SUN_CONTINUES - call BattleScript_ActivateWeatherAbilities - end2 - -BattleScript_SunlightFaded:: - printstring STRINGID_SUNLIGHTFADED - waitmessage B_WAIT_TIME_LONG - call BattleScript_ActivateWeatherAbilities - end2 - -BattleScript_FogContinues:: - printstring STRINGID_FOGISDEEP - waitmessage B_WAIT_TIME_LONG - playanimation BS_ATTACKER, B_ANIM_FOG_CONTINUES - call BattleScript_ActivateWeatherAbilities - end2 - -BattleScript_FogEnded_Ret:: - printstring STRINGID_FOGLIFTED - waitmessage B_WAIT_TIME_LONG - call BattleScript_ActivateWeatherAbilities - return - -BattleScript_FogEnded:: - call BattleScript_FogEnded_Ret - end2 - BattleScript_OverworldStatusStarts:: printfromtable gStartingStatusStringIds waitmessage B_WAIT_TIME_LONG diff --git a/include/battle_scripts.h b/include/battle_scripts.h index 743a5117b8..ef30b10b8a 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -50,21 +50,12 @@ extern const u8 BattleScript_DoSwitchOut[]; extern const u8 BattleScript_MoveSwitchOpenPartyScreen[]; extern const u8 BattleScript_Pausex20[]; extern const u8 BattleScript_LevelUp[]; - extern const u8 BattleScript_WeatherContinues[]; extern const u8 BattleScript_WeatherFaded[]; - -extern const u8 BattleScript_RainContinuesOrEnds[]; -extern const u8 BattleScript_SnowContinuesOrEnds[]; extern const u8 BattleScript_DamagingWeatherContinues[]; extern const u8 BattleScript_DamagingWeather[]; -extern const u8 BattleScript_IceBodyHeal[]; -extern const u8 BattleScript_SandStormHailSnowEnds[]; -extern const u8 BattleScript_SunlightContinues[]; -extern const u8 BattleScript_SunlightFaded[]; -extern const u8 BattleScript_FogContinues[]; extern const u8 BattleScript_FogEnded_Ret[]; -extern const u8 BattleScript_FogEnded[]; +extern const u8 BattleScript_IceBodyHeal[]; extern const u8 BattleScript_OverworldStatusStarts[]; extern const u8 BattleScript_OverworldWeatherStarts[]; extern const u8 BattleScript_OverworldTerrain[]; diff --git a/include/constants/battle.h b/include/constants/battle.h index 4d4021de03..99e498b628 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -288,27 +288,26 @@ enum BattleWeather BATTLE_WEATHER_RAIN, BATTLE_WEATHER_RAIN_PRIMAL, BATTLE_WEATHER_RAIN_DOWNPOUR, - BATTLE_WEATHER_SANDSTORM, BATTLE_WEATHER_SUN, BATTLE_WEATHER_SUN_PRIMAL, + BATTLE_WEATHER_SANDSTORM, BATTLE_WEATHER_HAIL, BATTLE_WEATHER_SNOW, BATTLE_WEATHER_FOG, BATTLE_WEATHER_STRONG_WINDS, + BATTLE_WEATHER_COUNT, }; -#define BATTLE_WEATHER_COUNT 10 - // Battle Weather flags #define B_WEATHER_NONE 0 #define B_WEATHER_RAIN_NORMAL (1 << BATTLE_WEATHER_RAIN) #define B_WEATHER_RAIN_PRIMAL (1 << BATTLE_WEATHER_RAIN_PRIMAL) #define B_WEATHER_RAIN_DOWNPOUR (1 << BATTLE_WEATHER_RAIN_DOWNPOUR) // unused #define B_WEATHER_RAIN (B_WEATHER_RAIN_NORMAL | B_WEATHER_RAIN_PRIMAL | B_WEATHER_RAIN_DOWNPOUR) -#define B_WEATHER_SANDSTORM (1 << BATTLE_WEATHER_SANDSTORM) #define B_WEATHER_SUN_NORMAL (1 << BATTLE_WEATHER_SUN) #define B_WEATHER_SUN_PRIMAL (1 << BATTLE_WEATHER_SUN_PRIMAL) #define B_WEATHER_SUN (B_WEATHER_SUN_NORMAL | B_WEATHER_SUN_PRIMAL) +#define B_WEATHER_SANDSTORM (1 << BATTLE_WEATHER_SANDSTORM) #define B_WEATHER_HAIL (1 << BATTLE_WEATHER_HAIL) #define B_WEATHER_SNOW (1 << BATTLE_WEATHER_SNOW) #define B_WEATHER_FOG (1 << BATTLE_WEATHER_FOG) diff --git a/src/battle_util.c b/src/battle_util.c index df350905a2..7efd58f659 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1521,12 +1521,6 @@ enum ENDTURN_TAILWIND, ENDTURN_WISH, ENDTURN_WEATHER, - // ENDTURN_RAIN, - // ENDTURN_SANDSTORM, - // ENDTURN_SUN, - // ENDTURN_HAIL, - // ENDTURN_SNOW, - // ENDTURN_FOG, ENDTURN_DAMAGE_NON_TYPES, ENDTURN_GRAVITY, ENDTURN_WATER_SPORT, @@ -1570,6 +1564,8 @@ static bool32 EndTurnTerrain(u32 terrainFlag, u32 stringTableId) struct BattleWeatherInfo { + u16 flag; + u8 rock; u8 endMessage; u8 continuesMessage; u8 animation; @@ -1579,6 +1575,17 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = { [BATTLE_WEATHER_RAIN] = { + .flag = B_WEATHER_RAIN_NORMAL, + .rock = HOLD_EFFECT_DAMP_ROCK, + .endMessage = B_MSG_WEATHER_END_RAIN, + .continuesMessage = B_MSG_WEATHER_TURN_RAIN, + .animation = B_ANIM_RAIN_CONTINUES, + }, + + [BATTLE_WEATHER_RAIN_PRIMAL] = + { + .flag = B_WEATHER_RAIN_PRIMAL, + .rock = HOLD_EFFECT_DAMP_ROCK, .endMessage = B_MSG_WEATHER_END_RAIN, .continuesMessage = B_MSG_WEATHER_TURN_RAIN, .animation = B_ANIM_RAIN_CONTINUES, @@ -1586,6 +1593,8 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = [BATTLE_WEATHER_RAIN_DOWNPOUR] = { + .flag = B_WEATHER_RAIN_NORMAL, + .rock = HOLD_EFFECT_DAMP_ROCK, .endMessage = B_MSG_WEATHER_END_RAIN, .continuesMessage = B_MSG_WEATHER_TURN_DOWNPOUR, .animation = B_ANIM_RAIN_CONTINUES, @@ -1593,6 +1602,17 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = [BATTLE_WEATHER_SUN] = { + .flag = B_WEATHER_SUN_NORMAL, + .rock = HOLD_EFFECT_HEAT_ROCK, + .endMessage = B_MSG_WEATHER_END_SUN, + .continuesMessage = B_MSG_WEATHER_TURN_SUN, + .animation = B_ANIM_SUN_CONTINUES, + }, + + [BATTLE_WEATHER_SUN_PRIMAL] = + { + .flag = B_WEATHER_SUN_PRIMAL, + .rock = HOLD_EFFECT_HEAT_ROCK, .endMessage = B_MSG_WEATHER_END_SUN, .continuesMessage = B_MSG_WEATHER_TURN_SUN, .animation = B_ANIM_SUN_CONTINUES, @@ -1600,6 +1620,8 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = [BATTLE_WEATHER_SANDSTORM] = { + .flag = B_WEATHER_SANDSTORM, + .rock = HOLD_EFFECT_SMOOTH_ROCK, .endMessage = B_MSG_WEATHER_END_SANDSTORM, .continuesMessage = B_MSG_WEATHER_TURN_SANDSTORM, .animation = B_ANIM_SANDSTORM_CONTINUES, @@ -1607,6 +1629,8 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = [BATTLE_WEATHER_HAIL] = { + .flag = B_WEATHER_HAIL, + .rock = HOLD_EFFECT_ICY_ROCK, .endMessage = B_MSG_WEATHER_END_HAIL, .continuesMessage = B_MSG_WEATHER_TURN_HAIL, .animation = B_ANIM_HAIL_CONTINUES, @@ -1614,6 +1638,8 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = [BATTLE_WEATHER_SNOW] = { + .flag = B_WEATHER_SNOW, + .rock = HOLD_EFFECT_ICY_ROCK, .endMessage = B_MSG_WEATHER_END_SNOW, .continuesMessage = B_MSG_WEATHER_TURN_SNOW, .animation = B_ANIM_SNOW_CONTINUES, @@ -1621,6 +1647,8 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = [BATTLE_WEATHER_FOG] = { + .flag = B_WEATHER_FOG, + .rock = HOLD_EFFECT_NONE, .endMessage = B_MSG_WEATHER_END_FOG, .continuesMessage = B_MSG_WEATHER_TURN_FOG, .animation = B_ANIM_FOG_CONTINUES, @@ -1628,6 +1656,8 @@ static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = [BATTLE_WEATHER_STRONG_WINDS] = { + .flag = B_WEATHER_STRONG_WINDS, + .rock = HOLD_EFFECT_NONE, .endMessage = B_MSG_WEATHER_END_STRONG_WINDS, .continuesMessage = B_MSG_WEATHER_TURN_STRONG_WINDS, .animation = B_ANIM_STRONG_WINDS, @@ -1650,14 +1680,7 @@ static bool32 TryEndTurnWeather(void) if (currBattleWeather == 0xFF) return effect; - if (gBattleWeather & B_WEATHER_PRIMAL_ANY) // Might be redundant. handled in else case? - { - gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].continuesMessage; - gBattleScripting.animArg1 = sBattleWeatherInfo[currBattleWeather].animation; - BattleScriptExecute(BattleScript_WeatherContinues); - effect++; - } - else if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) + if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].endMessage; BattleScriptExecute(BattleScript_WeatherFaded); @@ -1910,126 +1933,6 @@ u8 DoFieldEndTurnEffects(void) effect = TryEndTurnWeather(); gBattleStruct->turnCountersTracker++; break; - // case ENDTURN_RAIN: - // if (gBattleWeather & B_WEATHER_RAIN) - // { - // if (!(gBattleWeather & B_WEATHER_RAIN_PRIMAL) - // && gWishFutureKnock.weatherDuration > 0 - // && --gWishFutureKnock.weatherDuration == 0) - // { - // gBattleWeather &= ~(B_WEATHER_RAIN | B_WEATHER_RAIN_DOWNPOUR); - // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_STOPPED; - // } - // else if (gBattleWeather & B_WEATHER_RAIN_DOWNPOUR) - // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOWNPOUR_CONTINUES; - // else - // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_RAIN_CONTINUES; - - // BattleScriptExecute(BattleScript_RainContinuesOrEnds); - // effect++; - // } - // gBattleStruct->turnCountersTracker++; - // break; - // case ENDTURN_SANDSTORM: - // if (gBattleWeather & B_WEATHER_SANDSTORM) - // { - // if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) - // { - // gBattleWeather &= ~B_WEATHER_SANDSTORM; - // gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; - // } - // else - // { - // gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; - // } - - // gBattleScripting.animArg1 = B_ANIM_SANDSTORM_CONTINUES; - // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SANDSTORM; - // BattleScriptExecute(gBattlescriptCurrInstr); - // effect++; - // } - // gBattleStruct->turnCountersTracker++; - // break; - // case ENDTURN_SUN: - // if (gBattleWeather & B_WEATHER_SUN) - // { - // if (!(gBattleWeather & B_WEATHER_SUN_PRIMAL) - // && gWishFutureKnock.weatherDuration > 0 - // && --gWishFutureKnock.weatherDuration == 0) - // { - // for (i = 0; i < gBattlersCount; i++) - // gDisableStructs[i].weatherAbilityDone = FALSE; - // gBattleWeather &= ~B_WEATHER_SUN; - // gBattlescriptCurrInstr = BattleScript_SunlightFaded; - // } - // else - // { - // gBattlescriptCurrInstr = BattleScript_SunlightContinues; - // } - - // BattleScriptExecute(gBattlescriptCurrInstr); - // effect++; - // } - // gBattleStruct->turnCountersTracker++; - // break; - // case ENDTURN_HAIL: - // if (gBattleWeather & B_WEATHER_HAIL) - // { - // if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) - // { - // gBattleWeather &= ~B_WEATHER_HAIL; - // gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; - // } - // else - // { - // gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; - // } - - // gBattleScripting.animArg1 = B_ANIM_HAIL_CONTINUES; - // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_HAIL; - // BattleScriptExecute(gBattlescriptCurrInstr); - // effect++; - // } - // gBattleStruct->turnCountersTracker++; - // break; - // case ENDTURN_SNOW: - // if (gBattleWeather & B_WEATHER_SNOW) - // { - // if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) - // { - // gBattleWeather &= ~B_WEATHER_SNOW; - // gBattlescriptCurrInstr = BattleScript_SandStormHailSnowEnds; - // } - // else - // { - // gBattlescriptCurrInstr = BattleScript_DamagingWeatherContinues; - // } - - // gBattleScripting.animArg1 = B_ANIM_SNOW_CONTINUES; - // gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SNOW; - // BattleScriptExecute(gBattlescriptCurrInstr); - // effect++; - // } - // gBattleStruct->turnCountersTracker++; - // break; - // case ENDTURN_FOG: - // if (gBattleWeather & B_WEATHER_FOG) - // { - // if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) - // { - // gBattleWeather &= ~B_WEATHER_FOG; - // gBattlescriptCurrInstr = BattleScript_FogEnded; - // } - // else - // { - // gBattlescriptCurrInstr = BattleScript_FogContinues; - // } - - // BattleScriptExecute(gBattlescriptCurrInstr); - // effect++; - // } - // gBattleStruct->turnCountersTracker++; - // break; case ENDTURN_DAMAGE_NON_TYPES: while (gBattleStruct->turnSideTracker < 2) { @@ -2349,6 +2252,7 @@ u8 DoBattlerEndTurnEffects(void) gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; if (gBattleStruct->moveDamage[battler] == 0) gBattleStruct->moveDamage[battler] = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SANDSTORM; BattleScriptExecute(BattleScript_DamagingWeather); effect++; } @@ -2375,6 +2279,7 @@ u8 DoBattlerEndTurnEffects(void) gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 16; if (gBattleStruct->moveDamage[battler] == 0) gBattleStruct->moveDamage[battler] = 1; + gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_HAIL; BattleScriptExecute(BattleScript_DamagingWeather); effect++; } @@ -3995,19 +3900,6 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2 } } -static const u16 sWeatherFlagsInfo[][2] = -{ - [BATTLE_WEATHER_RAIN] = {B_WEATHER_RAIN_NORMAL, HOLD_EFFECT_DAMP_ROCK}, - [BATTLE_WEATHER_RAIN_PRIMAL] = {B_WEATHER_RAIN_PRIMAL, HOLD_EFFECT_DAMP_ROCK}, - [BATTLE_WEATHER_SUN] = {B_WEATHER_SUN_NORMAL, HOLD_EFFECT_HEAT_ROCK}, - [BATTLE_WEATHER_SUN_PRIMAL] = {B_WEATHER_SUN_PRIMAL, HOLD_EFFECT_HEAT_ROCK}, - [BATTLE_WEATHER_SANDSTORM] = {B_WEATHER_SANDSTORM, HOLD_EFFECT_SMOOTH_ROCK}, - [BATTLE_WEATHER_HAIL] = {B_WEATHER_HAIL, HOLD_EFFECT_ICY_ROCK}, - [BATTLE_WEATHER_STRONG_WINDS] = {B_WEATHER_STRONG_WINDS, HOLD_EFFECT_NONE}, - [BATTLE_WEATHER_SNOW] = {B_WEATHER_SNOW, HOLD_EFFECT_ICY_ROCK}, - [BATTLE_WEATHER_FOG] = {B_WEATHER_FOG, HOLD_EFFECT_NONE}, -}; - bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility) { u16 battlerAbility = GetBattlerAbility(battler); @@ -4018,15 +3910,17 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbilit { return FALSE; } - else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sWeatherFlagsInfo[battleWeatherId][0])) + else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sBattleWeatherInfo[battleWeatherId].flag)) { - gBattleWeather = (sWeatherFlagsInfo[battleWeatherId][0] | sWeatherFlagsInfo[battleWeatherId][0]); + gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; return TRUE; } - else if (!(gBattleWeather & (sWeatherFlagsInfo[battleWeatherId][0] | sWeatherFlagsInfo[battleWeatherId][0]))) + else if (!(gBattleWeather & sBattleWeatherInfo[battleWeatherId].flag)) { - gBattleWeather = (sWeatherFlagsInfo[battleWeatherId][0]); - if (GetBattlerHoldEffect(battler, TRUE) == sWeatherFlagsInfo[battleWeatherId][1]) + gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; + if (gBattleWeather & B_WEATHER_PRIMAL_ANY) + gWishFutureKnock.weatherDuration = 0; + if (GetBattlerHoldEffect(battler, TRUE) == sBattleWeatherInfo[battleWeatherId].rock) gWishFutureKnock.weatherDuration = 8; else gWishFutureKnock.weatherDuration = 5; From d9db60218c6a11ebf3192de33980462f77f1cbd4 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 28 Dec 2024 22:58:16 +0100 Subject: [PATCH 11/85] some test fixes --- src/battle_script_commands.c | 6 +++--- src/battle_util.c | 1 + 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1f8b42801d..6f13c34495 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11589,9 +11589,9 @@ static void Cmd_setfieldweather(void) { CMD_ARGS(u8 weather); - u8 weather = cmd->weather; + u8 battleWeatherId = cmd->weather; - if (!TryChangeBattleWeather(gBattlerAttacker, weather, FALSE)) + if (!TryChangeBattleWeather(gBattlerAttacker, battleWeatherId, FALSE)) { gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_WEATHER_FAILED; @@ -11599,7 +11599,7 @@ static void Cmd_setfieldweather(void) return; } - switch (weather) + switch (battleWeatherId) { case BATTLE_WEATHER_RAIN: gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_STARTED_RAIN; diff --git a/src/battle_util.c b/src/battle_util.c index 2323a28ce7..04b6f59956 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1684,6 +1684,7 @@ static bool32 TryEndTurnWeather(void) if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { + gBattleWeather = B_WEATHER_NONE; gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].endMessage; BattleScriptExecute(BattleScript_WeatherFaded); effect++; From 3ac4f81de938e8306bd784387722b646d87e6ae5 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 28 Dec 2024 23:01:52 +0100 Subject: [PATCH 12/85] protosynthesis test fix --- src/battle_util.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/battle_util.c b/src/battle_util.c index 04b6f59956..99cdb8858a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1685,6 +1685,8 @@ static bool32 TryEndTurnWeather(void) if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { gBattleWeather = B_WEATHER_NONE; + for (u32 i = 0; i < gBattlersCount; i++) + gDisableStructs[i].weatherAbilityDone = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].endMessage; BattleScriptExecute(BattleScript_WeatherFaded); effect++; From c9bde52fd2d9512cc4bef5b78637f768e90ddb16 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sun, 29 Dec 2024 10:23:46 +0100 Subject: [PATCH 13/85] fix last tests --- src/battle_util.c | 215 +++++++++++++++++++++++--------------------- test/battle/ai/ai.c | 14 +-- 2 files changed, 119 insertions(+), 110 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 99cdb8858a..34d8cadb16 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -96,6 +96,109 @@ static const u8 sPkblToEscapeFactor[][3] = { static const u8 sGoNearCounterToCatchFactor[] = {4, 3, 2, 1}; static const u8 sGoNearCounterToEscapeFactor[] = {4, 4, 4, 4}; + +struct BattleWeatherInfo +{ + u16 flag; + u8 rock; + u8 endMessage; + u8 continuesMessage; + u8 animation; +}; + +static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = +{ + [BATTLE_WEATHER_RAIN] = + { + .flag = B_WEATHER_RAIN_NORMAL, + .rock = HOLD_EFFECT_DAMP_ROCK, + .endMessage = B_MSG_WEATHER_END_RAIN, + .continuesMessage = B_MSG_WEATHER_TURN_RAIN, + .animation = B_ANIM_RAIN_CONTINUES, + }, + + [BATTLE_WEATHER_RAIN_PRIMAL] = + { + .flag = B_WEATHER_RAIN_PRIMAL, + .rock = HOLD_EFFECT_DAMP_ROCK, + .endMessage = B_MSG_WEATHER_END_RAIN, + .continuesMessage = B_MSG_WEATHER_TURN_RAIN, + .animation = B_ANIM_RAIN_CONTINUES, + }, + + [BATTLE_WEATHER_RAIN_DOWNPOUR] = + { + .flag = B_WEATHER_RAIN_NORMAL, + .rock = HOLD_EFFECT_DAMP_ROCK, + .endMessage = B_MSG_WEATHER_END_RAIN, + .continuesMessage = B_MSG_WEATHER_TURN_DOWNPOUR, + .animation = B_ANIM_RAIN_CONTINUES, + }, + + [BATTLE_WEATHER_SUN] = + { + .flag = B_WEATHER_SUN_NORMAL, + .rock = HOLD_EFFECT_HEAT_ROCK, + .endMessage = B_MSG_WEATHER_END_SUN, + .continuesMessage = B_MSG_WEATHER_TURN_SUN, + .animation = B_ANIM_SUN_CONTINUES, + }, + + [BATTLE_WEATHER_SUN_PRIMAL] = + { + .flag = B_WEATHER_SUN_PRIMAL, + .rock = HOLD_EFFECT_HEAT_ROCK, + .endMessage = B_MSG_WEATHER_END_SUN, + .continuesMessage = B_MSG_WEATHER_TURN_SUN, + .animation = B_ANIM_SUN_CONTINUES, + }, + + [BATTLE_WEATHER_SANDSTORM] = + { + .flag = B_WEATHER_SANDSTORM, + .rock = HOLD_EFFECT_SMOOTH_ROCK, + .endMessage = B_MSG_WEATHER_END_SANDSTORM, + .continuesMessage = B_MSG_WEATHER_TURN_SANDSTORM, + .animation = B_ANIM_SANDSTORM_CONTINUES, + }, + + [BATTLE_WEATHER_HAIL] = + { + .flag = B_WEATHER_HAIL, + .rock = HOLD_EFFECT_ICY_ROCK, + .endMessage = B_MSG_WEATHER_END_HAIL, + .continuesMessage = B_MSG_WEATHER_TURN_HAIL, + .animation = B_ANIM_HAIL_CONTINUES, + }, + + [BATTLE_WEATHER_SNOW] = + { + .flag = B_WEATHER_SNOW, + .rock = HOLD_EFFECT_ICY_ROCK, + .endMessage = B_MSG_WEATHER_END_SNOW, + .continuesMessage = B_MSG_WEATHER_TURN_SNOW, + .animation = B_ANIM_SNOW_CONTINUES, + }, + + [BATTLE_WEATHER_FOG] = + { + .flag = B_WEATHER_FOG, + .rock = HOLD_EFFECT_NONE, + .endMessage = B_MSG_WEATHER_END_FOG, + .continuesMessage = B_MSG_WEATHER_TURN_FOG, + .animation = B_ANIM_FOG_CONTINUES, + }, + + [BATTLE_WEATHER_STRONG_WINDS] = + { + .flag = B_WEATHER_STRONG_WINDS, + .rock = HOLD_EFFECT_NONE, + .endMessage = B_MSG_WEATHER_END_STRONG_WINDS, + .continuesMessage = B_MSG_WEATHER_TURN_STRONG_WINDS, + .animation = B_ANIM_STRONG_WINDS, + }, +}; + static u8 CalcBeatUpPower(void) { u8 basePower; @@ -1564,108 +1667,6 @@ static bool32 EndTurnTerrain(u32 terrainFlag, u32 stringTableId) return FALSE; } -struct BattleWeatherInfo -{ - u16 flag; - u8 rock; - u8 endMessage; - u8 continuesMessage; - u8 animation; -}; - -static const struct BattleWeatherInfo sBattleWeatherInfo[BATTLE_WEATHER_COUNT] = -{ - [BATTLE_WEATHER_RAIN] = - { - .flag = B_WEATHER_RAIN_NORMAL, - .rock = HOLD_EFFECT_DAMP_ROCK, - .endMessage = B_MSG_WEATHER_END_RAIN, - .continuesMessage = B_MSG_WEATHER_TURN_RAIN, - .animation = B_ANIM_RAIN_CONTINUES, - }, - - [BATTLE_WEATHER_RAIN_PRIMAL] = - { - .flag = B_WEATHER_RAIN_PRIMAL, - .rock = HOLD_EFFECT_DAMP_ROCK, - .endMessage = B_MSG_WEATHER_END_RAIN, - .continuesMessage = B_MSG_WEATHER_TURN_RAIN, - .animation = B_ANIM_RAIN_CONTINUES, - }, - - [BATTLE_WEATHER_RAIN_DOWNPOUR] = - { - .flag = B_WEATHER_RAIN_NORMAL, - .rock = HOLD_EFFECT_DAMP_ROCK, - .endMessage = B_MSG_WEATHER_END_RAIN, - .continuesMessage = B_MSG_WEATHER_TURN_DOWNPOUR, - .animation = B_ANIM_RAIN_CONTINUES, - }, - - [BATTLE_WEATHER_SUN] = - { - .flag = B_WEATHER_SUN_NORMAL, - .rock = HOLD_EFFECT_HEAT_ROCK, - .endMessage = B_MSG_WEATHER_END_SUN, - .continuesMessage = B_MSG_WEATHER_TURN_SUN, - .animation = B_ANIM_SUN_CONTINUES, - }, - - [BATTLE_WEATHER_SUN_PRIMAL] = - { - .flag = B_WEATHER_SUN_PRIMAL, - .rock = HOLD_EFFECT_HEAT_ROCK, - .endMessage = B_MSG_WEATHER_END_SUN, - .continuesMessage = B_MSG_WEATHER_TURN_SUN, - .animation = B_ANIM_SUN_CONTINUES, - }, - - [BATTLE_WEATHER_SANDSTORM] = - { - .flag = B_WEATHER_SANDSTORM, - .rock = HOLD_EFFECT_SMOOTH_ROCK, - .endMessage = B_MSG_WEATHER_END_SANDSTORM, - .continuesMessage = B_MSG_WEATHER_TURN_SANDSTORM, - .animation = B_ANIM_SANDSTORM_CONTINUES, - }, - - [BATTLE_WEATHER_HAIL] = - { - .flag = B_WEATHER_HAIL, - .rock = HOLD_EFFECT_ICY_ROCK, - .endMessage = B_MSG_WEATHER_END_HAIL, - .continuesMessage = B_MSG_WEATHER_TURN_HAIL, - .animation = B_ANIM_HAIL_CONTINUES, - }, - - [BATTLE_WEATHER_SNOW] = - { - .flag = B_WEATHER_SNOW, - .rock = HOLD_EFFECT_ICY_ROCK, - .endMessage = B_MSG_WEATHER_END_SNOW, - .continuesMessage = B_MSG_WEATHER_TURN_SNOW, - .animation = B_ANIM_SNOW_CONTINUES, - }, - - [BATTLE_WEATHER_FOG] = - { - .flag = B_WEATHER_FOG, - .rock = HOLD_EFFECT_NONE, - .endMessage = B_MSG_WEATHER_END_FOG, - .continuesMessage = B_MSG_WEATHER_TURN_FOG, - .animation = B_ANIM_FOG_CONTINUES, - }, - - [BATTLE_WEATHER_STRONG_WINDS] = - { - .flag = B_WEATHER_STRONG_WINDS, - .rock = HOLD_EFFECT_NONE, - .endMessage = B_MSG_WEATHER_END_STRONG_WINDS, - .continuesMessage = B_MSG_WEATHER_TURN_STRONG_WINDS, - .animation = B_ANIM_STRONG_WINDS, - }, -}; - static bool32 TryEndTurnWeather(void) { u32 effect = 0; @@ -6490,12 +6491,20 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_ICE_FACE: - if (IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW) + u32 battlerWeatherAffected = IsBattlerWeatherAffected(battler, B_WEATHER_HAIL | B_WEATHER_SNOW); + if (battlerWeatherAffected && gBattleMons[battler].species == SPECIES_EISCUE) + { + // If Hail/Snow activates when in Eiscue is in base, prevent reversion when Eiscue Noice gets broken + gDisableStructs[battler].weatherAbilityDone = TRUE; + } + if (!gDisableStructs[battler].weatherAbilityDone + && battlerWeatherAffected && gBattleMons[battler].species == SPECIES_EISCUE_NOICE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED)) { // TODO: Convert this to a proper FORM_CHANGE type. gBattleScripting.battler = battler; + gDisableStructs[battler].weatherAbilityDone = TRUE; gBattleMons[battler].species = SPECIES_EISCUE_ICE; BattleScriptPushCursorAndCallback(BattleScript_BattlerFormChangeWithStringEnd3); effect++; diff --git a/test/battle/ai/ai.c b/test/battle/ai/ai.c index 60f9db1f5c..0883e3cc59 100644 --- a/test/battle/ai/ai.c +++ b/test/battle/ai/ai.c @@ -261,20 +261,20 @@ AI_SINGLE_BATTLE_TEST("AI chooses the safest option to faint the target, taking u16 abilityAtk = ABILITY_NONE, holdItemAtk = ITEM_NONE; // Psychic is not very effective, but always hits. Solarbeam requires a charging turn, Double Edge has recoil and Focus Blast can miss; - // PARAMETRIZE { abilityAtk = ABILITY_STURDY; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; expectedMove = MOVE_PSYCHIC; } + PARAMETRIZE { abilityAtk = ABILITY_STURDY; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; expectedMove = MOVE_PSYCHIC; } // Same as above, but ai mon has rock head ability, so it can use Double Edge without taking recoil damage. Psychic can also lower Special Defense, // but because it faints the target it doesn't matter. - // PARAMETRIZE { abilityAtk = ABILITY_ROCK_HEAD; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; - // expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_DOUBLE_EDGE; } + PARAMETRIZE { abilityAtk = ABILITY_ROCK_HEAD; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; + expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_DOUBLE_EDGE; } // This time it's Solarbeam + Psychic, because the weather is sunny. PARAMETRIZE { abilityAtk = ABILITY_DROUGHT; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_SOLAR_BEAM; } // Psychic and Solar Beam are chosen because user is holding Power Herb - // PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; - // expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_SOLAR_BEAM; } + PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SOLAR_BEAM; move3 = MOVE_PSYCHIC; move4 = MOVE_DOUBLE_EDGE; + expectedMove = MOVE_PSYCHIC; expectedMove2 = MOVE_SOLAR_BEAM; } // Skull Bash is chosen because it's the most accurate and is holding Power Herb - // PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_SLAM; move4 = MOVE_DOUBLE_EDGE; - // expectedMove = MOVE_SKULL_BASH; } + PARAMETRIZE { abilityAtk = ABILITY_STURDY; holdItemAtk = ITEM_POWER_HERB; move1 = MOVE_FOCUS_BLAST; move2 = MOVE_SKULL_BASH; move3 = MOVE_SLAM; move4 = MOVE_DOUBLE_EDGE; + expectedMove = MOVE_SKULL_BASH; } GIVEN { AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT); From dd985dbb56e97571a167ce036d2954e5553f5499 Mon Sep 17 00:00:00 2001 From: Cafe <46283144+Cafeei@users.noreply.github.com> Date: Fri, 3 Jan 2025 16:49:42 +0400 Subject: [PATCH 14/85] Fix formatting in WSL.md (#5942) --- docs/install/windows/WSL.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/install/windows/WSL.md b/docs/install/windows/WSL.md index 9534966488..a5dcbb4bbc 100644 --- a/docs/install/windows/WSL.md +++ b/docs/install/windows/WSL.md @@ -12,13 +12,13 @@ If you want the best performance and least amount of issues with Windows interfe 2. Once the process finishes, restart your machine. ### WSL1 -3a. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL1. +3. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL1. ```powershell wsl --set-version Ubuntu 1 ``` ### WSL2 -3a. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL2. +3. Open Windows Powershell **as Administrator** again (after restarting), and run the following command to configure Ubuntu to use WSL2. ```powershell wsl --set-version Ubuntu 2 From 8ccb385ce46d74b1b672f0b478752f74d58ac2a7 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 3 Jan 2025 14:15:05 +0100 Subject: [PATCH 15/85] Insomnia test used the wrong move in Turn section (#5939) --- test/battle/ability/insomnia.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/battle/ability/insomnia.c b/test/battle/ability/insomnia.c index 3098ce6d3f..524fa76338 100644 --- a/test/battle/ability/insomnia.c +++ b/test/battle/ability/insomnia.c @@ -26,7 +26,7 @@ SINGLE_BATTLE_TEST("Insomnia prevents yawn") PLAYER(SPECIES_DROWZEE) { Ability(ABILITY_INSOMNIA); } OPPONENT(SPECIES_WOBBUFFET); } WHEN { - TURN { MOVE(opponent, MOVE_SPORE); } + TURN { MOVE(opponent, MOVE_YAWN); } TURN {} TURN {} } SCENE { From c3b0f4dd7f75af3394535651c25f7bf861549eb9 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Fri, 3 Jan 2025 15:47:45 +0100 Subject: [PATCH 16/85] Fixes broken link battles (#5940) Co-authored-by: Hedara --- src/battle_util.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 4dfb39dc66..9245ef21fc 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -285,7 +285,7 @@ void HandleAction_UseMove(void) gBattlerTarget = battler; } } - else if (IsDoubleBattle() && moveTarget & MOVE_TARGET_RANDOM) + else if (IsDoubleBattle() && moveTarget & MOVE_TARGET_RANDOM) { gBattlerTarget = SetRandomTarget(gBattlerAttacker); if (gAbsentBattlerFlags & (1u << gBattlerTarget) @@ -301,7 +301,7 @@ void HandleAction_UseMove(void) else gBattlerTarget = gBattlerAttacker; } - else if (IsDoubleBattle() && moveTarget == MOVE_TARGET_FOES_AND_ALLY) + else if (IsDoubleBattle() && moveTarget == MOVE_TARGET_FOES_AND_ALLY) { for (gBattlerTarget = 0; gBattlerTarget < gBattlersCount; gBattlerTarget++) { @@ -932,22 +932,22 @@ static void UNUSED MarkAllBattlersForControllerExec(void) else { for (i = 0; i < gBattlersCount; i++) - gBattleControllerExecFlags |= 1 << i; + gBattleControllerExecFlags |= 1u << i; } } bool32 IsBattlerMarkedForControllerExec(u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) - return (gBattleControllerExecFlags & (1 << (battler + 28))) != 0; + return (gBattleControllerExecFlags & (1u << (battler + 28))) != 0; else - return (gBattleControllerExecFlags & (1 << battler)) != 0; + return (gBattleControllerExecFlags & (1u << battler)) != 0; } void MarkBattlerForControllerExec(u32 battler) { if (gBattleTypeFlags & BATTLE_TYPE_LINK) - gBattleControllerExecFlags |= 1u << (32 - MAX_BATTLERS_COUNT); + gBattleControllerExecFlags |= 1u << (battler + 32 - MAX_BATTLERS_COUNT); else gBattleControllerExecFlags |= 1u << battler; } From 401df8da4d487a23d136d366ef01e034229c0fde Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Fri, 3 Jan 2025 12:17:23 -0500 Subject: [PATCH 17/85] move overwrittenAbilities field to DisableStruct (#5946) Co-authored-by: ghoulslash --- include/battle.h | 2 +- src/battle_ai_util.c | 4 ++-- src/battle_controllers.c | 2 +- src/battle_main.c | 11 +++-------- src/battle_script_commands.c | 18 +++++++++--------- src/battle_util.c | 8 ++++---- 6 files changed, 20 insertions(+), 25 deletions(-) diff --git a/include/battle.h b/include/battle.h index b38c5115db..978aae60d7 100644 --- a/include/battle.h +++ b/include/battle.h @@ -139,6 +139,7 @@ struct DisableStruct u8 weatherAbilityDone:1; u8 terrainAbilityDone:1; u8 usedProteanLibero:1; + u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) }; struct ProtectStruct @@ -779,7 +780,6 @@ struct BattleStruct u8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects. u8 spriteIgnore0Hp:1; u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit. - u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching) u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party. u8 storedHealingWish:4; // Each battler as a bit. u8 storedLunarDance:4; // Each battler as a bit. diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 798713ef59..7b7621d312 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1347,8 +1347,8 @@ s32 AI_DecideKnownAbilityForTurn(u32 battlerId) u32 abilityAiRatings[NUM_ABILITY_SLOTS] = {0}; // We've had ability overwritten by e.g. Worry Seed. It is not part of AI_PARTY in case of switching - if (gBattleStruct->overwrittenAbilities[battlerId]) - return gBattleStruct->overwrittenAbilities[battlerId]; + if (gDisableStructs[battlerId].overwrittenAbility) + return gDisableStructs[battlerId].overwrittenAbility; // The AI knows its own ability. if (IsAiBattlerAware(battlerId)) diff --git a/src/battle_controllers.c b/src/battle_controllers.c index d5a7290c63..874d122745 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -1616,7 +1616,7 @@ static u32 GetBattlerMonData(u32 battler, struct Pokemon *party, u32 monId, u8 * u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gBattleStruct->overwrittenAbilities[battler] = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif break; diff --git a/src/battle_main.c b/src/battle_main.c index 191d5c8b07..1a0da73142 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3058,7 +3058,6 @@ static void BattleStartClearSetData(void) gBattleStruct->lastTakenMoveFrom[i][3] = MOVE_NONE; gBattleStruct->AI_monToSwitchIntoId[i] = PARTY_SIZE; gBattleStruct->skyDropTargets[i] = 0xFF; - gBattleStruct->overwrittenAbilities[i] = ABILITY_NONE; } gLastUsedMove = 0; @@ -3286,8 +3285,6 @@ void SwitchInClearSetData(u32 battler) // Reset G-Max Chi Strike boosts. gBattleStruct->bonusCritStages[battler] = 0; - gBattleStruct->overwrittenAbilities[battler] = ABILITY_NONE; - // Clear selected party ID so Revival Blessing doesn't get confused. gSelectedMonPartyId = PARTY_SIZE; @@ -3298,7 +3295,7 @@ void SwitchInClearSetData(u32 battler) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[i].ability = gBattleStruct->overwrittenAbilities[i] = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[i].ability = gDisableStructs[i].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif // TESTING @@ -3429,8 +3426,6 @@ const u8* FaintClearSetData(u32 battler) Ai_UpdateFaintData(battler); TryBattleFormChange(battler, FORM_CHANGE_FAINT); - gBattleStruct->overwrittenAbilities[battler] = ABILITY_NONE; - // If the fainted mon was involved in a Sky Drop if (gBattleStruct->skyDropTargets[battler] != 0xFF) { @@ -3537,7 +3532,7 @@ static void DoBattleIntro(void) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gBattleStruct->overwrittenAbilities[battler] = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif } @@ -3853,7 +3848,7 @@ static void TryDoEventsBeforeFirstTurn(void) u32 side = GetBattlerSide(i); u32 partyIndex = gBattlerPartyIndexes[i]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[i].ability = gBattleStruct->overwrittenAbilities[i] = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[i].ability = gDisableStructs[i].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); } } #endif // TESTING diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0e49700e2f..5ccc26244e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7177,7 +7177,7 @@ static void Cmd_switchindataupdate(void) u32 side = GetBattlerSide(battler); u32 partyIndex = gBattlerPartyIndexes[battler]; if (TestRunner_Battle_GetForcedAbility(side, partyIndex)) - gBattleMons[battler].ability = gBattleStruct->overwrittenAbilities[battler] = TestRunner_Battle_GetForcedAbility(side, partyIndex); + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = TestRunner_Battle_GetForcedAbility(side, partyIndex); } #endif @@ -9724,7 +9724,7 @@ static void Cmd_various(void) case VARIOUS_TRACE_ABILITY: { VARIOUS_ARGS(); - gBattleMons[battler].ability = gBattleStruct->overwrittenAbilities[battler] = gBattleStruct->tracedAbility[battler]; + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = gBattleStruct->tracedAbility[battler]; break; } case VARIOUS_TRY_ILLUSION_OFF: @@ -10324,7 +10324,7 @@ static void Cmd_various(void) gSpecialStatuses[gBattlerTarget].neutralizingGasRemoved = TRUE; gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = ABILITY_SIMPLE; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_SIMPLE; gBattlescriptCurrInstr = cmd->nextInstr; } return; @@ -10352,7 +10352,7 @@ static void Cmd_various(void) } else { - gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = gBattleMons[gBattlerAttacker].ability; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; gBattlescriptCurrInstr = cmd->nextInstr; } } @@ -12982,7 +12982,7 @@ static void Cmd_transformdataexecution(void) for (i = 0; i < offsetof(struct BattlePokemon, pp); i++) battleMonAttacker[i] = battleMonTarget[i]; - gBattleStruct->overwrittenAbilities[gBattlerAttacker] = GetBattlerAbility(gBattlerTarget); + gDisableStructs[gBattlerAttacker].overwrittenAbility = GetBattlerAbility(gBattlerTarget); for (i = 0; i < MAX_MON_MOVES; i++) { u32 pp = GetMovePP(gBattleMons[gBattlerAttacker].moves[i]); @@ -14744,7 +14744,7 @@ static void Cmd_trycopyability(void) else { gBattleScripting.abilityPopupOverwrite = gBattleMons[battler].ability; - gBattleMons[battler].ability = gBattleStruct->overwrittenAbilities[battler] = defAbility; + gBattleMons[battler].ability = gDisableStructs[battler].overwrittenAbility = defAbility; gLastUsedAbility = defAbility; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -14935,8 +14935,8 @@ static void Cmd_tryswapabilities(void) if (GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget)) gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerAttacker].ability; gLastUsedAbility = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = gBattleMons[gBattlerAttacker].ability; - gBattleMons[gBattlerAttacker].ability = gBattleStruct->overwrittenAbilities[gBattlerAttacker] = gLastUsedAbility; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gBattleMons[gBattlerAttacker].ability; + gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gLastUsedAbility; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -16245,7 +16245,7 @@ static void Cmd_tryworryseed(void) else { gBattleScripting.abilityPopupOverwrite = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = ABILITY_INSOMNIA; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = ABILITY_INSOMNIA; gBattlescriptCurrInstr = cmd->nextInstr; } } diff --git a/src/battle_util.c b/src/battle_util.c index fd264e4606..8229b648ed 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5747,7 +5747,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerTurnDamaged(gBattlerTarget) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker) - && gBattleStruct->overwrittenAbilities[gBattlerAttacker] != GetBattlerAbility(gBattlerTarget) + && gDisableStructs[gBattlerAttacker].overwrittenAbility != GetBattlerAbility(gBattlerTarget) && gBattleMons[gBattlerAttacker].ability != ABILITY_MUMMY && gBattleMons[gBattlerAttacker].ability != ABILITY_LINGERING_AROMA && !gAbilitiesInfo[gBattleMons[gBattlerAttacker].ability].cantBeSuppressed) @@ -5759,7 +5759,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } gLastUsedAbility = gBattleMons[gBattlerAttacker].ability; - gBattleMons[gBattlerAttacker].ability = gBattleStruct->overwrittenAbilities[gBattlerAttacker] = gBattleMons[gBattlerTarget].ability; + gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gBattleMons[gBattlerTarget].ability; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_MummyActivates; effect++; @@ -5782,8 +5782,8 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } gLastUsedAbility = gBattleMons[gBattlerAttacker].ability; - gBattleMons[gBattlerAttacker].ability = gBattleStruct->overwrittenAbilities[gBattlerAttacker] = gBattleMons[gBattlerTarget].ability; - gBattleMons[gBattlerTarget].ability = gBattleStruct->overwrittenAbilities[gBattlerTarget] = gLastUsedAbility; + gBattleMons[gBattlerAttacker].ability = gDisableStructs[gBattlerAttacker].overwrittenAbility = gBattleMons[gBattlerTarget].ability; + gBattleMons[gBattlerTarget].ability = gDisableStructs[gBattlerTarget].overwrittenAbility = gLastUsedAbility; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_WanderingSpiritActivates; effect++; From 80df54adc6671b94dc1a0a92c271520c42b32190 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 4 Jan 2025 10:56:56 +0100 Subject: [PATCH 18/85] review changes --- src/battle_util.c | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 34d8cadb16..33152376f2 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1672,13 +1672,14 @@ static bool32 TryEndTurnWeather(void) u32 effect = 0; u32 currBattleWeather = 0xFF; - if (gBattleWeather & B_WEATHER_RAIN) currBattleWeather = BATTLE_WEATHER_RAIN; - else if (gBattleWeather & B_WEATHER_SUN) currBattleWeather = BATTLE_WEATHER_SUN; - else if (gBattleWeather & B_WEATHER_SANDSTORM) currBattleWeather = BATTLE_WEATHER_SANDSTORM; - else if (gBattleWeather & B_WEATHER_HAIL) currBattleWeather = BATTLE_WEATHER_HAIL; - else if (gBattleWeather & B_WEATHER_SNOW) currBattleWeather = BATTLE_WEATHER_SNOW; - else if (gBattleWeather & B_WEATHER_FOG) currBattleWeather = BATTLE_WEATHER_FOG; - else if (gBattleWeather & B_WEATHER_STRONG_WINDS) currBattleWeather = BATTLE_WEATHER_STRONG_WINDS; + for (u32 weather = 0; weather < ARRAY_COUNT(sBattleWeatherInfo); weather++) + { + if (gBattleWeather & sBattleWeatherInfo[weather].flag) + { + currBattleWeather = weather; + break; + } + } if (currBattleWeather == 0xFF) return effect; @@ -4013,29 +4014,36 @@ bool32 HasNoMonsToSwitch(u32 battler, u8 partyIdBattlerOn1, u8 partyIdBattlerOn2 bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbility) { u16 battlerAbility = GetBattlerAbility(battler); - if (gBattleWeather & B_WEATHER_PRIMAL_ANY + + if (gBattleWeather & sBattleWeatherInfo[battleWeatherId].flag) + { + return FALSE; + } + else if (gBattleWeather & B_WEATHER_PRIMAL_ANY && battlerAbility != ABILITY_DESOLATE_LAND && battlerAbility != ABILITY_PRIMORDIAL_SEA && battlerAbility != ABILITY_DELTA_STREAM) { return FALSE; } - else if (B_ABILITY_WEATHER < GEN_6 && viaAbility && !(gBattleWeather & sBattleWeatherInfo[battleWeatherId].flag)) + else if (B_ABILITY_WEATHER < GEN_6 && viaAbility) { gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; return TRUE; } - else if (!(gBattleWeather & sBattleWeatherInfo[battleWeatherId].flag)) + else { + u32 rock = sBattleWeatherInfo[battleWeatherId].rock; gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; if (gBattleWeather & B_WEATHER_PRIMAL_ANY) gWishFutureKnock.weatherDuration = 0; - if (GetBattlerHoldEffect(battler, TRUE) == sBattleWeatherInfo[battleWeatherId].rock) + if (rock != 0 && GetBattlerHoldEffect(battler, TRUE) == rock) gWishFutureKnock.weatherDuration = 8; else gWishFutureKnock.weatherDuration = 5; return TRUE; } + return FALSE; } From 9eee076e643519bbe112da1b8e99c769f5225a68 Mon Sep 17 00:00:00 2001 From: AlexOn1ine Date: Sat, 4 Jan 2025 12:16:35 +0100 Subject: [PATCH 19/85] use one iterator --- src/battle_util.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 33152376f2..1f2e301f47 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -1669,14 +1669,15 @@ static bool32 EndTurnTerrain(u32 terrainFlag, u32 stringTableId) static bool32 TryEndTurnWeather(void) { + u32 i = 0; u32 effect = 0; u32 currBattleWeather = 0xFF; - for (u32 weather = 0; weather < ARRAY_COUNT(sBattleWeatherInfo); weather++) + for (i = 0; i < ARRAY_COUNT(sBattleWeatherInfo); i++) { - if (gBattleWeather & sBattleWeatherInfo[weather].flag) + if (gBattleWeather & sBattleWeatherInfo[i].flag) { - currBattleWeather = weather; + currBattleWeather = i; break; } } @@ -1687,7 +1688,7 @@ static bool32 TryEndTurnWeather(void) if (gWishFutureKnock.weatherDuration > 0 && --gWishFutureKnock.weatherDuration == 0) { gBattleWeather = B_WEATHER_NONE; - for (u32 i = 0; i < gBattlersCount; i++) + for (i = 0; i < gBattlersCount; i++) gDisableStructs[i].weatherAbilityDone = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = sBattleWeatherInfo[currBattleWeather].endMessage; BattleScriptExecute(BattleScript_WeatherFaded); From a7f77ed08da33efbb9b31a80c40586571782e39d Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Sat, 4 Jan 2025 05:25:03 -0800 Subject: [PATCH 20/85] Adds B_VAR_DIFFICULTY and related functions READ DESC (#5337) Co-authored-by: sbird Co-authored-by: Philipp AUER Co-authored-by: Martin Griffin Co-authored-by: hedara90 <90hedara@gmail.com> --- asm/macros/event.inc | 16 + data/event_scripts.s | 1 + include/config/battle.h | 1 + include/config/test.h | 4 + include/constants/battle_partner.h | 5 +- include/constants/difficulty.h | 15 + include/data.h | 66 +- include/difficulty.h | 17 + src/battle_controller_player_partner.c | 7 +- src/battle_message.c | 67 +- src/battle_tower.c | 21 +- src/data.c | 2 +- src/data/battle_partners.h | 4 +- src/data/trainers.h | 1710 ++++++++++++------------ src/difficulty.c | 95 ++ src/new_game.c | 2 + src/pokemon.c | 7 +- test/battle/trainer_control.c | 66 +- test/battle/trainer_control.h | 157 ++- test/battle/trainer_control.party | 60 + tools/trainerproc/main.c | 43 +- 21 files changed, 1432 insertions(+), 934 deletions(-) create mode 100644 include/constants/difficulty.h create mode 100644 include/difficulty.h create mode 100644 src/difficulty.c diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 1a01779702..2bb2027cb1 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -2437,3 +2437,19 @@ .2byte \dest .endm + .macro increasedifficulty + callnative Script_IncreaseDifficulty + .endm + + .macro decreasedifficulty + callnative Script_DecreaseDifficulty + .endm + + .macro getdifficulty var:req + callnative Script_GetDifficulty + .endm + + .macro setdifficulty difficulty:req + callnative Script_SetDifficulty + .byte \difficulty + .endm diff --git a/data/event_scripts.s b/data/event_scripts.s index 4d5e0a3393..71bc884308 100644 --- a/data/event_scripts.s +++ b/data/event_scripts.s @@ -20,6 +20,7 @@ #include "constants/contest.h" #include "constants/daycare.h" #include "constants/decorations.h" +#include "constants/difficulty.h" #include "constants/easy_chat.h" #include "constants/event_objects.h" #include "constants/event_object_movement.h" diff --git a/include/config/battle.h b/include/config/battle.h index 117e0cc31c..a834d01869 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -206,6 +206,7 @@ #define B_VAR_STARTING_STATUS 0 // If this var has a value, assigning a STATUS_FIELD_xx_TERRAIN to it before battle causes the battle to start with that terrain active. #define B_VAR_STARTING_STATUS_TIMER 0 // If this var has a value greater or equal than 1 field terrains will last that number of turns, otherwise they will last until they're overwritten. #define B_VAR_WILD_AI_FLAGS 0 // If not 0, you can use this var to add to default wild AI flags. NOT usable with flags above (1 << 15) +#define B_VAR_DIFFICULTY 0 // If not 0, you can use this var to control which difficulty version of a Trainer is loaded. This should be manually set by the developer using Script_SetDifficulty AFTER NewGameInitData has run. // Sky Battles #define B_FLAG_SKY_BATTLE 0 // If this flag has a value, the player will be able to engage in scripted Sky Battles. diff --git a/include/config/test.h b/include/config/test.h index cce97484df..90cf5a4b88 100644 --- a/include/config/test.h +++ b/include/config/test.h @@ -1129,6 +1129,10 @@ #undef P_FAMILY_PECHARUNT #define P_FAMILY_PECHARUNT TRUE +// Vars +#undef B_VAR_DIFFICULTY +#define B_VAR_DIFFICULTY VAR_UNUSED_0x404E + // Flags #undef B_FLAG_SLEEP_CLAUSE #define B_FLAG_SLEEP_CLAUSE FLAG_SPECIAL_FLAG_UNUSED_0x4003 diff --git a/include/constants/battle_partner.h b/include/constants/battle_partner.h index 5622349a88..c609ee5aa2 100644 --- a/include/constants/battle_partner.h +++ b/include/constants/battle_partner.h @@ -2,7 +2,8 @@ #ifndef GUARD_CONSTANTS_BATTLE_PARTNERS_H #define GUARD_CONSTANTS_BATTLE_PARTNERS_H -#define PARTNER_NONE 0 -#define PARTNER_STEVEN 1 +#define PARTNER_NONE 0 +#define PARTNER_STEVEN 1 +#define PARTNER_COUNT 2 #endif // GUARD_CONSTANTS_BATTLE_PARTNERS_H diff --git a/include/constants/difficulty.h b/include/constants/difficulty.h new file mode 100644 index 0000000000..44ef8d9d71 --- /dev/null +++ b/include/constants/difficulty.h @@ -0,0 +1,15 @@ +#ifndef GUARD_DIFFICULTY_CONSTANTS_H +#define GUARD_DIFFICULTY_CONSTANTS_H + +enum DifficultyLevel +{ + DIFFICULTY_EASY, + DIFFICULTY_NORMAL, //If you rename this, the word "Normal" in fprint_trainers must be replaced with the new difficulty name. + DIFFICULTY_HARD, + DIFFICULTY_COUNT, +}; + +#define DIFFICULTY_MIN 0 +#define DIFFICULTY_MAX (DIFFICULTY_COUNT - 1) + +#endif // GUARD_DIFFICULTY_CONSTANTS_H diff --git a/include/data.h b/include/data.h index 8d90d679b3..ad3cf4ec1e 100644 --- a/include/data.h +++ b/include/data.h @@ -3,6 +3,8 @@ #include "constants/moves.h" #include "constants/trainers.h" +#include "constants/battle.h" +#include "difficulty.h" #define MAX_TRAINER_ITEMS 4 @@ -164,8 +166,8 @@ extern const union AnimCmd *const sAnims_Trainer[]; extern const struct TrainerSprite gTrainerSprites[]; extern const struct TrainerBacksprite gTrainerBacksprites[]; -extern const struct Trainer gTrainers[]; -extern const struct Trainer gBattlePartners[]; +extern const struct Trainer gTrainers[DIFFICULTY_COUNT][TRAINERS_COUNT]; +extern const struct Trainer gBattlePartners[DIFFICULTY_COUNT][PARTNER_COUNT]; extern const struct TrainerClass gTrainerClasses[TRAINER_CLASS_COUNT]; @@ -191,71 +193,103 @@ static inline u16 SanitizeTrainerId(u16 trainerId) static inline const struct Trainer *GetTrainerStructFromId(u16 trainerId) { - return &gTrainers[SanitizeTrainerId(trainerId)]; + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + return &gTrainers[difficulty][sanitizedTrainerId]; } static inline const u8 GetTrainerClassFromId(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].trainerClass; + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + return gTrainers[difficulty][sanitizedTrainerId].trainerClass; } static inline const u8 *GetTrainerClassNameFromId(u16 trainerId) { + enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(trainerId); + if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) - return gTrainerClasses[gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerClass].name; + return gTrainerClasses[gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerClass].name; return gTrainerClasses[GetTrainerClassFromId(trainerId)].name; } static inline const u8 *GetTrainerNameFromId(u16 trainerId) { + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + enum DifficultyLevel partnerDifficulty = GetBattlePartnerDifficultyLevel(trainerId); + if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) - return gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName; - return gTrainers[SanitizeTrainerId(trainerId)].trainerName; + return gBattlePartners[partnerDifficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName; + return gTrainers[difficulty][sanitizedTrainerId].trainerName; } static inline const u8 GetTrainerPicFromId(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].trainerPic; + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + return gTrainers[difficulty][sanitizedTrainerId].trainerPic; } static inline const u8 GetTrainerStartingStatusFromId(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].startingStatus; + return gTrainers[GetCurrentDifficultyLevel()][SanitizeTrainerId(trainerId)].startingStatus; } static inline const bool32 IsTrainerDoubleBattle(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].doubleBattle; + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + return gTrainers[difficulty][sanitizedTrainerId].doubleBattle; } static inline const u8 GetTrainerPartySizeFromId(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].partySize; + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + return gTrainers[difficulty][sanitizedTrainerId].partySize; } static inline const bool32 DoesTrainerHaveMugshot(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].mugshotColor; + return gTrainers[GetCurrentDifficultyLevel()][SanitizeTrainerId(trainerId)].mugshotColor; } static inline const u8 GetTrainerMugshotColorFromId(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].mugshotColor; + return gTrainers[GetCurrentDifficultyLevel()][SanitizeTrainerId(trainerId)].mugshotColor; } static inline const u16 *GetTrainerItemsFromId(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].items; + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + return gTrainers[difficulty][sanitizedTrainerId].items; } static inline const struct TrainerMon *GetTrainerPartyFromId(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].party; + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + return gTrainers[difficulty][sanitizedTrainerId].party; } static inline const bool32 GetTrainerAIFlagsFromId(u16 trainerId) { - return gTrainers[SanitizeTrainerId(trainerId)].aiFlags; + u32 sanitizedTrainerId = SanitizeTrainerId(trainerId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + + return gTrainers[difficulty][sanitizedTrainerId].aiFlags; } #endif // GUARD_DATA_H diff --git a/include/difficulty.h b/include/difficulty.h new file mode 100644 index 0000000000..c8443367c9 --- /dev/null +++ b/include/difficulty.h @@ -0,0 +1,17 @@ +#ifndef GUARD_DIFFICULTY_H +#define GUARD_DIFFICULTY_H + +#include "constants/difficulty.h" +#include "script.h" + +enum DifficultyLevel GetCurrentDifficultyLevel(void); +void SetCurrentDifficultyLevel(enum DifficultyLevel); + +enum DifficultyLevel GetBattlePartnerDifficultyLevel(u16); +enum DifficultyLevel GetTrainerDifficultyLevel(u16); +void Script_IncreaseDifficulty(void); +void Script_DecreaseDifficulty(void); +void Script_GetDifficulty(void); +void Script_SetDifficulty(struct ScriptContext *); + +#endif // GUARD_DIFFICULTY_H diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 81170ec9de..8bb2bd9993 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -297,9 +297,11 @@ static void PlayerPartnerHandleDrawTrainerPic(u32 battler) s16 xPos, yPos; u32 trainerPicId; + enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(gPartnerTrainerId); + if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) { - trainerPicId = gBattlePartners[gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic; + trainerPicId = gBattlePartners[difficulty][gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic; xPos = 90; yPos = (8 - gTrainerBacksprites[trainerPicId].coordinates.size) * 4 + 80; } @@ -427,9 +429,10 @@ static void PlayerPartnerHandleHealthBarUpdate(u32 battler) static void PlayerPartnerHandleIntroTrainerBallThrow(u32 battler) { const u32 *trainerPal; + enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(gPartnerTrainerId); if (gPartnerTrainerId > TRAINER_PARTNER(PARTNER_NONE)) - trainerPal = gTrainerBacksprites[gBattlePartners[gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic].palette.data; + trainerPal = gTrainerBacksprites[gBattlePartners[difficulty][gPartnerTrainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerPic].palette.data; else if (IsAiVsAiBattle()) trainerPal = gTrainerSprites[GetTrainerPicFromId(gPartnerTrainerId)].palette.data; else diff --git a/src/battle_message.c b/src/battle_message.c index f11eb4a66d..de02a27ea3 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3560,8 +3560,10 @@ struct TrainerSlide const u8 *msgDynamax; }; -static const struct TrainerSlide sTrainerSlides[] = +static const struct TrainerSlide sTrainerSlides[DIFFICULTY_COUNT][TRAINERS_COUNT] = { + [DIFFICULTY_NORMAL] = + { /* Put any trainer slide-in messages inside this array. Example: { @@ -3580,7 +3582,14 @@ static const struct TrainerSlide sTrainerSlides[] = .msgBeforeFirstTurn = sText_GravityIntensified, .msgDynamax = sText_TargetWokeUp, }, + }, + [DIFFICULTY_EASY] = + { + }, + [DIFFICULTY_HARD] = + { */ + }, }; static u32 GetEnemyMonCount(u32 firstId, u32 lastId, bool32 onlyAlive) @@ -3657,118 +3666,120 @@ u32 ShouldDoTrainerSlide(u32 battler, u32 which) trainerId = gTrainerBattleOpponent_A; } + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(trainerId); + for (i = 0; i < ARRAY_COUNT(sTrainerSlides); i++) { - if (trainerId == sTrainerSlides[i].trainerId - && (((gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && sTrainerSlides[i].isFrontierTrainer) - || (!(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && !sTrainerSlides[i].isFrontierTrainer))) + if (trainerId == sTrainerSlides[difficulty]->trainerId + && (((gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && sTrainerSlides[difficulty]->isFrontierTrainer) + || (!(gBattleTypeFlags & BATTLE_TYPE_FRONTIER) && !sTrainerSlides[difficulty]->isFrontierTrainer))) { gBattleScripting.battler = battler; switch (which) { case TRAINER_SLIDE_LAST_SWITCHIN: - if (sTrainerSlides[i].msgLastSwitchIn != NULL && !CanBattlerSwitch(battler)) + if (sTrainerSlides[difficulty]->msgLastSwitchIn != NULL && !CanBattlerSwitch(battler)) { - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastSwitchIn; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgLastSwitchIn; return retValue; } break; case TRAINER_SLIDE_LAST_LOW_HP: - if (sTrainerSlides[i].msgLastLowHp != NULL + if (sTrainerSlides[difficulty]->msgLastLowHp != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == 1 && BattlerHPPercentage(battler, LESS_THAN_OR_EQUAL, 4) && !gBattleStruct->trainerSlideLowHpMsgDone) { gBattleStruct->trainerSlideLowHpMsgDone = TRUE; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastLowHp; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgLastLowHp; return retValue; } break; case TRAINER_SLIDE_FIRST_DOWN: - if (sTrainerSlides[i].msgFirstDown != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1) + if (sTrainerSlides[difficulty]->msgFirstDown != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1) { - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstDown; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgFirstDown; return retValue; } break; case TRAINER_SLIDE_LAST_HALF_HP: - if (sTrainerSlides[i].msgLastHalfHp != NULL + if (sTrainerSlides[difficulty]->msgLastHalfHp != NULL && GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE) - 1 && BattlerHPPercentage(battler, LESS_THAN_OR_EQUAL, 2) && BattlerHPPercentage(battler, GREATER_THAN, 4) && !gBattleStruct->trainerSlideHalfHpMsgDone) { gBattleStruct->trainerSlideHalfHpMsgDone = TRUE; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgLastHalfHp; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgLastHalfHp; return TRUE; } break; case TRAINER_SLIDE_FIRST_CRITICAL_HIT: - if (sTrainerSlides[i].msgFirstCriticalHit != NULL && gBattleStruct->trainerSlideFirstCriticalHitMsgState == 1) + if (sTrainerSlides[difficulty]->msgFirstCriticalHit != NULL && gBattleStruct->trainerSlideFirstCriticalHitMsgState == 1) { gBattleStruct->trainerSlideFirstCriticalHitMsgState = 2; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstCriticalHit; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgFirstCriticalHit; return TRUE; } break; case TRAINER_SLIDE_FIRST_SUPER_EFFECTIVE_HIT: - if (sTrainerSlides[i].msgFirstSuperEffectiveHit != NULL + if (sTrainerSlides[difficulty]->msgFirstSuperEffectiveHit != NULL && gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState == 1 && gBattleMons[battler].hp) { gBattleStruct->trainerSlideFirstSuperEffectiveHitMsgState = 2; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSuperEffectiveHit; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgFirstSuperEffectiveHit; return TRUE; } break; case TRAINER_SLIDE_FIRST_STAB_MOVE: - if (sTrainerSlides[i].msgFirstSTABMove != NULL + if (sTrainerSlides[difficulty]->msgFirstSTABMove != NULL && gBattleStruct->trainerSlideFirstSTABMoveMsgState == 1 && GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE)) { gBattleStruct->trainerSlideFirstSTABMoveMsgState = 2; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgFirstSTABMove; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgFirstSTABMove; return TRUE; } break; case TRAINER_SLIDE_PLAYER_MON_UNAFFECTED: - if (sTrainerSlides[i].msgPlayerMonUnaffected != NULL + if (sTrainerSlides[difficulty]->msgPlayerMonUnaffected != NULL && gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState == 1 && GetEnemyMonCount(firstId, lastId, TRUE) == GetEnemyMonCount(firstId, lastId, FALSE)) { gBattleStruct->trainerSlidePlayerMonUnaffectedMsgState = 2; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgPlayerMonUnaffected; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgPlayerMonUnaffected; return TRUE; } break; case TRAINER_SLIDE_MEGA_EVOLUTION: - if (sTrainerSlides[i].msgMegaEvolution != NULL && !gBattleStruct->trainerSlideMegaEvolutionMsgDone) + if (sTrainerSlides[difficulty]->msgMegaEvolution != NULL && !gBattleStruct->trainerSlideMegaEvolutionMsgDone) { gBattleStruct->trainerSlideMegaEvolutionMsgDone = TRUE; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgMegaEvolution; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgMegaEvolution; return TRUE; } break; case TRAINER_SLIDE_Z_MOVE: - if (sTrainerSlides[i].msgZMove != NULL && !gBattleStruct->trainerSlideZMoveMsgDone) + if (sTrainerSlides[difficulty]->msgZMove != NULL && !gBattleStruct->trainerSlideZMoveMsgDone) { gBattleStruct->trainerSlideZMoveMsgDone = TRUE; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgZMove; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgZMove; return TRUE; } break; case TRAINER_SLIDE_BEFORE_FIRST_TURN: - if (sTrainerSlides[i].msgBeforeFirstTurn != NULL && !gBattleStruct->trainerSlideBeforeFirstTurnMsgDone) + if (sTrainerSlides[difficulty]->msgBeforeFirstTurn != NULL && !gBattleStruct->trainerSlideBeforeFirstTurnMsgDone) { gBattleStruct->trainerSlideBeforeFirstTurnMsgDone = TRUE; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgBeforeFirstTurn; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgBeforeFirstTurn; return TRUE; } break; case TRAINER_SLIDE_DYNAMAX: - if (sTrainerSlides[i].msgDynamax != NULL && !gBattleStruct->trainerSlideDynamaxMsgDone) + if (sTrainerSlides[difficulty]->msgDynamax != NULL && !gBattleStruct->trainerSlideDynamaxMsgDone) { gBattleStruct->trainerSlideDynamaxMsgDone = TRUE; - gBattleStruct->trainerSlideMsg = sTrainerSlides[i].msgDynamax; + gBattleStruct->trainerSlideMsg = sTrainerSlides[difficulty]->msgDynamax; return TRUE; } break; diff --git a/src/battle_tower.c b/src/battle_tower.c index 9eda82f1b5..18b3d33886 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -699,7 +699,7 @@ static const u8 *const *const sPartnerApprenticeTextTables[NUM_APPRENTICES] = #include "data/battle_frontier/battle_tent.h" #include "data/partner_parties.h" -const struct Trainer gBattlePartners[] = +const struct Trainer gBattlePartners[DIFFICULTY_COUNT][PARTNER_COUNT] = { #include "data/battle_partners.h" }; @@ -1355,6 +1355,7 @@ u8 GetFrontierTrainerFrontSpriteId(u16 trainerId) u8 GetFrontierOpponentClass(u16 trainerId) { u8 trainerClass = 0; + enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(trainerId); SetFacilityPtrsGetLevel(); #if FREE_BATTLE_TOWER_E_READER == FALSE @@ -1371,7 +1372,7 @@ u8 GetFrontierOpponentClass(u16 trainerId) } else if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) { - trainerClass = gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerClass; + trainerClass = gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerClass; } else if (trainerId < FRONTIER_TRAINERS_COUNT) { @@ -1441,6 +1442,7 @@ static u8 GetFrontierTrainerFacilityClass(u16 trainerId) void GetFrontierTrainerName(u8 *dst, u16 trainerId) { s32 i = 0; + enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(trainerId); SetFacilityPtrsGetLevel(); if (trainerId == TRAINER_EREADER) @@ -1457,8 +1459,8 @@ void GetFrontierTrainerName(u8 *dst, u16 trainerId) } else if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) { - for (i = 0; gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName[i] != EOS; i++) - dst[i] = gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName[i]; + for (i = 0; gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName[i] != EOS; i++) + dst[i] = gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName[i]; } else if (trainerId < FRONTIER_TRAINERS_COUNT) { @@ -2965,6 +2967,7 @@ static void FillPartnerParty(u16 trainerId) u32 otID; u8 trainerName[(PLAYER_NAME_LENGTH * 3) + 1]; s32 ball = -1; + enum DifficultyLevel difficulty = GetBattlePartnerDifficultyLevel(trainerId); SetFacilityPtrsGetLevel(); if (trainerId > TRAINER_PARTNER(PARTNER_NONE)) @@ -2972,10 +2975,10 @@ static void FillPartnerParty(u16 trainerId) for (i = 0; i < 3; i++) ZeroMonData(&gPlayerParty[i + 3]); - for (i = 0; i < 3 && i < gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].partySize; i++) + for (i = 0; i < 3 && i < gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].partySize; i++) { - const struct TrainerMon *partyData = gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].party; - const u8 *partnerName = gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName; + const struct TrainerMon *partyData = gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].party; + const u8 *partnerName = gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName; for (k = 0; partnerName[k] != EOS && k < 3; k++) { @@ -3046,9 +3049,9 @@ static void FillPartnerParty(u16 trainerId) } CalculateMonStats(&gPlayerParty[i + 3]); - StringCopy(trainerName, gBattlePartners[trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName); + StringCopy(trainerName, gBattlePartners[difficulty][trainerId - TRAINER_PARTNER(PARTNER_NONE)].trainerName); SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_NAME, trainerName); - j = gBattlePartners[SanitizeTrainerId(trainerId - TRAINER_PARTNER(PARTNER_NONE))].encounterMusic_gender >> 7; + j = gBattlePartners[difficulty][SanitizeTrainerId(trainerId - TRAINER_PARTNER(PARTNER_NONE))].encounterMusic_gender >> 7; SetMonData(&gPlayerParty[i + 3], MON_DATA_OT_GENDER, &j); } } diff --git a/src/data.c b/src/data.c index ccb6b4c623..e50fa0c549 100644 --- a/src/data.c +++ b/src/data.c @@ -227,7 +227,7 @@ const union AnimCmd *const sAnims_Trainer[] ={ #include "data/trainer_parties.h" -const struct Trainer gTrainers[] = +const struct Trainer gTrainers[DIFFICULTY_COUNT][TRAINERS_COUNT] = { #include "data/trainers.h" }; diff --git a/src/data/battle_partners.h b/src/data/battle_partners.h index 95866d24fa..ce451e0a4e 100644 --- a/src/data/battle_partners.h +++ b/src/data/battle_partners.h @@ -9,7 +9,7 @@ #line 1 "src/data/battle_partners.party" #line 1 - [PARTNER_NONE] = + [DIFFICULTY_NORMAL][PARTNER_NONE] = { #line 3 .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, @@ -24,7 +24,7 @@ }, }, #line 8 - [PARTNER_STEVEN] = + [DIFFICULTY_NORMAL][PARTNER_STEVEN] = { #line 9 .trainerName = _("STEVEN"), diff --git a/src/data/trainers.h b/src/data/trainers.h index f8e0952716..a491b482ed 100644 --- a/src/data/trainers.h +++ b/src/data/trainers.h @@ -9,7 +9,7 @@ #line 1 "src/data/trainers.party" #line 76 - [TRAINER_NONE] = + [DIFFICULTY_NORMAL][TRAINER_NONE] = { #line 78 .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, @@ -26,7 +26,7 @@ }, }, #line 84 - [TRAINER_SAWYER_1] = + [DIFFICULTY_NORMAL][TRAINER_SAWYER_1] = { #line 85 .trainerName = _("SAWYER"), @@ -58,7 +58,7 @@ }, }, #line 97 - [TRAINER_GRUNT_AQUA_HIDEOUT_1] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_1] = { #line 98 .trainerName = _("GRUNT"), @@ -90,7 +90,7 @@ }, }, #line 110 - [TRAINER_GRUNT_AQUA_HIDEOUT_2] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_2] = { #line 111 .trainerName = _("GRUNT"), @@ -133,7 +133,7 @@ }, }, #line 127 - [TRAINER_GRUNT_AQUA_HIDEOUT_3] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_3] = { #line 128 .trainerName = _("GRUNT"), @@ -165,7 +165,7 @@ }, }, #line 140 - [TRAINER_GRUNT_AQUA_HIDEOUT_4] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_4] = { #line 141 .trainerName = _("GRUNT"), @@ -197,7 +197,7 @@ }, }, #line 153 - [TRAINER_GRUNT_SEAFLOOR_CAVERN_1] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_1] = { #line 154 .trainerName = _("GRUNT"), @@ -229,7 +229,7 @@ }, }, #line 166 - [TRAINER_GRUNT_SEAFLOOR_CAVERN_2] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_2] = { #line 167 .trainerName = _("GRUNT"), @@ -261,7 +261,7 @@ }, }, #line 179 - [TRAINER_GRUNT_SEAFLOOR_CAVERN_3] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_3] = { #line 180 .trainerName = _("GRUNT"), @@ -293,7 +293,7 @@ }, }, #line 192 - [TRAINER_GABRIELLE_1] = + [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_1] = { #line 193 .trainerName = _("GABRIELLE"), @@ -382,7 +382,7 @@ F_TRAINER_FEMALE | }, }, #line 225 - [TRAINER_GRUNT_PETALBURG_WOODS] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_PETALBURG_WOODS] = { #line 226 .trainerName = _("GRUNT"), @@ -414,7 +414,7 @@ F_TRAINER_FEMALE | }, }, #line 238 - [TRAINER_MARCEL] = + [DIFFICULTY_NORMAL][TRAINER_MARCEL] = { #line 239 .trainerName = _("MARCEL"), @@ -459,7 +459,7 @@ F_TRAINER_FEMALE | }, }, #line 256 - [TRAINER_ALBERTO] = + [DIFFICULTY_NORMAL][TRAINER_ALBERTO] = { #line 257 .trainerName = _("ALBERTO"), @@ -502,7 +502,7 @@ F_TRAINER_FEMALE | }, }, #line 273 - [TRAINER_ED] = + [DIFFICULTY_NORMAL][TRAINER_ED] = { #line 274 .trainerName = _("ED"), @@ -545,7 +545,7 @@ F_TRAINER_FEMALE | }, }, #line 290 - [TRAINER_GRUNT_SEAFLOOR_CAVERN_4] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_4] = { #line 291 .trainerName = _("GRUNT"), @@ -579,7 +579,7 @@ F_TRAINER_FEMALE | }, }, #line 303 - [TRAINER_DECLAN] = + [DIFFICULTY_NORMAL][TRAINER_DECLAN] = { #line 304 .trainerName = _("DECLAN"), @@ -611,7 +611,7 @@ F_TRAINER_FEMALE | }, }, #line 316 - [TRAINER_GRUNT_RUSTURF_TUNNEL] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_RUSTURF_TUNNEL] = { #line 317 .trainerName = _("GRUNT"), @@ -643,7 +643,7 @@ F_TRAINER_FEMALE | }, }, #line 329 - [TRAINER_GRUNT_WEATHER_INST_1] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_1] = { #line 330 .trainerName = _("GRUNT"), @@ -686,7 +686,7 @@ F_TRAINER_FEMALE | }, }, #line 346 - [TRAINER_GRUNT_WEATHER_INST_2] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_2] = { #line 347 .trainerName = _("GRUNT"), @@ -729,7 +729,7 @@ F_TRAINER_FEMALE | }, }, #line 363 - [TRAINER_GRUNT_WEATHER_INST_3] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_3] = { #line 364 .trainerName = _("GRUNT"), @@ -783,7 +783,7 @@ F_TRAINER_FEMALE | }, }, #line 384 - [TRAINER_GRUNT_MUSEUM_1] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MUSEUM_1] = { #line 385 .trainerName = _("GRUNT"), @@ -815,7 +815,7 @@ F_TRAINER_FEMALE | }, }, #line 397 - [TRAINER_GRUNT_MUSEUM_2] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MUSEUM_2] = { #line 398 .trainerName = _("GRUNT"), @@ -858,7 +858,7 @@ F_TRAINER_FEMALE | }, }, #line 414 - [TRAINER_GRUNT_SPACE_CENTER_1] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_1] = { #line 415 .trainerName = _("GRUNT"), @@ -890,7 +890,7 @@ F_TRAINER_FEMALE | }, }, #line 427 - [TRAINER_GRUNT_MT_PYRE_1] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_PYRE_1] = { #line 428 .trainerName = _("GRUNT"), @@ -922,7 +922,7 @@ F_TRAINER_FEMALE | }, }, #line 440 - [TRAINER_GRUNT_MT_PYRE_2] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_PYRE_2] = { #line 441 .trainerName = _("GRUNT"), @@ -954,7 +954,7 @@ F_TRAINER_FEMALE | }, }, #line 453 - [TRAINER_GRUNT_MT_PYRE_3] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_PYRE_3] = { #line 454 .trainerName = _("GRUNT"), @@ -997,7 +997,7 @@ F_TRAINER_FEMALE | }, }, #line 470 - [TRAINER_GRUNT_WEATHER_INST_4] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_4] = { #line 471 .trainerName = _("GRUNT"), @@ -1031,7 +1031,7 @@ F_TRAINER_FEMALE | }, }, #line 483 - [TRAINER_GRUNT_AQUA_HIDEOUT_5] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_5] = { #line 484 .trainerName = _("GRUNT"), @@ -1065,7 +1065,7 @@ F_TRAINER_FEMALE | }, }, #line 496 - [TRAINER_GRUNT_AQUA_HIDEOUT_6] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_6] = { #line 497 .trainerName = _("GRUNT"), @@ -1099,7 +1099,7 @@ F_TRAINER_FEMALE | }, }, #line 509 - [TRAINER_FREDRICK] = + [DIFFICULTY_NORMAL][TRAINER_FREDRICK] = { #line 510 .trainerName = _("FREDRICK"), @@ -1142,7 +1142,7 @@ F_TRAINER_FEMALE | }, }, #line 526 - [TRAINER_MATT] = + [DIFFICULTY_NORMAL][TRAINER_MATT] = { #line 527 .trainerName = _("MATT"), @@ -1187,7 +1187,7 @@ F_TRAINER_FEMALE | }, }, #line 544 - [TRAINER_ZANDER] = + [DIFFICULTY_NORMAL][TRAINER_ZANDER] = { #line 545 .trainerName = _("ZANDER"), @@ -1219,7 +1219,7 @@ F_TRAINER_FEMALE | }, }, #line 557 - [TRAINER_SHELLY_WEATHER_INSTITUTE] = + [DIFFICULTY_NORMAL][TRAINER_SHELLY_WEATHER_INSTITUTE] = { #line 558 .trainerName = _("SHELLY"), @@ -1264,7 +1264,7 @@ F_TRAINER_FEMALE | }, }, #line 574 - [TRAINER_SHELLY_SEAFLOOR_CAVERN] = + [DIFFICULTY_NORMAL][TRAINER_SHELLY_SEAFLOOR_CAVERN] = { #line 575 .trainerName = _("SHELLY"), @@ -1309,7 +1309,7 @@ F_TRAINER_FEMALE | }, }, #line 591 - [TRAINER_ARCHIE] = + [DIFFICULTY_NORMAL][TRAINER_ARCHIE] = { #line 592 .trainerName = _("ARCHIE"), @@ -1365,7 +1365,7 @@ F_TRAINER_FEMALE | }, }, #line 613 - [TRAINER_LEAH] = + [DIFFICULTY_NORMAL][TRAINER_LEAH] = { #line 614 .trainerName = _("LEAH"), @@ -1399,7 +1399,7 @@ F_TRAINER_FEMALE | }, }, #line 626 - [TRAINER_DAISY] = + [DIFFICULTY_NORMAL][TRAINER_DAISY] = { #line 627 .trainerName = _("DAISY"), @@ -1444,7 +1444,7 @@ F_TRAINER_FEMALE | }, }, #line 643 - [TRAINER_ROSE_1] = + [DIFFICULTY_NORMAL][TRAINER_ROSE_1] = { #line 644 .trainerName = _("ROSE"), @@ -1500,7 +1500,7 @@ F_TRAINER_FEMALE | }, }, #line 664 - [TRAINER_FELIX] = + [DIFFICULTY_NORMAL][TRAINER_FELIX] = { #line 665 .trainerName = _("FELIX"), @@ -1554,7 +1554,7 @@ F_TRAINER_FEMALE | }, }, #line 685 - [TRAINER_VIOLET] = + [DIFFICULTY_NORMAL][TRAINER_VIOLET] = { #line 686 .trainerName = _("VIOLET"), @@ -1599,7 +1599,7 @@ F_TRAINER_FEMALE | }, }, #line 702 - [TRAINER_ROSE_2] = + [DIFFICULTY_NORMAL][TRAINER_ROSE_2] = { #line 703 .trainerName = _("ROSE"), @@ -1644,7 +1644,7 @@ F_TRAINER_FEMALE | }, }, #line 719 - [TRAINER_ROSE_3] = + [DIFFICULTY_NORMAL][TRAINER_ROSE_3] = { #line 720 .trainerName = _("ROSE"), @@ -1700,7 +1700,7 @@ F_TRAINER_FEMALE | }, }, #line 740 - [TRAINER_ROSE_4] = + [DIFFICULTY_NORMAL][TRAINER_ROSE_4] = { #line 741 .trainerName = _("ROSE"), @@ -1756,7 +1756,7 @@ F_TRAINER_FEMALE | }, }, #line 761 - [TRAINER_ROSE_5] = + [DIFFICULTY_NORMAL][TRAINER_ROSE_5] = { #line 762 .trainerName = _("ROSE"), @@ -1812,7 +1812,7 @@ F_TRAINER_FEMALE | }, }, #line 782 - [TRAINER_DUSTY_1] = + [DIFFICULTY_NORMAL][TRAINER_DUSTY_1] = { #line 783 .trainerName = _("DUSTY"), @@ -1851,7 +1851,7 @@ F_TRAINER_FEMALE | }, }, #line 799 - [TRAINER_CHIP] = + [DIFFICULTY_NORMAL][TRAINER_CHIP] = { #line 800 .trainerName = _("CHIP"), @@ -1926,7 +1926,7 @@ F_TRAINER_FEMALE | }, }, #line 832 - [TRAINER_FOSTER] = + [DIFFICULTY_NORMAL][TRAINER_FOSTER] = { #line 833 .trainerName = _("FOSTER"), @@ -1983,7 +1983,7 @@ F_TRAINER_FEMALE | }, }, #line 857 - [TRAINER_DUSTY_2] = + [DIFFICULTY_NORMAL][TRAINER_DUSTY_2] = { #line 858 .trainerName = _("DUSTY"), @@ -2022,7 +2022,7 @@ F_TRAINER_FEMALE | }, }, #line 874 - [TRAINER_DUSTY_3] = + [DIFFICULTY_NORMAL][TRAINER_DUSTY_3] = { #line 875 .trainerName = _("DUSTY"), @@ -2061,7 +2061,7 @@ F_TRAINER_FEMALE | }, }, #line 891 - [TRAINER_DUSTY_4] = + [DIFFICULTY_NORMAL][TRAINER_DUSTY_4] = { #line 892 .trainerName = _("DUSTY"), @@ -2100,7 +2100,7 @@ F_TRAINER_FEMALE | }, }, #line 908 - [TRAINER_DUSTY_5] = + [DIFFICULTY_NORMAL][TRAINER_DUSTY_5] = { #line 909 .trainerName = _("DUSTY"), @@ -2139,7 +2139,7 @@ F_TRAINER_FEMALE | }, }, #line 925 - [TRAINER_GABBY_AND_TY_1] = + [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_1] = { #line 926 .trainerName = _("GABBY & TY"), @@ -2182,7 +2182,7 @@ F_TRAINER_FEMALE | }, }, #line 942 - [TRAINER_GABBY_AND_TY_2] = + [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_2] = { #line 943 .trainerName = _("GABBY & TY"), @@ -2225,7 +2225,7 @@ F_TRAINER_FEMALE | }, }, #line 959 - [TRAINER_GABBY_AND_TY_3] = + [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_3] = { #line 960 .trainerName = _("GABBY & TY"), @@ -2268,7 +2268,7 @@ F_TRAINER_FEMALE | }, }, #line 976 - [TRAINER_GABBY_AND_TY_4] = + [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_4] = { #line 977 .trainerName = _("GABBY & TY"), @@ -2311,7 +2311,7 @@ F_TRAINER_FEMALE | }, }, #line 993 - [TRAINER_GABBY_AND_TY_5] = + [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_5] = { #line 994 .trainerName = _("GABBY & TY"), @@ -2354,7 +2354,7 @@ F_TRAINER_FEMALE | }, }, #line 1010 - [TRAINER_GABBY_AND_TY_6] = + [DIFFICULTY_NORMAL][TRAINER_GABBY_AND_TY_6] = { #line 1011 .trainerName = _("GABBY & TY"), @@ -2411,7 +2411,7 @@ F_TRAINER_FEMALE | }, }, #line 1035 - [TRAINER_LOLA_1] = + [DIFFICULTY_NORMAL][TRAINER_LOLA_1] = { #line 1036 .trainerName = _("LOLA"), @@ -2456,7 +2456,7 @@ F_TRAINER_FEMALE | }, }, #line 1052 - [TRAINER_AUSTINA] = + [DIFFICULTY_NORMAL][TRAINER_AUSTINA] = { #line 1053 .trainerName = _("AUSTINA"), @@ -2490,7 +2490,7 @@ F_TRAINER_FEMALE | }, }, #line 1065 - [TRAINER_GWEN] = + [DIFFICULTY_NORMAL][TRAINER_GWEN] = { #line 1066 .trainerName = _("GWEN"), @@ -2524,7 +2524,7 @@ F_TRAINER_FEMALE | }, }, #line 1078 - [TRAINER_LOLA_2] = + [DIFFICULTY_NORMAL][TRAINER_LOLA_2] = { #line 1079 .trainerName = _("LOLA"), @@ -2569,7 +2569,7 @@ F_TRAINER_FEMALE | }, }, #line 1095 - [TRAINER_LOLA_3] = + [DIFFICULTY_NORMAL][TRAINER_LOLA_3] = { #line 1096 .trainerName = _("LOLA"), @@ -2614,7 +2614,7 @@ F_TRAINER_FEMALE | }, }, #line 1112 - [TRAINER_LOLA_4] = + [DIFFICULTY_NORMAL][TRAINER_LOLA_4] = { #line 1113 .trainerName = _("LOLA"), @@ -2659,7 +2659,7 @@ F_TRAINER_FEMALE | }, }, #line 1129 - [TRAINER_LOLA_5] = + [DIFFICULTY_NORMAL][TRAINER_LOLA_5] = { #line 1130 .trainerName = _("LOLA"), @@ -2704,7 +2704,7 @@ F_TRAINER_FEMALE | }, }, #line 1146 - [TRAINER_RICKY_1] = + [DIFFICULTY_NORMAL][TRAINER_RICKY_1] = { #line 1147 .trainerName = _("RICKY"), @@ -2743,7 +2743,7 @@ F_TRAINER_FEMALE | }, }, #line 1163 - [TRAINER_SIMON] = + [DIFFICULTY_NORMAL][TRAINER_SIMON] = { #line 1164 .trainerName = _("SIMON"), @@ -2786,7 +2786,7 @@ F_TRAINER_FEMALE | }, }, #line 1180 - [TRAINER_CHARLIE] = + [DIFFICULTY_NORMAL][TRAINER_CHARLIE] = { #line 1181 .trainerName = _("CHARLIE"), @@ -2818,7 +2818,7 @@ F_TRAINER_FEMALE | }, }, #line 1193 - [TRAINER_RICKY_2] = + [DIFFICULTY_NORMAL][TRAINER_RICKY_2] = { #line 1194 .trainerName = _("RICKY"), @@ -2857,7 +2857,7 @@ F_TRAINER_FEMALE | }, }, #line 1210 - [TRAINER_RICKY_3] = + [DIFFICULTY_NORMAL][TRAINER_RICKY_3] = { #line 1211 .trainerName = _("RICKY"), @@ -2896,7 +2896,7 @@ F_TRAINER_FEMALE | }, }, #line 1227 - [TRAINER_RICKY_4] = + [DIFFICULTY_NORMAL][TRAINER_RICKY_4] = { #line 1228 .trainerName = _("RICKY"), @@ -2935,7 +2935,7 @@ F_TRAINER_FEMALE | }, }, #line 1244 - [TRAINER_RICKY_5] = + [DIFFICULTY_NORMAL][TRAINER_RICKY_5] = { #line 1245 .trainerName = _("RICKY"), @@ -2974,7 +2974,7 @@ F_TRAINER_FEMALE | }, }, #line 1261 - [TRAINER_RANDALL] = + [DIFFICULTY_NORMAL][TRAINER_RANDALL] = { #line 1262 .trainerName = _("RANDALL"), @@ -3014,7 +3014,7 @@ F_TRAINER_FEMALE | }, }, #line 1278 - [TRAINER_PARKER] = + [DIFFICULTY_NORMAL][TRAINER_PARKER] = { #line 1279 .trainerName = _("PARKER"), @@ -3054,7 +3054,7 @@ F_TRAINER_FEMALE | }, }, #line 1295 - [TRAINER_GEORGE] = + [DIFFICULTY_NORMAL][TRAINER_GEORGE] = { #line 1296 .trainerName = _("GEORGE"), @@ -3096,7 +3096,7 @@ F_TRAINER_FEMALE | }, }, #line 1312 - [TRAINER_BERKE] = + [DIFFICULTY_NORMAL][TRAINER_BERKE] = { #line 1313 .trainerName = _("BERKE"), @@ -3135,7 +3135,7 @@ F_TRAINER_FEMALE | }, }, #line 1328 - [TRAINER_BRAXTON] = + [DIFFICULTY_NORMAL][TRAINER_BRAXTON] = { #line 1329 .trainerName = _("BRAXTON"), @@ -3248,7 +3248,7 @@ F_TRAINER_FEMALE | }, }, #line 1378 - [TRAINER_VINCENT] = + [DIFFICULTY_NORMAL][TRAINER_VINCENT] = { #line 1379 .trainerName = _("VINCENT"), @@ -3304,7 +3304,7 @@ F_TRAINER_FEMALE | }, }, #line 1400 - [TRAINER_LEROY] = + [DIFFICULTY_NORMAL][TRAINER_LEROY] = { #line 1401 .trainerName = _("LEROY"), @@ -3349,7 +3349,7 @@ F_TRAINER_FEMALE | }, }, #line 1418 - [TRAINER_WILTON_1] = + [DIFFICULTY_NORMAL][TRAINER_WILTON_1] = { #line 1419 .trainerName = _("WILTON"), @@ -3405,7 +3405,7 @@ F_TRAINER_FEMALE | }, }, #line 1440 - [TRAINER_EDGAR] = + [DIFFICULTY_NORMAL][TRAINER_EDGAR] = { #line 1441 .trainerName = _("EDGAR"), @@ -3450,7 +3450,7 @@ F_TRAINER_FEMALE | }, }, #line 1458 - [TRAINER_ALBERT] = + [DIFFICULTY_NORMAL][TRAINER_ALBERT] = { #line 1459 .trainerName = _("ALBERT"), @@ -3495,7 +3495,7 @@ F_TRAINER_FEMALE | }, }, #line 1476 - [TRAINER_SAMUEL] = + [DIFFICULTY_NORMAL][TRAINER_SAMUEL] = { #line 1477 .trainerName = _("SAMUEL"), @@ -3551,7 +3551,7 @@ F_TRAINER_FEMALE | }, }, #line 1498 - [TRAINER_VITO] = + [DIFFICULTY_NORMAL][TRAINER_VITO] = { #line 1499 .trainerName = _("VITO"), @@ -3618,7 +3618,7 @@ F_TRAINER_FEMALE | }, }, #line 1524 - [TRAINER_OWEN] = + [DIFFICULTY_NORMAL][TRAINER_OWEN] = { #line 1525 .trainerName = _("OWEN"), @@ -3674,7 +3674,7 @@ F_TRAINER_FEMALE | }, }, #line 1546 - [TRAINER_WILTON_2] = + [DIFFICULTY_NORMAL][TRAINER_WILTON_2] = { #line 1547 .trainerName = _("WILTON"), @@ -3730,7 +3730,7 @@ F_TRAINER_FEMALE | }, }, #line 1568 - [TRAINER_WILTON_3] = + [DIFFICULTY_NORMAL][TRAINER_WILTON_3] = { #line 1569 .trainerName = _("WILTON"), @@ -3786,7 +3786,7 @@ F_TRAINER_FEMALE | }, }, #line 1590 - [TRAINER_WILTON_4] = + [DIFFICULTY_NORMAL][TRAINER_WILTON_4] = { #line 1591 .trainerName = _("WILTON"), @@ -3842,7 +3842,7 @@ F_TRAINER_FEMALE | }, }, #line 1612 - [TRAINER_WILTON_5] = + [DIFFICULTY_NORMAL][TRAINER_WILTON_5] = { #line 1613 .trainerName = _("WILTON"), @@ -3898,7 +3898,7 @@ F_TRAINER_FEMALE | }, }, #line 1634 - [TRAINER_WARREN] = + [DIFFICULTY_NORMAL][TRAINER_WARREN] = { #line 1635 .trainerName = _("WARREN"), @@ -3943,7 +3943,7 @@ F_TRAINER_FEMALE | }, }, #line 1652 - [TRAINER_MARY] = + [DIFFICULTY_NORMAL][TRAINER_MARY] = { #line 1653 .trainerName = _("MARY"), @@ -3984,7 +3984,7 @@ F_TRAINER_FEMALE | }, }, #line 1668 - [TRAINER_ALEXIA] = + [DIFFICULTY_NORMAL][TRAINER_ALEXIA] = { #line 1669 .trainerName = _("ALEXIA"), @@ -4026,7 +4026,7 @@ F_TRAINER_FEMALE | }, }, #line 1685 - [TRAINER_JODY] = + [DIFFICULTY_NORMAL][TRAINER_JODY] = { #line 1686 .trainerName = _("JODY"), @@ -4067,7 +4067,7 @@ F_TRAINER_FEMALE | }, }, #line 1701 - [TRAINER_WENDY] = + [DIFFICULTY_NORMAL][TRAINER_WENDY] = { #line 1702 .trainerName = _("WENDY"), @@ -4146,7 +4146,7 @@ F_TRAINER_FEMALE | }, }, #line 1735 - [TRAINER_KEIRA] = + [DIFFICULTY_NORMAL][TRAINER_KEIRA] = { #line 1736 .trainerName = _("KEIRA"), @@ -4193,7 +4193,7 @@ F_TRAINER_FEMALE | }, }, #line 1753 - [TRAINER_BROOKE_1] = + [DIFFICULTY_NORMAL][TRAINER_BROOKE_1] = { #line 1754 .trainerName = _("BROOKE"), @@ -4251,7 +4251,7 @@ F_TRAINER_FEMALE | }, }, #line 1775 - [TRAINER_JENNIFER] = + [DIFFICULTY_NORMAL][TRAINER_JENNIFER] = { #line 1776 .trainerName = _("JENNIFER"), @@ -4287,7 +4287,7 @@ F_TRAINER_FEMALE | }, }, #line 1789 - [TRAINER_HOPE] = + [DIFFICULTY_NORMAL][TRAINER_HOPE] = { #line 1790 .trainerName = _("HOPE"), @@ -4323,7 +4323,7 @@ F_TRAINER_FEMALE | }, }, #line 1803 - [TRAINER_SHANNON] = + [DIFFICULTY_NORMAL][TRAINER_SHANNON] = { #line 1804 .trainerName = _("SHANNON"), @@ -4359,7 +4359,7 @@ F_TRAINER_FEMALE | }, }, #line 1817 - [TRAINER_MICHELLE] = + [DIFFICULTY_NORMAL][TRAINER_MICHELLE] = { #line 1818 .trainerName = _("MICHELLE"), @@ -4417,7 +4417,7 @@ F_TRAINER_FEMALE | }, }, #line 1839 - [TRAINER_CAROLINE] = + [DIFFICULTY_NORMAL][TRAINER_CAROLINE] = { #line 1840 .trainerName = _("CAROLINE"), @@ -4464,7 +4464,7 @@ F_TRAINER_FEMALE | }, }, #line 1857 - [TRAINER_JULIE] = + [DIFFICULTY_NORMAL][TRAINER_JULIE] = { #line 1858 .trainerName = _("JULIE"), @@ -4522,7 +4522,7 @@ F_TRAINER_FEMALE | }, }, #line 1879 - [TRAINER_BROOKE_2] = + [DIFFICULTY_NORMAL][TRAINER_BROOKE_2] = { #line 1880 .trainerName = _("BROOKE"), @@ -4580,7 +4580,7 @@ F_TRAINER_FEMALE | }, }, #line 1901 - [TRAINER_BROOKE_3] = + [DIFFICULTY_NORMAL][TRAINER_BROOKE_3] = { #line 1902 .trainerName = _("BROOKE"), @@ -4638,7 +4638,7 @@ F_TRAINER_FEMALE | }, }, #line 1923 - [TRAINER_BROOKE_4] = + [DIFFICULTY_NORMAL][TRAINER_BROOKE_4] = { #line 1924 .trainerName = _("BROOKE"), @@ -4696,7 +4696,7 @@ F_TRAINER_FEMALE | }, }, #line 1945 - [TRAINER_BROOKE_5] = + [DIFFICULTY_NORMAL][TRAINER_BROOKE_5] = { #line 1946 .trainerName = _("BROOKE"), @@ -4754,7 +4754,7 @@ F_TRAINER_FEMALE | }, }, #line 1967 - [TRAINER_PATRICIA] = + [DIFFICULTY_NORMAL][TRAINER_PATRICIA] = { #line 1968 .trainerName = _("PATRICIA"), @@ -4799,7 +4799,7 @@ F_TRAINER_FEMALE | }, }, #line 1984 - [TRAINER_KINDRA] = + [DIFFICULTY_NORMAL][TRAINER_KINDRA] = { #line 1985 .trainerName = _("KINDRA"), @@ -4844,7 +4844,7 @@ F_TRAINER_FEMALE | }, }, #line 2001 - [TRAINER_TAMMY] = + [DIFFICULTY_NORMAL][TRAINER_TAMMY] = { #line 2002 .trainerName = _("TAMMY"), @@ -4889,7 +4889,7 @@ F_TRAINER_FEMALE | }, }, #line 2018 - [TRAINER_VALERIE_1] = + [DIFFICULTY_NORMAL][TRAINER_VALERIE_1] = { #line 2019 .trainerName = _("VALERIE"), @@ -4923,7 +4923,7 @@ F_TRAINER_FEMALE | }, }, #line 2031 - [TRAINER_TASHA] = + [DIFFICULTY_NORMAL][TRAINER_TASHA] = { #line 2032 .trainerName = _("TASHA"), @@ -4957,7 +4957,7 @@ F_TRAINER_FEMALE | }, }, #line 2044 - [TRAINER_VALERIE_2] = + [DIFFICULTY_NORMAL][TRAINER_VALERIE_2] = { #line 2045 .trainerName = _("VALERIE"), @@ -5002,7 +5002,7 @@ F_TRAINER_FEMALE | }, }, #line 2061 - [TRAINER_VALERIE_3] = + [DIFFICULTY_NORMAL][TRAINER_VALERIE_3] = { #line 2062 .trainerName = _("VALERIE"), @@ -5047,7 +5047,7 @@ F_TRAINER_FEMALE | }, }, #line 2078 - [TRAINER_VALERIE_4] = + [DIFFICULTY_NORMAL][TRAINER_VALERIE_4] = { #line 2079 .trainerName = _("VALERIE"), @@ -5092,7 +5092,7 @@ F_TRAINER_FEMALE | }, }, #line 2095 - [TRAINER_VALERIE_5] = + [DIFFICULTY_NORMAL][TRAINER_VALERIE_5] = { #line 2096 .trainerName = _("VALERIE"), @@ -5148,7 +5148,7 @@ F_TRAINER_FEMALE | }, }, #line 2116 - [TRAINER_CINDY_1] = + [DIFFICULTY_NORMAL][TRAINER_CINDY_1] = { #line 2117 .trainerName = _("CINDY"), @@ -5186,7 +5186,7 @@ F_TRAINER_FEMALE | }, }, #line 2130 - [TRAINER_DAPHNE] = + [DIFFICULTY_NORMAL][TRAINER_DAPHNE] = { #line 2131 .trainerName = _("DAPHNE"), @@ -5251,7 +5251,7 @@ F_TRAINER_FEMALE | }, }, #line 2156 - [TRAINER_GRUNT_SPACE_CENTER_2] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_2] = { #line 2157 .trainerName = _("GRUNT"), @@ -5305,7 +5305,7 @@ F_TRAINER_FEMALE | }, }, #line 2177 - [TRAINER_CINDY_2] = + [DIFFICULTY_NORMAL][TRAINER_CINDY_2] = { #line 2178 .trainerName = _("CINDY"), @@ -5348,7 +5348,7 @@ F_TRAINER_FEMALE | }, }, #line 2193 - [TRAINER_BRIANNA] = + [DIFFICULTY_NORMAL][TRAINER_BRIANNA] = { #line 2194 .trainerName = _("BRIANNA"), @@ -5386,7 +5386,7 @@ F_TRAINER_FEMALE | }, }, #line 2207 - [TRAINER_NAOMI] = + [DIFFICULTY_NORMAL][TRAINER_NAOMI] = { #line 2208 .trainerName = _("NAOMI"), @@ -5424,7 +5424,7 @@ F_TRAINER_FEMALE | }, }, #line 2221 - [TRAINER_CINDY_3] = + [DIFFICULTY_NORMAL][TRAINER_CINDY_3] = { #line 2222 .trainerName = _("CINDY"), @@ -5462,7 +5462,7 @@ F_TRAINER_FEMALE | }, }, #line 2235 - [TRAINER_CINDY_4] = + [DIFFICULTY_NORMAL][TRAINER_CINDY_4] = { #line 2236 .trainerName = _("CINDY"), @@ -5500,7 +5500,7 @@ F_TRAINER_FEMALE | }, }, #line 2249 - [TRAINER_CINDY_5] = + [DIFFICULTY_NORMAL][TRAINER_CINDY_5] = { #line 2250 .trainerName = _("CINDY"), @@ -5538,7 +5538,7 @@ F_TRAINER_FEMALE | }, }, #line 2263 - [TRAINER_CINDY_6] = + [DIFFICULTY_NORMAL][TRAINER_CINDY_6] = { #line 2264 .trainerName = _("CINDY"), @@ -5583,7 +5583,7 @@ F_TRAINER_FEMALE | }, }, #line 2281 - [TRAINER_MELISSA] = + [DIFFICULTY_NORMAL][TRAINER_MELISSA] = { #line 2282 .trainerName = _("MELISSA"), @@ -5617,7 +5617,7 @@ F_TRAINER_FEMALE | }, }, #line 2294 - [TRAINER_SHEILA] = + [DIFFICULTY_NORMAL][TRAINER_SHEILA] = { #line 2295 .trainerName = _("SHEILA"), @@ -5651,7 +5651,7 @@ F_TRAINER_FEMALE | }, }, #line 2307 - [TRAINER_SHIRLEY] = + [DIFFICULTY_NORMAL][TRAINER_SHIRLEY] = { #line 2308 .trainerName = _("SHIRLEY"), @@ -5685,7 +5685,7 @@ F_TRAINER_FEMALE | }, }, #line 2320 - [TRAINER_JESSICA_1] = + [DIFFICULTY_NORMAL][TRAINER_JESSICA_1] = { #line 2321 .trainerName = _("JESSICA"), @@ -5744,7 +5744,7 @@ F_TRAINER_FEMALE | }, }, #line 2345 - [TRAINER_CONNIE] = + [DIFFICULTY_NORMAL][TRAINER_CONNIE] = { #line 2346 .trainerName = _("CONNIE"), @@ -5778,7 +5778,7 @@ F_TRAINER_FEMALE | }, }, #line 2358 - [TRAINER_BRIDGET] = + [DIFFICULTY_NORMAL][TRAINER_BRIDGET] = { #line 2359 .trainerName = _("BRIDGET"), @@ -5812,7 +5812,7 @@ F_TRAINER_FEMALE | }, }, #line 2371 - [TRAINER_OLIVIA] = + [DIFFICULTY_NORMAL][TRAINER_OLIVIA] = { #line 2372 .trainerName = _("OLIVIA"), @@ -5888,7 +5888,7 @@ F_TRAINER_FEMALE | }, }, #line 2403 - [TRAINER_TIFFANY] = + [DIFFICULTY_NORMAL][TRAINER_TIFFANY] = { #line 2404 .trainerName = _("TIFFANY"), @@ -5933,7 +5933,7 @@ F_TRAINER_FEMALE | }, }, #line 2420 - [TRAINER_JESSICA_2] = + [DIFFICULTY_NORMAL][TRAINER_JESSICA_2] = { #line 2421 .trainerName = _("JESSICA"), @@ -5992,7 +5992,7 @@ F_TRAINER_FEMALE | }, }, #line 2445 - [TRAINER_JESSICA_3] = + [DIFFICULTY_NORMAL][TRAINER_JESSICA_3] = { #line 2446 .trainerName = _("JESSICA"), @@ -6051,7 +6051,7 @@ F_TRAINER_FEMALE | }, }, #line 2470 - [TRAINER_JESSICA_4] = + [DIFFICULTY_NORMAL][TRAINER_JESSICA_4] = { #line 2471 .trainerName = _("JESSICA"), @@ -6110,7 +6110,7 @@ F_TRAINER_FEMALE | }, }, #line 2495 - [TRAINER_JESSICA_5] = + [DIFFICULTY_NORMAL][TRAINER_JESSICA_5] = { #line 2496 .trainerName = _("JESSICA"), @@ -6169,7 +6169,7 @@ F_TRAINER_FEMALE | }, }, #line 2520 - [TRAINER_WINSTON_1] = + [DIFFICULTY_NORMAL][TRAINER_WINSTON_1] = { #line 2521 .trainerName = _("WINSTON"), @@ -6205,7 +6205,7 @@ F_TRAINER_FEMALE | }, }, #line 2534 - [TRAINER_MOLLIE] = + [DIFFICULTY_NORMAL][TRAINER_MOLLIE] = { #line 2535 .trainerName = _("MOLLIE"), @@ -6250,7 +6250,7 @@ F_TRAINER_FEMALE | }, }, #line 2551 - [TRAINER_GARRET] = + [DIFFICULTY_NORMAL][TRAINER_GARRET] = { #line 2552 .trainerName = _("GARRET"), @@ -6286,7 +6286,7 @@ F_TRAINER_FEMALE | }, }, #line 2565 - [TRAINER_WINSTON_2] = + [DIFFICULTY_NORMAL][TRAINER_WINSTON_2] = { #line 2566 .trainerName = _("WINSTON"), @@ -6322,7 +6322,7 @@ F_TRAINER_FEMALE | }, }, #line 2579 - [TRAINER_WINSTON_3] = + [DIFFICULTY_NORMAL][TRAINER_WINSTON_3] = { #line 2580 .trainerName = _("WINSTON"), @@ -6358,7 +6358,7 @@ F_TRAINER_FEMALE | }, }, #line 2593 - [TRAINER_WINSTON_4] = + [DIFFICULTY_NORMAL][TRAINER_WINSTON_4] = { #line 2594 .trainerName = _("WINSTON"), @@ -6394,7 +6394,7 @@ F_TRAINER_FEMALE | }, }, #line 2607 - [TRAINER_WINSTON_5] = + [DIFFICULTY_NORMAL][TRAINER_WINSTON_5] = { #line 2608 .trainerName = _("WINSTON"), @@ -6437,7 +6437,7 @@ F_TRAINER_FEMALE | }, }, #line 2625 - [TRAINER_STEVE_1] = + [DIFFICULTY_NORMAL][TRAINER_STEVE_1] = { #line 2626 .trainerName = _("STEVE"), @@ -6469,7 +6469,7 @@ F_TRAINER_FEMALE | }, }, #line 2638 - [TRAINER_THALIA_1] = + [DIFFICULTY_NORMAL][TRAINER_THALIA_1] = { #line 2639 .trainerName = _("THALIA"), @@ -6514,7 +6514,7 @@ F_TRAINER_FEMALE | }, }, #line 2655 - [TRAINER_MARK] = + [DIFFICULTY_NORMAL][TRAINER_MARK] = { #line 2656 .trainerName = _("MARK"), @@ -6546,7 +6546,7 @@ F_TRAINER_FEMALE | }, }, #line 2668 - [TRAINER_GRUNT_MT_CHIMNEY_1] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_CHIMNEY_1] = { #line 2669 .trainerName = _("GRUNT"), @@ -6580,7 +6580,7 @@ F_TRAINER_FEMALE | }, }, #line 2681 - [TRAINER_STEVE_2] = + [DIFFICULTY_NORMAL][TRAINER_STEVE_2] = { #line 2682 .trainerName = _("STEVE"), @@ -6612,7 +6612,7 @@ F_TRAINER_FEMALE | }, }, #line 2694 - [TRAINER_STEVE_3] = + [DIFFICULTY_NORMAL][TRAINER_STEVE_3] = { #line 2695 .trainerName = _("STEVE"), @@ -6655,7 +6655,7 @@ F_TRAINER_FEMALE | }, }, #line 2711 - [TRAINER_STEVE_4] = + [DIFFICULTY_NORMAL][TRAINER_STEVE_4] = { #line 2712 .trainerName = _("STEVE"), @@ -6698,7 +6698,7 @@ F_TRAINER_FEMALE | }, }, #line 2728 - [TRAINER_STEVE_5] = + [DIFFICULTY_NORMAL][TRAINER_STEVE_5] = { #line 2729 .trainerName = _("STEVE"), @@ -6741,7 +6741,7 @@ F_TRAINER_FEMALE | }, }, #line 2745 - [TRAINER_LUIS] = + [DIFFICULTY_NORMAL][TRAINER_LUIS] = { #line 2746 .trainerName = _("LUIS"), @@ -6773,7 +6773,7 @@ F_TRAINER_FEMALE | }, }, #line 2758 - [TRAINER_DOMINIK] = + [DIFFICULTY_NORMAL][TRAINER_DOMINIK] = { #line 2759 .trainerName = _("DOMINIK"), @@ -6805,7 +6805,7 @@ F_TRAINER_FEMALE | }, }, #line 2771 - [TRAINER_DOUGLAS] = + [DIFFICULTY_NORMAL][TRAINER_DOUGLAS] = { #line 2772 .trainerName = _("DOUGLAS"), @@ -6848,7 +6848,7 @@ F_TRAINER_FEMALE | }, }, #line 2788 - [TRAINER_DARRIN] = + [DIFFICULTY_NORMAL][TRAINER_DARRIN] = { #line 2789 .trainerName = _("DARRIN"), @@ -6902,7 +6902,7 @@ F_TRAINER_FEMALE | }, }, #line 2809 - [TRAINER_TONY_1] = + [DIFFICULTY_NORMAL][TRAINER_TONY_1] = { #line 2810 .trainerName = _("TONY"), @@ -6934,7 +6934,7 @@ F_TRAINER_FEMALE | }, }, #line 2822 - [TRAINER_JEROME] = + [DIFFICULTY_NORMAL][TRAINER_JEROME] = { #line 2823 .trainerName = _("JEROME"), @@ -6966,7 +6966,7 @@ F_TRAINER_FEMALE | }, }, #line 2835 - [TRAINER_MATTHEW] = + [DIFFICULTY_NORMAL][TRAINER_MATTHEW] = { #line 2836 .trainerName = _("MATTHEW"), @@ -6998,7 +6998,7 @@ F_TRAINER_FEMALE | }, }, #line 2848 - [TRAINER_DAVID] = + [DIFFICULTY_NORMAL][TRAINER_DAVID] = { #line 2849 .trainerName = _("DAVID"), @@ -7041,7 +7041,7 @@ F_TRAINER_FEMALE | }, }, #line 2865 - [TRAINER_SPENCER] = + [DIFFICULTY_NORMAL][TRAINER_SPENCER] = { #line 2866 .trainerName = _("SPENCER"), @@ -7084,7 +7084,7 @@ F_TRAINER_FEMALE | }, }, #line 2882 - [TRAINER_ROLAND] = + [DIFFICULTY_NORMAL][TRAINER_ROLAND] = { #line 2883 .trainerName = _("ROLAND"), @@ -7116,7 +7116,7 @@ F_TRAINER_FEMALE | }, }, #line 2895 - [TRAINER_NOLEN] = + [DIFFICULTY_NORMAL][TRAINER_NOLEN] = { #line 2896 .trainerName = _("NOLEN"), @@ -7148,7 +7148,7 @@ F_TRAINER_FEMALE | }, }, #line 2908 - [TRAINER_STAN] = + [DIFFICULTY_NORMAL][TRAINER_STAN] = { #line 2909 .trainerName = _("STAN"), @@ -7180,7 +7180,7 @@ F_TRAINER_FEMALE | }, }, #line 2921 - [TRAINER_BARRY] = + [DIFFICULTY_NORMAL][TRAINER_BARRY] = { #line 2922 .trainerName = _("BARRY"), @@ -7212,7 +7212,7 @@ F_TRAINER_FEMALE | }, }, #line 2934 - [TRAINER_DEAN] = + [DIFFICULTY_NORMAL][TRAINER_DEAN] = { #line 2935 .trainerName = _("DEAN"), @@ -7266,7 +7266,7 @@ F_TRAINER_FEMALE | }, }, #line 2955 - [TRAINER_RODNEY] = + [DIFFICULTY_NORMAL][TRAINER_RODNEY] = { #line 2956 .trainerName = _("RODNEY"), @@ -7298,7 +7298,7 @@ F_TRAINER_FEMALE | }, }, #line 2968 - [TRAINER_RICHARD] = + [DIFFICULTY_NORMAL][TRAINER_RICHARD] = { #line 2969 .trainerName = _("RICHARD"), @@ -7330,7 +7330,7 @@ F_TRAINER_FEMALE | }, }, #line 2981 - [TRAINER_HERMAN] = + [DIFFICULTY_NORMAL][TRAINER_HERMAN] = { #line 2982 .trainerName = _("HERMAN"), @@ -7373,7 +7373,7 @@ F_TRAINER_FEMALE | }, }, #line 2998 - [TRAINER_SANTIAGO] = + [DIFFICULTY_NORMAL][TRAINER_SANTIAGO] = { #line 2999 .trainerName = _("SANTIAGO"), @@ -7416,7 +7416,7 @@ F_TRAINER_FEMALE | }, }, #line 3015 - [TRAINER_GILBERT] = + [DIFFICULTY_NORMAL][TRAINER_GILBERT] = { #line 3016 .trainerName = _("GILBERT"), @@ -7448,7 +7448,7 @@ F_TRAINER_FEMALE | }, }, #line 3028 - [TRAINER_FRANKLIN] = + [DIFFICULTY_NORMAL][TRAINER_FRANKLIN] = { #line 3029 .trainerName = _("FRANKLIN"), @@ -7480,7 +7480,7 @@ F_TRAINER_FEMALE | }, }, #line 3041 - [TRAINER_KEVIN] = + [DIFFICULTY_NORMAL][TRAINER_KEVIN] = { #line 3042 .trainerName = _("KEVIN"), @@ -7512,7 +7512,7 @@ F_TRAINER_FEMALE | }, }, #line 3054 - [TRAINER_JACK] = + [DIFFICULTY_NORMAL][TRAINER_JACK] = { #line 3055 .trainerName = _("JACK"), @@ -7544,7 +7544,7 @@ F_TRAINER_FEMALE | }, }, #line 3067 - [TRAINER_DUDLEY] = + [DIFFICULTY_NORMAL][TRAINER_DUDLEY] = { #line 3068 .trainerName = _("DUDLEY"), @@ -7598,7 +7598,7 @@ F_TRAINER_FEMALE | }, }, #line 3088 - [TRAINER_CHAD] = + [DIFFICULTY_NORMAL][TRAINER_CHAD] = { #line 3089 .trainerName = _("CHAD"), @@ -7641,7 +7641,7 @@ F_TRAINER_FEMALE | }, }, #line 3105 - [TRAINER_TONY_2] = + [DIFFICULTY_NORMAL][TRAINER_TONY_2] = { #line 3106 .trainerName = _("TONY"), @@ -7673,7 +7673,7 @@ F_TRAINER_FEMALE | }, }, #line 3118 - [TRAINER_TONY_3] = + [DIFFICULTY_NORMAL][TRAINER_TONY_3] = { #line 3119 .trainerName = _("TONY"), @@ -7705,7 +7705,7 @@ F_TRAINER_FEMALE | }, }, #line 3131 - [TRAINER_TONY_4] = + [DIFFICULTY_NORMAL][TRAINER_TONY_4] = { #line 3132 .trainerName = _("TONY"), @@ -7748,7 +7748,7 @@ F_TRAINER_FEMALE | }, }, #line 3148 - [TRAINER_TONY_5] = + [DIFFICULTY_NORMAL][TRAINER_TONY_5] = { #line 3149 .trainerName = _("TONY"), @@ -7791,7 +7791,7 @@ F_TRAINER_FEMALE | }, }, #line 3165 - [TRAINER_TAKAO] = + [DIFFICULTY_NORMAL][TRAINER_TAKAO] = { #line 3166 .trainerName = _("TAKAO"), @@ -7823,7 +7823,7 @@ F_TRAINER_FEMALE | }, }, #line 3178 - [TRAINER_HITOSHI] = + [DIFFICULTY_NORMAL][TRAINER_HITOSHI] = { #line 3179 .trainerName = _("HITOSHI"), @@ -7866,7 +7866,7 @@ F_TRAINER_FEMALE | }, }, #line 3195 - [TRAINER_KIYO] = + [DIFFICULTY_NORMAL][TRAINER_KIYO] = { #line 3196 .trainerName = _("KIYO"), @@ -7898,7 +7898,7 @@ F_TRAINER_FEMALE | }, }, #line 3208 - [TRAINER_KOICHI] = + [DIFFICULTY_NORMAL][TRAINER_KOICHI] = { #line 3209 .trainerName = _("KOICHI"), @@ -7941,7 +7941,7 @@ F_TRAINER_FEMALE | }, }, #line 3225 - [TRAINER_NOB_1] = + [DIFFICULTY_NORMAL][TRAINER_NOB_1] = { #line 3226 .trainerName = _("NOB"), @@ -7973,7 +7973,7 @@ F_TRAINER_FEMALE | }, }, #line 3238 - [TRAINER_NOB_2] = + [DIFFICULTY_NORMAL][TRAINER_NOB_2] = { #line 3239 .trainerName = _("NOB"), @@ -8005,7 +8005,7 @@ F_TRAINER_FEMALE | }, }, #line 3251 - [TRAINER_NOB_3] = + [DIFFICULTY_NORMAL][TRAINER_NOB_3] = { #line 3252 .trainerName = _("NOB"), @@ -8048,7 +8048,7 @@ F_TRAINER_FEMALE | }, }, #line 3268 - [TRAINER_NOB_4] = + [DIFFICULTY_NORMAL][TRAINER_NOB_4] = { #line 3269 .trainerName = _("NOB"), @@ -8102,7 +8102,7 @@ F_TRAINER_FEMALE | }, }, #line 3289 - [TRAINER_NOB_5] = + [DIFFICULTY_NORMAL][TRAINER_NOB_5] = { #line 3290 .trainerName = _("NOB"), @@ -8169,7 +8169,7 @@ F_TRAINER_FEMALE | }, }, #line 3314 - [TRAINER_YUJI] = + [DIFFICULTY_NORMAL][TRAINER_YUJI] = { #line 3315 .trainerName = _("YUJI"), @@ -8212,7 +8212,7 @@ F_TRAINER_FEMALE | }, }, #line 3331 - [TRAINER_DAISUKE] = + [DIFFICULTY_NORMAL][TRAINER_DAISUKE] = { #line 3332 .trainerName = _("DAISUKE"), @@ -8244,7 +8244,7 @@ F_TRAINER_FEMALE | }, }, #line 3344 - [TRAINER_ATSUSHI] = + [DIFFICULTY_NORMAL][TRAINER_ATSUSHI] = { #line 3345 .trainerName = _("ATSUSHI"), @@ -8276,7 +8276,7 @@ F_TRAINER_FEMALE | }, }, #line 3357 - [TRAINER_KIRK] = + [DIFFICULTY_NORMAL][TRAINER_KIRK] = { #line 3358 .trainerName = _("KIRK"), @@ -8332,7 +8332,7 @@ F_TRAINER_FEMALE | }, }, #line 3381 - [TRAINER_GRUNT_AQUA_HIDEOUT_7] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_7] = { #line 3382 .trainerName = _("GRUNT"), @@ -8377,7 +8377,7 @@ F_TRAINER_FEMALE | }, }, #line 3398 - [TRAINER_GRUNT_AQUA_HIDEOUT_8] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_AQUA_HIDEOUT_8] = { #line 3399 .trainerName = _("GRUNT"), @@ -8409,7 +8409,7 @@ F_TRAINER_FEMALE | }, }, #line 3411 - [TRAINER_SHAWN] = + [DIFFICULTY_NORMAL][TRAINER_SHAWN] = { #line 3412 .trainerName = _("SHAWN"), @@ -8452,7 +8452,7 @@ F_TRAINER_FEMALE | }, }, #line 3428 - [TRAINER_FERNANDO_1] = + [DIFFICULTY_NORMAL][TRAINER_FERNANDO_1] = { #line 3429 .trainerName = _("FERNANDO"), @@ -8495,7 +8495,7 @@ F_TRAINER_FEMALE | }, }, #line 3445 - [TRAINER_DALTON_1] = + [DIFFICULTY_NORMAL][TRAINER_DALTON_1] = { #line 3446 .trainerName = _("DALTON"), @@ -8538,7 +8538,7 @@ F_TRAINER_FEMALE | }, }, #line 3462 - [TRAINER_DALTON_2] = + [DIFFICULTY_NORMAL][TRAINER_DALTON_2] = { #line 3463 .trainerName = _("DALTON"), @@ -8592,7 +8592,7 @@ F_TRAINER_FEMALE | }, }, #line 3483 - [TRAINER_DALTON_3] = + [DIFFICULTY_NORMAL][TRAINER_DALTON_3] = { #line 3484 .trainerName = _("DALTON"), @@ -8646,7 +8646,7 @@ F_TRAINER_FEMALE | }, }, #line 3504 - [TRAINER_DALTON_4] = + [DIFFICULTY_NORMAL][TRAINER_DALTON_4] = { #line 3505 .trainerName = _("DALTON"), @@ -8700,7 +8700,7 @@ F_TRAINER_FEMALE | }, }, #line 3525 - [TRAINER_DALTON_5] = + [DIFFICULTY_NORMAL][TRAINER_DALTON_5] = { #line 3526 .trainerName = _("DALTON"), @@ -8754,7 +8754,7 @@ F_TRAINER_FEMALE | }, }, #line 3546 - [TRAINER_COLE] = + [DIFFICULTY_NORMAL][TRAINER_COLE] = { #line 3547 .trainerName = _("COLE"), @@ -8786,7 +8786,7 @@ F_TRAINER_FEMALE | }, }, #line 3559 - [TRAINER_JEFF] = + [DIFFICULTY_NORMAL][TRAINER_JEFF] = { #line 3560 .trainerName = _("JEFF"), @@ -8829,7 +8829,7 @@ F_TRAINER_FEMALE | }, }, #line 3576 - [TRAINER_AXLE] = + [DIFFICULTY_NORMAL][TRAINER_AXLE] = { #line 3577 .trainerName = _("AXLE"), @@ -8861,7 +8861,7 @@ F_TRAINER_FEMALE | }, }, #line 3589 - [TRAINER_JACE] = + [DIFFICULTY_NORMAL][TRAINER_JACE] = { #line 3590 .trainerName = _("JACE"), @@ -8893,7 +8893,7 @@ F_TRAINER_FEMALE | }, }, #line 3602 - [TRAINER_KEEGAN] = + [DIFFICULTY_NORMAL][TRAINER_KEEGAN] = { #line 3603 .trainerName = _("KEEGAN"), @@ -8925,7 +8925,7 @@ F_TRAINER_FEMALE | }, }, #line 3615 - [TRAINER_BERNIE_1] = + [DIFFICULTY_NORMAL][TRAINER_BERNIE_1] = { #line 3616 .trainerName = _("BERNIE"), @@ -8968,7 +8968,7 @@ F_TRAINER_FEMALE | }, }, #line 3632 - [TRAINER_BERNIE_2] = + [DIFFICULTY_NORMAL][TRAINER_BERNIE_2] = { #line 3633 .trainerName = _("BERNIE"), @@ -9011,7 +9011,7 @@ F_TRAINER_FEMALE | }, }, #line 3649 - [TRAINER_BERNIE_3] = + [DIFFICULTY_NORMAL][TRAINER_BERNIE_3] = { #line 3650 .trainerName = _("BERNIE"), @@ -9054,7 +9054,7 @@ F_TRAINER_FEMALE | }, }, #line 3666 - [TRAINER_BERNIE_4] = + [DIFFICULTY_NORMAL][TRAINER_BERNIE_4] = { #line 3667 .trainerName = _("BERNIE"), @@ -9097,7 +9097,7 @@ F_TRAINER_FEMALE | }, }, #line 3683 - [TRAINER_BERNIE_5] = + [DIFFICULTY_NORMAL][TRAINER_BERNIE_5] = { #line 3684 .trainerName = _("BERNIE"), @@ -9140,7 +9140,7 @@ F_TRAINER_FEMALE | }, }, #line 3700 - [TRAINER_DREW] = + [DIFFICULTY_NORMAL][TRAINER_DREW] = { #line 3701 .trainerName = _("DREW"), @@ -9179,7 +9179,7 @@ F_TRAINER_FEMALE | }, }, #line 3717 - [TRAINER_BEAU] = + [DIFFICULTY_NORMAL][TRAINER_BEAU] = { #line 3718 .trainerName = _("BEAU"), @@ -9254,7 +9254,7 @@ F_TRAINER_FEMALE | }, }, #line 3750 - [TRAINER_LARRY] = + [DIFFICULTY_NORMAL][TRAINER_LARRY] = { #line 3751 .trainerName = _("LARRY"), @@ -9286,7 +9286,7 @@ F_TRAINER_FEMALE | }, }, #line 3763 - [TRAINER_SHANE] = + [DIFFICULTY_NORMAL][TRAINER_SHANE] = { #line 3764 .trainerName = _("SHANE"), @@ -9329,7 +9329,7 @@ F_TRAINER_FEMALE | }, }, #line 3780 - [TRAINER_JUSTIN] = + [DIFFICULTY_NORMAL][TRAINER_JUSTIN] = { #line 3781 .trainerName = _("JUSTIN"), @@ -9361,7 +9361,7 @@ F_TRAINER_FEMALE | }, }, #line 3793 - [TRAINER_ETHAN_1] = + [DIFFICULTY_NORMAL][TRAINER_ETHAN_1] = { #line 3794 .trainerName = _("ETHAN"), @@ -9404,7 +9404,7 @@ F_TRAINER_FEMALE | }, }, #line 3810 - [TRAINER_AUTUMN] = + [DIFFICULTY_NORMAL][TRAINER_AUTUMN] = { #line 3811 .trainerName = _("AUTUMN"), @@ -9438,7 +9438,7 @@ F_TRAINER_FEMALE | }, }, #line 3823 - [TRAINER_TRAVIS] = + [DIFFICULTY_NORMAL][TRAINER_TRAVIS] = { #line 3824 .trainerName = _("TRAVIS"), @@ -9470,7 +9470,7 @@ F_TRAINER_FEMALE | }, }, #line 3836 - [TRAINER_ETHAN_2] = + [DIFFICULTY_NORMAL][TRAINER_ETHAN_2] = { #line 3837 .trainerName = _("ETHAN"), @@ -9513,7 +9513,7 @@ F_TRAINER_FEMALE | }, }, #line 3853 - [TRAINER_ETHAN_3] = + [DIFFICULTY_NORMAL][TRAINER_ETHAN_3] = { #line 3854 .trainerName = _("ETHAN"), @@ -9556,7 +9556,7 @@ F_TRAINER_FEMALE | }, }, #line 3870 - [TRAINER_ETHAN_4] = + [DIFFICULTY_NORMAL][TRAINER_ETHAN_4] = { #line 3871 .trainerName = _("ETHAN"), @@ -9610,7 +9610,7 @@ F_TRAINER_FEMALE | }, }, #line 3891 - [TRAINER_ETHAN_5] = + [DIFFICULTY_NORMAL][TRAINER_ETHAN_5] = { #line 3892 .trainerName = _("ETHAN"), @@ -9664,7 +9664,7 @@ F_TRAINER_FEMALE | }, }, #line 3912 - [TRAINER_BRENT] = + [DIFFICULTY_NORMAL][TRAINER_BRENT] = { #line 3913 .trainerName = _("BRENT"), @@ -9696,7 +9696,7 @@ F_TRAINER_FEMALE | }, }, #line 3925 - [TRAINER_DONALD] = + [DIFFICULTY_NORMAL][TRAINER_DONALD] = { #line 3926 .trainerName = _("DONALD"), @@ -9750,7 +9750,7 @@ F_TRAINER_FEMALE | }, }, #line 3946 - [TRAINER_TAYLOR] = + [DIFFICULTY_NORMAL][TRAINER_TAYLOR] = { #line 3947 .trainerName = _("TAYLOR"), @@ -9804,7 +9804,7 @@ F_TRAINER_FEMALE | }, }, #line 3967 - [TRAINER_JEFFREY_1] = + [DIFFICULTY_NORMAL][TRAINER_JEFFREY_1] = { #line 3968 .trainerName = _("JEFFREY"), @@ -9858,7 +9858,7 @@ F_TRAINER_FEMALE | }, }, #line 3988 - [TRAINER_DEREK] = + [DIFFICULTY_NORMAL][TRAINER_DEREK] = { #line 3989 .trainerName = _("DEREK"), @@ -9901,7 +9901,7 @@ F_TRAINER_FEMALE | }, }, #line 4005 - [TRAINER_JEFFREY_2] = + [DIFFICULTY_NORMAL][TRAINER_JEFFREY_2] = { #line 4006 .trainerName = _("JEFFREY"), @@ -9955,7 +9955,7 @@ F_TRAINER_FEMALE | }, }, #line 4026 - [TRAINER_JEFFREY_3] = + [DIFFICULTY_NORMAL][TRAINER_JEFFREY_3] = { #line 4027 .trainerName = _("JEFFREY"), @@ -10009,7 +10009,7 @@ F_TRAINER_FEMALE | }, }, #line 4047 - [TRAINER_JEFFREY_4] = + [DIFFICULTY_NORMAL][TRAINER_JEFFREY_4] = { #line 4048 .trainerName = _("JEFFREY"), @@ -10074,7 +10074,7 @@ F_TRAINER_FEMALE | }, }, #line 4072 - [TRAINER_JEFFREY_5] = + [DIFFICULTY_NORMAL][TRAINER_JEFFREY_5] = { #line 4073 .trainerName = _("JEFFREY"), @@ -10152,7 +10152,7 @@ F_TRAINER_FEMALE | }, }, #line 4101 - [TRAINER_EDWARD] = + [DIFFICULTY_NORMAL][TRAINER_EDWARD] = { #line 4102 .trainerName = _("EDWARD"), @@ -10188,7 +10188,7 @@ F_TRAINER_FEMALE | }, }, #line 4115 - [TRAINER_PRESTON] = + [DIFFICULTY_NORMAL][TRAINER_PRESTON] = { #line 4116 .trainerName = _("PRESTON"), @@ -10220,7 +10220,7 @@ F_TRAINER_FEMALE | }, }, #line 4128 - [TRAINER_VIRGIL] = + [DIFFICULTY_NORMAL][TRAINER_VIRGIL] = { #line 4129 .trainerName = _("VIRGIL"), @@ -10252,7 +10252,7 @@ F_TRAINER_FEMALE | }, }, #line 4141 - [TRAINER_BLAKE] = + [DIFFICULTY_NORMAL][TRAINER_BLAKE] = { #line 4142 .trainerName = _("BLAKE"), @@ -10284,7 +10284,7 @@ F_TRAINER_FEMALE | }, }, #line 4154 - [TRAINER_WILLIAM] = + [DIFFICULTY_NORMAL][TRAINER_WILLIAM] = { #line 4155 .trainerName = _("WILLIAM"), @@ -10338,7 +10338,7 @@ F_TRAINER_FEMALE | }, }, #line 4175 - [TRAINER_JOSHUA] = + [DIFFICULTY_NORMAL][TRAINER_JOSHUA] = { #line 4176 .trainerName = _("JOSHUA"), @@ -10381,7 +10381,7 @@ F_TRAINER_FEMALE | }, }, #line 4192 - [TRAINER_CAMERON_1] = + [DIFFICULTY_NORMAL][TRAINER_CAMERON_1] = { #line 4193 .trainerName = _("CAMERON"), @@ -10413,7 +10413,7 @@ F_TRAINER_FEMALE | }, }, #line 4205 - [TRAINER_CAMERON_2] = + [DIFFICULTY_NORMAL][TRAINER_CAMERON_2] = { #line 4206 .trainerName = _("CAMERON"), @@ -10456,7 +10456,7 @@ F_TRAINER_FEMALE | }, }, #line 4222 - [TRAINER_CAMERON_3] = + [DIFFICULTY_NORMAL][TRAINER_CAMERON_3] = { #line 4223 .trainerName = _("CAMERON"), @@ -10499,7 +10499,7 @@ F_TRAINER_FEMALE | }, }, #line 4239 - [TRAINER_CAMERON_4] = + [DIFFICULTY_NORMAL][TRAINER_CAMERON_4] = { #line 4240 .trainerName = _("CAMERON"), @@ -10542,7 +10542,7 @@ F_TRAINER_FEMALE | }, }, #line 4256 - [TRAINER_CAMERON_5] = + [DIFFICULTY_NORMAL][TRAINER_CAMERON_5] = { #line 4257 .trainerName = _("CAMERON"), @@ -10585,7 +10585,7 @@ F_TRAINER_FEMALE | }, }, #line 4273 - [TRAINER_JACLYN] = + [DIFFICULTY_NORMAL][TRAINER_JACLYN] = { #line 4274 .trainerName = _("JACLYN"), @@ -10623,7 +10623,7 @@ F_TRAINER_FEMALE | }, }, #line 4287 - [TRAINER_HANNAH] = + [DIFFICULTY_NORMAL][TRAINER_HANNAH] = { #line 4288 .trainerName = _("HANNAH"), @@ -10657,7 +10657,7 @@ F_TRAINER_FEMALE | }, }, #line 4300 - [TRAINER_SAMANTHA] = + [DIFFICULTY_NORMAL][TRAINER_SAMANTHA] = { #line 4301 .trainerName = _("SAMANTHA"), @@ -10691,7 +10691,7 @@ F_TRAINER_FEMALE | }, }, #line 4313 - [TRAINER_MAURA] = + [DIFFICULTY_NORMAL][TRAINER_MAURA] = { #line 4314 .trainerName = _("MAURA"), @@ -10725,7 +10725,7 @@ F_TRAINER_FEMALE | }, }, #line 4326 - [TRAINER_KAYLA] = + [DIFFICULTY_NORMAL][TRAINER_KAYLA] = { #line 4327 .trainerName = _("KAYLA"), @@ -10781,7 +10781,7 @@ F_TRAINER_FEMALE | }, }, #line 4347 - [TRAINER_ALEXIS] = + [DIFFICULTY_NORMAL][TRAINER_ALEXIS] = { #line 4348 .trainerName = _("ALEXIS"), @@ -10826,7 +10826,7 @@ F_TRAINER_FEMALE | }, }, #line 4364 - [TRAINER_JACKI_1] = + [DIFFICULTY_NORMAL][TRAINER_JACKI_1] = { #line 4365 .trainerName = _("JACKI"), @@ -10871,7 +10871,7 @@ F_TRAINER_FEMALE | }, }, #line 4381 - [TRAINER_JACKI_2] = + [DIFFICULTY_NORMAL][TRAINER_JACKI_2] = { #line 4382 .trainerName = _("JACKI"), @@ -10916,7 +10916,7 @@ F_TRAINER_FEMALE | }, }, #line 4398 - [TRAINER_JACKI_3] = + [DIFFICULTY_NORMAL][TRAINER_JACKI_3] = { #line 4399 .trainerName = _("JACKI"), @@ -10961,7 +10961,7 @@ F_TRAINER_FEMALE | }, }, #line 4415 - [TRAINER_JACKI_4] = + [DIFFICULTY_NORMAL][TRAINER_JACKI_4] = { #line 4416 .trainerName = _("JACKI"), @@ -11006,7 +11006,7 @@ F_TRAINER_FEMALE | }, }, #line 4432 - [TRAINER_JACKI_5] = + [DIFFICULTY_NORMAL][TRAINER_JACKI_5] = { #line 4433 .trainerName = _("JACKI"), @@ -11051,7 +11051,7 @@ F_TRAINER_FEMALE | }, }, #line 4449 - [TRAINER_WALTER_1] = + [DIFFICULTY_NORMAL][TRAINER_WALTER_1] = { #line 4450 .trainerName = _("WALTER"), @@ -11083,7 +11083,7 @@ F_TRAINER_FEMALE | }, }, #line 4462 - [TRAINER_MICAH] = + [DIFFICULTY_NORMAL][TRAINER_MICAH] = { #line 4463 .trainerName = _("MICAH"), @@ -11126,7 +11126,7 @@ F_TRAINER_FEMALE | }, }, #line 4479 - [TRAINER_THOMAS] = + [DIFFICULTY_NORMAL][TRAINER_THOMAS] = { #line 4480 .trainerName = _("THOMAS"), @@ -11158,7 +11158,7 @@ F_TRAINER_FEMALE | }, }, #line 4492 - [TRAINER_WALTER_2] = + [DIFFICULTY_NORMAL][TRAINER_WALTER_2] = { #line 4493 .trainerName = _("WALTER"), @@ -11190,7 +11190,7 @@ F_TRAINER_FEMALE | }, }, #line 4505 - [TRAINER_WALTER_3] = + [DIFFICULTY_NORMAL][TRAINER_WALTER_3] = { #line 4506 .trainerName = _("WALTER"), @@ -11247,7 +11247,7 @@ F_TRAINER_FEMALE | }, }, #line 4530 - [TRAINER_WALTER_4] = + [DIFFICULTY_NORMAL][TRAINER_WALTER_4] = { #line 4531 .trainerName = _("WALTER"), @@ -11303,7 +11303,7 @@ F_TRAINER_FEMALE | }, }, #line 4554 - [TRAINER_WALTER_5] = + [DIFFICULTY_NORMAL][TRAINER_WALTER_5] = { #line 4555 .trainerName = _("WALTER"), @@ -11378,7 +11378,7 @@ F_TRAINER_FEMALE | }, }, #line 4587 - [TRAINER_SIDNEY] = + [DIFFICULTY_NORMAL][TRAINER_SIDNEY] = { #line 4588 .trainerName = _("SIDNEY"), @@ -11495,7 +11495,7 @@ F_TRAINER_FEMALE | }, }, #line 4638 - [TRAINER_PHOEBE] = + [DIFFICULTY_NORMAL][TRAINER_PHOEBE] = { #line 4639 .trainerName = _("PHOEBE"), @@ -11614,7 +11614,7 @@ F_TRAINER_FEMALE | }, }, #line 4689 - [TRAINER_GLACIA] = + [DIFFICULTY_NORMAL][TRAINER_GLACIA] = { #line 4690 .trainerName = _("GLACIA"), @@ -11733,7 +11733,7 @@ F_TRAINER_FEMALE | }, }, #line 4740 - [TRAINER_DRAKE] = + [DIFFICULTY_NORMAL][TRAINER_DRAKE] = { #line 4741 .trainerName = _("DRAKE"), @@ -11850,7 +11850,7 @@ F_TRAINER_FEMALE | }, }, #line 4791 - [TRAINER_ROXANNE_1] = + [DIFFICULTY_NORMAL][TRAINER_ROXANNE_1] = { #line 4792 .trainerName = _("ROXANNE"), @@ -11931,7 +11931,7 @@ F_TRAINER_FEMALE | }, }, #line 4825 - [TRAINER_BRAWLY_1] = + [DIFFICULTY_NORMAL][TRAINER_BRAWLY_1] = { #line 4826 .trainerName = _("BRAWLY"), @@ -12010,7 +12010,7 @@ F_TRAINER_FEMALE | }, }, #line 4859 - [TRAINER_WATTSON_1] = + [DIFFICULTY_NORMAL][TRAINER_WATTSON_1] = { #line 4860 .trainerName = _("WATTSON"), @@ -12107,7 +12107,7 @@ F_TRAINER_FEMALE | }, }, #line 4901 - [TRAINER_FLANNERY_1] = + [DIFFICULTY_NORMAL][TRAINER_FLANNERY_1] = { #line 4902 .trainerName = _("FLANNERY"), @@ -12206,7 +12206,7 @@ F_TRAINER_FEMALE | }, }, #line 4943 - [TRAINER_NORMAN_1] = + [DIFFICULTY_NORMAL][TRAINER_NORMAN_1] = { #line 4944 .trainerName = _("NORMAN"), @@ -12303,7 +12303,7 @@ F_TRAINER_FEMALE | }, }, #line 4985 - [TRAINER_WINONA_1] = + [DIFFICULTY_NORMAL][TRAINER_WINONA_1] = { #line 4986 .trainerName = _("WINONA"), @@ -12420,7 +12420,7 @@ F_TRAINER_FEMALE | }, }, #line 5035 - [TRAINER_TATE_AND_LIZA_1] = + [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_1] = { #line 5036 .trainerName = _("TATE&LIZA"), @@ -12519,7 +12519,7 @@ F_TRAINER_FEMALE | }, }, #line 5077 - [TRAINER_JUAN_1] = + [DIFFICULTY_NORMAL][TRAINER_JUAN_1] = { #line 5078 .trainerName = _("JUAN"), @@ -12634,7 +12634,7 @@ F_TRAINER_FEMALE | }, }, #line 5127 - [TRAINER_JERRY_1] = + [DIFFICULTY_NORMAL][TRAINER_JERRY_1] = { #line 5128 .trainerName = _("JERRY"), @@ -12666,7 +12666,7 @@ F_TRAINER_FEMALE | }, }, #line 5140 - [TRAINER_TED] = + [DIFFICULTY_NORMAL][TRAINER_TED] = { #line 5141 .trainerName = _("TED"), @@ -12698,7 +12698,7 @@ F_TRAINER_FEMALE | }, }, #line 5153 - [TRAINER_PAUL] = + [DIFFICULTY_NORMAL][TRAINER_PAUL] = { #line 5154 .trainerName = _("PAUL"), @@ -12752,7 +12752,7 @@ F_TRAINER_FEMALE | }, }, #line 5174 - [TRAINER_JERRY_2] = + [DIFFICULTY_NORMAL][TRAINER_JERRY_2] = { #line 5175 .trainerName = _("JERRY"), @@ -12795,7 +12795,7 @@ F_TRAINER_FEMALE | }, }, #line 5191 - [TRAINER_JERRY_3] = + [DIFFICULTY_NORMAL][TRAINER_JERRY_3] = { #line 5192 .trainerName = _("JERRY"), @@ -12838,7 +12838,7 @@ F_TRAINER_FEMALE | }, }, #line 5208 - [TRAINER_JERRY_4] = + [DIFFICULTY_NORMAL][TRAINER_JERRY_4] = { #line 5209 .trainerName = _("JERRY"), @@ -12881,7 +12881,7 @@ F_TRAINER_FEMALE | }, }, #line 5225 - [TRAINER_JERRY_5] = + [DIFFICULTY_NORMAL][TRAINER_JERRY_5] = { #line 5226 .trainerName = _("JERRY"), @@ -12935,7 +12935,7 @@ F_TRAINER_FEMALE | }, }, #line 5246 - [TRAINER_KAREN_1] = + [DIFFICULTY_NORMAL][TRAINER_KAREN_1] = { #line 5247 .trainerName = _("KAREN"), @@ -12969,7 +12969,7 @@ F_TRAINER_FEMALE | }, }, #line 5259 - [TRAINER_GEORGIA] = + [DIFFICULTY_NORMAL][TRAINER_GEORGIA] = { #line 5260 .trainerName = _("GEORGIA"), @@ -13014,7 +13014,7 @@ F_TRAINER_FEMALE | }, }, #line 5276 - [TRAINER_KAREN_2] = + [DIFFICULTY_NORMAL][TRAINER_KAREN_2] = { #line 5277 .trainerName = _("KAREN"), @@ -13059,7 +13059,7 @@ F_TRAINER_FEMALE | }, }, #line 5293 - [TRAINER_KAREN_3] = + [DIFFICULTY_NORMAL][TRAINER_KAREN_3] = { #line 5294 .trainerName = _("KAREN"), @@ -13104,7 +13104,7 @@ F_TRAINER_FEMALE | }, }, #line 5310 - [TRAINER_KAREN_4] = + [DIFFICULTY_NORMAL][TRAINER_KAREN_4] = { #line 5311 .trainerName = _("KAREN"), @@ -13149,7 +13149,7 @@ F_TRAINER_FEMALE | }, }, #line 5327 - [TRAINER_KAREN_5] = + [DIFFICULTY_NORMAL][TRAINER_KAREN_5] = { #line 5328 .trainerName = _("KAREN"), @@ -13194,7 +13194,7 @@ F_TRAINER_FEMALE | }, }, #line 5344 - [TRAINER_KATE_AND_JOY] = + [DIFFICULTY_NORMAL][TRAINER_KATE_AND_JOY] = { #line 5345 .trainerName = _("KATE & JOY"), @@ -13251,7 +13251,7 @@ F_TRAINER_FEMALE | }, }, #line 5369 - [TRAINER_ANNA_AND_MEG_1] = + [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_1] = { #line 5370 .trainerName = _("ANNA & MEG"), @@ -13307,7 +13307,7 @@ F_TRAINER_FEMALE | }, }, #line 5393 - [TRAINER_ANNA_AND_MEG_2] = + [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_2] = { #line 5394 .trainerName = _("ANNA & MEG"), @@ -13363,7 +13363,7 @@ F_TRAINER_FEMALE | }, }, #line 5417 - [TRAINER_ANNA_AND_MEG_3] = + [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_3] = { #line 5418 .trainerName = _("ANNA & MEG"), @@ -13419,7 +13419,7 @@ F_TRAINER_FEMALE | }, }, #line 5441 - [TRAINER_ANNA_AND_MEG_4] = + [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_4] = { #line 5442 .trainerName = _("ANNA & MEG"), @@ -13475,7 +13475,7 @@ F_TRAINER_FEMALE | }, }, #line 5465 - [TRAINER_ANNA_AND_MEG_5] = + [DIFFICULTY_NORMAL][TRAINER_ANNA_AND_MEG_5] = { #line 5466 .trainerName = _("ANNA & MEG"), @@ -13531,7 +13531,7 @@ F_TRAINER_FEMALE | }, }, #line 5489 - [TRAINER_VICTOR] = + [DIFFICULTY_NORMAL][TRAINER_VICTOR] = { #line 5490 .trainerName = _("VICTOR"), @@ -13578,7 +13578,7 @@ F_TRAINER_FEMALE | }, }, #line 5506 - [TRAINER_MIGUEL_1] = + [DIFFICULTY_NORMAL][TRAINER_MIGUEL_1] = { #line 5507 .trainerName = _("MIGUEL"), @@ -13612,7 +13612,7 @@ F_TRAINER_FEMALE | }, }, #line 5519 - [TRAINER_COLTON] = + [DIFFICULTY_NORMAL][TRAINER_COLTON] = { #line 5520 .trainerName = _("COLTON"), @@ -13753,7 +13753,7 @@ F_TRAINER_FEMALE | }, }, #line 5576 - [TRAINER_MIGUEL_2] = + [DIFFICULTY_NORMAL][TRAINER_MIGUEL_2] = { #line 5577 .trainerName = _("MIGUEL"), @@ -13787,7 +13787,7 @@ F_TRAINER_FEMALE | }, }, #line 5589 - [TRAINER_MIGUEL_3] = + [DIFFICULTY_NORMAL][TRAINER_MIGUEL_3] = { #line 5590 .trainerName = _("MIGUEL"), @@ -13821,7 +13821,7 @@ F_TRAINER_FEMALE | }, }, #line 5602 - [TRAINER_MIGUEL_4] = + [DIFFICULTY_NORMAL][TRAINER_MIGUEL_4] = { #line 5603 .trainerName = _("MIGUEL"), @@ -13855,7 +13855,7 @@ F_TRAINER_FEMALE | }, }, #line 5615 - [TRAINER_MIGUEL_5] = + [DIFFICULTY_NORMAL][TRAINER_MIGUEL_5] = { #line 5616 .trainerName = _("MIGUEL"), @@ -13889,7 +13889,7 @@ F_TRAINER_FEMALE | }, }, #line 5628 - [TRAINER_VICTORIA] = + [DIFFICULTY_NORMAL][TRAINER_VICTORIA] = { #line 5629 .trainerName = _("VICTORIA"), @@ -13925,7 +13925,7 @@ F_TRAINER_FEMALE | }, }, #line 5641 - [TRAINER_VANESSA] = + [DIFFICULTY_NORMAL][TRAINER_VANESSA] = { #line 5642 .trainerName = _("VANESSA"), @@ -13961,7 +13961,7 @@ F_TRAINER_FEMALE | }, }, #line 5654 - [TRAINER_BETHANY] = + [DIFFICULTY_NORMAL][TRAINER_BETHANY] = { #line 5655 .trainerName = _("BETHANY"), @@ -14023,7 +14023,7 @@ F_TRAINER_FEMALE | }, }, #line 5675 - [TRAINER_ISABEL_1] = + [DIFFICULTY_NORMAL][TRAINER_ISABEL_1] = { #line 5676 .trainerName = _("ISABEL"), @@ -14072,7 +14072,7 @@ F_TRAINER_FEMALE | }, }, #line 5692 - [TRAINER_ISABEL_2] = + [DIFFICULTY_NORMAL][TRAINER_ISABEL_2] = { #line 5693 .trainerName = _("ISABEL"), @@ -14121,7 +14121,7 @@ F_TRAINER_FEMALE | }, }, #line 5709 - [TRAINER_ISABEL_3] = + [DIFFICULTY_NORMAL][TRAINER_ISABEL_3] = { #line 5710 .trainerName = _("ISABEL"), @@ -14170,7 +14170,7 @@ F_TRAINER_FEMALE | }, }, #line 5726 - [TRAINER_ISABEL_4] = + [DIFFICULTY_NORMAL][TRAINER_ISABEL_4] = { #line 5727 .trainerName = _("ISABEL"), @@ -14219,7 +14219,7 @@ F_TRAINER_FEMALE | }, }, #line 5743 - [TRAINER_ISABEL_5] = + [DIFFICULTY_NORMAL][TRAINER_ISABEL_5] = { #line 5744 .trainerName = _("ISABEL"), @@ -14268,7 +14268,7 @@ F_TRAINER_FEMALE | }, }, #line 5760 - [TRAINER_TIMOTHY_1] = + [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_1] = { #line 5761 .trainerName = _("TIMOTHY"), @@ -14300,7 +14300,7 @@ F_TRAINER_FEMALE | }, }, #line 5773 - [TRAINER_TIMOTHY_2] = + [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_2] = { #line 5774 .trainerName = _("TIMOTHY"), @@ -14339,7 +14339,7 @@ F_TRAINER_FEMALE | }, }, #line 5790 - [TRAINER_TIMOTHY_3] = + [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_3] = { #line 5791 .trainerName = _("TIMOTHY"), @@ -14378,7 +14378,7 @@ F_TRAINER_FEMALE | }, }, #line 5807 - [TRAINER_TIMOTHY_4] = + [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_4] = { #line 5808 .trainerName = _("TIMOTHY"), @@ -14417,7 +14417,7 @@ F_TRAINER_FEMALE | }, }, #line 5824 - [TRAINER_TIMOTHY_5] = + [DIFFICULTY_NORMAL][TRAINER_TIMOTHY_5] = { #line 5825 .trainerName = _("TIMOTHY"), @@ -14456,7 +14456,7 @@ F_TRAINER_FEMALE | }, }, #line 5841 - [TRAINER_VICKY] = + [DIFFICULTY_NORMAL][TRAINER_VICKY] = { #line 5842 .trainerName = _("VICKY"), @@ -14497,7 +14497,7 @@ F_TRAINER_FEMALE | }, }, #line 5858 - [TRAINER_SHELBY_1] = + [DIFFICULTY_NORMAL][TRAINER_SHELBY_1] = { #line 5859 .trainerName = _("SHELBY"), @@ -14542,7 +14542,7 @@ F_TRAINER_FEMALE | }, }, #line 5875 - [TRAINER_SHELBY_2] = + [DIFFICULTY_NORMAL][TRAINER_SHELBY_2] = { #line 5876 .trainerName = _("SHELBY"), @@ -14587,7 +14587,7 @@ F_TRAINER_FEMALE | }, }, #line 5892 - [TRAINER_SHELBY_3] = + [DIFFICULTY_NORMAL][TRAINER_SHELBY_3] = { #line 5893 .trainerName = _("SHELBY"), @@ -14632,7 +14632,7 @@ F_TRAINER_FEMALE | }, }, #line 5909 - [TRAINER_SHELBY_4] = + [DIFFICULTY_NORMAL][TRAINER_SHELBY_4] = { #line 5910 .trainerName = _("SHELBY"), @@ -14677,7 +14677,7 @@ F_TRAINER_FEMALE | }, }, #line 5926 - [TRAINER_SHELBY_5] = + [DIFFICULTY_NORMAL][TRAINER_SHELBY_5] = { #line 5927 .trainerName = _("SHELBY"), @@ -14722,7 +14722,7 @@ F_TRAINER_FEMALE | }, }, #line 5943 - [TRAINER_CALVIN_1] = + [DIFFICULTY_NORMAL][TRAINER_CALVIN_1] = { #line 5944 .trainerName = _("CALVIN"), @@ -14754,7 +14754,7 @@ F_TRAINER_FEMALE | }, }, #line 5956 - [TRAINER_BILLY] = + [DIFFICULTY_NORMAL][TRAINER_BILLY] = { #line 5957 .trainerName = _("BILLY"), @@ -14797,7 +14797,7 @@ F_TRAINER_FEMALE | }, }, #line 5973 - [TRAINER_JOSH] = + [DIFFICULTY_NORMAL][TRAINER_JOSH] = { #line 5974 .trainerName = _("JOSH"), @@ -14833,7 +14833,7 @@ F_TRAINER_FEMALE | }, }, #line 5987 - [TRAINER_TOMMY] = + [DIFFICULTY_NORMAL][TRAINER_TOMMY] = { #line 5988 .trainerName = _("TOMMY"), @@ -14876,7 +14876,7 @@ F_TRAINER_FEMALE | }, }, #line 6004 - [TRAINER_JOEY] = + [DIFFICULTY_NORMAL][TRAINER_JOEY] = { #line 6005 .trainerName = _("JOEY"), @@ -14908,7 +14908,7 @@ F_TRAINER_FEMALE | }, }, #line 6017 - [TRAINER_BEN] = + [DIFFICULTY_NORMAL][TRAINER_BEN] = { #line 6018 .trainerName = _("BEN"), @@ -14965,7 +14965,7 @@ F_TRAINER_FEMALE | }, }, #line 6042 - [TRAINER_QUINCY] = + [DIFFICULTY_NORMAL][TRAINER_QUINCY] = { #line 6043 .trainerName = _("QUINCY"), @@ -15024,7 +15024,7 @@ F_TRAINER_FEMALE | }, }, #line 6068 - [TRAINER_KATELYNN] = + [DIFFICULTY_NORMAL][TRAINER_KATELYNN] = { #line 6069 .trainerName = _("KATELYNN"), @@ -15085,7 +15085,7 @@ F_TRAINER_FEMALE | }, }, #line 6094 - [TRAINER_JAYLEN] = + [DIFFICULTY_NORMAL][TRAINER_JAYLEN] = { #line 6095 .trainerName = _("JAYLEN"), @@ -15117,7 +15117,7 @@ F_TRAINER_FEMALE | }, }, #line 6107 - [TRAINER_DILLON] = + [DIFFICULTY_NORMAL][TRAINER_DILLON] = { #line 6108 .trainerName = _("DILLON"), @@ -15149,7 +15149,7 @@ F_TRAINER_FEMALE | }, }, #line 6120 - [TRAINER_CALVIN_2] = + [DIFFICULTY_NORMAL][TRAINER_CALVIN_2] = { #line 6121 .trainerName = _("CALVIN"), @@ -15181,7 +15181,7 @@ F_TRAINER_FEMALE | }, }, #line 6133 - [TRAINER_CALVIN_3] = + [DIFFICULTY_NORMAL][TRAINER_CALVIN_3] = { #line 6134 .trainerName = _("CALVIN"), @@ -15224,7 +15224,7 @@ F_TRAINER_FEMALE | }, }, #line 6150 - [TRAINER_CALVIN_4] = + [DIFFICULTY_NORMAL][TRAINER_CALVIN_4] = { #line 6151 .trainerName = _("CALVIN"), @@ -15278,7 +15278,7 @@ F_TRAINER_FEMALE | }, }, #line 6171 - [TRAINER_CALVIN_5] = + [DIFFICULTY_NORMAL][TRAINER_CALVIN_5] = { #line 6172 .trainerName = _("CALVIN"), @@ -15332,7 +15332,7 @@ F_TRAINER_FEMALE | }, }, #line 6192 - [TRAINER_EDDIE] = + [DIFFICULTY_NORMAL][TRAINER_EDDIE] = { #line 6193 .trainerName = _("EDDIE"), @@ -15375,7 +15375,7 @@ F_TRAINER_FEMALE | }, }, #line 6209 - [TRAINER_ALLEN] = + [DIFFICULTY_NORMAL][TRAINER_ALLEN] = { #line 6210 .trainerName = _("ALLEN"), @@ -15418,7 +15418,7 @@ F_TRAINER_FEMALE | }, }, #line 6226 - [TRAINER_TIMMY] = + [DIFFICULTY_NORMAL][TRAINER_TIMMY] = { #line 6227 .trainerName = _("TIMMY"), @@ -15461,7 +15461,7 @@ F_TRAINER_FEMALE | }, }, #line 6243 - [TRAINER_WALLACE] = + [DIFFICULTY_NORMAL][TRAINER_WALLACE] = { #line 6244 .trainerName = _("WALLACE"), @@ -15596,7 +15596,7 @@ F_TRAINER_FEMALE | }, }, #line 6302 - [TRAINER_ANDREW] = + [DIFFICULTY_NORMAL][TRAINER_ANDREW] = { #line 6303 .trainerName = _("ANDREW"), @@ -15650,7 +15650,7 @@ F_TRAINER_FEMALE | }, }, #line 6323 - [TRAINER_IVAN] = + [DIFFICULTY_NORMAL][TRAINER_IVAN] = { #line 6324 .trainerName = _("IVAN"), @@ -15704,7 +15704,7 @@ F_TRAINER_FEMALE | }, }, #line 6344 - [TRAINER_CLAUDE] = + [DIFFICULTY_NORMAL][TRAINER_CLAUDE] = { #line 6345 .trainerName = _("CLAUDE"), @@ -15758,7 +15758,7 @@ F_TRAINER_FEMALE | }, }, #line 6365 - [TRAINER_ELLIOT_1] = + [DIFFICULTY_NORMAL][TRAINER_ELLIOT_1] = { #line 6366 .trainerName = _("ELLIOT"), @@ -15812,7 +15812,7 @@ F_TRAINER_FEMALE | }, }, #line 6386 - [TRAINER_NED] = + [DIFFICULTY_NORMAL][TRAINER_NED] = { #line 6387 .trainerName = _("NED"), @@ -15844,7 +15844,7 @@ F_TRAINER_FEMALE | }, }, #line 6399 - [TRAINER_DALE] = + [DIFFICULTY_NORMAL][TRAINER_DALE] = { #line 6400 .trainerName = _("DALE"), @@ -15909,7 +15909,7 @@ F_TRAINER_FEMALE | }, }, #line 6424 - [TRAINER_NOLAN] = + [DIFFICULTY_NORMAL][TRAINER_NOLAN] = { #line 6425 .trainerName = _("NOLAN"), @@ -15941,7 +15941,7 @@ F_TRAINER_FEMALE | }, }, #line 6437 - [TRAINER_BARNY] = + [DIFFICULTY_NORMAL][TRAINER_BARNY] = { #line 6438 .trainerName = _("BARNY"), @@ -15984,7 +15984,7 @@ F_TRAINER_FEMALE | }, }, #line 6454 - [TRAINER_WADE] = + [DIFFICULTY_NORMAL][TRAINER_WADE] = { #line 6455 .trainerName = _("WADE"), @@ -16016,7 +16016,7 @@ F_TRAINER_FEMALE | }, }, #line 6467 - [TRAINER_CARTER] = + [DIFFICULTY_NORMAL][TRAINER_CARTER] = { #line 6468 .trainerName = _("CARTER"), @@ -16059,7 +16059,7 @@ F_TRAINER_FEMALE | }, }, #line 6484 - [TRAINER_ELLIOT_2] = + [DIFFICULTY_NORMAL][TRAINER_ELLIOT_2] = { #line 6485 .trainerName = _("ELLIOT"), @@ -16113,7 +16113,7 @@ F_TRAINER_FEMALE | }, }, #line 6505 - [TRAINER_ELLIOT_3] = + [DIFFICULTY_NORMAL][TRAINER_ELLIOT_3] = { #line 6506 .trainerName = _("ELLIOT"), @@ -16178,7 +16178,7 @@ F_TRAINER_FEMALE | }, }, #line 6530 - [TRAINER_ELLIOT_4] = + [DIFFICULTY_NORMAL][TRAINER_ELLIOT_4] = { #line 6531 .trainerName = _("ELLIOT"), @@ -16243,7 +16243,7 @@ F_TRAINER_FEMALE | }, }, #line 6555 - [TRAINER_ELLIOT_5] = + [DIFFICULTY_NORMAL][TRAINER_ELLIOT_5] = { #line 6556 .trainerName = _("ELLIOT"), @@ -16308,7 +16308,7 @@ F_TRAINER_FEMALE | }, }, #line 6580 - [TRAINER_RONALD] = + [DIFFICULTY_NORMAL][TRAINER_RONALD] = { #line 6581 .trainerName = _("RONALD"), @@ -16395,7 +16395,7 @@ F_TRAINER_FEMALE | }, }, #line 6613 - [TRAINER_JACOB] = + [DIFFICULTY_NORMAL][TRAINER_JACOB] = { #line 6614 .trainerName = _("JACOB"), @@ -16449,7 +16449,7 @@ F_TRAINER_FEMALE | }, }, #line 6634 - [TRAINER_ANTHONY] = + [DIFFICULTY_NORMAL][TRAINER_ANTHONY] = { #line 6635 .trainerName = _("ANTHONY"), @@ -16492,7 +16492,7 @@ F_TRAINER_FEMALE | }, }, #line 6651 - [TRAINER_BENJAMIN_1] = + [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_1] = { #line 6652 .trainerName = _("BENJAMIN"), @@ -16524,7 +16524,7 @@ F_TRAINER_FEMALE | }, }, #line 6664 - [TRAINER_BENJAMIN_2] = + [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_2] = { #line 6665 .trainerName = _("BENJAMIN"), @@ -16556,7 +16556,7 @@ F_TRAINER_FEMALE | }, }, #line 6677 - [TRAINER_BENJAMIN_3] = + [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_3] = { #line 6678 .trainerName = _("BENJAMIN"), @@ -16588,7 +16588,7 @@ F_TRAINER_FEMALE | }, }, #line 6690 - [TRAINER_BENJAMIN_4] = + [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_4] = { #line 6691 .trainerName = _("BENJAMIN"), @@ -16620,7 +16620,7 @@ F_TRAINER_FEMALE | }, }, #line 6703 - [TRAINER_BENJAMIN_5] = + [DIFFICULTY_NORMAL][TRAINER_BENJAMIN_5] = { #line 6704 .trainerName = _("BENJAMIN"), @@ -16652,7 +16652,7 @@ F_TRAINER_FEMALE | }, }, #line 6716 - [TRAINER_ABIGAIL_1] = + [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_1] = { #line 6717 .trainerName = _("ABIGAIL"), @@ -16686,7 +16686,7 @@ F_TRAINER_FEMALE | }, }, #line 6729 - [TRAINER_JASMINE] = + [DIFFICULTY_NORMAL][TRAINER_JASMINE] = { #line 6730 .trainerName = _("JASMINE"), @@ -16742,7 +16742,7 @@ F_TRAINER_FEMALE | }, }, #line 6750 - [TRAINER_ABIGAIL_2] = + [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_2] = { #line 6751 .trainerName = _("ABIGAIL"), @@ -16776,7 +16776,7 @@ F_TRAINER_FEMALE | }, }, #line 6763 - [TRAINER_ABIGAIL_3] = + [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_3] = { #line 6764 .trainerName = _("ABIGAIL"), @@ -16810,7 +16810,7 @@ F_TRAINER_FEMALE | }, }, #line 6776 - [TRAINER_ABIGAIL_4] = + [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_4] = { #line 6777 .trainerName = _("ABIGAIL"), @@ -16844,7 +16844,7 @@ F_TRAINER_FEMALE | }, }, #line 6789 - [TRAINER_ABIGAIL_5] = + [DIFFICULTY_NORMAL][TRAINER_ABIGAIL_5] = { #line 6790 .trainerName = _("ABIGAIL"), @@ -16878,7 +16878,7 @@ F_TRAINER_FEMALE | }, }, #line 6802 - [TRAINER_DYLAN_1] = + [DIFFICULTY_NORMAL][TRAINER_DYLAN_1] = { #line 6803 .trainerName = _("DYLAN"), @@ -16910,7 +16910,7 @@ F_TRAINER_FEMALE | }, }, #line 6815 - [TRAINER_DYLAN_2] = + [DIFFICULTY_NORMAL][TRAINER_DYLAN_2] = { #line 6816 .trainerName = _("DYLAN"), @@ -16942,7 +16942,7 @@ F_TRAINER_FEMALE | }, }, #line 6828 - [TRAINER_DYLAN_3] = + [DIFFICULTY_NORMAL][TRAINER_DYLAN_3] = { #line 6829 .trainerName = _("DYLAN"), @@ -16974,7 +16974,7 @@ F_TRAINER_FEMALE | }, }, #line 6841 - [TRAINER_DYLAN_4] = + [DIFFICULTY_NORMAL][TRAINER_DYLAN_4] = { #line 6842 .trainerName = _("DYLAN"), @@ -17006,7 +17006,7 @@ F_TRAINER_FEMALE | }, }, #line 6854 - [TRAINER_DYLAN_5] = + [DIFFICULTY_NORMAL][TRAINER_DYLAN_5] = { #line 6855 .trainerName = _("DYLAN"), @@ -17038,7 +17038,7 @@ F_TRAINER_FEMALE | }, }, #line 6867 - [TRAINER_MARIA_1] = + [DIFFICULTY_NORMAL][TRAINER_MARIA_1] = { #line 6868 .trainerName = _("MARIA"), @@ -17072,7 +17072,7 @@ F_TRAINER_FEMALE | }, }, #line 6880 - [TRAINER_MARIA_2] = + [DIFFICULTY_NORMAL][TRAINER_MARIA_2] = { #line 6881 .trainerName = _("MARIA"), @@ -17106,7 +17106,7 @@ F_TRAINER_FEMALE | }, }, #line 6893 - [TRAINER_MARIA_3] = + [DIFFICULTY_NORMAL][TRAINER_MARIA_3] = { #line 6894 .trainerName = _("MARIA"), @@ -17140,7 +17140,7 @@ F_TRAINER_FEMALE | }, }, #line 6906 - [TRAINER_MARIA_4] = + [DIFFICULTY_NORMAL][TRAINER_MARIA_4] = { #line 6907 .trainerName = _("MARIA"), @@ -17174,7 +17174,7 @@ F_TRAINER_FEMALE | }, }, #line 6919 - [TRAINER_MARIA_5] = + [DIFFICULTY_NORMAL][TRAINER_MARIA_5] = { #line 6920 .trainerName = _("MARIA"), @@ -17208,7 +17208,7 @@ F_TRAINER_FEMALE | }, }, #line 6932 - [TRAINER_CAMDEN] = + [DIFFICULTY_NORMAL][TRAINER_CAMDEN] = { #line 6933 .trainerName = _("CAMDEN"), @@ -17251,7 +17251,7 @@ F_TRAINER_FEMALE | }, }, #line 6949 - [TRAINER_DEMETRIUS] = + [DIFFICULTY_NORMAL][TRAINER_DEMETRIUS] = { #line 6950 .trainerName = _("DEMETRIUS"), @@ -17294,7 +17294,7 @@ F_TRAINER_FEMALE | }, }, #line 6966 - [TRAINER_ISAIAH_1] = + [DIFFICULTY_NORMAL][TRAINER_ISAIAH_1] = { #line 6967 .trainerName = _("ISAIAH"), @@ -17326,7 +17326,7 @@ F_TRAINER_FEMALE | }, }, #line 6979 - [TRAINER_PABLO_1] = + [DIFFICULTY_NORMAL][TRAINER_PABLO_1] = { #line 6980 .trainerName = _("PABLO"), @@ -17369,7 +17369,7 @@ F_TRAINER_FEMALE | }, }, #line 6996 - [TRAINER_CHASE] = + [DIFFICULTY_NORMAL][TRAINER_CHASE] = { #line 6997 .trainerName = _("CHASE"), @@ -17412,7 +17412,7 @@ F_TRAINER_FEMALE | }, }, #line 7013 - [TRAINER_ISAIAH_2] = + [DIFFICULTY_NORMAL][TRAINER_ISAIAH_2] = { #line 7014 .trainerName = _("ISAIAH"), @@ -17444,7 +17444,7 @@ F_TRAINER_FEMALE | }, }, #line 7026 - [TRAINER_ISAIAH_3] = + [DIFFICULTY_NORMAL][TRAINER_ISAIAH_3] = { #line 7027 .trainerName = _("ISAIAH"), @@ -17476,7 +17476,7 @@ F_TRAINER_FEMALE | }, }, #line 7039 - [TRAINER_ISAIAH_4] = + [DIFFICULTY_NORMAL][TRAINER_ISAIAH_4] = { #line 7040 .trainerName = _("ISAIAH"), @@ -17508,7 +17508,7 @@ F_TRAINER_FEMALE | }, }, #line 7052 - [TRAINER_ISAIAH_5] = + [DIFFICULTY_NORMAL][TRAINER_ISAIAH_5] = { #line 7053 .trainerName = _("ISAIAH"), @@ -17540,7 +17540,7 @@ F_TRAINER_FEMALE | }, }, #line 7065 - [TRAINER_ISOBEL] = + [DIFFICULTY_NORMAL][TRAINER_ISOBEL] = { #line 7066 .trainerName = _("ISOBEL"), @@ -17574,7 +17574,7 @@ F_TRAINER_FEMALE | }, }, #line 7078 - [TRAINER_DONNY] = + [DIFFICULTY_NORMAL][TRAINER_DONNY] = { #line 7079 .trainerName = _("DONNY"), @@ -17619,7 +17619,7 @@ F_TRAINER_FEMALE | }, }, #line 7095 - [TRAINER_TALIA] = + [DIFFICULTY_NORMAL][TRAINER_TALIA] = { #line 7096 .trainerName = _("TALIA"), @@ -17653,7 +17653,7 @@ F_TRAINER_FEMALE | }, }, #line 7108 - [TRAINER_KATELYN_1] = + [DIFFICULTY_NORMAL][TRAINER_KATELYN_1] = { #line 7109 .trainerName = _("KATELYN"), @@ -17687,7 +17687,7 @@ F_TRAINER_FEMALE | }, }, #line 7121 - [TRAINER_ALLISON] = + [DIFFICULTY_NORMAL][TRAINER_ALLISON] = { #line 7122 .trainerName = _("ALLISON"), @@ -17732,7 +17732,7 @@ F_TRAINER_FEMALE | }, }, #line 7138 - [TRAINER_KATELYN_2] = + [DIFFICULTY_NORMAL][TRAINER_KATELYN_2] = { #line 7139 .trainerName = _("KATELYN"), @@ -17766,7 +17766,7 @@ F_TRAINER_FEMALE | }, }, #line 7151 - [TRAINER_KATELYN_3] = + [DIFFICULTY_NORMAL][TRAINER_KATELYN_3] = { #line 7152 .trainerName = _("KATELYN"), @@ -17800,7 +17800,7 @@ F_TRAINER_FEMALE | }, }, #line 7164 - [TRAINER_KATELYN_4] = + [DIFFICULTY_NORMAL][TRAINER_KATELYN_4] = { #line 7165 .trainerName = _("KATELYN"), @@ -17834,7 +17834,7 @@ F_TRAINER_FEMALE | }, }, #line 7177 - [TRAINER_KATELYN_5] = + [DIFFICULTY_NORMAL][TRAINER_KATELYN_5] = { #line 7178 .trainerName = _("KATELYN"), @@ -17868,7 +17868,7 @@ F_TRAINER_FEMALE | }, }, #line 7190 - [TRAINER_NICOLAS_1] = + [DIFFICULTY_NORMAL][TRAINER_NICOLAS_1] = { #line 7191 .trainerName = _("NICOLAS"), @@ -17911,7 +17911,7 @@ F_TRAINER_FEMALE | }, }, #line 7207 - [TRAINER_NICOLAS_2] = + [DIFFICULTY_NORMAL][TRAINER_NICOLAS_2] = { #line 7208 .trainerName = _("NICOLAS"), @@ -17954,7 +17954,7 @@ F_TRAINER_FEMALE | }, }, #line 7224 - [TRAINER_NICOLAS_3] = + [DIFFICULTY_NORMAL][TRAINER_NICOLAS_3] = { #line 7225 .trainerName = _("NICOLAS"), @@ -17997,7 +17997,7 @@ F_TRAINER_FEMALE | }, }, #line 7241 - [TRAINER_NICOLAS_4] = + [DIFFICULTY_NORMAL][TRAINER_NICOLAS_4] = { #line 7242 .trainerName = _("NICOLAS"), @@ -18051,7 +18051,7 @@ F_TRAINER_FEMALE | }, }, #line 7262 - [TRAINER_NICOLAS_5] = + [DIFFICULTY_NORMAL][TRAINER_NICOLAS_5] = { #line 7263 .trainerName = _("NICOLAS"), @@ -18107,7 +18107,7 @@ F_TRAINER_FEMALE | }, }, #line 7283 - [TRAINER_AARON] = + [DIFFICULTY_NORMAL][TRAINER_AARON] = { #line 7284 .trainerName = _("AARON"), @@ -18146,7 +18146,7 @@ F_TRAINER_FEMALE | }, }, #line 7300 - [TRAINER_PERRY] = + [DIFFICULTY_NORMAL][TRAINER_PERRY] = { #line 7301 .trainerName = _("PERRY"), @@ -18178,7 +18178,7 @@ F_TRAINER_FEMALE | }, }, #line 7313 - [TRAINER_HUGH] = + [DIFFICULTY_NORMAL][TRAINER_HUGH] = { #line 7314 .trainerName = _("HUGH"), @@ -18221,7 +18221,7 @@ F_TRAINER_FEMALE | }, }, #line 7330 - [TRAINER_PHIL] = + [DIFFICULTY_NORMAL][TRAINER_PHIL] = { #line 7331 .trainerName = _("PHIL"), @@ -18253,7 +18253,7 @@ F_TRAINER_FEMALE | }, }, #line 7343 - [TRAINER_JARED] = + [DIFFICULTY_NORMAL][TRAINER_JARED] = { #line 7344 .trainerName = _("JARED"), @@ -18307,7 +18307,7 @@ F_TRAINER_FEMALE | }, }, #line 7364 - [TRAINER_HUMBERTO] = + [DIFFICULTY_NORMAL][TRAINER_HUMBERTO] = { #line 7365 .trainerName = _("HUMBERTO"), @@ -18339,7 +18339,7 @@ F_TRAINER_FEMALE | }, }, #line 7377 - [TRAINER_PRESLEY] = + [DIFFICULTY_NORMAL][TRAINER_PRESLEY] = { #line 7378 .trainerName = _("PRESLEY"), @@ -18382,7 +18382,7 @@ F_TRAINER_FEMALE | }, }, #line 7394 - [TRAINER_EDWARDO] = + [DIFFICULTY_NORMAL][TRAINER_EDWARDO] = { #line 7395 .trainerName = _("EDWARDO"), @@ -18425,7 +18425,7 @@ F_TRAINER_FEMALE | }, }, #line 7411 - [TRAINER_COLIN] = + [DIFFICULTY_NORMAL][TRAINER_COLIN] = { #line 7412 .trainerName = _("COLIN"), @@ -18468,7 +18468,7 @@ F_TRAINER_FEMALE | }, }, #line 7428 - [TRAINER_ROBERT_1] = + [DIFFICULTY_NORMAL][TRAINER_ROBERT_1] = { #line 7429 .trainerName = _("ROBERT"), @@ -18500,7 +18500,7 @@ F_TRAINER_FEMALE | }, }, #line 7441 - [TRAINER_BENNY] = + [DIFFICULTY_NORMAL][TRAINER_BENNY] = { #line 7442 .trainerName = _("BENNY"), @@ -18554,7 +18554,7 @@ F_TRAINER_FEMALE | }, }, #line 7462 - [TRAINER_CHESTER] = + [DIFFICULTY_NORMAL][TRAINER_CHESTER] = { #line 7463 .trainerName = _("CHESTER"), @@ -18597,7 +18597,7 @@ F_TRAINER_FEMALE | }, }, #line 7479 - [TRAINER_ROBERT_2] = + [DIFFICULTY_NORMAL][TRAINER_ROBERT_2] = { #line 7480 .trainerName = _("ROBERT"), @@ -18640,7 +18640,7 @@ F_TRAINER_FEMALE | }, }, #line 7496 - [TRAINER_ROBERT_3] = + [DIFFICULTY_NORMAL][TRAINER_ROBERT_3] = { #line 7497 .trainerName = _("ROBERT"), @@ -18683,7 +18683,7 @@ F_TRAINER_FEMALE | }, }, #line 7513 - [TRAINER_ROBERT_4] = + [DIFFICULTY_NORMAL][TRAINER_ROBERT_4] = { #line 7514 .trainerName = _("ROBERT"), @@ -18726,7 +18726,7 @@ F_TRAINER_FEMALE | }, }, #line 7530 - [TRAINER_ROBERT_5] = + [DIFFICULTY_NORMAL][TRAINER_ROBERT_5] = { #line 7531 .trainerName = _("ROBERT"), @@ -18769,7 +18769,7 @@ F_TRAINER_FEMALE | }, }, #line 7547 - [TRAINER_ALEX] = + [DIFFICULTY_NORMAL][TRAINER_ALEX] = { #line 7548 .trainerName = _("ALEX"), @@ -18812,7 +18812,7 @@ F_TRAINER_FEMALE | }, }, #line 7564 - [TRAINER_BECK] = + [DIFFICULTY_NORMAL][TRAINER_BECK] = { #line 7565 .trainerName = _("BECK"), @@ -18844,7 +18844,7 @@ F_TRAINER_FEMALE | }, }, #line 7577 - [TRAINER_YASU] = + [DIFFICULTY_NORMAL][TRAINER_YASU] = { #line 7578 .trainerName = _("YASU"), @@ -18876,7 +18876,7 @@ F_TRAINER_FEMALE | }, }, #line 7590 - [TRAINER_TAKASHI] = + [DIFFICULTY_NORMAL][TRAINER_TAKASHI] = { #line 7591 .trainerName = _("TAKASHI"), @@ -18919,7 +18919,7 @@ F_TRAINER_FEMALE | }, }, #line 7607 - [TRAINER_DIANNE] = + [DIFFICULTY_NORMAL][TRAINER_DIANNE] = { #line 7608 .trainerName = _("DIANNE"), @@ -18974,7 +18974,7 @@ F_TRAINER_FEMALE | }, }, #line 7628 - [TRAINER_JANI] = + [DIFFICULTY_NORMAL][TRAINER_JANI] = { #line 7629 .trainerName = _("JANI"), @@ -19006,7 +19006,7 @@ F_TRAINER_FEMALE | }, }, #line 7640 - [TRAINER_LAO_1] = + [DIFFICULTY_NORMAL][TRAINER_LAO_1] = { #line 7641 .trainerName = _("LAO"), @@ -19079,7 +19079,7 @@ F_TRAINER_FEMALE | }, }, #line 7672 - [TRAINER_LUNG] = + [DIFFICULTY_NORMAL][TRAINER_LUNG] = { #line 7673 .trainerName = _("LUNG"), @@ -19120,7 +19120,7 @@ F_TRAINER_FEMALE | }, }, #line 7688 - [TRAINER_LAO_2] = + [DIFFICULTY_NORMAL][TRAINER_LAO_2] = { #line 7689 .trainerName = _("LAO"), @@ -19208,7 +19208,7 @@ F_TRAINER_FEMALE | }, }, #line 7725 - [TRAINER_LAO_3] = + [DIFFICULTY_NORMAL][TRAINER_LAO_3] = { #line 7726 .trainerName = _("LAO"), @@ -19296,7 +19296,7 @@ F_TRAINER_FEMALE | }, }, #line 7762 - [TRAINER_LAO_4] = + [DIFFICULTY_NORMAL][TRAINER_LAO_4] = { #line 7763 .trainerName = _("LAO"), @@ -19382,7 +19382,7 @@ F_TRAINER_FEMALE | }, }, #line 7797 - [TRAINER_LAO_5] = + [DIFFICULTY_NORMAL][TRAINER_LAO_5] = { #line 7798 .trainerName = _("LAO"), @@ -19472,7 +19472,7 @@ F_TRAINER_FEMALE | }, }, #line 7834 - [TRAINER_JOCELYN] = + [DIFFICULTY_NORMAL][TRAINER_JOCELYN] = { #line 7835 .trainerName = _("JOCELYN"), @@ -19506,7 +19506,7 @@ F_TRAINER_FEMALE | }, }, #line 7847 - [TRAINER_LAURA] = + [DIFFICULTY_NORMAL][TRAINER_LAURA] = { #line 7848 .trainerName = _("LAURA"), @@ -19540,7 +19540,7 @@ F_TRAINER_FEMALE | }, }, #line 7860 - [TRAINER_CYNDY_1] = + [DIFFICULTY_NORMAL][TRAINER_CYNDY_1] = { #line 7861 .trainerName = _("CYNDY"), @@ -19585,7 +19585,7 @@ F_TRAINER_FEMALE | }, }, #line 7877 - [TRAINER_CORA] = + [DIFFICULTY_NORMAL][TRAINER_CORA] = { #line 7878 .trainerName = _("CORA"), @@ -19619,7 +19619,7 @@ F_TRAINER_FEMALE | }, }, #line 7890 - [TRAINER_PAULA] = + [DIFFICULTY_NORMAL][TRAINER_PAULA] = { #line 7891 .trainerName = _("PAULA"), @@ -19653,7 +19653,7 @@ F_TRAINER_FEMALE | }, }, #line 7903 - [TRAINER_CYNDY_2] = + [DIFFICULTY_NORMAL][TRAINER_CYNDY_2] = { #line 7904 .trainerName = _("CYNDY"), @@ -19698,7 +19698,7 @@ F_TRAINER_FEMALE | }, }, #line 7920 - [TRAINER_CYNDY_3] = + [DIFFICULTY_NORMAL][TRAINER_CYNDY_3] = { #line 7921 .trainerName = _("CYNDY"), @@ -19743,7 +19743,7 @@ F_TRAINER_FEMALE | }, }, #line 7937 - [TRAINER_CYNDY_4] = + [DIFFICULTY_NORMAL][TRAINER_CYNDY_4] = { #line 7938 .trainerName = _("CYNDY"), @@ -19788,7 +19788,7 @@ F_TRAINER_FEMALE | }, }, #line 7954 - [TRAINER_CYNDY_5] = + [DIFFICULTY_NORMAL][TRAINER_CYNDY_5] = { #line 7955 .trainerName = _("CYNDY"), @@ -19833,7 +19833,7 @@ F_TRAINER_FEMALE | }, }, #line 7971 - [TRAINER_MADELINE_1] = + [DIFFICULTY_NORMAL][TRAINER_MADELINE_1] = { #line 7972 .trainerName = _("MADELINE"), @@ -19874,7 +19874,7 @@ F_TRAINER_FEMALE | }, }, #line 7988 - [TRAINER_CLARISSA] = + [DIFFICULTY_NORMAL][TRAINER_CLARISSA] = { #line 7989 .trainerName = _("CLARISSA"), @@ -19919,7 +19919,7 @@ F_TRAINER_FEMALE | }, }, #line 8005 - [TRAINER_ANGELICA] = + [DIFFICULTY_NORMAL][TRAINER_ANGELICA] = { #line 8006 .trainerName = _("ANGELICA"), @@ -19960,7 +19960,7 @@ F_TRAINER_FEMALE | }, }, #line 8022 - [TRAINER_MADELINE_2] = + [DIFFICULTY_NORMAL][TRAINER_MADELINE_2] = { #line 8023 .trainerName = _("MADELINE"), @@ -20001,7 +20001,7 @@ F_TRAINER_FEMALE | }, }, #line 8039 - [TRAINER_MADELINE_3] = + [DIFFICULTY_NORMAL][TRAINER_MADELINE_3] = { #line 8040 .trainerName = _("MADELINE"), @@ -20042,7 +20042,7 @@ F_TRAINER_FEMALE | }, }, #line 8056 - [TRAINER_MADELINE_4] = + [DIFFICULTY_NORMAL][TRAINER_MADELINE_4] = { #line 8057 .trainerName = _("MADELINE"), @@ -20101,7 +20101,7 @@ F_TRAINER_FEMALE | }, }, #line 8081 - [TRAINER_MADELINE_5] = + [DIFFICULTY_NORMAL][TRAINER_MADELINE_5] = { #line 8082 .trainerName = _("MADELINE"), @@ -20160,7 +20160,7 @@ F_TRAINER_FEMALE | }, }, #line 8106 - [TRAINER_BEVERLY] = + [DIFFICULTY_NORMAL][TRAINER_BEVERLY] = { #line 8107 .trainerName = _("BEVERLY"), @@ -20205,7 +20205,7 @@ F_TRAINER_FEMALE | }, }, #line 8123 - [TRAINER_IMANI] = + [DIFFICULTY_NORMAL][TRAINER_IMANI] = { #line 8124 .trainerName = _("IMANI"), @@ -20239,7 +20239,7 @@ F_TRAINER_FEMALE | }, }, #line 8136 - [TRAINER_KYLA] = + [DIFFICULTY_NORMAL][TRAINER_KYLA] = { #line 8137 .trainerName = _("KYLA"), @@ -20273,7 +20273,7 @@ F_TRAINER_FEMALE | }, }, #line 8149 - [TRAINER_DENISE] = + [DIFFICULTY_NORMAL][TRAINER_DENISE] = { #line 8150 .trainerName = _("DENISE"), @@ -20318,7 +20318,7 @@ F_TRAINER_FEMALE | }, }, #line 8166 - [TRAINER_BETH] = + [DIFFICULTY_NORMAL][TRAINER_BETH] = { #line 8167 .trainerName = _("BETH"), @@ -20352,7 +20352,7 @@ F_TRAINER_FEMALE | }, }, #line 8179 - [TRAINER_TARA] = + [DIFFICULTY_NORMAL][TRAINER_TARA] = { #line 8180 .trainerName = _("TARA"), @@ -20397,7 +20397,7 @@ F_TRAINER_FEMALE | }, }, #line 8196 - [TRAINER_MISSY] = + [DIFFICULTY_NORMAL][TRAINER_MISSY] = { #line 8197 .trainerName = _("MISSY"), @@ -20431,7 +20431,7 @@ F_TRAINER_FEMALE | }, }, #line 8209 - [TRAINER_ALICE] = + [DIFFICULTY_NORMAL][TRAINER_ALICE] = { #line 8210 .trainerName = _("ALICE"), @@ -20487,7 +20487,7 @@ F_TRAINER_FEMALE | }, }, #line 8230 - [TRAINER_JENNY_1] = + [DIFFICULTY_NORMAL][TRAINER_JENNY_1] = { #line 8231 .trainerName = _("JENNY"), @@ -20521,7 +20521,7 @@ F_TRAINER_FEMALE | }, }, #line 8243 - [TRAINER_GRACE] = + [DIFFICULTY_NORMAL][TRAINER_GRACE] = { #line 8244 .trainerName = _("GRACE"), @@ -20555,7 +20555,7 @@ F_TRAINER_FEMALE | }, }, #line 8256 - [TRAINER_TANYA] = + [DIFFICULTY_NORMAL][TRAINER_TANYA] = { #line 8257 .trainerName = _("TANYA"), @@ -20589,7 +20589,7 @@ F_TRAINER_FEMALE | }, }, #line 8269 - [TRAINER_SHARON] = + [DIFFICULTY_NORMAL][TRAINER_SHARON] = { #line 8270 .trainerName = _("SHARON"), @@ -20623,7 +20623,7 @@ F_TRAINER_FEMALE | }, }, #line 8282 - [TRAINER_NIKKI] = + [DIFFICULTY_NORMAL][TRAINER_NIKKI] = { #line 8283 .trainerName = _("NIKKI"), @@ -20668,7 +20668,7 @@ F_TRAINER_FEMALE | }, }, #line 8299 - [TRAINER_BRENDA] = + [DIFFICULTY_NORMAL][TRAINER_BRENDA] = { #line 8300 .trainerName = _("BRENDA"), @@ -20702,7 +20702,7 @@ F_TRAINER_FEMALE | }, }, #line 8312 - [TRAINER_KATIE] = + [DIFFICULTY_NORMAL][TRAINER_KATIE] = { #line 8313 .trainerName = _("KATIE"), @@ -20747,7 +20747,7 @@ F_TRAINER_FEMALE | }, }, #line 8329 - [TRAINER_SUSIE] = + [DIFFICULTY_NORMAL][TRAINER_SUSIE] = { #line 8330 .trainerName = _("SUSIE"), @@ -20781,7 +20781,7 @@ F_TRAINER_FEMALE | }, }, #line 8342 - [TRAINER_KARA] = + [DIFFICULTY_NORMAL][TRAINER_KARA] = { #line 8343 .trainerName = _("KARA"), @@ -20815,7 +20815,7 @@ F_TRAINER_FEMALE | }, }, #line 8355 - [TRAINER_DANA] = + [DIFFICULTY_NORMAL][TRAINER_DANA] = { #line 8356 .trainerName = _("DANA"), @@ -20849,7 +20849,7 @@ F_TRAINER_FEMALE | }, }, #line 8368 - [TRAINER_SIENNA] = + [DIFFICULTY_NORMAL][TRAINER_SIENNA] = { #line 8369 .trainerName = _("SIENNA"), @@ -20894,7 +20894,7 @@ F_TRAINER_FEMALE | }, }, #line 8385 - [TRAINER_DEBRA] = + [DIFFICULTY_NORMAL][TRAINER_DEBRA] = { #line 8386 .trainerName = _("DEBRA"), @@ -20928,7 +20928,7 @@ F_TRAINER_FEMALE | }, }, #line 8398 - [TRAINER_LINDA] = + [DIFFICULTY_NORMAL][TRAINER_LINDA] = { #line 8399 .trainerName = _("LINDA"), @@ -20973,7 +20973,7 @@ F_TRAINER_FEMALE | }, }, #line 8415 - [TRAINER_KAYLEE] = + [DIFFICULTY_NORMAL][TRAINER_KAYLEE] = { #line 8416 .trainerName = _("KAYLEE"), @@ -21018,7 +21018,7 @@ F_TRAINER_FEMALE | }, }, #line 8432 - [TRAINER_LAUREL] = + [DIFFICULTY_NORMAL][TRAINER_LAUREL] = { #line 8433 .trainerName = _("LAUREL"), @@ -21063,7 +21063,7 @@ F_TRAINER_FEMALE | }, }, #line 8449 - [TRAINER_CARLEE] = + [DIFFICULTY_NORMAL][TRAINER_CARLEE] = { #line 8450 .trainerName = _("CARLEE"), @@ -21097,7 +21097,7 @@ F_TRAINER_FEMALE | }, }, #line 8462 - [TRAINER_JENNY_2] = + [DIFFICULTY_NORMAL][TRAINER_JENNY_2] = { #line 8463 .trainerName = _("JENNY"), @@ -21131,7 +21131,7 @@ F_TRAINER_FEMALE | }, }, #line 8475 - [TRAINER_JENNY_3] = + [DIFFICULTY_NORMAL][TRAINER_JENNY_3] = { #line 8476 .trainerName = _("JENNY"), @@ -21165,7 +21165,7 @@ F_TRAINER_FEMALE | }, }, #line 8488 - [TRAINER_JENNY_4] = + [DIFFICULTY_NORMAL][TRAINER_JENNY_4] = { #line 8489 .trainerName = _("JENNY"), @@ -21210,7 +21210,7 @@ F_TRAINER_FEMALE | }, }, #line 8505 - [TRAINER_JENNY_5] = + [DIFFICULTY_NORMAL][TRAINER_JENNY_5] = { #line 8506 .trainerName = _("JENNY"), @@ -21266,7 +21266,7 @@ F_TRAINER_FEMALE | }, }, #line 8526 - [TRAINER_HEIDI] = + [DIFFICULTY_NORMAL][TRAINER_HEIDI] = { #line 8527 .trainerName = _("HEIDI"), @@ -21325,7 +21325,7 @@ F_TRAINER_FEMALE | }, }, #line 8551 - [TRAINER_BECKY] = + [DIFFICULTY_NORMAL][TRAINER_BECKY] = { #line 8552 .trainerName = _("BECKY"), @@ -21384,7 +21384,7 @@ F_TRAINER_FEMALE | }, }, #line 8576 - [TRAINER_CAROL] = + [DIFFICULTY_NORMAL][TRAINER_CAROL] = { #line 8577 .trainerName = _("CAROL"), @@ -21429,7 +21429,7 @@ F_TRAINER_FEMALE | }, }, #line 8593 - [TRAINER_NANCY] = + [DIFFICULTY_NORMAL][TRAINER_NANCY] = { #line 8594 .trainerName = _("NANCY"), @@ -21474,7 +21474,7 @@ F_TRAINER_FEMALE | }, }, #line 8610 - [TRAINER_MARTHA] = + [DIFFICULTY_NORMAL][TRAINER_MARTHA] = { #line 8611 .trainerName = _("MARTHA"), @@ -21519,7 +21519,7 @@ F_TRAINER_FEMALE | }, }, #line 8627 - [TRAINER_DIANA_1] = + [DIFFICULTY_NORMAL][TRAINER_DIANA_1] = { #line 8628 .trainerName = _("DIANA"), @@ -21575,7 +21575,7 @@ F_TRAINER_FEMALE | }, }, #line 8648 - [TRAINER_CEDRIC] = + [DIFFICULTY_NORMAL][TRAINER_CEDRIC] = { #line 8649 .trainerName = _("CEDRIC"), @@ -21614,7 +21614,7 @@ F_TRAINER_FEMALE | }, }, #line 8665 - [TRAINER_IRENE] = + [DIFFICULTY_NORMAL][TRAINER_IRENE] = { #line 8666 .trainerName = _("IRENE"), @@ -21659,7 +21659,7 @@ F_TRAINER_FEMALE | }, }, #line 8682 - [TRAINER_DIANA_2] = + [DIFFICULTY_NORMAL][TRAINER_DIANA_2] = { #line 8683 .trainerName = _("DIANA"), @@ -21715,7 +21715,7 @@ F_TRAINER_FEMALE | }, }, #line 8703 - [TRAINER_DIANA_3] = + [DIFFICULTY_NORMAL][TRAINER_DIANA_3] = { #line 8704 .trainerName = _("DIANA"), @@ -21771,7 +21771,7 @@ F_TRAINER_FEMALE | }, }, #line 8724 - [TRAINER_DIANA_4] = + [DIFFICULTY_NORMAL][TRAINER_DIANA_4] = { #line 8725 .trainerName = _("DIANA"), @@ -21827,7 +21827,7 @@ F_TRAINER_FEMALE | }, }, #line 8745 - [TRAINER_DIANA_5] = + [DIFFICULTY_NORMAL][TRAINER_DIANA_5] = { #line 8746 .trainerName = _("DIANA"), @@ -21883,7 +21883,7 @@ F_TRAINER_FEMALE | }, }, #line 8766 - [TRAINER_AMY_AND_LIV_1] = + [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_1] = { #line 8767 .trainerName = _("AMY & LIV"), @@ -21926,7 +21926,7 @@ F_TRAINER_FEMALE | }, }, #line 8783 - [TRAINER_AMY_AND_LIV_2] = + [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_2] = { #line 8784 .trainerName = _("AMY & LIV"), @@ -21969,7 +21969,7 @@ F_TRAINER_FEMALE | }, }, #line 8800 - [TRAINER_GINA_AND_MIA_1] = + [DIFFICULTY_NORMAL][TRAINER_GINA_AND_MIA_1] = { #line 8801 .trainerName = _("GINA & MIA"), @@ -22012,7 +22012,7 @@ F_TRAINER_FEMALE | }, }, #line 8817 - [TRAINER_MIU_AND_YUKI] = + [DIFFICULTY_NORMAL][TRAINER_MIU_AND_YUKI] = { #line 8818 .trainerName = _("MIU & YUKI"), @@ -22055,7 +22055,7 @@ F_TRAINER_FEMALE | }, }, #line 8834 - [TRAINER_AMY_AND_LIV_3] = + [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_3] = { #line 8835 .trainerName = _("AMY & LIV"), @@ -22098,7 +22098,7 @@ F_TRAINER_FEMALE | }, }, #line 8851 - [TRAINER_GINA_AND_MIA_2] = + [DIFFICULTY_NORMAL][TRAINER_GINA_AND_MIA_2] = { #line 8852 .trainerName = _("GINA & MIA"), @@ -22151,7 +22151,7 @@ F_TRAINER_FEMALE | }, }, #line 8872 - [TRAINER_AMY_AND_LIV_4] = + [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_4] = { #line 8873 .trainerName = _("AMY & LIV"), @@ -22194,7 +22194,7 @@ F_TRAINER_FEMALE | }, }, #line 8889 - [TRAINER_AMY_AND_LIV_5] = + [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_5] = { #line 8890 .trainerName = _("AMY & LIV"), @@ -22251,7 +22251,7 @@ F_TRAINER_FEMALE | }, }, #line 8914 - [TRAINER_AMY_AND_LIV_6] = + [DIFFICULTY_NORMAL][TRAINER_AMY_AND_LIV_6] = { #line 8915 .trainerName = _("AMY & LIV"), @@ -22308,7 +22308,7 @@ F_TRAINER_FEMALE | }, }, #line 8939 - [TRAINER_HUEY] = + [DIFFICULTY_NORMAL][TRAINER_HUEY] = { #line 8940 .trainerName = _("HUEY"), @@ -22351,7 +22351,7 @@ F_TRAINER_FEMALE | }, }, #line 8956 - [TRAINER_EDMOND] = + [DIFFICULTY_NORMAL][TRAINER_EDMOND] = { #line 8957 .trainerName = _("EDMOND"), @@ -22383,7 +22383,7 @@ F_TRAINER_FEMALE | }, }, #line 8969 - [TRAINER_ERNEST_1] = + [DIFFICULTY_NORMAL][TRAINER_ERNEST_1] = { #line 8970 .trainerName = _("ERNEST"), @@ -22426,7 +22426,7 @@ F_TRAINER_FEMALE | }, }, #line 8986 - [TRAINER_DWAYNE] = + [DIFFICULTY_NORMAL][TRAINER_DWAYNE] = { #line 8987 .trainerName = _("DWAYNE"), @@ -22480,7 +22480,7 @@ F_TRAINER_FEMALE | }, }, #line 9007 - [TRAINER_PHILLIP] = + [DIFFICULTY_NORMAL][TRAINER_PHILLIP] = { #line 9008 .trainerName = _("PHILLIP"), @@ -22523,7 +22523,7 @@ F_TRAINER_FEMALE | }, }, #line 9024 - [TRAINER_LEONARD] = + [DIFFICULTY_NORMAL][TRAINER_LEONARD] = { #line 9025 .trainerName = _("LEONARD"), @@ -22577,7 +22577,7 @@ F_TRAINER_FEMALE | }, }, #line 9045 - [TRAINER_DUNCAN] = + [DIFFICULTY_NORMAL][TRAINER_DUNCAN] = { #line 9046 .trainerName = _("DUNCAN"), @@ -22620,7 +22620,7 @@ F_TRAINER_FEMALE | }, }, #line 9062 - [TRAINER_ERNEST_2] = + [DIFFICULTY_NORMAL][TRAINER_ERNEST_2] = { #line 9063 .trainerName = _("ERNEST"), @@ -22674,7 +22674,7 @@ F_TRAINER_FEMALE | }, }, #line 9083 - [TRAINER_ERNEST_3] = + [DIFFICULTY_NORMAL][TRAINER_ERNEST_3] = { #line 9084 .trainerName = _("ERNEST"), @@ -22728,7 +22728,7 @@ F_TRAINER_FEMALE | }, }, #line 9104 - [TRAINER_ERNEST_4] = + [DIFFICULTY_NORMAL][TRAINER_ERNEST_4] = { #line 9105 .trainerName = _("ERNEST"), @@ -22782,7 +22782,7 @@ F_TRAINER_FEMALE | }, }, #line 9125 - [TRAINER_ERNEST_5] = + [DIFFICULTY_NORMAL][TRAINER_ERNEST_5] = { #line 9126 .trainerName = _("ERNEST"), @@ -22836,7 +22836,7 @@ F_TRAINER_FEMALE | }, }, #line 9146 - [TRAINER_ELI] = + [DIFFICULTY_NORMAL][TRAINER_ELI] = { #line 9147 .trainerName = _("ELI"), @@ -22868,7 +22868,7 @@ F_TRAINER_FEMALE | }, }, #line 9159 - [TRAINER_ANNIKA] = + [DIFFICULTY_NORMAL][TRAINER_ANNIKA] = { #line 9160 .trainerName = _("ANNIKA"), @@ -22931,7 +22931,7 @@ F_TRAINER_FEMALE | }, }, #line 9184 - [TRAINER_JAZMYN] = + [DIFFICULTY_NORMAL][TRAINER_JAZMYN] = { #line 9185 .trainerName = _("JAZMYN"), @@ -22967,7 +22967,7 @@ F_TRAINER_FEMALE | }, }, #line 9198 - [TRAINER_JONAS] = + [DIFFICULTY_NORMAL][TRAINER_JONAS] = { #line 9199 .trainerName = _("JONAS"), @@ -23006,7 +23006,7 @@ F_TRAINER_FEMALE | }, }, #line 9215 - [TRAINER_KAYLEY] = + [DIFFICULTY_NORMAL][TRAINER_KAYLEY] = { #line 9216 .trainerName = _("KAYLEY"), @@ -23047,7 +23047,7 @@ F_TRAINER_FEMALE | }, }, #line 9232 - [TRAINER_AURON] = + [DIFFICULTY_NORMAL][TRAINER_AURON] = { #line 9233 .trainerName = _("AURON"), @@ -23090,7 +23090,7 @@ F_TRAINER_FEMALE | }, }, #line 9249 - [TRAINER_KELVIN] = + [DIFFICULTY_NORMAL][TRAINER_KELVIN] = { #line 9250 .trainerName = _("KELVIN"), @@ -23133,7 +23133,7 @@ F_TRAINER_FEMALE | }, }, #line 9266 - [TRAINER_MARLEY] = + [DIFFICULTY_NORMAL][TRAINER_MARLEY] = { #line 9267 .trainerName = _("MARLEY"), @@ -23176,7 +23176,7 @@ F_TRAINER_FEMALE | }, }, #line 9284 - [TRAINER_REYNA] = + [DIFFICULTY_NORMAL][TRAINER_REYNA] = { #line 9285 .trainerName = _("REYNA"), @@ -23221,7 +23221,7 @@ F_TRAINER_FEMALE | }, }, #line 9301 - [TRAINER_HUDSON] = + [DIFFICULTY_NORMAL][TRAINER_HUDSON] = { #line 9302 .trainerName = _("HUDSON"), @@ -23253,7 +23253,7 @@ F_TRAINER_FEMALE | }, }, #line 9314 - [TRAINER_CONOR] = + [DIFFICULTY_NORMAL][TRAINER_CONOR] = { #line 9315 .trainerName = _("CONOR"), @@ -23296,7 +23296,7 @@ F_TRAINER_FEMALE | }, }, #line 9331 - [TRAINER_EDWIN_1] = + [DIFFICULTY_NORMAL][TRAINER_EDWIN_1] = { #line 9332 .trainerName = _("EDWIN"), @@ -23339,7 +23339,7 @@ F_TRAINER_FEMALE | }, }, #line 9348 - [TRAINER_HECTOR] = + [DIFFICULTY_NORMAL][TRAINER_HECTOR] = { #line 9349 .trainerName = _("HECTOR"), @@ -23382,7 +23382,7 @@ F_TRAINER_FEMALE | }, }, #line 9365 - [TRAINER_TABITHA_MOSSDEEP] = + [DIFFICULTY_NORMAL][TRAINER_TABITHA_MOSSDEEP] = { #line 9366 .trainerName = _("TABITHA"), @@ -23436,7 +23436,7 @@ F_TRAINER_FEMALE | }, }, #line 9386 - [TRAINER_EDWIN_2] = + [DIFFICULTY_NORMAL][TRAINER_EDWIN_2] = { #line 9387 .trainerName = _("EDWIN"), @@ -23479,7 +23479,7 @@ F_TRAINER_FEMALE | }, }, #line 9403 - [TRAINER_EDWIN_3] = + [DIFFICULTY_NORMAL][TRAINER_EDWIN_3] = { #line 9404 .trainerName = _("EDWIN"), @@ -23522,7 +23522,7 @@ F_TRAINER_FEMALE | }, }, #line 9420 - [TRAINER_EDWIN_4] = + [DIFFICULTY_NORMAL][TRAINER_EDWIN_4] = { #line 9421 .trainerName = _("EDWIN"), @@ -23565,7 +23565,7 @@ F_TRAINER_FEMALE | }, }, #line 9437 - [TRAINER_EDWIN_5] = + [DIFFICULTY_NORMAL][TRAINER_EDWIN_5] = { #line 9438 .trainerName = _("EDWIN"), @@ -23608,7 +23608,7 @@ F_TRAINER_FEMALE | }, }, #line 9454 - [TRAINER_WALLY_VR_1] = + [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_1] = { #line 9455 .trainerName = _("WALLY"), @@ -23721,7 +23721,7 @@ F_TRAINER_FEMALE | }, }, #line 9504 - [TRAINER_BRENDAN_ROUTE_103_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_103_MUDKIP] = { #line 9505 .trainerName = _("BRENDAN"), @@ -23753,7 +23753,7 @@ F_TRAINER_FEMALE | }, }, #line 9517 - [TRAINER_BRENDAN_ROUTE_110_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_110_MUDKIP] = { #line 9518 .trainerName = _("BRENDAN"), @@ -23807,7 +23807,7 @@ F_TRAINER_FEMALE | }, }, #line 9538 - [TRAINER_BRENDAN_ROUTE_119_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_119_MUDKIP] = { #line 9539 .trainerName = _("BRENDAN"), @@ -23861,7 +23861,7 @@ F_TRAINER_FEMALE | }, }, #line 9559 - [TRAINER_BRENDAN_ROUTE_103_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_103_TREECKO] = { #line 9560 .trainerName = _("BRENDAN"), @@ -23893,7 +23893,7 @@ F_TRAINER_FEMALE | }, }, #line 9572 - [TRAINER_BRENDAN_ROUTE_110_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_110_TREECKO] = { #line 9573 .trainerName = _("BRENDAN"), @@ -23947,7 +23947,7 @@ F_TRAINER_FEMALE | }, }, #line 9593 - [TRAINER_BRENDAN_ROUTE_119_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_119_TREECKO] = { #line 9594 .trainerName = _("BRENDAN"), @@ -24001,7 +24001,7 @@ F_TRAINER_FEMALE | }, }, #line 9614 - [TRAINER_BRENDAN_ROUTE_103_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_103_TORCHIC] = { #line 9615 .trainerName = _("BRENDAN"), @@ -24033,7 +24033,7 @@ F_TRAINER_FEMALE | }, }, #line 9627 - [TRAINER_BRENDAN_ROUTE_110_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_110_TORCHIC] = { #line 9628 .trainerName = _("BRENDAN"), @@ -24087,7 +24087,7 @@ F_TRAINER_FEMALE | }, }, #line 9648 - [TRAINER_BRENDAN_ROUTE_119_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_ROUTE_119_TORCHIC] = { #line 9649 .trainerName = _("BRENDAN"), @@ -24141,7 +24141,7 @@ F_TRAINER_FEMALE | }, }, #line 9669 - [TRAINER_MAY_ROUTE_103_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_103_MUDKIP] = { #line 9670 .trainerName = _("MAY"), @@ -24175,7 +24175,7 @@ F_TRAINER_FEMALE | }, }, #line 9682 - [TRAINER_MAY_ROUTE_110_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_110_MUDKIP] = { #line 9683 .trainerName = _("MAY"), @@ -24231,7 +24231,7 @@ F_TRAINER_FEMALE | }, }, #line 9703 - [TRAINER_MAY_ROUTE_119_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_119_MUDKIP] = { #line 9704 .trainerName = _("MAY"), @@ -24287,7 +24287,7 @@ F_TRAINER_FEMALE | }, }, #line 9724 - [TRAINER_MAY_ROUTE_103_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_103_TREECKO] = { #line 9725 .trainerName = _("MAY"), @@ -24321,7 +24321,7 @@ F_TRAINER_FEMALE | }, }, #line 9737 - [TRAINER_MAY_ROUTE_110_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_110_TREECKO] = { #line 9738 .trainerName = _("MAY"), @@ -24377,7 +24377,7 @@ F_TRAINER_FEMALE | }, }, #line 9758 - [TRAINER_MAY_ROUTE_119_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_119_TREECKO] = { #line 9759 .trainerName = _("MAY"), @@ -24433,7 +24433,7 @@ F_TRAINER_FEMALE | }, }, #line 9779 - [TRAINER_MAY_ROUTE_103_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_103_TORCHIC] = { #line 9780 .trainerName = _("MAY"), @@ -24467,7 +24467,7 @@ F_TRAINER_FEMALE | }, }, #line 9792 - [TRAINER_MAY_ROUTE_110_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_110_TORCHIC] = { #line 9793 .trainerName = _("MAY"), @@ -24523,7 +24523,7 @@ F_TRAINER_FEMALE | }, }, #line 9813 - [TRAINER_MAY_ROUTE_119_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_MAY_ROUTE_119_TORCHIC] = { #line 9814 .trainerName = _("MAY"), @@ -24579,7 +24579,7 @@ F_TRAINER_FEMALE | }, }, #line 9834 - [TRAINER_ISAAC_1] = + [DIFFICULTY_NORMAL][TRAINER_ISAAC_1] = { #line 9835 .trainerName = _("ISAAC"), @@ -24666,7 +24666,7 @@ F_TRAINER_FEMALE | }, }, #line 9867 - [TRAINER_DAVIS] = + [DIFFICULTY_NORMAL][TRAINER_DAVIS] = { #line 9868 .trainerName = _("DAVIS"), @@ -24698,7 +24698,7 @@ F_TRAINER_FEMALE | }, }, #line 9880 - [TRAINER_MITCHELL] = + [DIFFICULTY_NORMAL][TRAINER_MITCHELL] = { #line 9881 .trainerName = _("MITCHELL"), @@ -24755,7 +24755,7 @@ F_TRAINER_FEMALE | }, }, #line 9905 - [TRAINER_ISAAC_2] = + [DIFFICULTY_NORMAL][TRAINER_ISAAC_2] = { #line 9906 .trainerName = _("ISAAC"), @@ -24842,7 +24842,7 @@ F_TRAINER_FEMALE | }, }, #line 9938 - [TRAINER_ISAAC_3] = + [DIFFICULTY_NORMAL][TRAINER_ISAAC_3] = { #line 9939 .trainerName = _("ISAAC"), @@ -24929,7 +24929,7 @@ F_TRAINER_FEMALE | }, }, #line 9971 - [TRAINER_ISAAC_4] = + [DIFFICULTY_NORMAL][TRAINER_ISAAC_4] = { #line 9972 .trainerName = _("ISAAC"), @@ -25016,7 +25016,7 @@ F_TRAINER_FEMALE | }, }, #line 10004 - [TRAINER_ISAAC_5] = + [DIFFICULTY_NORMAL][TRAINER_ISAAC_5] = { #line 10005 .trainerName = _("ISAAC"), @@ -25103,7 +25103,7 @@ F_TRAINER_FEMALE | }, }, #line 10037 - [TRAINER_LYDIA_1] = + [DIFFICULTY_NORMAL][TRAINER_LYDIA_1] = { #line 10038 .trainerName = _("LYDIA"), @@ -25192,7 +25192,7 @@ F_TRAINER_FEMALE | }, }, #line 10070 - [TRAINER_HALLE] = + [DIFFICULTY_NORMAL][TRAINER_HALLE] = { #line 10071 .trainerName = _("HALLE"), @@ -25239,7 +25239,7 @@ F_TRAINER_FEMALE | }, }, #line 10088 - [TRAINER_GARRISON] = + [DIFFICULTY_NORMAL][TRAINER_GARRISON] = { #line 10089 .trainerName = _("GARRISON"), @@ -25271,7 +25271,7 @@ F_TRAINER_FEMALE | }, }, #line 10101 - [TRAINER_LYDIA_2] = + [DIFFICULTY_NORMAL][TRAINER_LYDIA_2] = { #line 10102 .trainerName = _("LYDIA"), @@ -25360,7 +25360,7 @@ F_TRAINER_FEMALE | }, }, #line 10134 - [TRAINER_LYDIA_3] = + [DIFFICULTY_NORMAL][TRAINER_LYDIA_3] = { #line 10135 .trainerName = _("LYDIA"), @@ -25449,7 +25449,7 @@ F_TRAINER_FEMALE | }, }, #line 10167 - [TRAINER_LYDIA_4] = + [DIFFICULTY_NORMAL][TRAINER_LYDIA_4] = { #line 10168 .trainerName = _("LYDIA"), @@ -25538,7 +25538,7 @@ F_TRAINER_FEMALE | }, }, #line 10200 - [TRAINER_LYDIA_5] = + [DIFFICULTY_NORMAL][TRAINER_LYDIA_5] = { #line 10201 .trainerName = _("LYDIA"), @@ -25627,7 +25627,7 @@ F_TRAINER_FEMALE | }, }, #line 10233 - [TRAINER_JACKSON_1] = + [DIFFICULTY_NORMAL][TRAINER_JACKSON_1] = { #line 10234 .trainerName = _("JACKSON"), @@ -25661,7 +25661,7 @@ F_TRAINER_FEMALE | }, }, #line 10247 - [TRAINER_LORENZO] = + [DIFFICULTY_NORMAL][TRAINER_LORENZO] = { #line 10248 .trainerName = _("LORENZO"), @@ -25717,7 +25717,7 @@ F_TRAINER_FEMALE | }, }, #line 10269 - [TRAINER_SEBASTIAN] = + [DIFFICULTY_NORMAL][TRAINER_SEBASTIAN] = { #line 10270 .trainerName = _("SEBASTIAN"), @@ -25751,7 +25751,7 @@ F_TRAINER_FEMALE | }, }, #line 10283 - [TRAINER_JACKSON_2] = + [DIFFICULTY_NORMAL][TRAINER_JACKSON_2] = { #line 10284 .trainerName = _("JACKSON"), @@ -25785,7 +25785,7 @@ F_TRAINER_FEMALE | }, }, #line 10297 - [TRAINER_JACKSON_3] = + [DIFFICULTY_NORMAL][TRAINER_JACKSON_3] = { #line 10298 .trainerName = _("JACKSON"), @@ -25819,7 +25819,7 @@ F_TRAINER_FEMALE | }, }, #line 10311 - [TRAINER_JACKSON_4] = + [DIFFICULTY_NORMAL][TRAINER_JACKSON_4] = { #line 10312 .trainerName = _("JACKSON"), @@ -25853,7 +25853,7 @@ F_TRAINER_FEMALE | }, }, #line 10325 - [TRAINER_JACKSON_5] = + [DIFFICULTY_NORMAL][TRAINER_JACKSON_5] = { #line 10326 .trainerName = _("JACKSON"), @@ -25898,7 +25898,7 @@ F_TRAINER_FEMALE | }, }, #line 10343 - [TRAINER_CATHERINE_1] = + [DIFFICULTY_NORMAL][TRAINER_CATHERINE_1] = { #line 10344 .trainerName = _("CATHERINE"), @@ -25945,7 +25945,7 @@ F_TRAINER_FEMALE | }, }, #line 10361 - [TRAINER_JENNA] = + [DIFFICULTY_NORMAL][TRAINER_JENNA] = { #line 10362 .trainerName = _("JENNA"), @@ -26003,7 +26003,7 @@ F_TRAINER_FEMALE | }, }, #line 10383 - [TRAINER_SOPHIA] = + [DIFFICULTY_NORMAL][TRAINER_SOPHIA] = { #line 10384 .trainerName = _("SOPHIA"), @@ -26050,7 +26050,7 @@ F_TRAINER_FEMALE | }, }, #line 10401 - [TRAINER_CATHERINE_2] = + [DIFFICULTY_NORMAL][TRAINER_CATHERINE_2] = { #line 10402 .trainerName = _("CATHERINE"), @@ -26097,7 +26097,7 @@ F_TRAINER_FEMALE | }, }, #line 10419 - [TRAINER_CATHERINE_3] = + [DIFFICULTY_NORMAL][TRAINER_CATHERINE_3] = { #line 10420 .trainerName = _("CATHERINE"), @@ -26144,7 +26144,7 @@ F_TRAINER_FEMALE | }, }, #line 10437 - [TRAINER_CATHERINE_4] = + [DIFFICULTY_NORMAL][TRAINER_CATHERINE_4] = { #line 10438 .trainerName = _("CATHERINE"), @@ -26191,7 +26191,7 @@ F_TRAINER_FEMALE | }, }, #line 10455 - [TRAINER_CATHERINE_5] = + [DIFFICULTY_NORMAL][TRAINER_CATHERINE_5] = { #line 10456 .trainerName = _("CATHERINE"), @@ -26238,7 +26238,7 @@ F_TRAINER_FEMALE | }, }, #line 10473 - [TRAINER_JULIO] = + [DIFFICULTY_NORMAL][TRAINER_JULIO] = { #line 10474 .trainerName = _("JULIO"), @@ -26270,7 +26270,7 @@ F_TRAINER_FEMALE | }, }, #line 10486 - [TRAINER_GRUNT_SEAFLOOR_CAVERN_5] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SEAFLOOR_CAVERN_5] = { #line 10487 .trainerName = _("GRUNT"), @@ -26313,7 +26313,7 @@ F_TRAINER_FEMALE | }, }, #line 10503 - [TRAINER_GRUNT_UNUSED] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_UNUSED] = { #line 10504 .trainerName = _("GRUNT"), @@ -26358,7 +26358,7 @@ F_TRAINER_FEMALE | }, }, #line 10520 - [TRAINER_GRUNT_MT_PYRE_4] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_PYRE_4] = { #line 10521 .trainerName = _("GRUNT"), @@ -26403,7 +26403,7 @@ F_TRAINER_FEMALE | }, }, #line 10537 - [TRAINER_GRUNT_JAGGED_PASS] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_JAGGED_PASS] = { #line 10538 .trainerName = _("GRUNT"), @@ -26446,7 +26446,7 @@ F_TRAINER_FEMALE | }, }, #line 10554 - [TRAINER_MARC] = + [DIFFICULTY_NORMAL][TRAINER_MARC] = { #line 10555 .trainerName = _("MARC"), @@ -26489,7 +26489,7 @@ F_TRAINER_FEMALE | }, }, #line 10571 - [TRAINER_BRENDEN] = + [DIFFICULTY_NORMAL][TRAINER_BRENDEN] = { #line 10572 .trainerName = _("BRENDEN"), @@ -26521,7 +26521,7 @@ F_TRAINER_FEMALE | }, }, #line 10584 - [TRAINER_LILITH] = + [DIFFICULTY_NORMAL][TRAINER_LILITH] = { #line 10585 .trainerName = _("LILITH"), @@ -26555,7 +26555,7 @@ F_TRAINER_FEMALE | }, }, #line 10597 - [TRAINER_CRISTIAN] = + [DIFFICULTY_NORMAL][TRAINER_CRISTIAN] = { #line 10598 .trainerName = _("CRISTIAN"), @@ -26587,7 +26587,7 @@ F_TRAINER_FEMALE | }, }, #line 10610 - [TRAINER_SYLVIA] = + [DIFFICULTY_NORMAL][TRAINER_SYLVIA] = { #line 10611 .trainerName = _("SYLVIA"), @@ -26621,7 +26621,7 @@ F_TRAINER_FEMALE | }, }, #line 10623 - [TRAINER_LEONARDO] = + [DIFFICULTY_NORMAL][TRAINER_LEONARDO] = { #line 10624 .trainerName = _("LEONARDO"), @@ -26653,7 +26653,7 @@ F_TRAINER_FEMALE | }, }, #line 10636 - [TRAINER_ATHENA] = + [DIFFICULTY_NORMAL][TRAINER_ATHENA] = { #line 10637 .trainerName = _("ATHENA"), @@ -26711,7 +26711,7 @@ F_TRAINER_FEMALE | }, }, #line 10659 - [TRAINER_HARRISON] = + [DIFFICULTY_NORMAL][TRAINER_HARRISON] = { #line 10660 .trainerName = _("HARRISON"), @@ -26743,7 +26743,7 @@ F_TRAINER_FEMALE | }, }, #line 10672 - [TRAINER_GRUNT_MT_CHIMNEY_2] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MT_CHIMNEY_2] = { #line 10673 .trainerName = _("GRUNT"), @@ -26775,7 +26775,7 @@ F_TRAINER_FEMALE | }, }, #line 10685 - [TRAINER_CLARENCE] = + [DIFFICULTY_NORMAL][TRAINER_CLARENCE] = { #line 10686 .trainerName = _("CLARENCE"), @@ -26807,7 +26807,7 @@ F_TRAINER_FEMALE | }, }, #line 10698 - [TRAINER_TERRY] = + [DIFFICULTY_NORMAL][TRAINER_TERRY] = { #line 10699 .trainerName = _("TERRY"), @@ -26841,7 +26841,7 @@ F_TRAINER_FEMALE | }, }, #line 10711 - [TRAINER_NATE] = + [DIFFICULTY_NORMAL][TRAINER_NATE] = { #line 10712 .trainerName = _("NATE"), @@ -26873,7 +26873,7 @@ F_TRAINER_FEMALE | }, }, #line 10724 - [TRAINER_KATHLEEN] = + [DIFFICULTY_NORMAL][TRAINER_KATHLEEN] = { #line 10725 .trainerName = _("KATHLEEN"), @@ -26907,7 +26907,7 @@ F_TRAINER_FEMALE | }, }, #line 10737 - [TRAINER_CLIFFORD] = + [DIFFICULTY_NORMAL][TRAINER_CLIFFORD] = { #line 10738 .trainerName = _("CLIFFORD"), @@ -26939,7 +26939,7 @@ F_TRAINER_FEMALE | }, }, #line 10750 - [TRAINER_NICHOLAS] = + [DIFFICULTY_NORMAL][TRAINER_NICHOLAS] = { #line 10751 .trainerName = _("NICHOLAS"), @@ -26971,7 +26971,7 @@ F_TRAINER_FEMALE | }, }, #line 10763 - [TRAINER_GRUNT_SPACE_CENTER_3] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_3] = { #line 10764 .trainerName = _("GRUNT"), @@ -27016,7 +27016,7 @@ F_TRAINER_FEMALE | }, }, #line 10780 - [TRAINER_GRUNT_SPACE_CENTER_4] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_4] = { #line 10781 .trainerName = _("GRUNT"), @@ -27048,7 +27048,7 @@ F_TRAINER_FEMALE | }, }, #line 10793 - [TRAINER_GRUNT_SPACE_CENTER_5] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_5] = { #line 10794 .trainerName = _("GRUNT"), @@ -27080,7 +27080,7 @@ F_TRAINER_FEMALE | }, }, #line 10806 - [TRAINER_GRUNT_SPACE_CENTER_6] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_6] = { #line 10807 .trainerName = _("GRUNT"), @@ -27112,7 +27112,7 @@ F_TRAINER_FEMALE | }, }, #line 10819 - [TRAINER_GRUNT_SPACE_CENTER_7] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_SPACE_CENTER_7] = { #line 10820 .trainerName = _("GRUNT"), @@ -27144,7 +27144,7 @@ F_TRAINER_FEMALE | }, }, #line 10832 - [TRAINER_MACEY] = + [DIFFICULTY_NORMAL][TRAINER_MACEY] = { #line 10833 .trainerName = _("MACEY"), @@ -27178,7 +27178,7 @@ F_TRAINER_FEMALE | }, }, #line 10845 - [TRAINER_BRENDAN_RUSTBORO_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_RUSTBORO_TREECKO] = { #line 10846 .trainerName = _("BRENDAN"), @@ -27221,7 +27221,7 @@ F_TRAINER_FEMALE | }, }, #line 10862 - [TRAINER_BRENDAN_RUSTBORO_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_RUSTBORO_MUDKIP] = { #line 10863 .trainerName = _("BRENDAN"), @@ -27264,7 +27264,7 @@ F_TRAINER_FEMALE | }, }, #line 10879 - [TRAINER_PAXTON] = + [DIFFICULTY_NORMAL][TRAINER_PAXTON] = { #line 10880 .trainerName = _("PAXTON"), @@ -27307,7 +27307,7 @@ F_TRAINER_FEMALE | }, }, #line 10896 - [TRAINER_ISABELLA] = + [DIFFICULTY_NORMAL][TRAINER_ISABELLA] = { #line 10897 .trainerName = _("ISABELLA"), @@ -27341,7 +27341,7 @@ F_TRAINER_FEMALE | }, }, #line 10909 - [TRAINER_GRUNT_WEATHER_INST_5] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_WEATHER_INST_5] = { #line 10910 .trainerName = _("GRUNT"), @@ -27386,7 +27386,7 @@ F_TRAINER_FEMALE | }, }, #line 10926 - [TRAINER_TABITHA_MT_CHIMNEY] = + [DIFFICULTY_NORMAL][TRAINER_TABITHA_MT_CHIMNEY] = { #line 10927 .trainerName = _("TABITHA"), @@ -27451,7 +27451,7 @@ F_TRAINER_FEMALE | }, }, #line 10951 - [TRAINER_JONATHAN] = + [DIFFICULTY_NORMAL][TRAINER_JONATHAN] = { #line 10952 .trainerName = _("JONATHAN"), @@ -27496,7 +27496,7 @@ F_TRAINER_FEMALE | }, }, #line 10969 - [TRAINER_BRENDAN_RUSTBORO_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_RUSTBORO_TORCHIC] = { #line 10970 .trainerName = _("BRENDAN"), @@ -27539,7 +27539,7 @@ F_TRAINER_FEMALE | }, }, #line 10986 - [TRAINER_MAY_RUSTBORO_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_MAY_RUSTBORO_MUDKIP] = { #line 10987 .trainerName = _("MAY"), @@ -27584,7 +27584,7 @@ F_TRAINER_FEMALE | }, }, #line 11003 - [TRAINER_MAXIE_MAGMA_HIDEOUT] = + [DIFFICULTY_NORMAL][TRAINER_MAXIE_MAGMA_HIDEOUT] = { #line 11004 .trainerName = _("MAXIE"), @@ -27640,7 +27640,7 @@ F_TRAINER_FEMALE | }, }, #line 11025 - [TRAINER_MAXIE_MT_CHIMNEY] = + [DIFFICULTY_NORMAL][TRAINER_MAXIE_MT_CHIMNEY] = { #line 11026 .trainerName = _("MAXIE"), @@ -27696,7 +27696,7 @@ F_TRAINER_FEMALE | }, }, #line 11047 - [TRAINER_TIANA] = + [DIFFICULTY_NORMAL][TRAINER_TIANA] = { #line 11048 .trainerName = _("TIANA"), @@ -27741,7 +27741,7 @@ F_TRAINER_FEMALE | }, }, #line 11064 - [TRAINER_HALEY_1] = + [DIFFICULTY_NORMAL][TRAINER_HALEY_1] = { #line 11065 .trainerName = _("HALEY"), @@ -27786,7 +27786,7 @@ F_TRAINER_FEMALE | }, }, #line 11081 - [TRAINER_JANICE] = + [DIFFICULTY_NORMAL][TRAINER_JANICE] = { #line 11082 .trainerName = _("JANICE"), @@ -27820,7 +27820,7 @@ F_TRAINER_FEMALE | }, }, #line 11094 - [TRAINER_VIVI] = + [DIFFICULTY_NORMAL][TRAINER_VIVI] = { #line 11095 .trainerName = _("VIVI"), @@ -27876,7 +27876,7 @@ F_TRAINER_FEMALE | }, }, #line 11115 - [TRAINER_HALEY_2] = + [DIFFICULTY_NORMAL][TRAINER_HALEY_2] = { #line 11116 .trainerName = _("HALEY"), @@ -27921,7 +27921,7 @@ F_TRAINER_FEMALE | }, }, #line 11132 - [TRAINER_HALEY_3] = + [DIFFICULTY_NORMAL][TRAINER_HALEY_3] = { #line 11133 .trainerName = _("HALEY"), @@ -27966,7 +27966,7 @@ F_TRAINER_FEMALE | }, }, #line 11149 - [TRAINER_HALEY_4] = + [DIFFICULTY_NORMAL][TRAINER_HALEY_4] = { #line 11150 .trainerName = _("HALEY"), @@ -28011,7 +28011,7 @@ F_TRAINER_FEMALE | }, }, #line 11166 - [TRAINER_HALEY_5] = + [DIFFICULTY_NORMAL][TRAINER_HALEY_5] = { #line 11167 .trainerName = _("HALEY"), @@ -28067,7 +28067,7 @@ F_TRAINER_FEMALE | }, }, #line 11187 - [TRAINER_SALLY] = + [DIFFICULTY_NORMAL][TRAINER_SALLY] = { #line 11188 .trainerName = _("SALLY"), @@ -28101,7 +28101,7 @@ F_TRAINER_FEMALE | }, }, #line 11200 - [TRAINER_ROBIN] = + [DIFFICULTY_NORMAL][TRAINER_ROBIN] = { #line 11201 .trainerName = _("ROBIN"), @@ -28157,7 +28157,7 @@ F_TRAINER_FEMALE | }, }, #line 11221 - [TRAINER_ANDREA] = + [DIFFICULTY_NORMAL][TRAINER_ANDREA] = { #line 11222 .trainerName = _("ANDREA"), @@ -28191,7 +28191,7 @@ F_TRAINER_FEMALE | }, }, #line 11234 - [TRAINER_CRISSY] = + [DIFFICULTY_NORMAL][TRAINER_CRISSY] = { #line 11235 .trainerName = _("CRISSY"), @@ -28236,7 +28236,7 @@ F_TRAINER_FEMALE | }, }, #line 11251 - [TRAINER_RICK] = + [DIFFICULTY_NORMAL][TRAINER_RICK] = { #line 11252 .trainerName = _("RICK"), @@ -28279,7 +28279,7 @@ F_TRAINER_FEMALE | }, }, #line 11268 - [TRAINER_LYLE] = + [DIFFICULTY_NORMAL][TRAINER_LYLE] = { #line 11269 .trainerName = _("LYLE"), @@ -28344,7 +28344,7 @@ F_TRAINER_FEMALE | }, }, #line 11293 - [TRAINER_JOSE] = + [DIFFICULTY_NORMAL][TRAINER_JOSE] = { #line 11294 .trainerName = _("JOSE"), @@ -28387,7 +28387,7 @@ F_TRAINER_FEMALE | }, }, #line 11310 - [TRAINER_DOUG] = + [DIFFICULTY_NORMAL][TRAINER_DOUG] = { #line 11311 .trainerName = _("DOUG"), @@ -28430,7 +28430,7 @@ F_TRAINER_FEMALE | }, }, #line 11327 - [TRAINER_GREG] = + [DIFFICULTY_NORMAL][TRAINER_GREG] = { #line 11328 .trainerName = _("GREG"), @@ -28473,7 +28473,7 @@ F_TRAINER_FEMALE | }, }, #line 11344 - [TRAINER_KENT] = + [DIFFICULTY_NORMAL][TRAINER_KENT] = { #line 11345 .trainerName = _("KENT"), @@ -28505,7 +28505,7 @@ F_TRAINER_FEMALE | }, }, #line 11357 - [TRAINER_JAMES_1] = + [DIFFICULTY_NORMAL][TRAINER_JAMES_1] = { #line 11358 .trainerName = _("JAMES"), @@ -28548,7 +28548,7 @@ F_TRAINER_FEMALE | }, }, #line 11374 - [TRAINER_JAMES_2] = + [DIFFICULTY_NORMAL][TRAINER_JAMES_2] = { #line 11375 .trainerName = _("JAMES"), @@ -28580,7 +28580,7 @@ F_TRAINER_FEMALE | }, }, #line 11387 - [TRAINER_JAMES_3] = + [DIFFICULTY_NORMAL][TRAINER_JAMES_3] = { #line 11388 .trainerName = _("JAMES"), @@ -28623,7 +28623,7 @@ F_TRAINER_FEMALE | }, }, #line 11404 - [TRAINER_JAMES_4] = + [DIFFICULTY_NORMAL][TRAINER_JAMES_4] = { #line 11405 .trainerName = _("JAMES"), @@ -28677,7 +28677,7 @@ F_TRAINER_FEMALE | }, }, #line 11425 - [TRAINER_JAMES_5] = + [DIFFICULTY_NORMAL][TRAINER_JAMES_5] = { #line 11426 .trainerName = _("JAMES"), @@ -28742,7 +28742,7 @@ F_TRAINER_FEMALE | }, }, #line 11450 - [TRAINER_BRICE] = + [DIFFICULTY_NORMAL][TRAINER_BRICE] = { #line 11451 .trainerName = _("BRICE"), @@ -28785,7 +28785,7 @@ F_TRAINER_FEMALE | }, }, #line 11467 - [TRAINER_TRENT_1] = + [DIFFICULTY_NORMAL][TRAINER_TRENT_1] = { #line 11468 .trainerName = _("TRENT"), @@ -28839,7 +28839,7 @@ F_TRAINER_FEMALE | }, }, #line 11488 - [TRAINER_LENNY] = + [DIFFICULTY_NORMAL][TRAINER_LENNY] = { #line 11489 .trainerName = _("LENNY"), @@ -28882,7 +28882,7 @@ F_TRAINER_FEMALE | }, }, #line 11505 - [TRAINER_LUCAS_1] = + [DIFFICULTY_NORMAL][TRAINER_LUCAS_1] = { #line 11506 .trainerName = _("LUCAS"), @@ -28925,7 +28925,7 @@ F_TRAINER_FEMALE | }, }, #line 11522 - [TRAINER_ALAN] = + [DIFFICULTY_NORMAL][TRAINER_ALAN] = { #line 11523 .trainerName = _("ALAN"), @@ -28979,7 +28979,7 @@ F_TRAINER_FEMALE | }, }, #line 11543 - [TRAINER_CLARK] = + [DIFFICULTY_NORMAL][TRAINER_CLARK] = { #line 11544 .trainerName = _("CLARK"), @@ -29011,7 +29011,7 @@ F_TRAINER_FEMALE | }, }, #line 11556 - [TRAINER_ERIC] = + [DIFFICULTY_NORMAL][TRAINER_ERIC] = { #line 11557 .trainerName = _("ERIC"), @@ -29054,7 +29054,7 @@ F_TRAINER_FEMALE | }, }, #line 11573 - [TRAINER_LUCAS_2] = + [DIFFICULTY_NORMAL][TRAINER_LUCAS_2] = { #line 11574 .trainerName = _("LUCAS"), @@ -29091,7 +29091,7 @@ F_TRAINER_FEMALE | }, }, #line 11588 - [TRAINER_MIKE_1] = + [DIFFICULTY_NORMAL][TRAINER_MIKE_1] = { #line 11589 .trainerName = _("MIKE"), @@ -29144,7 +29144,7 @@ F_TRAINER_FEMALE | }, }, #line 11609 - [TRAINER_MIKE_2] = + [DIFFICULTY_NORMAL][TRAINER_MIKE_2] = { #line 11610 .trainerName = _("MIKE"), @@ -29198,7 +29198,7 @@ F_TRAINER_FEMALE | }, }, #line 11630 - [TRAINER_TRENT_2] = + [DIFFICULTY_NORMAL][TRAINER_TRENT_2] = { #line 11631 .trainerName = _("TRENT"), @@ -29263,7 +29263,7 @@ F_TRAINER_FEMALE | }, }, #line 11655 - [TRAINER_TRENT_3] = + [DIFFICULTY_NORMAL][TRAINER_TRENT_3] = { #line 11656 .trainerName = _("TRENT"), @@ -29328,7 +29328,7 @@ F_TRAINER_FEMALE | }, }, #line 11680 - [TRAINER_TRENT_4] = + [DIFFICULTY_NORMAL][TRAINER_TRENT_4] = { #line 11681 .trainerName = _("TRENT"), @@ -29393,7 +29393,7 @@ F_TRAINER_FEMALE | }, }, #line 11705 - [TRAINER_TRENT_5] = + [DIFFICULTY_NORMAL][TRAINER_TRENT_5] = { #line 11706 .trainerName = _("TRENT"), @@ -29458,7 +29458,7 @@ F_TRAINER_FEMALE | }, }, #line 11730 - [TRAINER_DEZ_AND_LUKE] = + [DIFFICULTY_NORMAL][TRAINER_DEZ_AND_LUKE] = { #line 11731 .trainerName = _("DEZ & LUKE"), @@ -29501,7 +29501,7 @@ F_TRAINER_FEMALE | }, }, #line 11747 - [TRAINER_LEA_AND_JED] = + [DIFFICULTY_NORMAL][TRAINER_LEA_AND_JED] = { #line 11748 .trainerName = _("LEA & JED"), @@ -29544,7 +29544,7 @@ F_TRAINER_FEMALE | }, }, #line 11764 - [TRAINER_KIRA_AND_DAN_1] = + [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_1] = { #line 11765 .trainerName = _("KIRA & DAN"), @@ -29587,7 +29587,7 @@ F_TRAINER_FEMALE | }, }, #line 11781 - [TRAINER_KIRA_AND_DAN_2] = + [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_2] = { #line 11782 .trainerName = _("KIRA & DAN"), @@ -29630,7 +29630,7 @@ F_TRAINER_FEMALE | }, }, #line 11798 - [TRAINER_KIRA_AND_DAN_3] = + [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_3] = { #line 11799 .trainerName = _("KIRA & DAN"), @@ -29673,7 +29673,7 @@ F_TRAINER_FEMALE | }, }, #line 11815 - [TRAINER_KIRA_AND_DAN_4] = + [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_4] = { #line 11816 .trainerName = _("KIRA & DAN"), @@ -29716,7 +29716,7 @@ F_TRAINER_FEMALE | }, }, #line 11832 - [TRAINER_KIRA_AND_DAN_5] = + [DIFFICULTY_NORMAL][TRAINER_KIRA_AND_DAN_5] = { #line 11833 .trainerName = _("KIRA & DAN"), @@ -29759,7 +29759,7 @@ F_TRAINER_FEMALE | }, }, #line 11849 - [TRAINER_JOHANNA] = + [DIFFICULTY_NORMAL][TRAINER_JOHANNA] = { #line 11850 .trainerName = _("JOHANNA"), @@ -29793,7 +29793,7 @@ F_TRAINER_FEMALE | }, }, #line 11862 - [TRAINER_GERALD] = + [DIFFICULTY_NORMAL][TRAINER_GERALD] = { #line 11863 .trainerName = _("GERALD"), @@ -29834,7 +29834,7 @@ F_TRAINER_FEMALE | }, }, #line 11880 - [TRAINER_VIVIAN] = + [DIFFICULTY_NORMAL][TRAINER_VIVIAN] = { #line 11881 .trainerName = _("VIVIAN"), @@ -29893,7 +29893,7 @@ F_TRAINER_FEMALE | }, }, #line 11905 - [TRAINER_DANIELLE] = + [DIFFICULTY_NORMAL][TRAINER_DANIELLE] = { #line 11906 .trainerName = _("DANIELLE"), @@ -29934,7 +29934,7 @@ F_TRAINER_FEMALE | }, }, #line 11922 - [TRAINER_HIDEO] = + [DIFFICULTY_NORMAL][TRAINER_HIDEO] = { #line 11923 .trainerName = _("HIDEO"), @@ -29991,7 +29991,7 @@ F_TRAINER_FEMALE | }, }, #line 11947 - [TRAINER_KEIGO] = + [DIFFICULTY_NORMAL][TRAINER_KEIGO] = { #line 11948 .trainerName = _("KEIGO"), @@ -30048,7 +30048,7 @@ F_TRAINER_FEMALE | }, }, #line 11972 - [TRAINER_RILEY] = + [DIFFICULTY_NORMAL][TRAINER_RILEY] = { #line 11973 .trainerName = _("RILEY"), @@ -30105,7 +30105,7 @@ F_TRAINER_FEMALE | }, }, #line 11997 - [TRAINER_FLINT] = + [DIFFICULTY_NORMAL][TRAINER_FLINT] = { #line 11998 .trainerName = _("FLINT"), @@ -30148,7 +30148,7 @@ F_TRAINER_FEMALE | }, }, #line 12014 - [TRAINER_ASHLEY] = + [DIFFICULTY_NORMAL][TRAINER_ASHLEY] = { #line 12015 .trainerName = _("ASHLEY"), @@ -30204,7 +30204,7 @@ F_TRAINER_FEMALE | }, }, #line 12035 - [TRAINER_WALLY_MAUVILLE] = + [DIFFICULTY_NORMAL][TRAINER_WALLY_MAUVILLE] = { #line 12036 .trainerName = _("WALLY"), @@ -30236,7 +30236,7 @@ F_TRAINER_FEMALE | }, }, #line 12048 - [TRAINER_WALLY_VR_2] = + [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_2] = { #line 12049 .trainerName = _("WALLY"), @@ -30349,7 +30349,7 @@ F_TRAINER_FEMALE | }, }, #line 12098 - [TRAINER_WALLY_VR_3] = + [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_3] = { #line 12099 .trainerName = _("WALLY"), @@ -30462,7 +30462,7 @@ F_TRAINER_FEMALE | }, }, #line 12148 - [TRAINER_WALLY_VR_4] = + [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_4] = { #line 12149 .trainerName = _("WALLY"), @@ -30575,7 +30575,7 @@ F_TRAINER_FEMALE | }, }, #line 12198 - [TRAINER_WALLY_VR_5] = + [DIFFICULTY_NORMAL][TRAINER_WALLY_VR_5] = { #line 12199 .trainerName = _("WALLY"), @@ -30688,7 +30688,7 @@ F_TRAINER_FEMALE | }, }, #line 12248 - [TRAINER_BRENDAN_LILYCOVE_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_LILYCOVE_MUDKIP] = { #line 12249 .trainerName = _("BRENDAN"), @@ -30753,7 +30753,7 @@ F_TRAINER_FEMALE | }, }, #line 12273 - [TRAINER_BRENDAN_LILYCOVE_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_LILYCOVE_TREECKO] = { #line 12274 .trainerName = _("BRENDAN"), @@ -30818,7 +30818,7 @@ F_TRAINER_FEMALE | }, }, #line 12298 - [TRAINER_BRENDAN_LILYCOVE_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_LILYCOVE_TORCHIC] = { #line 12299 .trainerName = _("BRENDAN"), @@ -30883,7 +30883,7 @@ F_TRAINER_FEMALE | }, }, #line 12323 - [TRAINER_MAY_LILYCOVE_MUDKIP] = + [DIFFICULTY_NORMAL][TRAINER_MAY_LILYCOVE_MUDKIP] = { #line 12324 .trainerName = _("MAY"), @@ -30950,7 +30950,7 @@ F_TRAINER_FEMALE | }, }, #line 12348 - [TRAINER_MAY_LILYCOVE_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_MAY_LILYCOVE_TREECKO] = { #line 12349 .trainerName = _("MAY"), @@ -31017,7 +31017,7 @@ F_TRAINER_FEMALE | }, }, #line 12373 - [TRAINER_MAY_LILYCOVE_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_MAY_LILYCOVE_TORCHIC] = { #line 12374 .trainerName = _("MAY"), @@ -31084,7 +31084,7 @@ F_TRAINER_FEMALE | }, }, #line 12398 - [TRAINER_JONAH] = + [DIFFICULTY_NORMAL][TRAINER_JONAH] = { #line 12399 .trainerName = _("JONAH"), @@ -31138,7 +31138,7 @@ F_TRAINER_FEMALE | }, }, #line 12419 - [TRAINER_HENRY] = + [DIFFICULTY_NORMAL][TRAINER_HENRY] = { #line 12420 .trainerName = _("HENRY"), @@ -31181,7 +31181,7 @@ F_TRAINER_FEMALE | }, }, #line 12436 - [TRAINER_ROGER] = + [DIFFICULTY_NORMAL][TRAINER_ROGER] = { #line 12437 .trainerName = _("ROGER"), @@ -31235,7 +31235,7 @@ F_TRAINER_FEMALE | }, }, #line 12457 - [TRAINER_ALEXA] = + [DIFFICULTY_NORMAL][TRAINER_ALEXA] = { #line 12458 .trainerName = _("ALEXA"), @@ -31282,7 +31282,7 @@ F_TRAINER_FEMALE | }, }, #line 12475 - [TRAINER_RUBEN] = + [DIFFICULTY_NORMAL][TRAINER_RUBEN] = { #line 12476 .trainerName = _("RUBEN"), @@ -31327,7 +31327,7 @@ F_TRAINER_FEMALE | }, }, #line 12493 - [TRAINER_KOJI_1] = + [DIFFICULTY_NORMAL][TRAINER_KOJI_1] = { #line 12494 .trainerName = _("KOJI"), @@ -31359,7 +31359,7 @@ F_TRAINER_FEMALE | }, }, #line 12506 - [TRAINER_WAYNE] = + [DIFFICULTY_NORMAL][TRAINER_WAYNE] = { #line 12507 .trainerName = _("WAYNE"), @@ -31413,7 +31413,7 @@ F_TRAINER_FEMALE | }, }, #line 12527 - [TRAINER_AIDAN] = + [DIFFICULTY_NORMAL][TRAINER_AIDAN] = { #line 12528 .trainerName = _("AIDAN"), @@ -31456,7 +31456,7 @@ F_TRAINER_FEMALE | }, }, #line 12544 - [TRAINER_REED] = + [DIFFICULTY_NORMAL][TRAINER_REED] = { #line 12545 .trainerName = _("REED"), @@ -31499,7 +31499,7 @@ F_TRAINER_FEMALE | }, }, #line 12561 - [TRAINER_TISHA] = + [DIFFICULTY_NORMAL][TRAINER_TISHA] = { #line 12562 .trainerName = _("TISHA"), @@ -31533,7 +31533,7 @@ F_TRAINER_FEMALE | }, }, #line 12574 - [TRAINER_TORI_AND_TIA] = + [DIFFICULTY_NORMAL][TRAINER_TORI_AND_TIA] = { #line 12575 .trainerName = _("TORI & TIA"), @@ -31576,7 +31576,7 @@ F_TRAINER_FEMALE | }, }, #line 12591 - [TRAINER_KIM_AND_IRIS] = + [DIFFICULTY_NORMAL][TRAINER_KIM_AND_IRIS] = { #line 12592 .trainerName = _("KIM & IRIS"), @@ -31633,7 +31633,7 @@ F_TRAINER_FEMALE | }, }, #line 12616 - [TRAINER_TYRA_AND_IVY] = + [DIFFICULTY_NORMAL][TRAINER_TYRA_AND_IVY] = { #line 12617 .trainerName = _("TYRA & IVY"), @@ -31690,7 +31690,7 @@ F_TRAINER_FEMALE | }, }, #line 12641 - [TRAINER_MEL_AND_PAUL] = + [DIFFICULTY_NORMAL][TRAINER_MEL_AND_PAUL] = { #line 12642 .trainerName = _("MEL & PAUL"), @@ -31747,7 +31747,7 @@ F_TRAINER_FEMALE | }, }, #line 12666 - [TRAINER_JOHN_AND_JAY_1] = + [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_1] = { #line 12667 .trainerName = _("JOHN & JAY"), @@ -31804,7 +31804,7 @@ F_TRAINER_FEMALE | }, }, #line 12691 - [TRAINER_JOHN_AND_JAY_2] = + [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_2] = { #line 12692 .trainerName = _("JOHN & JAY"), @@ -31861,7 +31861,7 @@ F_TRAINER_FEMALE | }, }, #line 12716 - [TRAINER_JOHN_AND_JAY_3] = + [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_3] = { #line 12717 .trainerName = _("JOHN & JAY"), @@ -31918,7 +31918,7 @@ F_TRAINER_FEMALE | }, }, #line 12741 - [TRAINER_JOHN_AND_JAY_4] = + [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_4] = { #line 12742 .trainerName = _("JOHN & JAY"), @@ -31975,7 +31975,7 @@ F_TRAINER_FEMALE | }, }, #line 12766 - [TRAINER_JOHN_AND_JAY_5] = + [DIFFICULTY_NORMAL][TRAINER_JOHN_AND_JAY_5] = { #line 12767 .trainerName = _("JOHN & JAY"), @@ -32032,7 +32032,7 @@ F_TRAINER_FEMALE | }, }, #line 12791 - [TRAINER_RELI_AND_IAN] = + [DIFFICULTY_NORMAL][TRAINER_RELI_AND_IAN] = { #line 12792 .trainerName = _("RELI & IAN"), @@ -32075,7 +32075,7 @@ F_TRAINER_FEMALE | }, }, #line 12808 - [TRAINER_LILA_AND_ROY_1] = + [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_1] = { #line 12809 .trainerName = _("LILA & ROY"), @@ -32118,7 +32118,7 @@ F_TRAINER_FEMALE | }, }, #line 12825 - [TRAINER_LILA_AND_ROY_2] = + [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_2] = { #line 12826 .trainerName = _("LILA & ROY"), @@ -32161,7 +32161,7 @@ F_TRAINER_FEMALE | }, }, #line 12842 - [TRAINER_LILA_AND_ROY_3] = + [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_3] = { #line 12843 .trainerName = _("LILA & ROY"), @@ -32204,7 +32204,7 @@ F_TRAINER_FEMALE | }, }, #line 12859 - [TRAINER_LILA_AND_ROY_4] = + [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_4] = { #line 12860 .trainerName = _("LILA & ROY"), @@ -32247,7 +32247,7 @@ F_TRAINER_FEMALE | }, }, #line 12876 - [TRAINER_LILA_AND_ROY_5] = + [DIFFICULTY_NORMAL][TRAINER_LILA_AND_ROY_5] = { #line 12877 .trainerName = _("LILA & ROY"), @@ -32290,7 +32290,7 @@ F_TRAINER_FEMALE | }, }, #line 12893 - [TRAINER_LISA_AND_RAY] = + [DIFFICULTY_NORMAL][TRAINER_LISA_AND_RAY] = { #line 12894 .trainerName = _("LISA & RAY"), @@ -32333,7 +32333,7 @@ F_TRAINER_FEMALE | }, }, #line 12910 - [TRAINER_CHRIS] = + [DIFFICULTY_NORMAL][TRAINER_CHRIS] = { #line 12911 .trainerName = _("CHRIS"), @@ -32398,7 +32398,7 @@ F_TRAINER_FEMALE | }, }, #line 12935 - [TRAINER_DAWSON] = + [DIFFICULTY_NORMAL][TRAINER_DAWSON] = { #line 12936 .trainerName = _("DAWSON"), @@ -32443,7 +32443,7 @@ F_TRAINER_FEMALE | }, }, #line 12952 - [TRAINER_SARAH] = + [DIFFICULTY_NORMAL][TRAINER_SARAH] = { #line 12953 .trainerName = _("SARAH"), @@ -32492,7 +32492,7 @@ F_TRAINER_FEMALE | }, }, #line 12970 - [TRAINER_DARIAN] = + [DIFFICULTY_NORMAL][TRAINER_DARIAN] = { #line 12971 .trainerName = _("DARIAN"), @@ -32524,7 +32524,7 @@ F_TRAINER_FEMALE | }, }, #line 12983 - [TRAINER_HAILEY] = + [DIFFICULTY_NORMAL][TRAINER_HAILEY] = { #line 12984 .trainerName = _("HAILEY"), @@ -32558,7 +32558,7 @@ F_TRAINER_FEMALE | }, }, #line 12996 - [TRAINER_CHANDLER] = + [DIFFICULTY_NORMAL][TRAINER_CHANDLER] = { #line 12997 .trainerName = _("CHANDLER"), @@ -32601,7 +32601,7 @@ F_TRAINER_FEMALE | }, }, #line 13013 - [TRAINER_KALEB] = + [DIFFICULTY_NORMAL][TRAINER_KALEB] = { #line 13014 .trainerName = _("KALEB"), @@ -32648,7 +32648,7 @@ F_TRAINER_FEMALE | }, }, #line 13030 - [TRAINER_JOSEPH] = + [DIFFICULTY_NORMAL][TRAINER_JOSEPH] = { #line 13031 .trainerName = _("JOSEPH"), @@ -32691,7 +32691,7 @@ F_TRAINER_FEMALE | }, }, #line 13047 - [TRAINER_ALYSSA] = + [DIFFICULTY_NORMAL][TRAINER_ALYSSA] = { #line 13048 .trainerName = _("ALYSSA"), @@ -32725,7 +32725,7 @@ F_TRAINER_FEMALE | }, }, #line 13060 - [TRAINER_MARCOS] = + [DIFFICULTY_NORMAL][TRAINER_MARCOS] = { #line 13061 .trainerName = _("MARCOS"), @@ -32757,7 +32757,7 @@ F_TRAINER_FEMALE | }, }, #line 13073 - [TRAINER_RHETT] = + [DIFFICULTY_NORMAL][TRAINER_RHETT] = { #line 13074 .trainerName = _("RHETT"), @@ -32789,7 +32789,7 @@ F_TRAINER_FEMALE | }, }, #line 13086 - [TRAINER_TYRON] = + [DIFFICULTY_NORMAL][TRAINER_TYRON] = { #line 13087 .trainerName = _("TYRON"), @@ -32821,7 +32821,7 @@ F_TRAINER_FEMALE | }, }, #line 13099 - [TRAINER_CELINA] = + [DIFFICULTY_NORMAL][TRAINER_CELINA] = { #line 13100 .trainerName = _("CELINA"), @@ -32855,7 +32855,7 @@ F_TRAINER_FEMALE | }, }, #line 13112 - [TRAINER_BIANCA] = + [DIFFICULTY_NORMAL][TRAINER_BIANCA] = { #line 13113 .trainerName = _("BIANCA"), @@ -32889,7 +32889,7 @@ F_TRAINER_FEMALE | }, }, #line 13125 - [TRAINER_HAYDEN] = + [DIFFICULTY_NORMAL][TRAINER_HAYDEN] = { #line 13126 .trainerName = _("HAYDEN"), @@ -32921,7 +32921,7 @@ F_TRAINER_FEMALE | }, }, #line 13138 - [TRAINER_SOPHIE] = + [DIFFICULTY_NORMAL][TRAINER_SOPHIE] = { #line 13139 .trainerName = _("SOPHIE"), @@ -32966,7 +32966,7 @@ F_TRAINER_FEMALE | }, }, #line 13155 - [TRAINER_COBY] = + [DIFFICULTY_NORMAL][TRAINER_COBY] = { #line 13156 .trainerName = _("COBY"), @@ -33009,7 +33009,7 @@ F_TRAINER_FEMALE | }, }, #line 13172 - [TRAINER_LAWRENCE] = + [DIFFICULTY_NORMAL][TRAINER_LAWRENCE] = { #line 13173 .trainerName = _("LAWRENCE"), @@ -33052,7 +33052,7 @@ F_TRAINER_FEMALE | }, }, #line 13189 - [TRAINER_WYATT] = + [DIFFICULTY_NORMAL][TRAINER_WYATT] = { #line 13190 .trainerName = _("WYATT"), @@ -33095,7 +33095,7 @@ F_TRAINER_FEMALE | }, }, #line 13206 - [TRAINER_ANGELINA] = + [DIFFICULTY_NORMAL][TRAINER_ANGELINA] = { #line 13207 .trainerName = _("ANGELINA"), @@ -33140,7 +33140,7 @@ F_TRAINER_FEMALE | }, }, #line 13223 - [TRAINER_KAI] = + [DIFFICULTY_NORMAL][TRAINER_KAI] = { #line 13224 .trainerName = _("KAI"), @@ -33172,7 +33172,7 @@ F_TRAINER_FEMALE | }, }, #line 13236 - [TRAINER_CHARLOTTE] = + [DIFFICULTY_NORMAL][TRAINER_CHARLOTTE] = { #line 13237 .trainerName = _("CHARLOTTE"), @@ -33206,7 +33206,7 @@ F_TRAINER_FEMALE | }, }, #line 13249 - [TRAINER_DEANDRE] = + [DIFFICULTY_NORMAL][TRAINER_DEANDRE] = { #line 13250 .trainerName = _("DEANDRE"), @@ -33260,7 +33260,7 @@ F_TRAINER_FEMALE | }, }, #line 13270 - [TRAINER_GRUNT_MAGMA_HIDEOUT_1] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_1] = { #line 13271 .trainerName = _("GRUNT"), @@ -33292,7 +33292,7 @@ F_TRAINER_FEMALE | }, }, #line 13283 - [TRAINER_GRUNT_MAGMA_HIDEOUT_2] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_2] = { #line 13284 .trainerName = _("GRUNT"), @@ -33324,7 +33324,7 @@ F_TRAINER_FEMALE | }, }, #line 13296 - [TRAINER_GRUNT_MAGMA_HIDEOUT_3] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_3] = { #line 13297 .trainerName = _("GRUNT"), @@ -33356,7 +33356,7 @@ F_TRAINER_FEMALE | }, }, #line 13309 - [TRAINER_GRUNT_MAGMA_HIDEOUT_4] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_4] = { #line 13310 .trainerName = _("GRUNT"), @@ -33399,7 +33399,7 @@ F_TRAINER_FEMALE | }, }, #line 13326 - [TRAINER_GRUNT_MAGMA_HIDEOUT_5] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_5] = { #line 13327 .trainerName = _("GRUNT"), @@ -33442,7 +33442,7 @@ F_TRAINER_FEMALE | }, }, #line 13343 - [TRAINER_GRUNT_MAGMA_HIDEOUT_6] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_6] = { #line 13344 .trainerName = _("GRUNT"), @@ -33474,7 +33474,7 @@ F_TRAINER_FEMALE | }, }, #line 13356 - [TRAINER_GRUNT_MAGMA_HIDEOUT_7] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_7] = { #line 13357 .trainerName = _("GRUNT"), @@ -33506,7 +33506,7 @@ F_TRAINER_FEMALE | }, }, #line 13369 - [TRAINER_GRUNT_MAGMA_HIDEOUT_8] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_8] = { #line 13370 .trainerName = _("GRUNT"), @@ -33538,7 +33538,7 @@ F_TRAINER_FEMALE | }, }, #line 13382 - [TRAINER_GRUNT_MAGMA_HIDEOUT_9] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_9] = { #line 13383 .trainerName = _("GRUNT"), @@ -33570,7 +33570,7 @@ F_TRAINER_FEMALE | }, }, #line 13395 - [TRAINER_GRUNT_MAGMA_HIDEOUT_10] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_10] = { #line 13396 .trainerName = _("GRUNT"), @@ -33602,7 +33602,7 @@ F_TRAINER_FEMALE | }, }, #line 13408 - [TRAINER_GRUNT_MAGMA_HIDEOUT_11] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_11] = { #line 13409 .trainerName = _("GRUNT"), @@ -33634,7 +33634,7 @@ F_TRAINER_FEMALE | }, }, #line 13421 - [TRAINER_GRUNT_MAGMA_HIDEOUT_12] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_12] = { #line 13422 .trainerName = _("GRUNT"), @@ -33666,7 +33666,7 @@ F_TRAINER_FEMALE | }, }, #line 13434 - [TRAINER_GRUNT_MAGMA_HIDEOUT_13] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_13] = { #line 13435 .trainerName = _("GRUNT"), @@ -33698,7 +33698,7 @@ F_TRAINER_FEMALE | }, }, #line 13447 - [TRAINER_GRUNT_MAGMA_HIDEOUT_14] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_14] = { #line 13448 .trainerName = _("GRUNT"), @@ -33732,7 +33732,7 @@ F_TRAINER_FEMALE | }, }, #line 13460 - [TRAINER_GRUNT_MAGMA_HIDEOUT_15] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_15] = { #line 13461 .trainerName = _("GRUNT"), @@ -33766,7 +33766,7 @@ F_TRAINER_FEMALE | }, }, #line 13473 - [TRAINER_GRUNT_MAGMA_HIDEOUT_16] = + [DIFFICULTY_NORMAL][TRAINER_GRUNT_MAGMA_HIDEOUT_16] = { #line 13474 .trainerName = _("GRUNT"), @@ -33800,7 +33800,7 @@ F_TRAINER_FEMALE | }, }, #line 13486 - [TRAINER_TABITHA_MAGMA_HIDEOUT] = + [DIFFICULTY_NORMAL][TRAINER_TABITHA_MAGMA_HIDEOUT] = { #line 13487 .trainerName = _("TABITHA"), @@ -33865,7 +33865,7 @@ F_TRAINER_FEMALE | }, }, #line 13511 - [TRAINER_DARCY] = + [DIFFICULTY_NORMAL][TRAINER_DARCY] = { #line 13512 .trainerName = _("DARCY"), @@ -33912,7 +33912,7 @@ F_TRAINER_FEMALE | }, }, #line 13529 - [TRAINER_MAXIE_MOSSDEEP] = + [DIFFICULTY_NORMAL][TRAINER_MAXIE_MOSSDEEP] = { #line 13530 .trainerName = _("MAXIE"), @@ -33966,7 +33966,7 @@ F_TRAINER_FEMALE | }, }, #line 13550 - [TRAINER_PETE] = + [DIFFICULTY_NORMAL][TRAINER_PETE] = { #line 13551 .trainerName = _("PETE"), @@ -33998,7 +33998,7 @@ F_TRAINER_FEMALE | }, }, #line 13563 - [TRAINER_ISABELLE] = + [DIFFICULTY_NORMAL][TRAINER_ISABELLE] = { #line 13564 .trainerName = _("ISABELLE"), @@ -34032,7 +34032,7 @@ F_TRAINER_FEMALE | }, }, #line 13576 - [TRAINER_ANDRES_1] = + [DIFFICULTY_NORMAL][TRAINER_ANDRES_1] = { #line 13577 .trainerName = _("ANDRES"), @@ -34075,7 +34075,7 @@ F_TRAINER_FEMALE | }, }, #line 13593 - [TRAINER_JOSUE] = + [DIFFICULTY_NORMAL][TRAINER_JOSUE] = { #line 13594 .trainerName = _("JOSUE"), @@ -34118,7 +34118,7 @@ F_TRAINER_FEMALE | }, }, #line 13610 - [TRAINER_CAMRON] = + [DIFFICULTY_NORMAL][TRAINER_CAMRON] = { #line 13611 .trainerName = _("CAMRON"), @@ -34150,7 +34150,7 @@ F_TRAINER_FEMALE | }, }, #line 13623 - [TRAINER_CORY_1] = + [DIFFICULTY_NORMAL][TRAINER_CORY_1] = { #line 13624 .trainerName = _("CORY"), @@ -34204,7 +34204,7 @@ F_TRAINER_FEMALE | }, }, #line 13644 - [TRAINER_CAROLINA] = + [DIFFICULTY_NORMAL][TRAINER_CAROLINA] = { #line 13645 .trainerName = _("CAROLINA"), @@ -34262,7 +34262,7 @@ F_TRAINER_FEMALE | }, }, #line 13666 - [TRAINER_ELIJAH] = + [DIFFICULTY_NORMAL][TRAINER_ELIJAH] = { #line 13667 .trainerName = _("ELIJAH"), @@ -34305,7 +34305,7 @@ F_TRAINER_FEMALE | }, }, #line 13683 - [TRAINER_CELIA] = + [DIFFICULTY_NORMAL][TRAINER_CELIA] = { #line 13684 .trainerName = _("CELIA"), @@ -34350,7 +34350,7 @@ F_TRAINER_FEMALE | }, }, #line 13700 - [TRAINER_BRYAN] = + [DIFFICULTY_NORMAL][TRAINER_BRYAN] = { #line 13701 .trainerName = _("BRYAN"), @@ -34393,7 +34393,7 @@ F_TRAINER_FEMALE | }, }, #line 13717 - [TRAINER_BRANDEN] = + [DIFFICULTY_NORMAL][TRAINER_BRANDEN] = { #line 13718 .trainerName = _("BRANDEN"), @@ -34436,7 +34436,7 @@ F_TRAINER_FEMALE | }, }, #line 13734 - [TRAINER_BRYANT] = + [DIFFICULTY_NORMAL][TRAINER_BRYANT] = { #line 13735 .trainerName = _("BRYANT"), @@ -34479,7 +34479,7 @@ F_TRAINER_FEMALE | }, }, #line 13751 - [TRAINER_SHAYLA] = + [DIFFICULTY_NORMAL][TRAINER_SHAYLA] = { #line 13752 .trainerName = _("SHAYLA"), @@ -34524,7 +34524,7 @@ F_TRAINER_FEMALE | }, }, #line 13768 - [TRAINER_KYRA] = + [DIFFICULTY_NORMAL][TRAINER_KYRA] = { #line 13769 .trainerName = _("KYRA"), @@ -34569,7 +34569,7 @@ F_TRAINER_FEMALE | }, }, #line 13785 - [TRAINER_JAIDEN] = + [DIFFICULTY_NORMAL][TRAINER_JAIDEN] = { #line 13786 .trainerName = _("JAIDEN"), @@ -34612,7 +34612,7 @@ F_TRAINER_FEMALE | }, }, #line 13802 - [TRAINER_ALIX] = + [DIFFICULTY_NORMAL][TRAINER_ALIX] = { #line 13803 .trainerName = _("ALIX"), @@ -34657,7 +34657,7 @@ F_TRAINER_FEMALE | }, }, #line 13819 - [TRAINER_HELENE] = + [DIFFICULTY_NORMAL][TRAINER_HELENE] = { #line 13820 .trainerName = _("HELENE"), @@ -34702,7 +34702,7 @@ F_TRAINER_FEMALE | }, }, #line 13836 - [TRAINER_MARLENE] = + [DIFFICULTY_NORMAL][TRAINER_MARLENE] = { #line 13837 .trainerName = _("MARLENE"), @@ -34747,7 +34747,7 @@ F_TRAINER_FEMALE | }, }, #line 13853 - [TRAINER_DEVAN] = + [DIFFICULTY_NORMAL][TRAINER_DEVAN] = { #line 13854 .trainerName = _("DEVAN"), @@ -34790,7 +34790,7 @@ F_TRAINER_FEMALE | }, }, #line 13870 - [TRAINER_JOHNSON] = + [DIFFICULTY_NORMAL][TRAINER_JOHNSON] = { #line 13871 .trainerName = _("JOHNSON"), @@ -34833,7 +34833,7 @@ F_TRAINER_FEMALE | }, }, #line 13887 - [TRAINER_MELINA] = + [DIFFICULTY_NORMAL][TRAINER_MELINA] = { #line 13888 .trainerName = _("MELINA"), @@ -34867,7 +34867,7 @@ F_TRAINER_FEMALE | }, }, #line 13900 - [TRAINER_BRANDI] = + [DIFFICULTY_NORMAL][TRAINER_BRANDI] = { #line 13901 .trainerName = _("BRANDI"), @@ -34901,7 +34901,7 @@ F_TRAINER_FEMALE | }, }, #line 13913 - [TRAINER_AISHA] = + [DIFFICULTY_NORMAL][TRAINER_AISHA] = { #line 13914 .trainerName = _("AISHA"), @@ -34935,7 +34935,7 @@ F_TRAINER_FEMALE | }, }, #line 13926 - [TRAINER_MAKAYLA] = + [DIFFICULTY_NORMAL][TRAINER_MAKAYLA] = { #line 13927 .trainerName = _("MAKAYLA"), @@ -34982,7 +34982,7 @@ F_TRAINER_FEMALE | }, }, #line 13944 - [TRAINER_FABIAN] = + [DIFFICULTY_NORMAL][TRAINER_FABIAN] = { #line 13945 .trainerName = _("FABIAN"), @@ -35014,7 +35014,7 @@ F_TRAINER_FEMALE | }, }, #line 13957 - [TRAINER_DAYTON] = + [DIFFICULTY_NORMAL][TRAINER_DAYTON] = { #line 13958 .trainerName = _("DAYTON"), @@ -35057,7 +35057,7 @@ F_TRAINER_FEMALE | }, }, #line 13974 - [TRAINER_RACHEL] = + [DIFFICULTY_NORMAL][TRAINER_RACHEL] = { #line 13975 .trainerName = _("RACHEL"), @@ -35091,7 +35091,7 @@ F_TRAINER_FEMALE | }, }, #line 13987 - [TRAINER_LEONEL] = + [DIFFICULTY_NORMAL][TRAINER_LEONEL] = { #line 13988 .trainerName = _("LEONEL"), @@ -35131,7 +35131,7 @@ F_TRAINER_FEMALE | }, }, #line 14004 - [TRAINER_CALLIE] = + [DIFFICULTY_NORMAL][TRAINER_CALLIE] = { #line 14005 .trainerName = _("CALLIE"), @@ -35176,7 +35176,7 @@ F_TRAINER_FEMALE | }, }, #line 14021 - [TRAINER_CALE] = + [DIFFICULTY_NORMAL][TRAINER_CALE] = { #line 14022 .trainerName = _("CALE"), @@ -35219,7 +35219,7 @@ F_TRAINER_FEMALE | }, }, #line 14038 - [TRAINER_MYLES] = + [DIFFICULTY_NORMAL][TRAINER_MYLES] = { #line 14039 .trainerName = _("MYLES"), @@ -35306,7 +35306,7 @@ F_TRAINER_FEMALE | }, }, #line 14071 - [TRAINER_PAT] = + [DIFFICULTY_NORMAL][TRAINER_PAT] = { #line 14072 .trainerName = _("PAT"), @@ -35395,7 +35395,7 @@ F_TRAINER_FEMALE | }, }, #line 14104 - [TRAINER_CRISTIN_1] = + [DIFFICULTY_NORMAL][TRAINER_CRISTIN_1] = { #line 14105 .trainerName = _("CRISTIN"), @@ -35442,7 +35442,7 @@ F_TRAINER_FEMALE | }, }, #line 14122 - [TRAINER_MAY_RUSTBORO_TREECKO] = + [DIFFICULTY_NORMAL][TRAINER_MAY_RUSTBORO_TREECKO] = { #line 14123 .trainerName = _("MAY"), @@ -35487,7 +35487,7 @@ F_TRAINER_FEMALE | }, }, #line 14139 - [TRAINER_MAY_RUSTBORO_TORCHIC] = + [DIFFICULTY_NORMAL][TRAINER_MAY_RUSTBORO_TORCHIC] = { #line 14140 .trainerName = _("MAY"), @@ -35532,7 +35532,7 @@ F_TRAINER_FEMALE | }, }, #line 14156 - [TRAINER_ROXANNE_2] = + [DIFFICULTY_NORMAL][TRAINER_ROXANNE_2] = { #line 14157 .trainerName = _("ROXANNE"), @@ -35633,7 +35633,7 @@ F_TRAINER_FEMALE | }, }, #line 14198 - [TRAINER_ROXANNE_3] = + [DIFFICULTY_NORMAL][TRAINER_ROXANNE_3] = { #line 14199 .trainerName = _("ROXANNE"), @@ -35752,7 +35752,7 @@ F_TRAINER_FEMALE | }, }, #line 14248 - [TRAINER_ROXANNE_4] = + [DIFFICULTY_NORMAL][TRAINER_ROXANNE_4] = { #line 14249 .trainerName = _("ROXANNE"), @@ -35871,7 +35871,7 @@ F_TRAINER_FEMALE | }, }, #line 14298 - [TRAINER_ROXANNE_5] = + [DIFFICULTY_NORMAL][TRAINER_ROXANNE_5] = { #line 14299 .trainerName = _("ROXANNE"), @@ -36008,7 +36008,7 @@ F_TRAINER_FEMALE | }, }, #line 14356 - [TRAINER_BRAWLY_2] = + [DIFFICULTY_NORMAL][TRAINER_BRAWLY_2] = { #line 14357 .trainerName = _("BRAWLY"), @@ -36107,7 +36107,7 @@ F_TRAINER_FEMALE | }, }, #line 14398 - [TRAINER_BRAWLY_3] = + [DIFFICULTY_NORMAL][TRAINER_BRAWLY_3] = { #line 14399 .trainerName = _("BRAWLY"), @@ -36206,7 +36206,7 @@ F_TRAINER_FEMALE | }, }, #line 14440 - [TRAINER_BRAWLY_4] = + [DIFFICULTY_NORMAL][TRAINER_BRAWLY_4] = { #line 14441 .trainerName = _("BRAWLY"), @@ -36323,7 +36323,7 @@ F_TRAINER_FEMALE | }, }, #line 14490 - [TRAINER_BRAWLY_5] = + [DIFFICULTY_NORMAL][TRAINER_BRAWLY_5] = { #line 14491 .trainerName = _("BRAWLY"), @@ -36458,7 +36458,7 @@ F_TRAINER_FEMALE | }, }, #line 14548 - [TRAINER_WATTSON_2] = + [DIFFICULTY_NORMAL][TRAINER_WATTSON_2] = { #line 14549 .trainerName = _("WATTSON"), @@ -36557,7 +36557,7 @@ F_TRAINER_FEMALE | }, }, #line 14590 - [TRAINER_WATTSON_3] = + [DIFFICULTY_NORMAL][TRAINER_WATTSON_3] = { #line 14591 .trainerName = _("WATTSON"), @@ -36674,7 +36674,7 @@ F_TRAINER_FEMALE | }, }, #line 14640 - [TRAINER_WATTSON_4] = + [DIFFICULTY_NORMAL][TRAINER_WATTSON_4] = { #line 14641 .trainerName = _("WATTSON"), @@ -36791,7 +36791,7 @@ F_TRAINER_FEMALE | }, }, #line 14690 - [TRAINER_WATTSON_5] = + [DIFFICULTY_NORMAL][TRAINER_WATTSON_5] = { #line 14691 .trainerName = _("WATTSON"), @@ -36926,7 +36926,7 @@ F_TRAINER_FEMALE | }, }, #line 14748 - [TRAINER_FLANNERY_2] = + [DIFFICULTY_NORMAL][TRAINER_FLANNERY_2] = { #line 14749 .trainerName = _("FLANNERY"), @@ -37029,7 +37029,7 @@ F_TRAINER_FEMALE | }, }, #line 14790 - [TRAINER_FLANNERY_3] = + [DIFFICULTY_NORMAL][TRAINER_FLANNERY_3] = { #line 14791 .trainerName = _("FLANNERY"), @@ -37150,7 +37150,7 @@ F_TRAINER_FEMALE | }, }, #line 14840 - [TRAINER_FLANNERY_4] = + [DIFFICULTY_NORMAL][TRAINER_FLANNERY_4] = { #line 14841 .trainerName = _("FLANNERY"), @@ -37289,7 +37289,7 @@ F_TRAINER_FEMALE | }, }, #line 14898 - [TRAINER_FLANNERY_5] = + [DIFFICULTY_NORMAL][TRAINER_FLANNERY_5] = { #line 14899 .trainerName = _("FLANNERY"), @@ -37428,7 +37428,7 @@ F_TRAINER_FEMALE | }, }, #line 14956 - [TRAINER_NORMAN_2] = + [DIFFICULTY_NORMAL][TRAINER_NORMAN_2] = { #line 14957 .trainerName = _("NORMAN"), @@ -37527,7 +37527,7 @@ F_TRAINER_FEMALE | }, }, #line 14998 - [TRAINER_NORMAN_3] = + [DIFFICULTY_NORMAL][TRAINER_NORMAN_3] = { #line 14999 .trainerName = _("NORMAN"), @@ -37644,7 +37644,7 @@ F_TRAINER_FEMALE | }, }, #line 15048 - [TRAINER_NORMAN_4] = + [DIFFICULTY_NORMAL][TRAINER_NORMAN_4] = { #line 15049 .trainerName = _("NORMAN"), @@ -37761,7 +37761,7 @@ F_TRAINER_FEMALE | }, }, #line 15098 - [TRAINER_NORMAN_5] = + [DIFFICULTY_NORMAL][TRAINER_NORMAN_5] = { #line 15099 .trainerName = _("NORMAN"), @@ -37896,7 +37896,7 @@ F_TRAINER_FEMALE | }, }, #line 15156 - [TRAINER_WINONA_2] = + [DIFFICULTY_NORMAL][TRAINER_WINONA_2] = { #line 15157 .trainerName = _("WINONA"), @@ -38015,7 +38015,7 @@ F_TRAINER_FEMALE | }, }, #line 15206 - [TRAINER_WINONA_3] = + [DIFFICULTY_NORMAL][TRAINER_WINONA_3] = { #line 15207 .trainerName = _("WINONA"), @@ -38152,7 +38152,7 @@ F_TRAINER_FEMALE | }, }, #line 15264 - [TRAINER_WINONA_4] = + [DIFFICULTY_NORMAL][TRAINER_WINONA_4] = { #line 15265 .trainerName = _("WINONA"), @@ -38289,7 +38289,7 @@ F_TRAINER_FEMALE | }, }, #line 15322 - [TRAINER_WINONA_5] = + [DIFFICULTY_NORMAL][TRAINER_WINONA_5] = { #line 15323 .trainerName = _("WINONA"), @@ -38426,7 +38426,7 @@ F_TRAINER_FEMALE | }, }, #line 15380 - [TRAINER_TATE_AND_LIZA_2] = + [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_2] = { #line 15381 .trainerName = _("TATE&LIZA"), @@ -38545,7 +38545,7 @@ F_TRAINER_FEMALE | }, }, #line 15430 - [TRAINER_TATE_AND_LIZA_3] = + [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_3] = { #line 15431 .trainerName = _("TATE&LIZA"), @@ -38682,7 +38682,7 @@ F_TRAINER_FEMALE | }, }, #line 15488 - [TRAINER_TATE_AND_LIZA_4] = + [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_4] = { #line 15489 .trainerName = _("TATE&LIZA"), @@ -38819,7 +38819,7 @@ F_TRAINER_FEMALE | }, }, #line 15546 - [TRAINER_TATE_AND_LIZA_5] = + [DIFFICULTY_NORMAL][TRAINER_TATE_AND_LIZA_5] = { #line 15547 .trainerName = _("TATE&LIZA"), @@ -38956,7 +38956,7 @@ F_TRAINER_FEMALE | }, }, #line 15604 - [TRAINER_JUAN_2] = + [DIFFICULTY_NORMAL][TRAINER_JUAN_2] = { #line 15605 .trainerName = _("JUAN"), @@ -39073,7 +39073,7 @@ F_TRAINER_FEMALE | }, }, #line 15654 - [TRAINER_JUAN_3] = + [DIFFICULTY_NORMAL][TRAINER_JUAN_3] = { #line 15655 .trainerName = _("JUAN"), @@ -39190,7 +39190,7 @@ F_TRAINER_FEMALE | }, }, #line 15704 - [TRAINER_JUAN_4] = + [DIFFICULTY_NORMAL][TRAINER_JUAN_4] = { #line 15705 .trainerName = _("JUAN"), @@ -39325,7 +39325,7 @@ F_TRAINER_FEMALE | }, }, #line 15762 - [TRAINER_JUAN_5] = + [DIFFICULTY_NORMAL][TRAINER_JUAN_5] = { #line 15763 .trainerName = _("JUAN"), @@ -39460,7 +39460,7 @@ F_TRAINER_FEMALE | }, }, #line 15820 - [TRAINER_ANGELO] = + [DIFFICULTY_NORMAL][TRAINER_ANGELO] = { #line 15821 .trainerName = _("ANGELO"), @@ -39515,7 +39515,7 @@ F_TRAINER_FEMALE | }, }, #line 15843 - [TRAINER_DARIUS] = + [DIFFICULTY_NORMAL][TRAINER_DARIUS] = { #line 15844 .trainerName = _("DARIUS"), @@ -39547,7 +39547,7 @@ F_TRAINER_FEMALE | }, }, #line 15856 - [TRAINER_STEVEN] = + [DIFFICULTY_NORMAL][TRAINER_STEVEN] = { #line 15857 .trainerName = _("STEVEN"), @@ -39680,7 +39680,7 @@ F_TRAINER_FEMALE | }, }, #line 15914 - [TRAINER_ANABEL] = + [DIFFICULTY_NORMAL][TRAINER_ANABEL] = { #line 15915 .trainerName = _("ANABEL"), @@ -39714,7 +39714,7 @@ F_TRAINER_FEMALE | }, }, #line 15927 - [TRAINER_TUCKER] = + [DIFFICULTY_NORMAL][TRAINER_TUCKER] = { #line 15928 .trainerName = _("TUCKER"), @@ -39746,7 +39746,7 @@ F_TRAINER_FEMALE | }, }, #line 15940 - [TRAINER_SPENSER] = + [DIFFICULTY_NORMAL][TRAINER_SPENSER] = { #line 15941 .trainerName = _("SPENSER"), @@ -39778,7 +39778,7 @@ F_TRAINER_FEMALE | }, }, #line 15953 - [TRAINER_GRETA] = + [DIFFICULTY_NORMAL][TRAINER_GRETA] = { #line 15954 .trainerName = _("GRETA"), @@ -39812,7 +39812,7 @@ F_TRAINER_FEMALE | }, }, #line 15966 - [TRAINER_NOLAND] = + [DIFFICULTY_NORMAL][TRAINER_NOLAND] = { #line 15967 .trainerName = _("NOLAND"), @@ -39844,7 +39844,7 @@ F_TRAINER_FEMALE | }, }, #line 15979 - [TRAINER_LUCY] = + [DIFFICULTY_NORMAL][TRAINER_LUCY] = { #line 15980 .trainerName = _("LUCY"), @@ -39878,7 +39878,7 @@ F_TRAINER_FEMALE | }, }, #line 15992 - [TRAINER_BRANDON] = + [DIFFICULTY_NORMAL][TRAINER_BRANDON] = { #line 15993 .trainerName = _("BRANDON"), @@ -39910,7 +39910,7 @@ F_TRAINER_FEMALE | }, }, #line 16005 - [TRAINER_ANDRES_2] = + [DIFFICULTY_NORMAL][TRAINER_ANDRES_2] = { #line 16006 .trainerName = _("ANDRES"), @@ -39953,7 +39953,7 @@ F_TRAINER_FEMALE | }, }, #line 16022 - [TRAINER_ANDRES_3] = + [DIFFICULTY_NORMAL][TRAINER_ANDRES_3] = { #line 16023 .trainerName = _("ANDRES"), @@ -40007,7 +40007,7 @@ F_TRAINER_FEMALE | }, }, #line 16043 - [TRAINER_ANDRES_4] = + [DIFFICULTY_NORMAL][TRAINER_ANDRES_4] = { #line 16044 .trainerName = _("ANDRES"), @@ -40061,7 +40061,7 @@ F_TRAINER_FEMALE | }, }, #line 16064 - [TRAINER_ANDRES_5] = + [DIFFICULTY_NORMAL][TRAINER_ANDRES_5] = { #line 16065 .trainerName = _("ANDRES"), @@ -40115,7 +40115,7 @@ F_TRAINER_FEMALE | }, }, #line 16085 - [TRAINER_CORY_2] = + [DIFFICULTY_NORMAL][TRAINER_CORY_2] = { #line 16086 .trainerName = _("CORY"), @@ -40169,7 +40169,7 @@ F_TRAINER_FEMALE | }, }, #line 16106 - [TRAINER_CORY_3] = + [DIFFICULTY_NORMAL][TRAINER_CORY_3] = { #line 16107 .trainerName = _("CORY"), @@ -40223,7 +40223,7 @@ F_TRAINER_FEMALE | }, }, #line 16127 - [TRAINER_CORY_4] = + [DIFFICULTY_NORMAL][TRAINER_CORY_4] = { #line 16128 .trainerName = _("CORY"), @@ -40277,7 +40277,7 @@ F_TRAINER_FEMALE | }, }, #line 16148 - [TRAINER_CORY_5] = + [DIFFICULTY_NORMAL][TRAINER_CORY_5] = { #line 16149 .trainerName = _("CORY"), @@ -40331,7 +40331,7 @@ F_TRAINER_FEMALE | }, }, #line 16169 - [TRAINER_PABLO_2] = + [DIFFICULTY_NORMAL][TRAINER_PABLO_2] = { #line 16170 .trainerName = _("PABLO"), @@ -40374,7 +40374,7 @@ F_TRAINER_FEMALE | }, }, #line 16186 - [TRAINER_PABLO_3] = + [DIFFICULTY_NORMAL][TRAINER_PABLO_3] = { #line 16187 .trainerName = _("PABLO"), @@ -40428,7 +40428,7 @@ F_TRAINER_FEMALE | }, }, #line 16207 - [TRAINER_PABLO_4] = + [DIFFICULTY_NORMAL][TRAINER_PABLO_4] = { #line 16208 .trainerName = _("PABLO"), @@ -40482,7 +40482,7 @@ F_TRAINER_FEMALE | }, }, #line 16228 - [TRAINER_PABLO_5] = + [DIFFICULTY_NORMAL][TRAINER_PABLO_5] = { #line 16229 .trainerName = _("PABLO"), @@ -40536,7 +40536,7 @@ F_TRAINER_FEMALE | }, }, #line 16249 - [TRAINER_KOJI_2] = + [DIFFICULTY_NORMAL][TRAINER_KOJI_2] = { #line 16250 .trainerName = _("KOJI"), @@ -40579,7 +40579,7 @@ F_TRAINER_FEMALE | }, }, #line 16266 - [TRAINER_KOJI_3] = + [DIFFICULTY_NORMAL][TRAINER_KOJI_3] = { #line 16267 .trainerName = _("KOJI"), @@ -40633,7 +40633,7 @@ F_TRAINER_FEMALE | }, }, #line 16287 - [TRAINER_KOJI_4] = + [DIFFICULTY_NORMAL][TRAINER_KOJI_4] = { #line 16288 .trainerName = _("KOJI"), @@ -40687,7 +40687,7 @@ F_TRAINER_FEMALE | }, }, #line 16308 - [TRAINER_KOJI_5] = + [DIFFICULTY_NORMAL][TRAINER_KOJI_5] = { #line 16309 .trainerName = _("KOJI"), @@ -40741,7 +40741,7 @@ F_TRAINER_FEMALE | }, }, #line 16329 - [TRAINER_CRISTIN_2] = + [DIFFICULTY_NORMAL][TRAINER_CRISTIN_2] = { #line 16330 .trainerName = _("CRISTIN"), @@ -40788,7 +40788,7 @@ F_TRAINER_FEMALE | }, }, #line 16347 - [TRAINER_CRISTIN_3] = + [DIFFICULTY_NORMAL][TRAINER_CRISTIN_3] = { #line 16348 .trainerName = _("CRISTIN"), @@ -40846,7 +40846,7 @@ F_TRAINER_FEMALE | }, }, #line 16369 - [TRAINER_CRISTIN_4] = + [DIFFICULTY_NORMAL][TRAINER_CRISTIN_4] = { #line 16370 .trainerName = _("CRISTIN"), @@ -40904,7 +40904,7 @@ F_TRAINER_FEMALE | }, }, #line 16391 - [TRAINER_CRISTIN_5] = + [DIFFICULTY_NORMAL][TRAINER_CRISTIN_5] = { #line 16392 .trainerName = _("CRISTIN"), @@ -40962,7 +40962,7 @@ F_TRAINER_FEMALE | }, }, #line 16413 - [TRAINER_FERNANDO_2] = + [DIFFICULTY_NORMAL][TRAINER_FERNANDO_2] = { #line 16414 .trainerName = _("FERNANDO"), @@ -41016,7 +41016,7 @@ F_TRAINER_FEMALE | }, }, #line 16434 - [TRAINER_FERNANDO_3] = + [DIFFICULTY_NORMAL][TRAINER_FERNANDO_3] = { #line 16435 .trainerName = _("FERNANDO"), @@ -41070,7 +41070,7 @@ F_TRAINER_FEMALE | }, }, #line 16455 - [TRAINER_FERNANDO_4] = + [DIFFICULTY_NORMAL][TRAINER_FERNANDO_4] = { #line 16456 .trainerName = _("FERNANDO"), @@ -41124,7 +41124,7 @@ F_TRAINER_FEMALE | }, }, #line 16476 - [TRAINER_FERNANDO_5] = + [DIFFICULTY_NORMAL][TRAINER_FERNANDO_5] = { #line 16477 .trainerName = _("FERNANDO"), @@ -41178,7 +41178,7 @@ F_TRAINER_FEMALE | }, }, #line 16497 - [TRAINER_SAWYER_2] = + [DIFFICULTY_NORMAL][TRAINER_SAWYER_2] = { #line 16498 .trainerName = _("SAWYER"), @@ -41221,7 +41221,7 @@ F_TRAINER_FEMALE | }, }, #line 16514 - [TRAINER_SAWYER_3] = + [DIFFICULTY_NORMAL][TRAINER_SAWYER_3] = { #line 16515 .trainerName = _("SAWYER"), @@ -41275,7 +41275,7 @@ F_TRAINER_FEMALE | }, }, #line 16535 - [TRAINER_SAWYER_4] = + [DIFFICULTY_NORMAL][TRAINER_SAWYER_4] = { #line 16536 .trainerName = _("SAWYER"), @@ -41329,7 +41329,7 @@ F_TRAINER_FEMALE | }, }, #line 16556 - [TRAINER_SAWYER_5] = + [DIFFICULTY_NORMAL][TRAINER_SAWYER_5] = { #line 16557 .trainerName = _("SAWYER"), @@ -41383,7 +41383,7 @@ F_TRAINER_FEMALE | }, }, #line 16577 - [TRAINER_GABRIELLE_2] = + [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_2] = { #line 16578 .trainerName = _("GABRIELLE"), @@ -41472,7 +41472,7 @@ F_TRAINER_FEMALE | }, }, #line 16610 - [TRAINER_GABRIELLE_3] = + [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_3] = { #line 16611 .trainerName = _("GABRIELLE"), @@ -41561,7 +41561,7 @@ F_TRAINER_FEMALE | }, }, #line 16643 - [TRAINER_GABRIELLE_4] = + [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_4] = { #line 16644 .trainerName = _("GABRIELLE"), @@ -41650,7 +41650,7 @@ F_TRAINER_FEMALE | }, }, #line 16676 - [TRAINER_GABRIELLE_5] = + [DIFFICULTY_NORMAL][TRAINER_GABRIELLE_5] = { #line 16677 .trainerName = _("GABRIELLE"), @@ -41739,7 +41739,7 @@ F_TRAINER_FEMALE | }, }, #line 16709 - [TRAINER_THALIA_2] = + [DIFFICULTY_NORMAL][TRAINER_THALIA_2] = { #line 16710 .trainerName = _("THALIA"), @@ -41784,7 +41784,7 @@ F_TRAINER_FEMALE | }, }, #line 16726 - [TRAINER_THALIA_3] = + [DIFFICULTY_NORMAL][TRAINER_THALIA_3] = { #line 16727 .trainerName = _("THALIA"), @@ -41840,7 +41840,7 @@ F_TRAINER_FEMALE | }, }, #line 16747 - [TRAINER_THALIA_4] = + [DIFFICULTY_NORMAL][TRAINER_THALIA_4] = { #line 16748 .trainerName = _("THALIA"), @@ -41896,7 +41896,7 @@ F_TRAINER_FEMALE | }, }, #line 16768 - [TRAINER_THALIA_5] = + [DIFFICULTY_NORMAL][TRAINER_THALIA_5] = { #line 16769 .trainerName = _("THALIA"), @@ -41952,7 +41952,7 @@ F_TRAINER_FEMALE | }, }, #line 16789 - [TRAINER_MARIELA] = + [DIFFICULTY_NORMAL][TRAINER_MARIELA] = { #line 16790 .trainerName = _("MARIELA"), @@ -41984,7 +41984,7 @@ F_TRAINER_FEMALE | }, }, #line 16801 - [TRAINER_ALVARO] = + [DIFFICULTY_NORMAL][TRAINER_ALVARO] = { #line 16802 .trainerName = _("ALVARO"), @@ -42025,7 +42025,7 @@ F_TRAINER_FEMALE | }, }, #line 16817 - [TRAINER_EVERETT] = + [DIFFICULTY_NORMAL][TRAINER_EVERETT] = { #line 16818 .trainerName = _("EVERETT"), @@ -42055,7 +42055,7 @@ F_TRAINER_FEMALE | }, }, #line 16829 - [TRAINER_RED] = + [DIFFICULTY_NORMAL][TRAINER_RED] = { #line 16830 .trainerName = _("RED"), @@ -42085,7 +42085,7 @@ F_TRAINER_FEMALE | }, }, #line 16841 - [TRAINER_LEAF] = + [DIFFICULTY_NORMAL][TRAINER_LEAF] = { #line 16842 .trainerName = _("LEAF"), @@ -42117,7 +42117,7 @@ F_TRAINER_FEMALE | }, }, #line 16853 - [TRAINER_BRENDAN_PLACEHOLDER] = + [DIFFICULTY_NORMAL][TRAINER_BRENDAN_PLACEHOLDER] = { #line 16854 .trainerName = _("BRENDAN"), @@ -42147,7 +42147,7 @@ F_TRAINER_FEMALE | }, }, #line 16865 - [TRAINER_MAY_PLACEHOLDER] = + [DIFFICULTY_NORMAL][TRAINER_MAY_PLACEHOLDER] = { #line 16866 .trainerName = _("MAY"), diff --git a/src/difficulty.c b/src/difficulty.c new file mode 100644 index 0000000000..bf7caca313 --- /dev/null +++ b/src/difficulty.c @@ -0,0 +1,95 @@ +#include "global.h" +#include "data.h" +#include "event_data.h" +#include "script.h" +#include "constants/battle.h" + +enum DifficultyLevel GetCurrentDifficultyLevel(void) +{ + if (!B_VAR_DIFFICULTY) + return DIFFICULTY_NORMAL; + + return VarGet(B_VAR_DIFFICULTY); +} + +void SetCurrentDifficultyLevel(enum DifficultyLevel desiredDifficulty) +{ + if (!B_VAR_DIFFICULTY) + return; + + if (desiredDifficulty > DIFFICULTY_MAX) + desiredDifficulty = DIFFICULTY_MAX; + + VarSet(B_VAR_DIFFICULTY, desiredDifficulty); +} + +enum DifficultyLevel GetBattlePartnerDifficultyLevel(u16 partnerId) +{ + enum DifficultyLevel difficulty = GetCurrentDifficultyLevel(); + + if (partnerId > TRAINER_PARTNER(PARTNER_NONE)) + partnerId -= TRAINER_PARTNER(PARTNER_NONE); + + if (difficulty == DIFFICULTY_NORMAL) + return DIFFICULTY_NORMAL; + + if (gBattlePartners[difficulty][partnerId].party == NULL) + return DIFFICULTY_NORMAL; + + return difficulty; +} + +enum DifficultyLevel GetTrainerDifficultyLevel(u16 trainerId) +{ + enum DifficultyLevel difficulty = GetCurrentDifficultyLevel(); + + if (difficulty == DIFFICULTY_NORMAL) + return DIFFICULTY_NORMAL; + + if (gTrainers[difficulty][trainerId].party == NULL) + return DIFFICULTY_NORMAL; + + return difficulty; +} + +void Script_IncreaseDifficulty(void) +{ + enum DifficultyLevel currentDifficulty; + + if (!B_VAR_DIFFICULTY) + return; + + currentDifficulty = GetCurrentDifficultyLevel(); + + if (currentDifficulty++ > DIFFICULTY_MAX) + return; + + SetCurrentDifficultyLevel(currentDifficulty); +} + +void Script_DecreaseDifficulty(void) +{ + enum DifficultyLevel currentDifficulty; + + if (!B_VAR_DIFFICULTY) + return; + + currentDifficulty = GetCurrentDifficultyLevel(); + + if (!currentDifficulty) + return; + + SetCurrentDifficultyLevel(--currentDifficulty); +} + +void Script_GetDifficulty(void) +{ + gSpecialVar_Result = GetCurrentDifficultyLevel(); +} + +void Script_SetDifficulty(struct ScriptContext *ctx) +{ + enum DifficultyLevel desiredDifficulty = ScriptReadByte(ctx); + + SetCurrentDifficultyLevel(desiredDifficulty); +} diff --git a/src/new_game.c b/src/new_game.c index 0837475971..bdc020f9df 100644 --- a/src/new_game.c +++ b/src/new_game.c @@ -46,6 +46,7 @@ #include "union_room_chat.h" #include "constants/map_groups.h" #include "constants/items.h" +#include "difficulty.h" extern const u8 EventScript_ResetAllMapFlags[]; @@ -207,6 +208,7 @@ void NewGameInitData(void) WipeTrainerNameRecords(); ResetTrainerHillResults(); ResetContestLinkResults(); + SetCurrentDifficultyLevel(DIFFICULTY_NORMAL); ResetItemFlags(); ResetDexNav(); } diff --git a/src/pokemon.c b/src/pokemon.c index 241372f64a..bb590abd63 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -5143,12 +5143,15 @@ s32 GetBattlerMultiplayerId(u16 id) u8 GetTrainerEncounterMusicId(u16 trainerOpponentId) { + u32 sanitizedTrainerId = SanitizeTrainerId(trainerOpponentId); + enum DifficultyLevel difficulty = GetTrainerDifficultyLevel(sanitizedTrainerId); + if (InBattlePyramid()) return GetTrainerEncounterMusicIdInBattlePyramid(trainerOpponentId); else if (InTrainerHillChallenge()) return GetTrainerEncounterMusicIdInTrainerHill(trainerOpponentId); else - return gTrainers[SanitizeTrainerId(trainerOpponentId)].encounterMusic_gender & (F_TRAINER_FEMALE - 1); + return gTrainers[difficulty][sanitizedTrainerId].encounterMusic_gender & (F_TRAINER_FEMALE - 1); } u16 ModifyStatByNature(u8 nature, u16 stat, u8 statIndex) @@ -6088,7 +6091,7 @@ const u8 *GetTrainerPartnerName(void) { if (gPartnerTrainerId == TRAINER_PARTNER(PARTNER_STEVEN)) { - return GetTrainerNameFromId(TRAINER_STEVEN); + return GetTrainerNameFromId(PARTNER_STEVEN); } else { diff --git a/test/battle/trainer_control.c b/test/battle/trainer_control.c index 5344a26596..bbc49c2ed5 100644 --- a/test/battle/trainer_control.c +++ b/test/battle/trainer_control.c @@ -11,16 +11,32 @@ #include "constants/trainers.h" #include "constants/battle.h" -static const struct Trainer sTestTrainers[] = +#define NUM_TEST_TRAINERS 3 + +static const struct Trainer sTestTrainers[DIFFICULTY_COUNT][NUM_TEST_TRAINERS] = { #include "trainer_control.h" }; +enum DifficultyLevel GetTrainerDifficultyLevelTest(u16 trainerId) +{ + enum DifficultyLevel difficulty = GetCurrentDifficultyLevel(); + + if (difficulty == DIFFICULTY_NORMAL) + return DIFFICULTY_NORMAL; + + if (sTestTrainers[difficulty][trainerId].party == NULL) + return DIFFICULTY_NORMAL; + + return difficulty; +} + TEST("CreateNPCTrainerPartyForTrainer generates customized Pokémon") { + u32 currTrainer = 0; struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon)); u8 nickBuffer[20]; - CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainers[0], TRUE, BATTLE_TYPE_TRAINER); + CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainers[GetTrainerDifficultyLevelTest(currTrainer)][currTrainer], TRUE, BATTLE_TYPE_TRAINER); EXPECT(IsMonShiny(&testParty[0])); EXPECT(!IsMonShiny(&testParty[1])); @@ -94,8 +110,9 @@ TEST("CreateNPCTrainerPartyForTrainer generates customized Pokémon") TEST("CreateNPCTrainerPartyForTrainer generates different personalities for different mons") { + enum DifficultyLevel difficulty = GetTrainerDifficultyLevelTest(0); struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon)); - CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainers[0], TRUE, BATTLE_TYPE_TRAINER); + CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainers[difficulty][0], TRUE, BATTLE_TYPE_TRAINER); EXPECT(testParty[0].box.personality != testParty[1].box.personality); Free(testParty); } @@ -160,3 +177,46 @@ TEST("Trainer Class Balls apply to the entire party") } Free(testParty); } + +TEST("Difficulty default to Normal is the trainer doesn't have a member for the current diffuculty") +{ + SetCurrentDifficultyLevel(DIFFICULTY_EASY); + struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon)); + u32 currTrainer = 1; + CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainers[GetTrainerDifficultyLevelTest(currTrainer)][currTrainer], TRUE, BATTLE_TYPE_TRAINER); + EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_MEWTWO); + Free(testParty); +} + +TEST("Difficulty changes which party if used for NPCs if defined for the difficulty (EASY)") +{ + SetCurrentDifficultyLevel(DIFFICULTY_EASY); + struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon)); + u32 currTrainer = 2; + CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainers[GetTrainerDifficultyLevelTest(currTrainer)][currTrainer], TRUE, BATTLE_TYPE_TRAINER); + EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_METAPOD); + EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 1); + Free(testParty); +} + +TEST("Difficulty changes which party if used for NPCs if defined for the difficulty (HARD)") +{ + SetCurrentDifficultyLevel(DIFFICULTY_HARD); + struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon)); + u32 currTrainer = 2; + CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainers[GetTrainerDifficultyLevelTest(currTrainer)][currTrainer], TRUE, BATTLE_TYPE_TRAINER); + EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_ARCEUS); + EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 99); + Free(testParty); +} + +TEST("Difficulty changes which party if used for NPCs if defined for the difficulty (NORMAL)") +{ + SetCurrentDifficultyLevel(DIFFICULTY_NORMAL); + struct Pokemon *testParty = Alloc(6 * sizeof(struct Pokemon)); + u32 currTrainer = 2; + CreateNPCTrainerPartyFromTrainer(testParty, &sTestTrainers[GetTrainerDifficultyLevelTest(currTrainer)][currTrainer], TRUE, BATTLE_TYPE_TRAINER); + EXPECT(GetMonData(&testParty[0], MON_DATA_SPECIES) == SPECIES_MEWTWO); + EXPECT(GetMonData(&testParty[0], MON_DATA_LEVEL) == 50); + Free(testParty); +} diff --git a/test/battle/trainer_control.h b/test/battle/trainer_control.h index 72db458de7..9bb878f76f 100644 --- a/test/battle/trainer_control.h +++ b/test/battle/trainer_control.h @@ -9,7 +9,7 @@ #line 1 "test/battle/trainer_control.party" #line 1 - [0] = + [DIFFICULTY_NORMAL][0] = { #line 2 .trainerName = _("Test1"), @@ -87,3 +87,158 @@ }, }, }, +#line 33 +#line 40 + [DIFFICULTY_NORMAL][1] = + { +#line 34 + .trainerName = _("Test2"), +#line 35 + .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, +#line 36 + .trainerPic = TRAINER_PIC_RED, + .encounterMusic_gender = +#line 38 + TRAINER_ENCOUNTER_MUSIC_MALE, +#line 39 + .doubleBattle = FALSE, + .partySize = 1, + .party = (const struct TrainerMon[]) + { + { +#line 42 + .species = SPECIES_MEWTWO, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 44 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 43 + .lvl = 5, + .nature = NATURE_HARDY, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + }, + }, + }, +#line 45 +#line 52 + [DIFFICULTY_HARD][1] = + { +#line 46 + .trainerName = _("Test2"), +#line 47 + .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, +#line 48 + .trainerPic = TRAINER_PIC_RED, + .encounterMusic_gender = +#line 50 + TRAINER_ENCOUNTER_MUSIC_MALE, +#line 51 + .doubleBattle = FALSE, + .partySize = 1, + .party = (const struct TrainerMon[]) + { + { +#line 54 + .species = SPECIES_YVELTAL, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 56 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 55 + .lvl = 99, + .nature = NATURE_HARDY, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + }, + }, + }, +#line 57 +#line 64 + [DIFFICULTY_NORMAL][2] = + { +#line 58 + .trainerName = _("Test2"), +#line 59 + .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, +#line 60 + .trainerPic = TRAINER_PIC_RED, + .encounterMusic_gender = +#line 62 + TRAINER_ENCOUNTER_MUSIC_MALE, +#line 63 + .doubleBattle = FALSE, + .partySize = 1, + .party = (const struct TrainerMon[]) + { + { +#line 66 + .species = SPECIES_MEWTWO, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 68 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 67 + .lvl = 50, + .nature = NATURE_HARDY, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + }, + }, + }, +#line 69 +#line 76 + [DIFFICULTY_EASY][2] = + { +#line 70 + .trainerName = _("Test2"), +#line 71 + .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, +#line 72 + .trainerPic = TRAINER_PIC_RED, + .encounterMusic_gender = +#line 74 + TRAINER_ENCOUNTER_MUSIC_MALE, +#line 75 + .doubleBattle = FALSE, + .partySize = 1, + .party = (const struct TrainerMon[]) + { + { +#line 78 + .species = SPECIES_METAPOD, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 80 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 79 + .lvl = 1, + .nature = NATURE_HARDY, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + }, + }, + }, +#line 81 +#line 88 + [DIFFICULTY_HARD][2] = + { +#line 82 + .trainerName = _("Test2"), +#line 83 + .trainerClass = TRAINER_CLASS_PKMN_TRAINER_1, +#line 84 + .trainerPic = TRAINER_PIC_RED, + .encounterMusic_gender = +#line 86 + TRAINER_ENCOUNTER_MUSIC_MALE, +#line 87 + .doubleBattle = FALSE, + .partySize = 1, + .party = (const struct TrainerMon[]) + { + { +#line 90 + .species = SPECIES_ARCEUS, + .gender = TRAINER_MON_RANDOM_GENDER, +#line 92 + .iv = TRAINER_PARTY_IVS(31, 31, 31, 31, 31, 31), +#line 91 + .lvl = 99, + .nature = NATURE_HARDY, + .dynamaxLevel = MAX_DYNAMAX_LEVEL, + }, + }, + }, diff --git a/test/battle/trainer_control.party b/test/battle/trainer_control.party index 8ebfc0e664..3357bb70fe 100644 --- a/test/battle/trainer_control.party +++ b/test/battle/trainer_control.party @@ -29,3 +29,63 @@ IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe Wynaut Level: 5 IVs: 0 HP / 0 Atk / 0 Def / 0 SpA / 0 SpD / 0 Spe + +=== 1 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Double Battle: No +Difficulty: Normal + +Mewtwo +Level: 5 + +=== 1 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Double Battle: No +Difficulty: HARD + +Yveltal +Level: 99 + +=== 2 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Double Battle: No +Difficulty: Normal + +Mewtwo +Level: 50 + +=== 2 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Double Battle: No +Difficulty: Easy + +Metapod +Level: 1 + +=== 2 === +Name: Test2 +Class: Pkmn Trainer 1 +Pic: Red +Gender: Male +Music: Male +Double Battle: No +Difficulty: Hard + +Arceus +Level: 99 diff --git a/tools/trainerproc/main.c b/tools/trainerproc/main.c index 7cddb06930..fda4ac7c3f 100644 --- a/tools/trainerproc/main.c +++ b/tools/trainerproc/main.c @@ -123,6 +123,9 @@ struct Trainer struct String starting_status; int starting_status_line; + + struct String difficulty; + int difficulty_line; }; static bool is_empty_string(struct String s) @@ -1195,9 +1198,16 @@ static bool parse_trainer(struct Parser *p, const struct Parsed *parsed, struct trainer->starting_status_line = value.location.line; trainer->starting_status = token_string(&value); } + else if (is_literal_token(&key, "Difficulty")) + { + if (trainer->difficulty_line) + any_error = !set_show_parse_error(p, key.location, "duplicate 'Difficulty'"); + trainer->difficulty_line = value.location.line; + trainer->difficulty = token_string(&value); + } else { - any_error = !set_show_parse_error(p, key.location, "expected one of 'Name', 'Class', 'Pic', 'Gender', 'Music', 'Items', 'Double Battle', or 'AI'"); + any_error = !set_show_parse_error(p, key.location, "expected one of 'Name', 'Class', 'Pic', 'Gender', 'Music', 'Items', 'Double Battle', 'Difficulty', or 'AI'"); } } if (!trainer->pic_line) @@ -1618,7 +1628,14 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par { struct Trainer *trainer = &parsed->trainers[i]; fprintf(f, "#line %d\n", trainer->id_line); - fprintf(f, " ["); + if (is_empty_string(trainer->difficulty)) + trainer->difficulty = literal_string("Normal"); + else + fprintf(f, "#line %d\n", trainer->difficulty_line); + fprint_constant(f, " [DIFFICULTY",trainer->difficulty); + fprintf(f, "]"); + + fprintf(f, "["); fprint_string(f, trainer->id); fprintf(f, "] =\n"); fprintf(f, " {\n"); @@ -1741,17 +1758,17 @@ static void fprint_trainers(const char *output_path, FILE *f, struct Parsed *par switch (pokemon->gender) { - case GENDER_ANY: - fprintf(f, " .gender = TRAINER_MON_RANDOM_GENDER,\n"); - break; - case GENDER_MALE: - fprintf(f, "#line %d\n", pokemon->header_line); - fprintf(f, " .gender = TRAINER_MON_MALE,\n"); - break; - case GENDER_FEMALE: - fprintf(f, "#line %d\n", pokemon->header_line); - fprintf(f, " .gender = TRAINER_MON_FEMALE,\n"); - break; + case GENDER_ANY: + fprintf(f, " .gender = TRAINER_MON_RANDOM_GENDER,\n"); + break; + case GENDER_MALE: + fprintf(f, "#line %d\n", pokemon->header_line); + fprintf(f, " .gender = TRAINER_MON_MALE,\n"); + break; + case GENDER_FEMALE: + fprintf(f, "#line %d\n", pokemon->header_line); + fprintf(f, " .gender = TRAINER_MON_FEMALE,\n"); + break; } if (!is_empty_string(pokemon->item)) From b8ccc29126e3d41db4e2ad66cfa2e47963a21b20 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Sat, 4 Jan 2025 14:40:10 -0500 Subject: [PATCH 21/85] Update scope.md (#5948) --- docs/scope.md | 53 +++++++++++++++++++++++++++------------------------ 1 file changed, 28 insertions(+), 25 deletions(-) diff --git a/docs/scope.md b/docs/scope.md index 1bec4f2db7..41369eda29 100644 --- a/docs/scope.md +++ b/docs/scope.md @@ -1,11 +1,12 @@ # Document Purpose -This document is a guide for contributors and Senate to decide if a feature is within "scope" for pokeemerald-expansion. If a feature is not in scope, then it should not be merged. Even if an opened PR is within scope, this does not mean it will be merged, as acceptance criteria will often come down to the details of the implementation. +This document is a guide for contributors and Senate to decide if a feature is within "scope" for pokeemerald-expansion. "Scope" in this case comprises a list of features and concepts that could be merged if an appropriate implementation is submitted. If a feature is not in scope, then it should not be merged. Even if an opened PR is within scope, this does not mean it will be merged, as acceptance criteria will often come down to the details of the implementation. # Definitions * **Showdown Supported (SS)**: A core series game who's metagame can be played on Showdown. - * Notably, this is every [core series game](https://bulbapedia.bulbagarden.net/wiki/Core_series#List_of_core_series_games) except Pokémon Legends: Arceus. + * Includes every [core series game](https://bulbapedia.bulbagarden.net/wiki/Core_series#List_of_core_series_games) except Pokémon Legends: Arceus. + * Does not include [spin-off games](https://bulbapedia.bulbagarden.net/wiki/Spin-off_Pokémon_games) such as Pokémon Colosseum, Pokémon XD, Pokémon Trozei!, etc. * **Base Expansion Version**: "A .gba file built from an unmodified `master` or `upcoming` branch of `pokeemerald-expansion`. * **Vanilla Emerald Version**: A .gba file built from an unmodified `master` branch of pret's `pokeemerald`. @@ -17,38 +18,40 @@ A pull request meets the scope criteria if: ## In Scope Categories -1. **SS Species:** Adds Species that have appeared in a Showdown-supported title -2. **SS Moves:** Adds Moves and Move Animations that have appeared in a Showdown-supported title -3. **SS Abilities:** Adds Abilities that have appeared in a Showdown-supported title -4. **SS Items:** Adds Items that have appeared in a Showdown-supported title -5. **SS Gimmicks:** Adds Gimmicks that have appeared in a Showdown-supported title -6. **SS Battle Types:** Adds Special Battle Types that have appeared in a Showdown-supported title -7. **SS Battle Mechanics:** Adds mechanical battle changes that have appeared in a Showdown-supported title -8. **Improve Battle AI:** Improve the Battle AI in a way that allows it to approach the skill and capability of a human competitive player -9. **Base Link Compatibility:** Link compatibility with base -10. **SS Overworld / Menu Updates:** Replicate overworld or menu changes from Showdown-supported Pokémon titles -11. **Speed Up:** Speed up the player experience of features found in base -12. **Compression:** Automatically compress assets -13. **Novel Experience:** Adds a novel experience included in another Showdown Supported title -15. **Helper Features:** Eases the addition or inclusion of any of the aforementioned +1. **SS Species**: Adds Species that have appeared in a Showdown-supported title. Includes follower sprites for all defined species including battle-only ones (ie. Megas) +2. **SS Moves**: Adds Moves and Move Animations that have appeared in a Showdown-supported title +3. **SS Abilities**: Adds Abilities that have appeared in a Showdown-supported title +4. **SS Items**: Adds Items that have appeared in a Showdown-supported title +5. **SS Gimmicks**: Adds Gimmicks that have appeared in a Showdown-supported title (Dynamax, Mega Evolution, etc.) +6. **SS Battle Types**: Adds Special Battle Types that have appeared in a Showdown-supported title (Triple battles, etc.) +7. **SS Battle Mechanics**: Adds mechanical battle changes that have appeared in a Showdown-supported title, and allow developers to choose which generation suits them where applicable +8. **Battle AI Behaviour**: Improvements towards the capability of a human competitive player, and unique or interesting behaviours otherwise +9. **Base Link Compatibility**: The ability for two Base Expansion Version's to connect, trade, and battle one another +10. **SS Overworld Features**: Add overworld changes / additions from Showdown-supported Pokémon titles (followers, raids, sideways stairs, etc.) +11. **SS Menu Features**: Add menu changes / additions from Showdown-supported Pokémon titles (type effectivness indicator, PC functions, etc.) +12. **Speed Up**: Optimize code to run more efficiently, take up less space, and work better overall to improves the developer and / or player experience +13. **Compression**: Reduces the size of graphic or sound assets, etc. Includes automatic compression +14. **Novel Experience**: Adds a novel experience included in another Showdown Supported title (poffins, fishing minigames, etc.) +15. **Helper Features**: Eases the addition or inclusion of any of the aforementioned, or facilitates developer ease of use ## Not In Scope Categories -1. **Non-SS Species**: Adds Species that have NOT appeared in a Showdown-supported title -2. **Non-SS Moves**: Adds Moves and Move Animations that have NOT appeared in a Showdown-supported title -3. **Non-SS Abilities**: Adds Abilities that have NOT appeared in a Showdown-supported title -4. **Non-SS Items**: Adds Items that have NOT appeared in a Showdown-supported title -5. **Non-SS Gimmicks**: Adds Gimmicks that have NOT appeared in a Showdown-supported title +1. **Non-SS Species**: Adds Species that have NOT appeared in a Showdown-supported title (Fakemon, CAP Pokémon, etc.) +2. **Non-SS Moves**: Adds Moves and Move Animations that have NOT appeared in a Showdown-supported title +3. **Non-SS Abilities**: Adds Abilities that have NOT appeared in a Showdown-supported title +4. **Non-SS Items**: Adds Items that have NOT appeared in a Showdown-supported title +5. **Non-SS Gimmicks**: Adds Gimmicks that have NOT appeared in a Showdown-supported title (Showdown's Other Metagames, etc.) 6. **Non-SS Battle Types**: Adds Special Battle Types that have NOT appeared in a Showdown-supported title +7. **Non-SS or SS Overworld Maps**: Adds overworld maps from either Showdown-supported titles or non-Showdown-supported titles 7. **Duplicate Feature UI**: Adds functionality that duplicates the core functionality of an existing vanilla feature -8. **Vanilla Link Compatibility**: Link compatibility with vanilla +8. **Vanilla Link Compatibility**: The ability for Base Expansion Version and Vanilla Emerald Version to connect, trade, and battle one another ## Discussion Required Categories Pull Requests that fall into this category should be brought up to maintainers, who will discuss and vote as to whether or not the feature is considered in scope. Considerations for acceptance may include invasiveness of implementation, popularity, ease of maintenance, etc. -1. **Developer Ease of Use:** Lowers barrier of entry for developers to use existing behavior -2. **Fangame Features:** Adds a popular feature from other fangames -3. **Popular Non-SS Features:** Exceptions can be made for uniquely popular or requested features (Drowsy, PLA Legend Plate, etc.) +1. **Developer Ease of Use**: Lowers barrier of entry for developers to use existing behavior +2. **Fangame Features**: Adds a popular feature from other fangames +3. **Popular Non-SS Features**: Exceptions can be made for uniquely popular or requested features (Drowsy, PLA Legend Plate, etc.) 4. **External Program**: External programs like poryscript, porymoves, etc. From d7bbb2e6288b1d973a29f2fe2205b42a11f462ce Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 4 Jan 2025 17:42:14 -0300 Subject: [PATCH 22/85] Easy customizable Hidden Move types (#5872) --- include/data.h | 3 ++- src/battle_main.c | 15 ++++++++----- src/data/types_info.h | 31 ++++++++++++++++++++++---- test/battle/move_effect/hidden_power.c | 27 ++++++++++++++++++++++ 4 files changed, 65 insertions(+), 11 deletions(-) diff --git a/include/data.h b/include/data.h index ad3cf4ec1e..1d2a1291f9 100644 --- a/include/data.h +++ b/include/data.h @@ -114,7 +114,8 @@ struct TypeInfo u16 damageCategory:2; // Used for B_PHYSICAL_SPECIAL_SPLIT <= GEN_3 u16 useSecondTypeIconPalette:1; u16 isSpecialCaseType:1; - u16 padding:12; + u16 isHiddenPowerType:1; // Changing this for any type will change the distribution of all Hidden Power types from vanilla. + u16 padding:11; const u32 *const paletteTMHM; //u16 enhanceItem; //u16 berry; diff --git a/src/battle_main.c b/src/battle_main.c index 1a0da73142..1938cef20c 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -5966,12 +5966,15 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, u8 *ateBoost) | ((GetMonData(mon, MON_DATA_SPDEF_IV) & 1) << 5); } - // Subtract 6 instead of 1 below because 5 types are excluded (TYPE_NONE, TYPE_NORMAL, TYPE_MYSTERY, TYPE_FAIRY and TYPE_STELLAR) - // The final + 2 skips past TYPE_NONE and Normal. - moveType = ((NUMBER_OF_MON_TYPES - 6) * typeBits) / 63 + 2; - if (moveType >= TYPE_MYSTERY) - moveType++; - return ((moveType | F_DYNAMIC_TYPE_IGNORE_PHYSICALITY) & 0x3F); + u32 hpTypes[NUMBER_OF_MON_TYPES] = {0}; + u32 i, hpTypeCount = 0; + for (i = 0; i < NUMBER_OF_MON_TYPES; i++) + { + if (gTypesInfo[i].isHiddenPowerType) + hpTypes[hpTypeCount++] = i; + } + moveType = ((hpTypeCount - 1) * typeBits) / 63; + return ((hpTypes[moveType] | F_DYNAMIC_TYPE_IGNORE_PHYSICALITY) & 0x3F); } break; case EFFECT_CHANGE_TYPE_ON_ITEM: diff --git a/src/data/types_info.h b/src/data/types_info.h index d14012ed5c..ea962b4a44 100644 --- a/src/data/types_info.h +++ b/src/data/types_info.h @@ -40,10 +40,12 @@ const uq4_12_t gTypeEffectivenessTable[NUMBER_OF_MON_TYPES][NUMBER_OF_MON_TYPES] #undef ______ #undef X -// .generic is large enough that the text for TYPE_ELECTRIC will exceed TEXT_BUFF_ARRAY_COUNT. -// In this array there's commented-out data such as references to type-resist berries that would otherwise would go unused. -// However, we figured this information would be useful for users that want to add their own types as a reminder of -// what data would they need to add in order to have their new types be fully fledged like official types. +// Notes regarding custom data: +// - The "generic" field is large enough that the text for TYPE_ELECTRIC will exceed TEXT_BUFF_ARRAY_COUNT. +// - In this array there's commented-out data such as references to type-resist berries that would otherwise would go unused. +// However, we figured this information would be useful for users that want to add their own types as a reminder of +// what data would they need to add in order to have their new types be fully fledged like official types. +// - Changing "isHiddenPowerType" for any type will change the distribution of all Hidden Power types from vanilla. const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = { [TYPE_NONE] = @@ -56,6 +58,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_NormalTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = TRUE, + .isHiddenPowerType = FALSE, }, [TYPE_NORMAL] = { @@ -69,6 +72,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_NormalTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = FALSE, //.enhanceItem = ITEM_SILK_SCARF, //.berry = ITEM_CHILAN_BERRY, //.gem = ITEM_NORMAL_GEM, @@ -88,6 +92,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_FightingTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_BLACK_BELT, //.berry = ITEM_CHOPLE_BERRY, //.gem = ITEM_FIGHTING_GEM, @@ -109,6 +114,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_FlyingTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_SHARP_BEAK, //.berry = ITEM_COBA_BERRY, //.gem = ITEM_FLYING_GEM, @@ -130,6 +136,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_PoisonTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_POISON_BARB, //.berry = ITEM_KEBIA_BERRY, //.gem = ITEM_POISON_GEM, @@ -151,6 +158,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_GroundTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_SOFT_SAND, //.berry = ITEM_SHUCA_BERRY, //.gem = ITEM_GROUND_GEM, @@ -172,6 +180,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_RockTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_HARD_STONE, //.berry = ITEM_CHARTI_BERRY, //.gem = ITEM_ROCK_GEM, @@ -193,6 +202,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_BugTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_SILVER_POWDER, //.berry = ITEM_TANGA_BERRY, //.gem = ITEM_BUG_GEM, @@ -214,6 +224,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_GhostTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_SPELL_TAG, //.berry = ITEM_KASIB_BERRY, //.gem = ITEM_GHOST_GEM, @@ -235,6 +246,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_SteelTMHM, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_METAL_COAT, //.berry = ITEM_BABIRI_BERRY, //.gem = ITEM_STEEL_GEM, @@ -253,6 +265,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .damageCategory = DAMAGE_CATEGORY_SPECIAL, .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = TRUE, + .isHiddenPowerType = FALSE, }, [TYPE_FIRE] = { @@ -266,6 +279,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_FireTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_CHARCOAL, //.berry = ITEM_OCCA_BERRY, //.gem = ITEM_FIRE_GEM, @@ -287,6 +301,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_WaterTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_MYSTIC_WATER, //.berry = ITEM_PASSHO_BERRY, //.gem = ITEM_WATER_GEM, @@ -308,6 +323,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_GrassTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_MIRACLE_SEED, //.berry = ITEM_RINDO_BERRY, //.gem = ITEM_GRASS_GEM, @@ -329,6 +345,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_ElectricTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_MAGNET, //.berry = ITEM_WACAN_BERRY, //.gem = ITEM_ELECTRIC_GEM, @@ -350,6 +367,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_PsychicTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_TWISTED_SPOON, //.berry = ITEM_PAYAPA_BERRY, //.gem = ITEM_PSYCHIC_GEM, @@ -371,6 +389,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_IceTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_NEVER_MELT_ICE, //.berry = ITEM_YACHE_BERRY, //.gem = ITEM_ICE_GEM, @@ -392,6 +411,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_DragonTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_DRAGON_FANG, //.berry = ITEM_HABAN_BERRY, //.gem = ITEM_DRAGON_GEM, @@ -413,6 +433,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_DarkTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = TRUE, //.enhanceItem = ITEM_BLACK_GLASSES, //.berry = ITEM_COLBUR_BERRY, //.gem = ITEM_DARK_GEM, @@ -434,6 +455,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_FairyTMHM, .useSecondTypeIconPalette = TRUE, .isSpecialCaseType = FALSE, + .isHiddenPowerType = FALSE, //.enhanceItem = ITEM_FAIRY_FEATHER, //.berry = ITEM_ROSELI_BERRY, //.gem = ITEM_FAIRY_GEM, @@ -454,6 +476,7 @@ const struct TypeInfo gTypesInfo[NUMBER_OF_MON_TYPES] = .paletteTMHM = gItemIconPalette_NormalTMHM, // failsafe .useSecondTypeIconPalette = FALSE, .isSpecialCaseType = TRUE, + .isHiddenPowerType = FALSE, // .teraShard = ITEM_STELLAR_TERA_SHARD, }, }; diff --git a/test/battle/move_effect/hidden_power.c b/test/battle/move_effect/hidden_power.c index 8ec63c21a7..3b2af8d99a 100644 --- a/test/battle/move_effect/hidden_power.c +++ b/test/battle/move_effect/hidden_power.c @@ -1,6 +1,33 @@ #include "global.h" #include "test/battle.h" +ASSUMPTIONS +{ + ASSUME(gTypesInfo[TYPE_NONE].isHiddenPowerType == FALSE); + ASSUME(gTypesInfo[TYPE_NORMAL].isHiddenPowerType == FALSE); + ASSUME(gTypesInfo[TYPE_FIGHTING].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_FLYING].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_POISON].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_GROUND].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_ROCK].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_BUG].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_GHOST].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_STEEL].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_MYSTERY].isHiddenPowerType == FALSE); + ASSUME(gTypesInfo[TYPE_FIRE].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_WATER].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_GRASS].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_ELECTRIC].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_PSYCHIC].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_ICE].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_DRAGON].isHiddenPowerType == TRUE); + ASSUME(gTypesInfo[TYPE_DARK].isHiddenPowerType == TRUE); + // Any type after Dark shouldn't be part of Hidden Power officially. + for (u32 j = TYPE_DARK + 1; j < NUMBER_OF_MON_TYPES; j++) { + ASSUME(gTypesInfo[j].isHiddenPowerType == FALSE); + } +} + // IV combinations sourced from https://www.smogon.com/forums/threads/hidden-power-iv-combinations.78083/ SINGLE_BATTLE_TEST("Hidden Power's type is determined by IVs") { From 76964dd96a45bb45fcd7ed19086b361cc908835e Mon Sep 17 00:00:00 2001 From: khbsd Date: Sat, 4 Jan 2025 17:24:58 -0600 Subject: [PATCH 23/85] Fly from Pokenav (#5679) --- include/config/overworld.h | 1 + include/overworld.h | 1 + include/pokenav.h | 4 +++ include/region_map.h | 5 +++ src/field_effect.c | 9 ++++-- src/field_region_map.c | 45 ++++++++++++++++++++++++--- src/pokenav_main_menu.c | 26 ++++++++-------- src/pokenav_region_map.c | 57 +++++++++++++++++++++++++++++++++-- src/region_map.c | 62 +++++++++++++++++++++++++------------- 9 files changed, 167 insertions(+), 43 deletions(-) diff --git a/include/config/overworld.h b/include/config/overworld.h index 464024025b..bc65470751 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -85,6 +85,7 @@ #define OW_FLAG_NO_ENCOUNTER 0 // If this flag is set, wild encounters will be disabled. #define OW_FLAG_NO_TRAINER_SEE 0 // If this flag is set, trainers will not battle the player unless they're talked to. #define OW_FLAG_NO_COLLISION 0 // If this flag is set, the player will be able to walk over tiles with collision. Mainly intended for debugging purposes. +#define OW_FLAG_POKE_RIDER 0 // If this flag is set, the player will be able to use fly from the Pokenav Region Map and the Town Map key item by pressing 'R' on a city/location they are able to fly to. #define BATTLE_PYRAMID_RANDOM_ENCOUNTERS FALSE // If set to TRUE, battle pyramid Pokemon will be generated randomly based on the round's challenge instead of hardcoded in src/data/battle_frontier/battle_pyramid_level_50_wild_mons.h (or open_level_wild_mons.h) diff --git a/include/overworld.h b/include/overworld.h index 28a4aa9277..ea23c15b30 100644 --- a/include/overworld.h +++ b/include/overworld.h @@ -52,6 +52,7 @@ extern bool8 (*gFieldCallback2)(void); extern u8 gLocalLinkPlayerId; extern u8 gFieldLinkPlayerCount; extern bool8 gExitStairsMovementDisabled; +extern bool8 gSkipShowMonAnim; extern const struct UCoords32 gDirectionToVectors[]; diff --git a/include/pokenav.h b/include/pokenav.h index 174c338e27..5c238a6c54 100644 --- a/include/pokenav.h +++ b/include/pokenav.h @@ -171,6 +171,8 @@ enum HELPBAR_NONE, HELPBAR_MAP_ZOOMED_OUT, HELPBAR_MAP_ZOOMED_IN, + HELPBAR_MAP_ZOOMED_OUT_CANFLY, + HELPBAR_MAP_ZOOMED_IN_CANFLY, HELPBAR_CONDITION_MON_LIST, HELPBAR_CONDITION_MON_STATUS, HELPBAR_CONDITION_MARKINGS, @@ -295,6 +297,7 @@ enum POKENAV_MAP_FUNC_ZOOM_OUT, POKENAV_MAP_FUNC_ZOOM_IN, POKENAV_MAP_FUNC_EXIT, + POKENAV_MAP_FUNC_FLY }; // Modes for PokenavFadeScreen @@ -438,6 +441,7 @@ void CreateRegionMapLoopedTask(s32); bool32 IsRegionMapLoopedTaskActive(void); void FreeRegionMapSubstruct1(void); void FreeRegionMapSubstruct2(void); +void UpdateRegionMapHelpBarText(void); // pokenav_conditions.c u32 PokenavCallback_Init_ConditionGraph_Party(void); diff --git a/include/region_map.h b/include/region_map.h index 9f0b110a65..08277651de 100644 --- a/include/region_map.h +++ b/include/region_map.h @@ -14,6 +14,7 @@ enum MAP_INPUT_MOVE_END, MAP_INPUT_A_BUTTON, MAP_INPUT_B_BUTTON, + MAP_INPUT_R_BUTTON }; enum { @@ -115,6 +116,10 @@ void TrySetPlayerIconBlink(void); void BlendRegionMap(u16 color, u32 coeff); void SetRegionMapDataForZoom(void); +//Pokenav Fly funcs +u32 FilterFlyDestination(struct RegionMap* regionMap); +void SetFlyDestination(struct RegionMap* regionMap); + extern const struct RegionMapLocation gRegionMapEntries[]; #endif //GUARD_REGION_MAP_H diff --git a/src/field_effect.c b/src/field_effect.c index dda30138b6..45631be6a3 100644 --- a/src/field_effect.c +++ b/src/field_effect.c @@ -1,6 +1,7 @@ #include "global.h" #include "data.h" #include "decompress.h" +#include "event_data.h" #include "event_object_movement.h" #include "field_camera.h" #include "field_control_avatar.h" @@ -28,9 +29,10 @@ #include "trainer_pokemon_sprites.h" #include "trig.h" #include "util.h" -#include "constants/field_effects.h" #include "constants/event_objects.h" #include "constants/event_object_movement.h" +#include "constants/field_effects.h" +#include "constants/flags.h" #include "constants/metatile_behaviors.h" #include "constants/rgb.h" #include "constants/songs.h" @@ -39,6 +41,7 @@ #define subsprite_table(ptr) {.subsprites = ptr, .subspriteCount = (sizeof ptr) / (sizeof(struct Subsprite))} EWRAM_DATA s32 gFieldEffectArguments[8] = {0}; +EWRAM_DATA bool8 gSkipShowMonAnim = FALSE; // Static type declarations @@ -3231,7 +3234,8 @@ static void FlyOutFieldEffect_ShowMon(struct Task *task) { task->tState++; gFieldEffectArguments[0] = task->tMonId; - FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); + if (!gSkipShowMonAnim) + FieldEffectStart(FLDEFF_FIELD_MOVE_SHOW_MON_INIT); } } @@ -3480,6 +3484,7 @@ static void StartFlyBirdReturnToBall(u8 spriteId) u8 FldEff_FlyIn(void) { CreateTask(Task_FlyIn, 254); + gSkipShowMonAnim = FALSE; // Clears this variable so flying via the party menu keeps the show mon animation return 0; } diff --git a/src/field_region_map.c b/src/field_region_map.c index 73fc14582b..966d2d1327 100644 --- a/src/field_region_map.c +++ b/src/field_region_map.c @@ -1,17 +1,22 @@ #include "global.h" #include "bg.h" +#include "event_data.h" +#include "field_effect.h" #include "gpu_regs.h" #include "international_string_util.h" #include "main.h" #include "malloc.h" #include "menu.h" +#include "overworld.h" #include "palette.h" #include "region_map.h" +#include "sound.h" #include "strings.h" #include "text.h" #include "text_window.h" #include "window.h" #include "constants/rgb.h" +#include "constants/songs.h" /* * This is the type of map shown when interacting with the metatiles for @@ -44,7 +49,8 @@ static void MCB2_InitRegionMapRegisters(void); static void VBCB_FieldUpdateRegionMap(void); static void MCB2_FieldUpdateRegionMap(void); static void FieldUpdateRegionMap(void); -static void PrintRegionMapSecName(void); +static void PrintRegionMapSecName(); +static void PrintTitleWindowText(); static const struct BgTemplate sFieldRegionMapBgTemplates[] = { { @@ -139,8 +145,6 @@ static void MCB2_FieldUpdateRegionMap(void) static void FieldUpdateRegionMap(void) { - u8 offset; - switch (sFieldRegionMapHandler->state) { case 0: @@ -151,8 +155,8 @@ static void FieldUpdateRegionMap(void) break; case 1: DrawStdFrameWithCustomTileAndPalette(WIN_TITLE, FALSE, 0x27, 0xd); - offset = GetStringCenterAlignXOffset(FONT_NORMAL, gText_Hoenn, 0x38); - AddTextPrinterParameterized(WIN_TITLE, FONT_NORMAL, gText_Hoenn, offset, 1, 0, NULL); + FillWindowPixelBuffer(WIN_TITLE, PIXEL_FILL(1)); + PrintTitleWindowText(); ScheduleBgCopyTilemapToVram(0); DrawStdFrameWithCustomTileAndPalette(WIN_MAPSEC_NAME, FALSE, 0x27, 0xd); PrintRegionMapSecName(); @@ -176,11 +180,21 @@ static void FieldUpdateRegionMap(void) { case MAP_INPUT_MOVE_END: PrintRegionMapSecName(); + PrintTitleWindowText(); break; case MAP_INPUT_A_BUTTON: case MAP_INPUT_B_BUTTON: sFieldRegionMapHandler->state++; break; + case MAP_INPUT_R_BUTTON: + if (sFieldRegionMapHandler->regionMap.mapSecType == MAPSECTYPE_CITY_CANFLY + && FlagGet(OW_FLAG_POKE_RIDER) && Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE) + { + PlaySE(SE_SELECT); + SetFlyDestination(&sFieldRegionMapHandler->regionMap); + gSkipShowMonAnim = TRUE; + ReturnToFieldFromFlyMapSelect(); + } } break; case 5: @@ -213,3 +227,24 @@ static void PrintRegionMapSecName(void) CopyWindowToVram(WIN_MAPSEC_NAME, COPYWIN_FULL); } } + +static void PrintTitleWindowText(void) +{ + static const u8 FlyPromptText[] = _("{R_BUTTON} FLY"); + u32 hoennOffset = GetStringCenterAlignXOffset(FONT_NORMAL, gText_Hoenn, 0x38); + u32 flyOffset = GetStringCenterAlignXOffset(FONT_NORMAL, FlyPromptText, 0x38); + + FillWindowPixelBuffer(WIN_TITLE, PIXEL_FILL(1)); + + if (sFieldRegionMapHandler->regionMap.mapSecType == MAPSECTYPE_CITY_CANFLY + && FlagGet(OW_FLAG_POKE_RIDER) && Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE) + { + AddTextPrinterParameterized(WIN_TITLE, FONT_NORMAL, FlyPromptText, flyOffset, 1, 0, NULL); + ScheduleBgCopyTilemapToVram(WIN_TITLE); + } + else + { + AddTextPrinterParameterized(WIN_TITLE, FONT_NORMAL, gText_Hoenn, hoennOffset, 1, 0, NULL); + CopyWindowToVram(WIN_TITLE, COPYWIN_FULL); + } +} diff --git a/src/pokenav_main_menu.c b/src/pokenav_main_menu.c index dfd656833d..4c4777e5d5 100644 --- a/src/pokenav_main_menu.c +++ b/src/pokenav_main_menu.c @@ -86,18 +86,20 @@ static const struct WindowTemplate sHelpBarWindowTemplate[] = static const u8 *const sHelpBarTexts[HELPBAR_COUNT] = { - [HELPBAR_NONE] = COMPOUND_STRING("{CLEAR 0x80}"), - [HELPBAR_MAP_ZOOMED_OUT] = COMPOUND_STRING("{A_BUTTON}ZOOM {B_BUTTON}CANCEL"), - [HELPBAR_MAP_ZOOMED_IN] = COMPOUND_STRING("{A_BUTTON}FULL {B_BUTTON}CANCEL"), - [HELPBAR_CONDITION_MON_LIST] = COMPOUND_STRING("{A_BUTTON}CONDITION {B_BUTTON}CANCEL"), - [HELPBAR_CONDITION_MON_STATUS] = COMPOUND_STRING("{A_BUTTON}MARKINGS {B_BUTTON}CANCEL"), - [HELPBAR_CONDITION_MARKINGS] = COMPOUND_STRING("{A_BUTTON}SELECT MARK {B_BUTTON}CANCEL"), - [HELPBAR_MC_TRAINER_LIST] = COMPOUND_STRING("{A_BUTTON}MENU {B_BUTTON}CANCEL"), - [HELPBAR_MC_CALL_MENU] = COMPOUND_STRING("{A_BUTTON}OK {B_BUTTON}CANCEL"), - [HELPBAR_MC_CHECK_PAGE] = COMPOUND_STRING("{B_BUTTON}CANCEL"), - [HELPBAR_RIBBONS_MON_LIST] = COMPOUND_STRING("{A_BUTTON}RIBBONS {B_BUTTON}CANCEL"), - [HELPBAR_RIBBONS_LIST] = COMPOUND_STRING("{A_BUTTON}CHECK {B_BUTTON}CANCEL"), - [HELPBAR_RIBBONS_CHECK] = COMPOUND_STRING("{B_BUTTON}CANCEL"), + [HELPBAR_NONE] = COMPOUND_STRING("{CLEAR 0x80}"), + [HELPBAR_MAP_ZOOMED_OUT] = COMPOUND_STRING("{A_BUTTON}ZOOM {B_BUTTON}CANCEL"), + [HELPBAR_MAP_ZOOMED_IN] = COMPOUND_STRING("{A_BUTTON}FULL {B_BUTTON}CANCEL"), + [HELPBAR_MAP_ZOOMED_OUT_CANFLY] = COMPOUND_STRING("{A_BUTTON}ZOOM {B_BUTTON}CANCEL {R_BUTTON}FLY"), + [HELPBAR_MAP_ZOOMED_IN_CANFLY] = COMPOUND_STRING("{A_BUTTON}FULL {B_BUTTON}CANCEL {R_BUTTON}FLY"), + [HELPBAR_CONDITION_MON_LIST] = COMPOUND_STRING("{A_BUTTON}CONDITION {B_BUTTON}CANCEL"), + [HELPBAR_CONDITION_MON_STATUS] = COMPOUND_STRING("{A_BUTTON}MARKINGS {B_BUTTON}CANCEL"), + [HELPBAR_CONDITION_MARKINGS] = COMPOUND_STRING("{A_BUTTON}SELECT MARK {B_BUTTON}CANCEL"), + [HELPBAR_MC_TRAINER_LIST] = COMPOUND_STRING("{A_BUTTON}MENU {B_BUTTON}CANCEL"), + [HELPBAR_MC_CALL_MENU] = COMPOUND_STRING("{A_BUTTON}OK {B_BUTTON}CANCEL"), + [HELPBAR_MC_CHECK_PAGE] = COMPOUND_STRING("{B_BUTTON}CANCEL"), + [HELPBAR_RIBBONS_MON_LIST] = COMPOUND_STRING("{A_BUTTON}RIBBONS {B_BUTTON}CANCEL"), + [HELPBAR_RIBBONS_LIST] = COMPOUND_STRING("{A_BUTTON}CHECK {B_BUTTON}CANCEL"), + [HELPBAR_RIBBONS_CHECK] = COMPOUND_STRING("{B_BUTTON}CANCEL"), }; static const u8 sHelpBarTextColors[3] = diff --git a/src/pokenav_region_map.c b/src/pokenav_region_map.c index f81ff42966..b17689aad8 100755 --- a/src/pokenav_region_map.c +++ b/src/pokenav_region_map.c @@ -2,8 +2,11 @@ #include "bg.h" #include "decompress.h" #include "landmark.h" +#include "event_data.h" +#include "field_effect.h" #include "main.h" #include "menu.h" +#include "overworld.h" #include "palette.h" #include "pokenav.h" #include "region_map.h" @@ -73,6 +76,7 @@ static u32 LoopedTask_UpdateInfoAfterCursorMove(s32); static u32 LoopedTask_RegionMapZoomOut(s32); static u32 LoopedTask_RegionMapZoomIn(s32); static u32 LoopedTask_ExitRegionMap(s32); +static u32 LoopedTask_TreatAsPokeNavFlyMap(s32); extern const u16 gRegionMapCityZoomTiles_Pal[]; extern const u32 gRegionMapCityZoomText_Gfx[]; @@ -119,7 +123,8 @@ static const LoopedTask sRegionMapLoopTaskFuncs[] = [POKENAV_MAP_FUNC_CURSOR_MOVED] = LoopedTask_UpdateInfoAfterCursorMove, [POKENAV_MAP_FUNC_ZOOM_OUT] = LoopedTask_RegionMapZoomOut, [POKENAV_MAP_FUNC_ZOOM_IN] = LoopedTask_RegionMapZoomIn, - [POKENAV_MAP_FUNC_EXIT] = LoopedTask_ExitRegionMap + [POKENAV_MAP_FUNC_EXIT] = LoopedTask_ExitRegionMap, + [POKENAV_MAP_FUNC_FLY] = LoopedTask_TreatAsPokeNavFlyMap, }; static const struct CompressedSpriteSheet sCityZoomTextSpriteSheet[1] = @@ -204,6 +209,8 @@ u32 GetRegionMapCallback(void) static u32 HandleRegionMapInput(struct Pokenav_RegionMapMenu *state) { + struct RegionMap* regionMap = GetSubstructPtr(POKENAV_SUBSTRUCT_REGION_MAP); + switch (DoRegionMapInputCallback()) { case MAP_INPUT_MOVE_END: @@ -215,6 +222,10 @@ static u32 HandleRegionMapInput(struct Pokenav_RegionMapMenu *state) case MAP_INPUT_B_BUTTON: state->callback = GetExitRegionMapMenuId; return POKENAV_MAP_FUNC_EXIT; + case MAP_INPUT_R_BUTTON: + if (regionMap->mapSecType == MAPSECTYPE_CITY_CANFLY && FlagGet(OW_FLAG_POKE_RIDER) + && Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE) + return POKENAV_MAP_FUNC_FLY; } return POKENAV_MAP_FUNC_NONE; @@ -365,6 +376,7 @@ static u32 LoopedTask_OpenRegionMap(s32 taskState) else menuGfxId = POKENAV_GFX_MAP_MENU_ZOOMED_IN; + UpdateRegionMapHelpBarText(); LoadLeftHeaderGfxForIndex(menuGfxId); ShowLeftHeaderGfx(menuGfxId, TRUE, TRUE); PokenavFadeScreen(POKENAV_FADE_FROM_BLACK); @@ -385,6 +397,7 @@ static u32 LoopedTask_UpdateInfoAfterCursorMove(s32 taskState) { case 0: UpdateMapSecInfoWindow(state); + UpdateRegionMapHelpBarText(); return LT_INC_AND_PAUSE; case 1: if (IsDma3ManagerBusyWithBgCopy_(state)) @@ -408,7 +421,7 @@ static u32 LoopedTask_RegionMapZoomOut(s32 taskState) if (UpdateRegionMapZoom() || IsChangeBgYForZoomActive()) return LT_PAUSE; - PrintHelpBarText(HELPBAR_MAP_ZOOMED_OUT); + UpdateRegionMapHelpBarText(); return LT_INC_AND_PAUSE; case 2: if (WaitForHelpBar()) @@ -441,7 +454,7 @@ static u32 LoopedTask_RegionMapZoomIn(s32 taskState) if (UpdateRegionMapZoom() || IsChangeBgYForZoomActive()) return LT_PAUSE; - PrintHelpBarText(HELPBAR_MAP_ZOOMED_IN); + UpdateRegionMapHelpBarText(); return LT_INC_AND_PAUSE; case 3: if (WaitForHelpBar()) @@ -482,6 +495,23 @@ static u32 LoopedTask_ExitRegionMap(s32 taskState) return LT_FINISH; } +static u32 LoopedTask_TreatAsPokeNavFlyMap(s32 taskState) +{ + switch (taskState) + { + case 0: + PlaySE(SE_SELECT); + struct RegionMap* regionMap = GetSubstructPtr(POKENAV_SUBSTRUCT_REGION_MAP); + SetFlyDestination(regionMap); + gSkipShowMonAnim = TRUE; + ReturnToFieldFromFlyMapSelect(); + + return LT_FINISH; + } + + return LT_FINISH; +} + static void LoadCityZoomViewGfx(void) { int i; @@ -740,3 +770,24 @@ static void SetCityZoomTextInvisibility(bool32 invisible) for (i = 0; i < (int)ARRAY_COUNT(state->cityZoomTextSprites); i++) state->cityZoomTextSprites[i]->invisible = invisible; } + +void UpdateRegionMapHelpBarText(void) +{ + struct RegionMap* regionMap = GetSubstructPtr(POKENAV_SUBSTRUCT_REGION_MAP); + + if (regionMap->mapSecType == MAPSECTYPE_CITY_CANFLY && FlagGet(OW_FLAG_POKE_RIDER) + && Overworld_MapTypeAllowsTeleportAndFly(gMapHeader.mapType) == TRUE) + { + if (IsRegionMapZoomed()) + PrintHelpBarText(HELPBAR_MAP_ZOOMED_IN_CANFLY); + else + PrintHelpBarText(HELPBAR_MAP_ZOOMED_OUT_CANFLY); + } + else + { + if (IsRegionMapZoomed()) + PrintHelpBarText(HELPBAR_MAP_ZOOMED_IN); + else + PrintHelpBarText(HELPBAR_MAP_ZOOMED_OUT); + } +} diff --git a/src/region_map.c b/src/region_map.c index 92771c8220..aba1162f5b 100644 --- a/src/region_map.c +++ b/src/region_map.c @@ -680,6 +680,10 @@ static u8 ProcessRegionMapInput_Full(void) { input = MAP_INPUT_B_BUTTON; } + else if (JOY_NEW(R_BUTTON)) + { + input = MAP_INPUT_R_BUTTON; + } if (input == MAP_INPUT_MOVE_START) { sRegionMap->cursorMovementFrameCounter = 4; @@ -759,6 +763,10 @@ static u8 ProcessRegionMapInput_Zoomed(void) { input = MAP_INPUT_B_BUTTON; } + else if (JOY_NEW(R_BUTTON)) + { + input = MAP_INPUT_R_BUTTON; + } if (input == MAP_INPUT_MOVE_START) { sRegionMap->inputCallback = MoveRegionMapCursor_Zoomed; @@ -1992,27 +2000,9 @@ static void CB_ExitFlyMap(void) FreeRegionMapIconResources(); if (sFlyMap->choseFlyLocation) { - switch (sFlyMap->regionMap.mapSecId) - { - case MAPSEC_SOUTHERN_ISLAND: - SetWarpDestinationToHealLocation(HEAL_LOCATION_SOUTHERN_ISLAND_EXTERIOR); - break; - case MAPSEC_BATTLE_FRONTIER: - SetWarpDestinationToHealLocation(HEAL_LOCATION_BATTLE_FRONTIER_OUTSIDE_EAST); - break; - case MAPSEC_LITTLEROOT_TOWN: - SetWarpDestinationToHealLocation(gSaveBlock2Ptr->playerGender == MALE ? HEAL_LOCATION_LITTLEROOT_TOWN_BRENDANS_HOUSE : HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE); - break; - case MAPSEC_EVER_GRANDE_CITY: - SetWarpDestinationToHealLocation(FlagGet(FLAG_LANDMARK_POKEMON_LEAGUE) && sFlyMap->regionMap.posWithinMapSec == 0 ? HEAL_LOCATION_EVER_GRANDE_CITY_POKEMON_LEAGUE : HEAL_LOCATION_EVER_GRANDE_CITY); - break; - default: - if (sMapHealLocations[sFlyMap->regionMap.mapSecId][2] != HEAL_LOCATION_NONE) - SetWarpDestinationToHealLocation(sMapHealLocations[sFlyMap->regionMap.mapSecId][2]); - else - SetWarpDestinationToMapWarp(sMapHealLocations[sFlyMap->regionMap.mapSecId][0], sMapHealLocations[sFlyMap->regionMap.mapSecId][1], WARP_ID_NONE); - break; - } + struct RegionMap* tempRegionMap = &sFlyMap->regionMap; + + SetFlyDestination(tempRegionMap); ReturnToFieldFromFlyMapSelect(); } else @@ -2025,3 +2015,33 @@ static void CB_ExitFlyMap(void) break; } } + +u32 FilterFlyDestination(struct RegionMap* regionMap) +{ + switch (regionMap->mapSecId) + { + case MAPSEC_SOUTHERN_ISLAND: + return HEAL_LOCATION_SOUTHERN_ISLAND_EXTERIOR; + case MAPSEC_BATTLE_FRONTIER: + return HEAL_LOCATION_BATTLE_FRONTIER_OUTSIDE_EAST; + case MAPSEC_LITTLEROOT_TOWN: + return (gSaveBlock2Ptr->playerGender == MALE ? HEAL_LOCATION_LITTLEROOT_TOWN_BRENDANS_HOUSE : HEAL_LOCATION_LITTLEROOT_TOWN_MAYS_HOUSE); + case MAPSEC_EVER_GRANDE_CITY: + return (FlagGet(FLAG_LANDMARK_POKEMON_LEAGUE) && regionMap->posWithinMapSec == 0 ? HEAL_LOCATION_EVER_GRANDE_CITY_POKEMON_LEAGUE : HEAL_LOCATION_EVER_GRANDE_CITY); + default: + if (sMapHealLocations[regionMap->mapSecId][2] != HEAL_LOCATION_NONE) + return sMapHealLocations[regionMap->mapSecId][2]; + else + return WARP_ID_NONE; + } +} + +void SetFlyDestination(struct RegionMap* regionMap) +{ + u32 flyDestination = FilterFlyDestination(regionMap); + + if (flyDestination != WARP_ID_NONE) + SetWarpDestinationToHealLocation(flyDestination); + else + SetWarpDestinationToMapWarp(sMapHealLocations[regionMap->mapSecId][0], sMapHealLocations[regionMap->mapSecId][1], WARP_ID_NONE); +} From c6d92eaf8064a434717c4d29e5960695b627359e Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 5 Jan 2025 11:32:48 -0300 Subject: [PATCH 24/85] Removed references to HANDLE_EXPANDED_MOVE_NAME in docs (#5955) --- docs/tutorials/how_to_new_move.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/docs/tutorials/how_to_new_move.md b/docs/tutorials/how_to_new_move.md index 9ddc09b904..e3a2eb0a12 100644 --- a/docs/tutorials/how_to_new_move.md +++ b/docs/tutorials/how_to_new_move.md @@ -28,7 +28,7 @@ Let's look at an example: ```c [MOVE_THUNDER_SHOCK] = { - .name = HANDLE_EXPANDED_MOVE_NAME("ThunderShock", "Thunder Shock"), + .name = COMPOUND_STRING("Thunder Shock"), .description = COMPOUND_STRING( "An electrical attack that\n" "may paralyze the foe."), @@ -51,7 +51,7 @@ Let's look at an example: .contestComboMoves = {COMBO_STARTER_CHARGE}, }, ``` -The `HANDLE_EXPANDED_MOVE_NAME` allows the usage of a name of extended character length, so long as the `B_EXPANDED_MOVE_NAMES` is set to `TRUE`, whereas by default it's limited in Gen 3 to 12 characters. Most of the fields here are obvious, but the two important ones for determining what a move actually *does* are `effect` and `additionalEffects`. +Most of the fields here are obvious, but the two important ones for determining what a move actually *does* are `effect` and `additionalEffects`. The `effect` represents how the move actually works when called in battle - it can be a two turn move, or a move that only works if the target is holding an item, for example. How each effect works is pretty much unique, but the way a move of a particular effect is executed is defined by a script [`data/battle_scripts_1.s`](#databattle_scripts_1s), and any *variable* characteristics such as typing or power are defined in either [`src/battle_script_commands.c`](#srcbattle_script_commandsc) or [`src/battle_util.c`](#srcbattle_utilc), depending on the effect. The vast majority of non-status moves are simply `EFFECT_HIT`, in that they deal damage and apply `additionalEffects` (if defined). From cbd0b3ef0cf134d6fa0495cd4e589257e136bea3 Mon Sep 17 00:00:00 2001 From: shachar700 <48739719+shachar700@users.noreply.github.com> Date: Sun, 5 Jan 2025 17:45:21 +0200 Subject: [PATCH 25/85] Field effect for cutting grass is missing setfieldeffectargument. Issue #5766 (#5952) --- data/scripts/field_move_scripts.inc | 12 ++++++++++++ include/event_scripts.h | 1 + src/fldeff_cut.c | 2 +- 3 files changed, 14 insertions(+), 1 deletion(-) diff --git a/data/scripts/field_move_scripts.inc b/data/scripts/field_move_scripts.inc index 0a7660b4ce..f1bd3618e1 100644 --- a/data/scripts/field_move_scripts.inc +++ b/data/scripts/field_move_scripts.inc @@ -385,6 +385,18 @@ EventScript_UseDig:: lockall goto EventScript_DigCommon + +EventScript_CutGrassCommon: + isfollowerfieldmoveuser VAR_0x8004 + setfieldeffectargument 3, VAR_0x8004 @ skip pose if true + dofieldeffect FLDEFF_USE_CUT_ON_GRASS + waitstate + +@ Use Cut grass from party menu +EventScript_UseCutGrass:: + lockall + goto EventScript_CutGrassCommon + Text_CantDive: .string "The sea is deep here. A POKéMON\n" .string "may be able to go underwater.$" diff --git a/include/event_scripts.h b/include/event_scripts.h index 60a8d6123e..04bcf32760 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -405,6 +405,7 @@ extern const u8 EventScript_UseFlash[]; extern const u8 EventScript_UseCut[]; extern const u8 EventScript_UseRockSmash[]; extern const u8 EventScript_UseDig[]; +extern const u8 EventScript_UseCutGrass[]; //player pc extern const u8 LittlerootTown_BrendansHouse_2F_EventScript_TurnOffPlayerPC[]; diff --git a/src/fldeff_cut.c b/src/fldeff_cut.c index 2304381673..a7eccf651c 100644 --- a/src/fldeff_cut.c +++ b/src/fldeff_cut.c @@ -277,8 +277,8 @@ bool8 SetUpFieldMove_Cut(void) static void FieldCallback_CutGrass(void) { - FieldEffectStart(FLDEFF_USE_CUT_ON_GRASS); gFieldEffectArguments[0] = GetCursorSelectionMonId(); + ScriptContext_SetupScript(EventScript_UseCutGrass); } bool8 FldEff_UseCutOnGrass(void) From 40ba25dd3ef2a437f7a8cfdc25230952ce40b606 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 5 Jan 2025 13:47:49 -0300 Subject: [PATCH 26/85] Converted 2 various to callnative (#5950) --- asm/macros/battle_script.inc | 4 +- include/constants/battle_script_commands.h | 2 - src/battle_script_commands.c | 76 +++++++++++----------- src/data/moves_info.h | 2 +- test/battle/move_effect/court_change.c | 66 ++++++++++++++++++- test/battle/move_effect/speed_swap.c | 58 +++++++++++++++++ 6 files changed, 162 insertions(+), 46 deletions(-) create mode 100644 test/battle/move_effect/speed_swap.c diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 80e9b36789..730b184449 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -2337,11 +2337,11 @@ .endm .macro swapsidestatuses - various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES + callnative BS_CourtChangeSwapSideStatuses .endm .macro swapstats stat:req - various BS_ATTACKER, VARIOUS_SWAP_STATS + callnative BS_SwapStats .byte \stat .endm diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index bd1c61ec09..808ee406d2 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -216,8 +216,6 @@ enum CmdVarious VARIOUS_SAVE_BATTLER_ITEM, VARIOUS_RESTORE_BATTLER_ITEM, VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM, - VARIOUS_SWAP_SIDE_STATUSES, - VARIOUS_SWAP_STATS, }; // Cmd_manipulatedamage diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 4fc74022c7..b08b53a044 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9404,8 +9404,10 @@ static bool32 IsTeatimeAffected(u32 battler) sideTimerOpp->structField = BATTLE_OPPOSITE(temp); \ } \ -static void CourtChangeSwapSideStatuses(void) +void BS_CourtChangeSwapSideStatuses(void) { + NATIVE_ARGS(); + struct SideTimer *sideTimerPlayer = &gSideTimers[B_SIDE_PLAYER]; struct SideTimer *sideTimerOpp = &gSideTimers[B_SIDE_OPPONENT]; u32 temp; @@ -9446,6 +9448,8 @@ static void CourtChangeSwapSideStatuses(void) // Swap what type set the Gigantamax damage over time effect SWAP(sideTimerPlayer->damageNonTypesType, sideTimerOpp->damageNonTypesType, temp); + + gBattlescriptCurrInstr = cmd->nextInstr; } static void HandleScriptMegaPrimalBurst(u32 caseId, u32 battler, u32 type) @@ -11317,44 +11321,6 @@ static void Cmd_various(void) gBattleMons[battler].item = gLastUsedItem; break; } - case VARIOUS_SWAP_SIDE_STATUSES: - { - VARIOUS_ARGS(); - CourtChangeSwapSideStatuses(); - break; - } - case VARIOUS_SWAP_STATS: - { - VARIOUS_ARGS(u8 stat); - - u8 stat = cmd->stat; - u16 temp; - - switch (stat) - { - case STAT_HP: - SWAP(gBattleMons[gBattlerAttacker].hp, gBattleMons[gBattlerTarget].hp, temp); - break; - case STAT_ATK: - SWAP(gBattleMons[gBattlerAttacker].attack, gBattleMons[gBattlerTarget].attack, temp); - break; - case STAT_DEF: - SWAP(gBattleMons[gBattlerAttacker].defense, gBattleMons[gBattlerTarget].defense, temp); - break; - case STAT_SPEED: - SWAP(gBattleMons[gBattlerAttacker].speed, gBattleMons[gBattlerTarget].speed, temp); - break; - case STAT_SPATK: - SWAP(gBattleMons[gBattlerAttacker].spAttack, gBattleMons[gBattlerTarget].spAttack, temp); - break; - case STAT_SPDEF: - SWAP(gBattleMons[gBattlerAttacker].spDefense, gBattleMons[gBattlerTarget].spDefense, temp); - break; - } - PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); - gBattlescriptCurrInstr = cmd->nextInstr; - return; - } } // End of switch (cmd->id) gBattlescriptCurrInstr = cmd->nextInstr; @@ -18025,3 +17991,35 @@ void BS_JumpIfCriticalHit(void) else gBattlescriptCurrInstr = cmd->nextInstr; } + +void BS_SwapStats(void) +{ + NATIVE_ARGS(u8 stat); + + u32 stat = cmd->stat; + u32 temp; + + switch (stat) + { + case STAT_HP: + SWAP(gBattleMons[gBattlerAttacker].hp, gBattleMons[gBattlerTarget].hp, temp); + break; + case STAT_ATK: + SWAP(gBattleMons[gBattlerAttacker].attack, gBattleMons[gBattlerTarget].attack, temp); + break; + case STAT_DEF: + SWAP(gBattleMons[gBattlerAttacker].defense, gBattleMons[gBattlerTarget].defense, temp); + break; + case STAT_SPEED: + SWAP(gBattleMons[gBattlerAttacker].speed, gBattleMons[gBattlerTarget].speed, temp); + break; + case STAT_SPATK: + SWAP(gBattleMons[gBattlerAttacker].spAttack, gBattleMons[gBattlerTarget].spAttack, temp); + break; + case STAT_SPDEF: + SWAP(gBattleMons[gBattlerAttacker].spDefense, gBattleMons[gBattlerTarget].spDefense, temp); + break; + } + PREPARE_STAT_BUFFER(gBattleTextBuff1, stat); + gBattlescriptCurrInstr = cmd->nextInstr; +} diff --git a/src/data/moves_info.h b/src/data/moves_info.h index 2c28621286..ec9e209dda 100644 --- a/src/data/moves_info.h +++ b/src/data/moves_info.h @@ -21567,7 +21567,7 @@ const struct MoveInfo gMovesInfo[MOVES_COUNT_DYNAMAX] = [MOVE_G_MAX_CANNONADE] = { - .name = COMPOUND_STRING("G-Max Canonade"), + .name = COMPOUND_STRING("G-Max Cannonade"), .description = sNullDescription, //ANIM TODO .effect = EFFECT_MAX_MOVE, .power = 10, diff --git a/test/battle/move_effect/court_change.c b/test/battle/move_effect/court_change.c index 0727baff5e..817ab134ca 100644 --- a/test/battle/move_effect/court_change.c +++ b/test/battle/move_effect/court_change.c @@ -106,7 +106,7 @@ DOUBLE_BATTLE_TEST("Court Change used by the player swaps Mist, Safeguard, Auror MESSAGE("The opposing Wobbuffet used Tailwind!"); MESSAGE("Wynaut used Court Change!"); MESSAGE("Wynaut swapped the battle effects affecting each side of the field!"); - // The effects now end for the player side. + // The effects now end for the player side. MESSAGE("Your team's Mist wore off!"); MESSAGE("Your team is no longer protected by Safeguard!"); MESSAGE("Your team's Reflect wore off!"); @@ -153,4 +153,66 @@ DOUBLE_BATTLE_TEST("Court Change used by the opponent swaps Mist, Safeguard, Aur } } -TO_DO_BATTLE_TEST("Court Change used by the player swaps G-Max Steelsurge, G-Max Vine Lash, G-Max Wildfire, G-Max Cannonade"); +DOUBLE_BATTLE_TEST("Court Change used by the player swaps G-Max Steelsurge") +{ + GIVEN { + PLAYER(SPECIES_COPPERAJAH) { GigantamaxFactor(TRUE); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerLeft, MOVE_IRON_HEAD, target: opponentRight, gimmick: GIMMICK_DYNAMAX); } + TURN { MOVE(opponentLeft, MOVE_COURT_CHANGE); } + TURN { SWITCH(opponentLeft, 2); SWITCH(playerLeft, 2); } + } SCENE { + MESSAGE("Copperajah used G-Max Steelsurge!"); + SEND_IN_MESSAGE("Wobbuffet"); + MESSAGE("The sharp steel bit into Wobbuffet!"); + NONE_OF { + MESSAGE("The sharp steel bit into the opposing Wynaut!"); + } + } +} + +DOUBLE_BATTLE_TEST("Court Change used by the player swaps G-Max Vine Lash, G-Max Wildfire, G-Max Cannonade") +{ + u32 species, move; + PARAMETRIZE { species = SPECIES_VENUSAUR; move = MOVE_VINE_WHIP; } + PARAMETRIZE { species = SPECIES_CHARIZARD; move = MOVE_EMBER; } + PARAMETRIZE { species = SPECIES_BLASTOISE; move = MOVE_WATER_GUN; } + GIVEN { + PLAYER(species) { GigantamaxFactor(TRUE); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { + MOVE(playerLeft, move, target: opponentRight, gimmick: GIMMICK_DYNAMAX); + MOVE(opponentLeft, MOVE_COURT_CHANGE); + } + } SCENE { + switch (species) { + case SPECIES_VENUSAUR: + MESSAGE("Venusaur used G-Max Vine Lash!"); + MESSAGE("Wobbuffet is hurt by G-Max Vine Lash's ferocious beating!"); + break; + case SPECIES_CHARIZARD: + MESSAGE("Charizard used G-Max Wildfire!"); + MESSAGE("Wobbuffet is burning up within G-Max Wildfire's flames!"); + break; + case SPECIES_BLASTOISE: + MESSAGE("Blastoise used G-Max Cannonade!"); + MESSAGE("Wobbuffet is hurt by G-Max Cannonade's vortex!"); + break; + } + NONE_OF { + MESSAGE("The opposing Wynaut is hurt by G-Max Vine Lash's ferocious beating!"); + MESSAGE("The opposing Wynaut is burning up within G-Max Wildfire's flames!"); + MESSAGE("The opposing Wynaut is hurt by G-Max Cannonade's vortex!"); + } + } +} diff --git a/test/battle/move_effect/speed_swap.c b/test/battle/move_effect/speed_swap.c new file mode 100644 index 0000000000..0a87b26236 --- /dev/null +++ b/test/battle/move_effect/speed_swap.c @@ -0,0 +1,58 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(GetMoveEffect(MOVE_SPEED_SWAP) == EFFECT_SPEED_SWAP); +} + +SINGLE_BATTLE_TEST("Speed Swap swaps user and target's speed stats") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(6); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(10); } + }WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_SPEED_SWAP); } + TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_TACKLE); } + } SCENE { + // Turn 1 + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPEED_SWAP, player); + // Turn 2 + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + } THEN { + EXPECT_EQ(player->speed, 10); + EXPECT_EQ(opponent->speed, 6); + } +} + +SINGLE_BATTLE_TEST("Speed Swap doesn't swap user and target's speed modifiers") +{ + u32 species, ability, move; + PARAMETRIZE { species = SPECIES_WOBBUFFET; ability = ABILITY_TELEPATHY; move = MOVE_ROCK_POLISH; } // x2.0 + PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_SWIFT_SWIM; move = MOVE_RAIN_DANCE; } // x2.0 + GIVEN { + ASSUME(GetMoveEffect(MOVE_ROCK_POLISH) == EFFECT_SPEED_UP_2); + ASSUME(GetMoveEffect(MOVE_RAIN_DANCE) == EFFECT_RAIN_DANCE); + PLAYER(SPECIES_WOBBUFFET) { Speed(8); } + OPPONENT(species) { Speed(10); Ability(ability); } + }WHEN { + TURN { MOVE(opponent, move); MOVE(player, MOVE_SPEED_SWAP); } + TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_TACKLE); } + } SCENE { + // Turn 1 + ANIMATION(ANIM_TYPE_MOVE, move, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPEED_SWAP, player); + // Turn 2 + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); // Opponent is still first + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + } THEN { + EXPECT_EQ(player->speed, 10); + EXPECT_EQ(opponent->speed, 8); + if (move == MOVE_ROCK_POLISH) { + EXPECT_EQ(player->statStages[STAT_SPEED], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPEED], DEFAULT_STAT_STAGE + 2); + } + } +} From 5317371fea83dad230527d8b6a86c654bd32e95f Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:03:41 +0100 Subject: [PATCH 27/85] Last fix for Sparkling Aria / Covert Cloak / Shield Dust interaction (#5956) --- include/battle_util.h | 1 + src/battle_script_commands.c | 2 +- src/battle_util.c | 17 +++++++++++++++++ test/battle/ability/shield_dust.c | 1 - test/battle/hold_effect/covert_cloak.c | 25 +++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 2 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 1d316667e0..5ab3c3495b 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -338,5 +338,6 @@ bool32 IsSleepClauseEnabled(); void ClearDamageCalcResults(void); u32 DoesDestinyBondFail(u32 battler); bool32 IsMoveEffectBlockedByTarget(u32 ability); +u32 NumAffectedSpreadMoveTargets(void); #endif // GUARD_BATTLE_UTIL_H diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b08b53a044..1c5c7bbc17 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6275,7 +6275,7 @@ static void Cmd_moveend(void) if ((gBattleMons[gBattlerTarget].status1 & argStatus) && IsBattlerAlive(gBattlerTarget) && !DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove) - && (gBattleStruct->numSpreadTargets > 1 || !IsMoveEffectBlockedByTarget(GetBattlerAbility(gBattlerTarget)))) + && (NumAffectedSpreadMoveTargets() > 1 || !IsMoveEffectBlockedByTarget(GetBattlerAbility(gBattlerTarget)))) { gBattleMons[gBattlerTarget].status1 &= ~(argStatus); diff --git a/src/battle_util.c b/src/battle_util.c index 19551f8854..a6429d935b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -12224,3 +12224,20 @@ bool32 IsMoveEffectBlockedByTarget(u32 ability) return FALSE; } + +u32 NumAffectedSpreadMoveTargets(void) +{ + u32 targetCount = 1; + + if (!IsDoubleSpreadMove()) + return targetCount; + + targetCount = 0; + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (MoveResultHasEffect(battler)) + targetCount++; + } + + return targetCount; +} diff --git a/test/battle/ability/shield_dust.c b/test/battle/ability/shield_dust.c index 5833615027..bb56f84211 100644 --- a/test/battle/ability/shield_dust.c +++ b/test/battle/ability/shield_dust.c @@ -149,7 +149,6 @@ DOUBLE_BATTLE_TEST("Shield Dust does or does not block Sparkling Aria depending DOUBLE_BATTLE_TEST("Shield Dust blocks Sparkling Aria if all other targets avoid getting hit by") { - KNOWN_FAILING; // #4636 GIVEN { PLAYER(SPECIES_PRIMARINA); PLAYER(SPECIES_VIVILLON) { Ability(ABILITY_SHIELD_DUST); Status1(STATUS1_BURN); } diff --git a/test/battle/hold_effect/covert_cloak.c b/test/battle/hold_effect/covert_cloak.c index 150ddcbba3..183033cb71 100644 --- a/test/battle/hold_effect/covert_cloak.c +++ b/test/battle/hold_effect/covert_cloak.c @@ -150,6 +150,31 @@ DOUBLE_BATTLE_TEST("Covert Cloak does or does not block Sparkling Aria depending } } +DOUBLE_BATTLE_TEST("Covert Cloak does block Sparkling Aria when only one mon is hit") +{ + u32 move; + PARAMETRIZE { move = MOVE_PROTECT; } + PARAMETRIZE { move = MOVE_FLY; } + + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET) { Item(ITEM_COVERT_CLOAK); Status1(STATUS1_BURN); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, move, target: playerLeft); + MOVE(playerRight, move, target: opponentRight); + MOVE(playerLeft, MOVE_SPARKLING_ARIA); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SPARKLING_ARIA, playerLeft); + NONE_OF { + MESSAGE("The opposing Wobbuffet's burn was cured!"); + STATUS_ICON(opponentLeft, none: TRUE); + } + } +} + SINGLE_BATTLE_TEST("Covert Cloak blocks Sparkling Aria in singles") { GIVEN { From adb4a1ff48646b553d106df7793956566950294c Mon Sep 17 00:00:00 2001 From: LOuroboros Date: Mon, 6 Jan 2025 08:03:44 -0300 Subject: [PATCH 28/85] Added the Gen. 4+ berries to gBerryCrush_BerryData (#5937) --- src/berry.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/src/berry.c b/src/berry.c index a287073df1..4730799e0c 100644 --- a/src/berry.c +++ b/src/berry.c @@ -1654,6 +1654,24 @@ const struct BerryCrushBerryData gBerryCrush_BerryData[] = { [ITEM_WATMEL_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 250}, [ITEM_DURIN_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 250}, [ITEM_BELUE_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 250}, + [ITEM_CHILAN_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 80, .powder = 70}, + [ITEM_OCCA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 100, .powder = 100}, + [ITEM_PASSHO_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 60, .powder = 30}, + [ITEM_WACAN_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_RINDO_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_YACHE_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_CHOPLE_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_KEBIA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_SHUCA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 20}, + [ITEM_COBA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_PAYAPA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_TANGA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_CHARTI_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_KASIB_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_HABAN_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 50, .powder = 30}, + [ITEM_COLBUR_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 60, .powder = 50}, + [ITEM_BABIRI_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 80, .powder = 50}, + [ITEM_ROSELI_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 60, .powder = 50}, [ITEM_LIECHI_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, [ITEM_GANLON_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, [ITEM_SALAC_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, @@ -1661,6 +1679,13 @@ const struct BerryCrushBerryData gBerryCrush_BerryData[] = { [ITEM_APICOT_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 180, .powder = 500}, [ITEM_LANSAT_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 200, .powder = 750}, [ITEM_STARF_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 200, .powder = 750}, + [ITEM_ENIGMA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 150, .powder = 200}, + [ITEM_MICLE_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 130, .powder = 250}, + [ITEM_CUSTAP_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 200, .powder = 750}, + [ITEM_JABOCA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 130, .powder = 250}, + [ITEM_ROWAP_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 130, .powder = 250}, + [ITEM_KEE_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 500}, + [ITEM_MARANGA_BERRY - FIRST_BERRY_INDEX] = {.difficulty = 160, .powder = 500}, [ITEM_ENIGMA_BERRY_E_READER - FIRST_BERRY_INDEX] = {.difficulty = 150, .powder = 200} }; From bc409b3028bfec46fa62d8fdfd5d0e8921b989d9 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 6 Jan 2025 12:14:13 +0100 Subject: [PATCH 29/85] Battle Weather Refactor oversight (#5960) --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index a6429d935b..8d00cc0f2a 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -4043,7 +4043,7 @@ bool32 TryChangeBattleWeather(u32 battler, u32 battleWeatherId, bool32 viaAbilit gBattleWeather = sBattleWeatherInfo[battleWeatherId].flag; if (gBattleWeather & B_WEATHER_PRIMAL_ANY) gWishFutureKnock.weatherDuration = 0; - if (rock != 0 && GetBattlerHoldEffect(battler, TRUE) == rock) + else if (rock != 0 && GetBattlerHoldEffect(battler, TRUE) == rock) gWishFutureKnock.weatherDuration = 8; else gWishFutureKnock.weatherDuration = 5; From 0294beddf1e30d082316312aa13d1b3d638c4096 Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Mon, 6 Jan 2025 11:23:09 -0600 Subject: [PATCH 30/85] Add manual breaking back to "What will (mon) do?" message (#5908) --- src/battle_controller_player.c | 1 - src/battle_controller_safari.c | 1 - src/battle_message.c | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 00e73735e8..982c9e4f27 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2044,7 +2044,6 @@ static void PlayerHandleChooseAction(u32 battler) ActionSelectionCreateCursorAt(gActionSelectionCursor[battler], 0); PREPARE_MON_NICK_BUFFER(gBattleTextBuff1, battler, gBattlerPartyIndexes[battler]); BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPkmnDo); - BreakStringAutomatic(gDisplayedStringBattle, WindowWidthPx(B_WIN_ACTION_PROMPT), 2, FONT_NORMAL); if (B_SHOW_PARTNER_TARGET && gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && IsBattlerAlive(B_POSITION_PLAYER_RIGHT)) { diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index 932ce47fd9..abb2aba946 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -299,7 +299,6 @@ static void SafariHandleChooseAction(u32 battler) ActionSelectionCreateCursorAt(gActionSelectionCursor[battler], 0); BattleStringExpandPlaceholdersToDisplayedString(gText_WhatWillPkmnDo2); - BreakStringAutomatic(gDisplayedStringBattle, WindowWidthPx(B_WIN_ACTION_PROMPT), 2, FONT_NORMAL); BattlePutTextOnWindow(gDisplayedStringBattle, B_WIN_ACTION_PROMPT); } diff --git a/src/battle_message.c b/src/battle_message.c index 7ad18214e1..32a0c017f3 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -1406,8 +1406,8 @@ const u8 gText_PkmnIsEvolving[] = _("What?\n{STR_VAR_1} is evolving!"); const u8 gText_CongratsPkmnEvolved[] = _("Congratulations! Your {STR_VAR_1}\nevolved into {STR_VAR_2}!{WAIT_SE}\p"); const u8 gText_PkmnStoppedEvolving[] = _("Huh? {STR_VAR_1}\nstopped evolving!\p"); const u8 gText_EllipsisQuestionMark[] = _("……?\p"); -const u8 gText_WhatWillPkmnDo[] = _("What will {B_BUFF1} do?"); -const u8 gText_WhatWillPkmnDo2[] = _("What will {B_PLAYER_NAME} do?"); +const u8 gText_WhatWillPkmnDo[] = _("What will\n{B_BUFF1} do?"); +const u8 gText_WhatWillPkmnDo2[] = _("What will\n{B_PLAYER_NAME} do?"); const u8 gText_WhatWillWallyDo[] = _("What will\nWALLY do?"); const u8 gText_LinkStandby[] = _("{PAUSE 16}Link standby…"); const u8 gText_BattleMenu[] = _("Battle{CLEAR_TO 56}Bag\nPokémon{CLEAR_TO 56}Run"); From 04da838d88b53b8182ef2d7c5dd325f2703a88b2 Mon Sep 17 00:00:00 2001 From: wiz1989 <80073265+wiz1989@users.noreply.github.com> Date: Tue, 7 Jan 2025 14:00:09 +0100 Subject: [PATCH 31/85] Innards Out and Future Sight interaction --- include/battle.h | 1 + include/battle_ai_util.h | 1 + src/battle_ai_util.c | 8 ++++ src/battle_script_commands.c | 6 +++ src/battle_util.c | 24 +++++++++-- test/battle/ability/innards_out.c | 63 ++++++++++++++++++++++++++++ test/battle/hold_effect/shell_bell.c | 35 ++++++++++++++++ 7 files changed, 134 insertions(+), 4 deletions(-) create mode 100644 test/battle/hold_effect/shell_bell.c diff --git a/include/battle.h b/include/battle.h index f0571d747e..27f7be5173 100644 --- a/include/battle.h +++ b/include/battle.h @@ -310,6 +310,7 @@ struct WishFutureKnock u8 wishPartyId[MAX_BATTLERS_COUNT]; u8 weatherDuration; u8 knockedOffMons[NUM_BATTLE_SIDES]; // Each battler is represented by a bit. + u8 futureSightDmg[MAX_BATTLERS_COUNT]; }; struct AI_SavedBattleMon diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index c74cad2e78..b26b608e99 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -137,6 +137,7 @@ bool32 ShouldSetRain(u32 battlerAtk, u32 ability, u32 holdEffect); bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, u32 holdEffect); bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef); bool32 IsHealingMove(u32 move); +bool32 IsForeSeenMove(u32 moveId); bool32 HasHealingEffect(u32 battler); bool32 IsTrappingMove(u32 move); bool32 HasTrappingMoveEffect(u32 battler); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index b68112374d..3e841a3d69 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2188,6 +2188,14 @@ bool32 HasHealingEffect(u32 battlerId) return FALSE; } +bool32 IsForeSeenMove(u32 moveId) +{ + if (moveId == MOVE_FUTURE_SIGHT || moveId == MOVE_DOOM_DESIRE) + return TRUE; + else + return FALSE; +} + bool32 IsTrappingMove(u32 move) { switch (gMovesInfo[move].effect) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2f31b230ae..6f3b85daa5 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2459,6 +2459,11 @@ static void Cmd_datahpupdate(void) if (gSpecialStatuses[battler].shellBellDmg == 0 && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE)) gSpecialStatuses[battler].shellBellDmg = gHpDealt; + // Record damage for foreseen moves + if (gWishFutureKnock.futureSightDmg[battler] == 0 + && IsForeSeenMove(gWishFutureKnock.futureSightMove[battler])) + gWishFutureKnock.futureSightDmg[battler] = gHpDealt; + // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are // used in combination as general damage trackers for other purposes. specialDmg is additionally used // to help determine if a fire move should defrost the target. @@ -13955,6 +13960,7 @@ static void Cmd_trysetfutureattack(void) gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; gWishFutureKnock.futureSightCounter[gBattlerTarget] = 3; + gWishFutureKnock.futureSightDmg[gBattlerTarget] = 0; if (gCurrentMove == MOVE_DOOM_DESIRE) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; diff --git a/src/battle_util.c b/src/battle_util.c index 9245ef21fc..b3fc4042c8 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5803,10 +5803,26 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !IsBattlerAlive(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) { - gBattleMoveDamage = gSpecialStatuses[gBattlerTarget].shellBellDmg; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_AftermathDmg; - effect++; + //special Future Sight handling + if (IsForeSeenMove(gWishFutureKnock.futureSightMove[gBattlerTarget])) + { + //no Innards Out effect if Future Sight user is currently not on field + if (gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == gBattlerPartyIndexes[gBattlerAttacker] + || gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == BATTLE_PARTNER(gBattlerPartyIndexes[gBattlerAttacker])) + { + gBattleMoveDamage = gWishFutureKnock.futureSightDmg[gBattlerTarget]; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AftermathDmg; + effect++; + } + } + else + { + gBattleMoveDamage = gSpecialStatuses[gBattlerTarget].shellBellDmg; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AftermathDmg; + effect++; + } } break; case ABILITY_EFFECT_SPORE: diff --git a/test/battle/ability/innards_out.c b/test/battle/ability/innards_out.c index 5837b98d1f..e14356b07b 100644 --- a/test/battle/ability/innards_out.c +++ b/test/battle/ability/innards_out.c @@ -65,3 +65,66 @@ SINGLE_BATTLE_TEST("Innards Out does not damage Magic Guard Pokemon") NOT HP_BAR(opponent); } } + +// IO damage for Future Sight must equal the actually lost HP of the Future Sight target +SINGLE_BATTLE_TEST("Innards Out uses correct damage amount for Future Sight") +{ + GIVEN { + PLAYER(SPECIES_PYUKUMUKU) { HP(1); Ability(ABILITY_INNARDS_OUT); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_FUTURE_SIGHT); } + TURN { } + TURN { SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, opponent); + MESSAGE("Pyukumuku took the Future Sight attack!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_INNARDS_OUT); + HP_BAR(opponent, damage: 1); + } +} + +// IO shouldn't trigger if future sight user is no longer on field +SINGLE_BATTLE_TEST("Innards Out doesn't trigger if Future Sight user is not on field") +{ + GIVEN { + PLAYER(SPECIES_PYUKUMUKU) { HP(1); Ability(ABILITY_INNARDS_OUT); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_FUTURE_SIGHT); } + TURN { SWITCH(opponent, 1); } + TURN { SEND_OUT(player, 1); } //SEND_OUT(opponent, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, opponent); + MESSAGE("Pyukumuku took the Future Sight attack!"); + HP_BAR(player); + NONE_OF { + ABILITY_POPUP(player, ABILITY_INNARDS_OUT); + HP_BAR(opponent); + } + } +} + +//IO should trigger if future sight user returns on the field +SINGLE_BATTLE_TEST("Innards Out triggers if Future Sight user is back on the field") +{ + GIVEN { + PLAYER(SPECIES_PYUKUMUKU) { HP(1); Ability(ABILITY_INNARDS_OUT); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_FUTURE_SIGHT); } + TURN { SWITCH(opponent, 1); } + TURN { SWITCH(opponent, 0); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, opponent); + MESSAGE("Pyukumuku took the Future Sight attack!"); + HP_BAR(player); + ABILITY_POPUP(player, ABILITY_INNARDS_OUT); + HP_BAR(opponent); + } +} diff --git a/test/battle/hold_effect/shell_bell.c b/test/battle/hold_effect/shell_bell.c new file mode 100644 index 0000000000..dbcb593fa5 --- /dev/null +++ b/test/battle/hold_effect/shell_bell.c @@ -0,0 +1,35 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Shell Bell restores 1/8 HP of damage dealt") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Level(16); Item(ITEM_SHELL_BELL); HP(10); } + OPPONENT(SPECIES_WOBBUFFET) { Level(16); }; + } WHEN { + TURN { MOVE(player, MOVE_SEISMIC_TOSS); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SEISMIC_TOSS, player); + HP_BAR(opponent); + HP_BAR(player, damage: -2); + } +} + +SINGLE_BATTLE_TEST("Shell Bell doesn't restore HP for damage dealt by a foreseen move") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Level(16); Item(ITEM_SHELL_BELL); HP(10); } + OPPONENT(SPECIES_WOBBUFFET) { Level(16); }; + } WHEN { + TURN { MOVE(player, MOVE_FUTURE_SIGHT); } + TURN { } + TURN { } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + MESSAGE("The opposing Wobbuffet took the Future Sight attack!"); + HP_BAR(opponent); + NONE_OF { + HP_BAR(player); + } + } +} From 5bfc25a4fff708af2440cd654daf355f43fffd50 Mon Sep 17 00:00:00 2001 From: wiz1989 <80073265+wiz1989@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:33:22 +0100 Subject: [PATCH 32/85] changed data according to suggestions from the PR --- include/battle_ai_util.h | 1 - src/battle_ai_util.c | 8 -------- src/battle_script_commands.c | 2 +- src/battle_util.c | 2 +- test/battle/ability/innards_out.c | 6 +++--- test/battle/hold_effect/shell_bell.c | 1 + 6 files changed, 6 insertions(+), 14 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index b26b608e99..c74cad2e78 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -137,7 +137,6 @@ bool32 ShouldSetRain(u32 battlerAtk, u32 ability, u32 holdEffect); bool32 ShouldSetSun(u32 battlerAtk, u32 atkAbility, u32 holdEffect); bool32 HasSleepMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef); bool32 IsHealingMove(u32 move); -bool32 IsForeSeenMove(u32 moveId); bool32 HasHealingEffect(u32 battler); bool32 IsTrappingMove(u32 move); bool32 HasTrappingMoveEffect(u32 battler); diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 3e841a3d69..b68112374d 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2188,14 +2188,6 @@ bool32 HasHealingEffect(u32 battlerId) return FALSE; } -bool32 IsForeSeenMove(u32 moveId) -{ - if (moveId == MOVE_FUTURE_SIGHT || moveId == MOVE_DOOM_DESIRE) - return TRUE; - else - return FALSE; -} - bool32 IsTrappingMove(u32 move) { switch (gMovesInfo[move].effect) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6f3b85daa5..31ae0f2646 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2461,7 +2461,7 @@ static void Cmd_datahpupdate(void) // Record damage for foreseen moves if (gWishFutureKnock.futureSightDmg[battler] == 0 - && IsForeSeenMove(gWishFutureKnock.futureSightMove[battler])) + && gMovesInfo[gWishFutureKnock.futureSightMove[battler]].effect == EFFECT_FUTURE_SIGHT) gWishFutureKnock.futureSightDmg[battler] = gHpDealt; // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are diff --git a/src/battle_util.c b/src/battle_util.c index b3fc4042c8..54d6862c48 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5804,7 +5804,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker)) { //special Future Sight handling - if (IsForeSeenMove(gWishFutureKnock.futureSightMove[gBattlerTarget])) + if (gMovesInfo[gWishFutureKnock.futureSightMove[battler]].effect == EFFECT_FUTURE_SIGHT) { //no Innards Out effect if Future Sight user is currently not on field if (gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == gBattlerPartyIndexes[gBattlerAttacker] diff --git a/test/battle/ability/innards_out.c b/test/battle/ability/innards_out.c index e14356b07b..e4f8e58ef6 100644 --- a/test/battle/ability/innards_out.c +++ b/test/battle/ability/innards_out.c @@ -66,10 +66,10 @@ SINGLE_BATTLE_TEST("Innards Out does not damage Magic Guard Pokemon") } } -// IO damage for Future Sight must equal the actually lost HP of the Future Sight target SINGLE_BATTLE_TEST("Innards Out uses correct damage amount for Future Sight") { GIVEN { + ASSUME(gMovesInfo[MOVE_FUTURE_SIGHT].effect == EFFECT_FUTURE_SIGHT); PLAYER(SPECIES_PYUKUMUKU) { HP(1); Ability(ABILITY_INNARDS_OUT); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); @@ -86,10 +86,10 @@ SINGLE_BATTLE_TEST("Innards Out uses correct damage amount for Future Sight") } } -// IO shouldn't trigger if future sight user is no longer on field SINGLE_BATTLE_TEST("Innards Out doesn't trigger if Future Sight user is not on field") { GIVEN { + ASSUME(gMovesInfo[MOVE_FUTURE_SIGHT].effect == EFFECT_FUTURE_SIGHT); PLAYER(SPECIES_PYUKUMUKU) { HP(1); Ability(ABILITY_INNARDS_OUT); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); @@ -109,10 +109,10 @@ SINGLE_BATTLE_TEST("Innards Out doesn't trigger if Future Sight user is not on f } } -//IO should trigger if future sight user returns on the field SINGLE_BATTLE_TEST("Innards Out triggers if Future Sight user is back on the field") { GIVEN { + ASSUME(gMovesInfo[MOVE_FUTURE_SIGHT].effect == EFFECT_FUTURE_SIGHT); PLAYER(SPECIES_PYUKUMUKU) { HP(1); Ability(ABILITY_INNARDS_OUT); } OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); diff --git a/test/battle/hold_effect/shell_bell.c b/test/battle/hold_effect/shell_bell.c index dbcb593fa5..9cac6831d9 100644 --- a/test/battle/hold_effect/shell_bell.c +++ b/test/battle/hold_effect/shell_bell.c @@ -18,6 +18,7 @@ SINGLE_BATTLE_TEST("Shell Bell restores 1/8 HP of damage dealt") SINGLE_BATTLE_TEST("Shell Bell doesn't restore HP for damage dealt by a foreseen move") { GIVEN { + ASSUME(gMovesInfo[MOVE_FUTURE_SIGHT].effect == EFFECT_FUTURE_SIGHT); PLAYER(SPECIES_WOBBUFFET) { Level(16); Item(ITEM_SHELL_BELL); HP(10); } OPPONENT(SPECIES_WOBBUFFET) { Level(16); }; } WHEN { From c10287b4c1c14d1857dbeb24b416990dfaf044a3 Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Tue, 7 Jan 2025 19:08:31 +0000 Subject: [PATCH 33/85] Fixes various Dynamax HP conversions/calculations (#5933) --- include/battle.h | 1 - include/battle_dynamax.h | 2 +- include/battle_util.h | 2 +- include/pokemon.h | 1 + src/battle_controller_player.c | 40 +++++----- src/battle_dynamax.c | 26 ++++--- src/battle_script_commands.c | 2 +- src/battle_util.c | 25 ++++++- src/pokemon.c | 7 ++ test/battle/gimmick/dynamax.c | 133 ++++++++++++++++++++++++++++++++- 10 files changed, 196 insertions(+), 43 deletions(-) diff --git a/include/battle.h b/include/battle.h index 27f7be5173..99c86181f6 100644 --- a/include/battle.h +++ b/include/battle.h @@ -589,7 +589,6 @@ struct DynamaxData u8 dynamaxTurns[MAX_BATTLERS_COUNT]; u16 baseMoves[MAX_BATTLERS_COUNT]; // base move of Max Move u16 lastUsedBaseMove; - u16 levelUpHP; }; struct BattleGimmickData diff --git a/include/battle_dynamax.h b/include/battle_dynamax.h index 20cd4d5e79..9957c37a10 100644 --- a/include/battle_dynamax.h +++ b/include/battle_dynamax.h @@ -58,7 +58,7 @@ enum MaxMoveEffect bool32 CanDynamax(u32 battler); bool32 IsGigantamaxed(u32 battler); -void ApplyDynamaxHPMultiplier(u32 battler, struct Pokemon* mon); +void ApplyDynamaxHPMultiplier(struct Pokemon* mon); void ActivateDynamax(u32 battler); u16 GetNonDynamaxHP(u32 battler); u16 GetNonDynamaxMaxHP(u32 battler); diff --git a/include/battle_util.h b/include/battle_util.h index 5c151665b9..1eacdaa03d 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -286,7 +286,7 @@ u32 GetBattlerMoveTargetType(u32 battler, u32 move); bool32 CanTargetBattler(u32 battlerAtk, u32 battlerDef, u16 move); void CopyMonLevelAndBaseStatsToBattleMon(u32 battler, struct Pokemon *mon); void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon); -void RecalcBattlerStats(u32 battler, struct Pokemon *mon); +void RecalcBattlerStats(u32 battler, struct Pokemon *mon, bool32 isDynamaxing); bool32 IsAlly(u32 battlerAtk, u32 battlerDef); bool32 IsGen6ExpShareEnabled(void); bool32 MoveHasAdditionalEffect(u32 move, u32 moveEffect); diff --git a/include/pokemon.h b/include/pokemon.h index 8aca6c58d5..f5493542ae 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -910,5 +910,6 @@ const u8 *GetMoveAnimationScript(u16 moveId); void UpdateDaysPassedSinceFormChange(u16 days); void TrySetDayLimitToFormChange(struct Pokemon *mon); u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler); +uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier); #endif // GUARD_POKEMON_H diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 982c9e4f27..059836561c 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1410,6 +1410,14 @@ void Task_PlayerController_RestoreBgmAfterCry(u8 taskId) #define tExpTask_gainedExp_2 data[4] // Stored as two half-words containing a word. #define tExpTask_frames data[10] +static void DynamaxModifyHPLevelUp(struct Pokemon *mon, u32 battler, u32 oldMaxHP) +{ + ApplyDynamaxHPMultiplier(mon); + gBattleScripting.levelUpHP = GetMonData(mon, MON_DATA_MAX_HP) - oldMaxHP; // overwrite levelUpHP since it overflows + gBattleMons[battler].hp += gBattleScripting.levelUpHP; + SetMonData(mon, MON_DATA_HP, &gBattleMons[battler].hp); +} + static s32 GetTaskExpValue(u8 taskId) { return (u16)(gTasks[taskId].tExpTask_gainedExp_1) | (gTasks[taskId].tExpTask_gainedExp_2 << 16); @@ -1428,21 +1436,16 @@ static void Task_GiveExpToMon(u8 taskId) u8 level = GetMonData(mon, MON_DATA_LEVEL); u32 currExp = GetMonData(mon, MON_DATA_EXP); u32 nextLvlExp = gExperienceTables[gSpeciesInfo[species].growthRate][level + 1]; + u32 oldMaxHP = GetMonData(mon, MON_DATA_MAX_HP); if (currExp + gainedExp >= nextLvlExp) { SetMonData(mon, MON_DATA_EXP, &nextLvlExp); - gBattleStruct->dynamax.levelUpHP = GetMonData(mon, MON_DATA_HP) \ - + UQ_4_12_TO_INT((gBattleScripting.levelUpHP * UQ_4_12(1.5)) + UQ_4_12_ROUND); CalculateMonStats(mon); // Reapply Dynamax HP multiplier after stats are recalculated. if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && monId == gBattlerPartyIndexes[battler]) - { - ApplyDynamaxHPMultiplier(battler, mon); - gBattleMons[battler].hp = gBattleStruct->dynamax.levelUpHP; - SetMonData(mon, MON_DATA_HP, &gBattleMons[battler].hp); - } + DynamaxModifyHPLevelUp(mon, battler, oldMaxHP); gainedExp -= nextLvlExp - currExp; BtlController_EmitTwoReturnValues(battler, BUFFER_B, RET_VALUE_LEVELED_UP, gainedExp); @@ -1491,6 +1494,7 @@ static void Task_GiveExpWithExpBar(u8 taskId) { u8 level; u16 species; + u32 oldMaxHP; s32 currExp, expOnNextLvl, newExpPoints; if (gTasks[taskId].tExpTask_frames < 13) @@ -1502,31 +1506,27 @@ static void Task_GiveExpWithExpBar(u8 taskId) u8 monId = gTasks[taskId].tExpTask_monId; s32 gainedExp = GetTaskExpValue(taskId); u8 battler = gTasks[taskId].tExpTask_battler; + struct Pokemon *mon = &gPlayerParty[monId]; newExpPoints = MoveBattleBar(battler, gHealthboxSpriteIds[battler], EXP_BAR, 0); SetHealthboxSpriteVisible(gHealthboxSpriteIds[battler]); if (newExpPoints == -1) // The bar has been filled with given exp points. { m4aSongNumStop(SE_EXP); - level = GetMonData(&gPlayerParty[monId], MON_DATA_LEVEL); - currExp = GetMonData(&gPlayerParty[monId], MON_DATA_EXP); - species = GetMonData(&gPlayerParty[monId], MON_DATA_SPECIES); + level = GetMonData(mon, MON_DATA_LEVEL); + currExp = GetMonData(mon, MON_DATA_EXP); + species = GetMonData(mon, MON_DATA_SPECIES); + oldMaxHP = GetMonData(mon, MON_DATA_MAX_HP); expOnNextLvl = gExperienceTables[gSpeciesInfo[species].growthRate][level + 1]; if (currExp + gainedExp >= expOnNextLvl) { - SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &expOnNextLvl); - gBattleStruct->dynamax.levelUpHP = GetMonData(&gPlayerParty[monId], MON_DATA_HP) \ - + UQ_4_12_TO_INT((gBattleScripting.levelUpHP * UQ_4_12(1.5)) + UQ_4_12_ROUND); - CalculateMonStats(&gPlayerParty[monId]); + SetMonData(mon, MON_DATA_EXP, &expOnNextLvl); + CalculateMonStats(mon); // Reapply Dynamax HP multiplier after stats are recalculated. if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && monId == gBattlerPartyIndexes[battler]) - { - ApplyDynamaxHPMultiplier(battler, &gPlayerParty[monId]); - gBattleMons[battler].hp = gBattleStruct->dynamax.levelUpHP; - SetMonData(&gPlayerParty[monId], MON_DATA_HP, &gBattleMons[battler].hp); - } + DynamaxModifyHPLevelUp(mon, battler, oldMaxHP); gainedExp -= expOnNextLvl - currExp; BtlController_EmitTwoReturnValues(battler, BUFFER_B, RET_VALUE_LEVELED_UP, gainedExp); @@ -1535,7 +1535,7 @@ static void Task_GiveExpWithExpBar(u8 taskId) else { currExp += gainedExp; - SetMonData(&gPlayerParty[monId], MON_DATA_EXP, &currExp); + SetMonData(mon, MON_DATA_EXP, &currExp); gBattlerControllerFuncs[battler] = Controller_WaitForString; DestroyTask(taskId); } diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 17425b51d8..0f55b33dab 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -123,22 +123,22 @@ bool32 CanDynamax(u32 battler) // Returns whether a battler is transformed into a Gigantamax form. bool32 IsGigantamaxed(u32 battler) { - struct Pokemon *mon = &GetSideParty(GetBattlerSide(battler))[gBattlerPartyIndexes[battler]]; + struct Pokemon *mon = GetPartyBattlerData(battler); if ((gSpeciesInfo[gBattleMons[battler].species].isGigantamax) && GetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR)) return TRUE; return FALSE; } // Applies the HP Multiplier for Dynamaxed Pokemon and Raid Bosses. -void ApplyDynamaxHPMultiplier(u32 battler, struct Pokemon* mon) +void ApplyDynamaxHPMultiplier(struct Pokemon* mon) { if (GetMonData(mon, MON_DATA_SPECIES) == SPECIES_SHEDINJA) return; else { - 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; + uq4_12_t multiplier = GetDynamaxLevelHPMultiplier(GetMonData(mon, MON_DATA_DYNAMAX_LEVEL), FALSE); + u32 hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP) * multiplier) + UQ_4_12_ROUND); + u32 maxHP = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_MAX_HP) * multiplier) + UQ_4_12_ROUND); SetMonData(mon, MON_DATA_HP, &hp); SetMonData(mon, MON_DATA_MAX_HP, &maxHP); } @@ -151,8 +151,9 @@ u16 GetNonDynamaxHP(u32 battler) return gBattleMons[battler].hp; else { - u16 mult = UQ_4_12(1.0/1.5); // placeholder - u16 hp = UQ_4_12_TO_INT((gBattleMons[battler].hp * mult) + UQ_4_12_ROUND); + struct Pokemon *mon = GetPartyBattlerData(battler); + uq4_12_t mult = GetDynamaxLevelHPMultiplier(GetMonData(mon, MON_DATA_DYNAMAX_LEVEL), TRUE); + u32 hp = UQ_4_12_TO_INT((gBattleMons[battler].hp * mult) + UQ_4_12_ROUND); return hp; } } @@ -164,8 +165,9 @@ u16 GetNonDynamaxMaxHP(u32 battler) return gBattleMons[battler].maxHP; else { - u16 mult = UQ_4_12(1.0/1.5); // placeholder - u16 maxHP = UQ_4_12_TO_INT((gBattleMons[battler].maxHP * mult) + UQ_4_12_ROUND); + struct Pokemon *mon = GetPartyBattlerData(battler); + uq4_12_t mult = GetDynamaxLevelHPMultiplier(GetMonData(mon, MON_DATA_DYNAMAX_LEVEL), TRUE); + u32 maxHP = UQ_4_12_TO_INT((gBattleMons[battler].maxHP * mult) + UQ_4_12_ROUND); return maxHP; } } @@ -202,7 +204,7 @@ void UndoDynamax(u32 battler) if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX) { struct Pokemon *mon = (side == B_SIDE_PLAYER) ? &gPlayerParty[monId] : &gEnemyParty[monId]; - u16 mult = UQ_4_12(1.0/1.5); // placeholder + uq4_12_t mult = GetDynamaxLevelHPMultiplier(GetMonData(mon, MON_DATA_DYNAMAX_LEVEL), TRUE); gBattleMons[battler].hp = UQ_4_12_TO_INT((GetMonData(mon, MON_DATA_HP) * mult + 1) + UQ_4_12_ROUND); // round up SetMonData(mon, MON_DATA_HP, &gBattleMons[battler].hp); CalculateMonStats(mon); @@ -508,10 +510,10 @@ void BS_UpdateDynamax(void) { NATIVE_ARGS(); u32 battler = gBattleScripting.battler; - struct Pokemon *mon = &GetSideParty(GetBattlerSide(battler))[gBattlerPartyIndexes[battler]]; + struct Pokemon *mon = GetPartyBattlerData(battler); if (!IsGigantamaxed(battler)) // RecalcBattlerStats will get called on form change. - RecalcBattlerStats(battler, mon); + RecalcBattlerStats(battler, mon, GetActiveGimmick(battler) == GIMMICK_DYNAMAX); UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], mon, HEALTHBOX_ALL); gBattlescriptCurrInstr = cmd->nextInstr; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 31ae0f2646..dd4e504a1d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -10157,7 +10157,7 @@ static void Cmd_various(void) // Change stats. else if (cmd->case_ == 1) { - RecalcBattlerStats(battler, mon); + RecalcBattlerStats(battler, mon, FALSE); } // Update healthbox. else diff --git a/src/battle_util.c b/src/battle_util.c index 54d6862c48..c35c072b77 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -11083,7 +11083,7 @@ bool32 TryBattleFormChange(u32 battler, u32 method) TryToSetBattleFormChangeMoves(&party[monId], method); SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); gBattleMons[battler].species = targetSpecies; - RecalcBattlerStats(battler, &party[monId]); + RecalcBattlerStats(battler, &party[monId], method == FORM_CHANGE_BATTLE_GIGANTAMAX); return TRUE; } else if (gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE) @@ -11108,7 +11108,7 @@ bool32 TryBattleFormChange(u32 battler, u32 method) // Reverts the original species TryToSetBattleFormChangeMoves(&party[monId], method); SetMonData(&party[monId], MON_DATA_SPECIES, &gBattleStruct->changedSpecies[side][monId]); - RecalcBattlerStats(battler, &party[monId]); + RecalcBattlerStats(battler, &party[monId], method == FORM_CHANGE_BATTLE_GIGANTAMAX); // Battler data is not updated with regular form's ability, not doing so could cause wrong ability activation. if (method == FORM_CHANGE_FAINT) gBattleMons[battler].ability = abilityForm; @@ -11696,11 +11696,28 @@ void CopyMonAbilityAndTypesToBattleMon(u32 battler, struct Pokemon *mon) gBattleMons[battler].types[2] = TYPE_MYSTERY; } -void RecalcBattlerStats(u32 battler, struct Pokemon *mon) +void RecalcBattlerStats(u32 battler, struct Pokemon *mon, bool32 isDynamaxing) { + u32 hp = GetMonData(mon, MON_DATA_HP); + u32 oldMaxHp = GetMonData(mon, MON_DATA_MAX_HP); CalculateMonStats(mon); if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && gChosenActionByBattler[battler] != B_ACTION_SWITCH) - ApplyDynamaxHPMultiplier(battler, mon); + { + ApplyDynamaxHPMultiplier(mon); + u32 newMaxHp = GetMonData(mon, MON_DATA_MAX_HP); + if (!isDynamaxing) + { + if (newMaxHp > oldMaxHp) // restore hp gained from changing form, without this, dynamaxed form changes are calculated incorrectly + { + hp += (newMaxHp - oldMaxHp); + SetMonData(mon, MON_DATA_HP, &hp); + } + else + { + SetMonData(mon, MON_DATA_HP, &hp); + } + } + } CopyMonLevelAndBaseStatsToBattleMon(battler, mon); CopyMonAbilityAndTypesToBattleMon(battler, mon); } diff --git a/src/pokemon.c b/src/pokemon.c index c5162ecfd0..d6ed5020b8 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -6978,3 +6978,10 @@ u32 CheckDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler) return moveType; return gMovesInfo[move].type; } + +uq4_12_t GetDynamaxLevelHPMultiplier(u32 dynamaxLevel, bool32 inverseMultiplier) +{ + if (inverseMultiplier) + return UQ_4_12(1.0/(1.5 + 0.05 * dynamaxLevel)); + return UQ_4_12(1.5 + 0.05 * dynamaxLevel); +} diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index f910f551a4..0e3ae532bf 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -7,7 +7,7 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax increases HP and max HP by 1.5x", u16 hp) u32 dynamax; PARAMETRIZE { dynamax = GIMMICK_NONE; } PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; } - GIVEN { // TODO: Dynamax level + GIVEN { PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); } WHEN { @@ -25,6 +25,49 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax increases HP and max HP by 1.5x", u16 hp) } } +SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax Level increases HP and max HP multipliers by 0.05 for each level", u16 hp) +{ + u32 dynamax, level; + PARAMETRIZE { dynamax = GIMMICK_NONE; level = 0; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 0; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 1; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 2; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 3; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 4; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 5; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 6; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 7; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 8; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 9; } + PARAMETRIZE { dynamax = GIMMICK_DYNAMAX; level = 10; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { DynamaxLevel(level); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE, gimmick: dynamax); MOVE(opponent, MOVE_CELEBRATE); } + } SCENE { + if (dynamax) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player); + MESSAGE("Wobbuffet used Max Strike!"); + } + MESSAGE("The opposing Wobbuffet used Celebrate!"); + } THEN { + results[i].hp = player->hp; + } FINALLY { + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.5), results[1].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.55), results[2].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.6), results[3].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.65), results[4].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.7), results[5].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.75), results[6].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.8), results[7].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.85), results[8].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.9), results[9].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(1.95), results[10].hp); + EXPECT_MUL_EQ(results[0].hp, Q_4_12(2.0), results[11].hp); + } +} + SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax expires after three turns", u16 hp) { u32 dynamax; @@ -38,8 +81,8 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax expires after three turns", u16 hp) TURN { MOVE(player, MOVE_TACKLE); } // 2nd max move TURN { MOVE(player, MOVE_TACKLE); } // 3rd max move } SCENE { - int i; - for (i = 0; i < DYNAMAX_TURNS_COUNT; ++i) { + int j; + for (j = 0; j < DYNAMAX_TURNS_COUNT; ++j) { if (dynamax) MESSAGE("Wobbuffet used Max Strike!"); else @@ -55,6 +98,49 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax expires after three turns", u16 hp) } } +SINGLE_BATTLE_TEST("(DYNAMAX) Dynamax expires after three turns and correctly converts HP according to Dynamax Level") +{ + u32 dynamaxLevel, dynamax; + u16 capturedHP, finalHP; + s16 capturedDamage; + PARAMETRIZE { dynamaxLevel = 0; dynamax = GIMMICK_NONE; } + PARAMETRIZE { dynamaxLevel = 0; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 1; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 2; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 3; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 4; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 5; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 6; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 7; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 8; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 9; dynamax = GIMMICK_DYNAMAX; } + PARAMETRIZE { dynamaxLevel = 10; dynamax = GIMMICK_DYNAMAX; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { DynamaxLevel(dynamaxLevel); HP(200); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_CELEBRATE, gimmick: dynamax); } + TURN { MOVE(player, MOVE_TACKLE); MOVE(opponent, MOVE_TACKLE); } + TURN { } + } SCENE { + if (dynamax) + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + if (dynamax) + HP_BAR(player, captureHP: &capturedHP); + else + HP_BAR(player, captureDamage: &capturedDamage); + if (dynamax) + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + finalHP = player->hp; + if (dynamax) + EXPECT_MUL_EQ(finalHP, GetDynamaxLevelHPMultiplier(dynamaxLevel, FALSE), capturedHP); + EXPECT_LE(finalHP, 200); + EXPECT_GE(finalHP, 200 - capturedDamage); + } +} + SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon cannot be flinched") { GIVEN { @@ -311,6 +397,47 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon lose their substitutes") } } +SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon that changes forms does not gain HP") +{ + u16 capturedHP, finalHP; + GIVEN { + PLAYER(SPECIES_GRENINJA_BATTLE_BOND) { Ability(ABILITY_BATTLE_BOND); HP(100); Speed(100); } + OPPONENT(SPECIES_CATERPIE) { HP(1); Speed(1000); } + OPPONENT(SPECIES_WOBBUFFET) { Speed(10); } + } WHEN { + TURN { MOVE(opponent, MOVE_TACKLE); MOVE(player, MOVE_TACKLE, gimmick: GIMMICK_DYNAMAX); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, opponent); + HP_BAR(player, captureHP: &capturedHP); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAX_STRIKE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + finalHP = player->hp; + EXPECT_EQ(capturedHP, finalHP); + } +} + +SINGLE_BATTLE_TEST("(DYNAMAX) Dynamaxed Pokemon that changes forms does not gain HP unless the new form gains Max HP") +{ + u32 hp = 1, maxHP = 200; + u32 species; + PARAMETRIZE { species = SPECIES_ZYGARDE_10_POWER_CONSTRUCT; } + PARAMETRIZE { species = SPECIES_ZYGARDE_50_POWER_CONSTRUCT; } + GIVEN { + PLAYER(species) { Ability(ABILITY_POWER_CONSTRUCT); HP(hp); MaxHP(maxHP); DynamaxLevel(0); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_TACKLE, gimmick: GIMMICK_DYNAMAX); } + } SCENE { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_DYNAMAX_GROWTH, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAX_STRIKE, player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + } THEN { + EXPECT_MUL_EQ(maxHP - hp, GetDynamaxLevelHPMultiplier(0, FALSE), player->maxHP - player->hp); + } +} + SINGLE_BATTLE_TEST("(DYNAMAX) Max Moves deal 1/4 damage through protect", s16 damage) { bool32 protected; From 46fc560320e5595095d3219ef0acaf29143c55d0 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Tue, 7 Jan 2025 15:17:14 -0500 Subject: [PATCH 34/85] Update scope.md (again) (#5971) --- docs/scope.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/scope.md b/docs/scope.md index 41369eda29..fe6333090f 100644 --- a/docs/scope.md +++ b/docs/scope.md @@ -42,9 +42,9 @@ A pull request meets the scope criteria if: 4. **Non-SS Items**: Adds Items that have NOT appeared in a Showdown-supported title 5. **Non-SS Gimmicks**: Adds Gimmicks that have NOT appeared in a Showdown-supported title (Showdown's Other Metagames, etc.) 6. **Non-SS Battle Types**: Adds Special Battle Types that have NOT appeared in a Showdown-supported title -7. **Non-SS or SS Overworld Maps**: Adds overworld maps from either Showdown-supported titles or non-Showdown-supported titles -7. **Duplicate Feature UI**: Adds functionality that duplicates the core functionality of an existing vanilla feature -8. **Vanilla Link Compatibility**: The ability for Base Expansion Version and Vanilla Emerald Version to connect, trade, and battle one another +7. **Overworld Maps**: Adds overworld maps from either Showdown-supported titles or non-Showdown-supported titles +8. **Duplicate UIs**: Adds additional user interface that covers the same functionality of an existing feature (HGSS Pokédex, BW Summary Screen, etc.) +9. **Vanilla Link Compatibility**: The ability for Base Expansion Version and Vanilla Emerald Version to connect, trade, and battle one another ## Discussion Required Categories From c3833fa55fcb4fd3ca11aeaede09e6306bf2bbb6 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 7 Jan 2025 21:24:12 +0100 Subject: [PATCH 35/85] Fixes Parting Shot / Eject Pack interaction (#5963) --- src/battle_script_commands.c | 12 ++++++++---- test/battle/hold_effect/eject_pack.c | 19 +++++++++++++++++++ test/battle/move_effect/hit_escape.c | 20 ++++++++++---------- 3 files changed, 37 insertions(+), 14 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index dd4e504a1d..19b095333c 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6466,18 +6466,22 @@ static void Cmd_moveend(void) gLastUsedItem = gBattleMons[battler].item; if (gMovesInfo[gCurrentMove].effect == EFFECT_HIT_ESCAPE) gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection - effect = TRUE; - BattleScriptPushCursor(); - gBattleStruct->usedEjectItem |= 1u << battler; if (ejectButtonBattlers & (1u << battler)) { + effect = TRUE; + gBattleStruct->usedEjectItem |= 1u << battler; + BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_EjectButtonActivates; AI_DATA->ejectButtonSwitch = TRUE; } else // Eject Pack { - if (!(gBattleResources->flags->flags[gBattlerTarget] & RESOURCE_FLAG_EMERGENCY_EXIT)) + if (!(gBattleResources->flags->flags[gBattlerTarget] & RESOURCE_FLAG_EMERGENCY_EXIT) + && !(gMovesInfo[gCurrentMove].effect == EFFECT_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) { + effect = TRUE; + gBattleStruct->usedEjectItem |= 1u << battler; + BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_EjectPackActivates; AI_DATA->ejectPackSwitch = TRUE; gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage = TRUE; diff --git a/test/battle/hold_effect/eject_pack.c b/test/battle/hold_effect/eject_pack.c index 0d2696392f..bba874e1b3 100644 --- a/test/battle/hold_effect/eject_pack.c +++ b/test/battle/hold_effect/eject_pack.c @@ -102,3 +102,22 @@ SINGLE_BATTLE_TEST("Eject Pack activates once intimidate mon switches in") MESSAGE("Wobbuffet is switched out with the Eject Pack!"); } } + +SINGLE_BATTLE_TEST("Eject Pack will not activate if Parting Shot user can switch out") +{ + ASSUME(gItemsInfo[ITEM_EJECT_PACK].holdEffect == HOLD_EFFECT_EJECT_PACK); + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_EJECT_PACK); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_PARTING_SHOT); SEND_OUT(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PARTING_SHOT, opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + MESSAGE("Wobbuffet is switched out with the Eject Pack!"); + } + } +} diff --git a/test/battle/move_effect/hit_escape.c b/test/battle/move_effect/hit_escape.c index 0a494cc667..fb69e1b2fe 100644 --- a/test/battle/move_effect/hit_escape.c +++ b/test/battle/move_effect/hit_escape.c @@ -6,7 +6,7 @@ ASSUMPTIONS ASSUME(gMovesInfo[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE); } -SINGLE_BATTLE_TEST("U-turn switches the user out") +SINGLE_BATTLE_TEST("Hit Escape: U-turn switches the user out") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -21,7 +21,7 @@ SINGLE_BATTLE_TEST("U-turn switches the user out") } } -SINGLE_BATTLE_TEST("U-turn does not switch the user out if the battle ends") +SINGLE_BATTLE_TEST("Hit Escape: U-turn does not switch the user out if the battle ends") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -35,7 +35,7 @@ SINGLE_BATTLE_TEST("U-turn does not switch the user out if the battle ends") } } -SINGLE_BATTLE_TEST("U-turn does not switch the user out if no replacements") +SINGLE_BATTLE_TEST("Hit Escape: U-turn does not switch the user out if no replacements") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -48,7 +48,7 @@ SINGLE_BATTLE_TEST("U-turn does not switch the user out if no replacements") } } -SINGLE_BATTLE_TEST("U-turn does not switch the user out if replacements fainted") +SINGLE_BATTLE_TEST("Hit Escape: U-turn does not switch the user out if replacements fainted") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -62,7 +62,7 @@ SINGLE_BATTLE_TEST("U-turn does not switch the user out if replacements fainted" } } -SINGLE_BATTLE_TEST("U-turn does not switch the user out if Wimp Out activates") +SINGLE_BATTLE_TEST("Hit Escape: U-turn does not switch the user out if Wimp Out activates") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -79,7 +79,7 @@ SINGLE_BATTLE_TEST("U-turn does not switch the user out if Wimp Out activates") } } -SINGLE_BATTLE_TEST("U-turn switches the user out if Wimp Out fails to activate") +SINGLE_BATTLE_TEST("Hit Escape: U-turn switches the user out if Wimp Out fails to activate") { GIVEN { PLAYER(SPECIES_WOBBUFFET); @@ -95,7 +95,7 @@ SINGLE_BATTLE_TEST("U-turn switches the user out if Wimp Out fails to activate") } } -SINGLE_BATTLE_TEST("U-turn switches the user out after Ice Face activates") +SINGLE_BATTLE_TEST("Hit Escape: U-turn switches the user out after Ice Face activates") { GIVEN { ASSUME(gMovesInfo[MOVE_U_TURN].category == DAMAGE_CATEGORY_PHYSICAL); @@ -113,7 +113,7 @@ SINGLE_BATTLE_TEST("U-turn switches the user out after Ice Face activates") } } -SINGLE_BATTLE_TEST("Held items are consumed immediately after a mon switched in by U-turn and Intimidate activates after it: player side") +SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon switched in by U-turn and Intimidate activates after it: player side") { GIVEN { PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); }; @@ -136,7 +136,7 @@ SINGLE_BATTLE_TEST("Held items are consumed immediately after a mon switched in } } -SINGLE_BATTLE_TEST("Held items are consumed immediately after a mon switched in by U-turn and Intimidate activates after it: opposing side") +SINGLE_BATTLE_TEST("Hit Escape: Held items are consumed immediately after a mon switched in by U-turn and Intimidate activates after it: opposing side") { GIVEN { PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); }; @@ -159,7 +159,7 @@ SINGLE_BATTLE_TEST("Held items are consumed immediately after a mon switched in } } -SINGLE_BATTLE_TEST("Electric Seed boost is received by the right pokemon after U-turn and Intimidate") +SINGLE_BATTLE_TEST("Hit Escape: Electric Seed boost is received by the right pokemon after U-turn and Intimidate") { GIVEN { PLAYER(SPECIES_TAPU_KOKO) { Ability(ABILITY_ELECTRIC_SURGE); }; From 5391b451ae62194a694ec2c431c32cae338b6e4a Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 7 Jan 2025 21:50:23 +0100 Subject: [PATCH 36/85] Shell Bell Clean up / Simplification and Tests (#5924) --- include/battle.h | 12 +-- src/battle_script_commands.c | 32 ++---- src/battle_util.c | 19 ++-- test/battle/hold_effect/life_orb.c | 0 test/battle/hold_effect/shell_bell.c | 141 +++++++++++++++++++++++++++ 5 files changed, 160 insertions(+), 44 deletions(-) create mode 100644 test/battle/hold_effect/life_orb.c create mode 100644 test/battle/hold_effect/shell_bell.c diff --git a/include/battle.h b/include/battle.h index 978aae60d7..05c3b3a822 100644 --- a/include/battle.h +++ b/include/battle.h @@ -68,9 +68,6 @@ #define BATTLE_BUFFER_LINK_SIZE 0x1000 -// Special indicator value for shellBellDmg in SpecialStatus -#define IGNORE_SHELL_BELL 0xFFFF - struct ResourceFlags { u32 flags[MAX_BATTLERS_COUNT]; @@ -200,7 +197,6 @@ struct ProtectStruct struct SpecialStatus { - s32 shellBellDmg; s32 physicalDmg; s32 specialDmg; u8 physicalBattlerId; @@ -212,7 +208,8 @@ struct SpecialStatus u8 faintedHasReplacement:1; u8 focusBanded:1; u8 focusSashed:1; - u8 unused:2; + u8 emergencyExited:1; + u8 afterYou:1; // End of byte u8 sturdied:1; u8 stormDrainRedirected:1; @@ -231,16 +228,13 @@ struct SpecialStatus u8 neutralizingGasRemoved:1; // See VARIOUS_TRY_END_NEUTRALIZING_GAS u8 affectionEndured:1; // End of byte - u8 damagedMons:4; // Mons that have been damaged directly by using a move, includes substitute. u8 dancerUsedMove:1; u8 dancerOriginalTarget:3; - // End of byte - u8 emergencyExited:1; - u8 afterYou:1; u8 preventLifeOrbDamage:1; // So that Life Orb doesn't activate various effects. u8 distortedTypeMatchups:1; u8 teraShellAbilityDone:1; u8 criticalHit:1; + // End of byte }; struct SideTimer diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1c5c7bbc17..ba606632f7 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2124,12 +2124,12 @@ static void Cmd_adjustdamage(void) continue; if (DoesSubstituteBlockMove(gBattlerAttacker, battlerDef, gCurrentMove)) - goto END; + continue; if (DoesDisguiseBlockMove(battlerDef, gCurrentMove)) { gBattleStruct->enduredDamage |= 1u << battlerDef; - goto END; + continue; } if (GetBattlerAbility(battlerDef) == ABILITY_ICE_FACE && IsBattleMovePhysical(gCurrentMove) && gBattleMons[battlerDef].species == SPECIES_EISCUE) { @@ -2139,10 +2139,10 @@ static void Cmd_adjustdamage(void) RecordAbilityBattle(gBattlerTarget, ABILITY_ICE_FACE); gBattleResources->flags->flags[battlerDef] |= RESOURCE_FLAG_ICE_FACE; // Form change will be done after attack animation in Cmd_resultmessage. - goto END; + continue; } if (gBattleMons[gBattlerTarget].hp > gBattleStruct->moveDamage[battlerDef]) - goto END; + continue; holdEffect = GetBattlerHoldEffect(battlerDef, TRUE); param = GetBattlerHoldEffectParam(battlerDef); @@ -2178,7 +2178,7 @@ static void Cmd_adjustdamage(void) && !gSpecialStatuses[battlerDef].focusSashed && (B_AFFECTION_MECHANICS == FALSE || !gSpecialStatuses[battlerDef].affectionEndured) && !gSpecialStatuses[battlerDef].sturdied) - goto END; + continue; // Handle reducing the dmg to 1 hp. gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1; @@ -2204,10 +2204,6 @@ static void Cmd_adjustdamage(void) { gBattleStruct->moveResultFlags[battlerDef] |= MOVE_RESULT_FOE_ENDURED_AFFECTION; } - - END: - if (!(gBattleStruct->moveResultFlags[battlerDef] & MOVE_RESULT_NO_EFFECT) && gBattleStruct->moveDamage[battlerDef] >= 1) - gSpecialStatuses[gBattlerAttacker].damagedMons |= 1u << battlerDef; } if (calcSpreadMoveDamage) @@ -2580,14 +2576,10 @@ static void Cmd_datahpupdate(void) { if (gDisableStructs[battler].substituteHP >= gBattleStruct->moveDamage[battler]) { - if (gSpecialStatuses[battler].shellBellDmg == 0) - gSpecialStatuses[battler].shellBellDmg = gBattleStruct->moveDamage[battler]; gDisableStructs[battler].substituteHP -= gBattleStruct->moveDamage[battler]; } else { - if (gSpecialStatuses[battler].shellBellDmg == 0) - gSpecialStatuses[battler].shellBellDmg = gDisableStructs[battler].substituteHP; gBattleStruct->moveDamage[battler] = gDisableStructs[battler].substituteHP; gDisableStructs[battler].substituteHP = 0; } @@ -2653,10 +2645,6 @@ static void Cmd_datahpupdate(void) gBattleMons[battler].hp = 0; } - // Record damage for Shell Bell - if (gSpecialStatuses[battler].shellBellDmg == 0 && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE)) - gSpecialStatuses[battler].shellBellDmg = gBattleStruct->moveDamage[battler]; - u32 effect = GetMoveEffect(gCurrentMove); // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are @@ -2700,13 +2688,7 @@ static void Cmd_datahpupdate(void) MarkBattlerForControllerExec(battler); } } - else - { - // MOVE_RESULT_NO_EFFECT was set - battler = GetBattlerForBattleScript(cmd->battler); - if (gSpecialStatuses[battler].shellBellDmg == 0) - gSpecialStatuses[battler].shellBellDmg = IGNORE_SHELL_BELL; - } + gBattlescriptCurrInstr = cmd->nextInstr; } @@ -6996,7 +6978,6 @@ static void Cmd_moveend(void) gBattleStruct->ateBoost[gBattlerAttacker] = FALSE; gStatuses3[gBattlerAttacker] &= ~STATUS3_ME_FIRST; gSpecialStatuses[gBattlerAttacker].gemBoost = FALSE; - gSpecialStatuses[gBattlerAttacker].damagedMons = 0; gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage = 0; gSpecialStatuses[gBattlerTarget].berryReduced = FALSE; gSpecialStatuses[gBattlerTarget].distortedTypeMatchups = FALSE; @@ -13247,7 +13228,6 @@ static void Cmd_painsplitdmgcalc(void) gBattleStruct->moveDamage[gBattlerTarget] = GetNonDynamaxHP(gBattlerTarget) - hpDiff; gBattleStruct->moveDamage[gBattlerAttacker] = gBattleMons[gBattlerAttacker].hp - hpDiff; - gSpecialStatuses[gBattlerTarget].shellBellDmg = IGNORE_SHELL_BELL; gBattlescriptCurrInstr = cmd->nextInstr; } else diff --git a/src/battle_util.c b/src/battle_util.c index 8d00cc0f2a..41b61f6014 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2949,7 +2949,6 @@ bool32 HandleWishPerishSongOnTurnEnd(void) gBattlerTarget = battler; gBattlerAttacker = gWishFutureKnock.futureSightBattlerIndex[battler]; - gSpecialStatuses[gBattlerTarget].shellBellDmg = IGNORE_SHELL_BELL; gCurrentMove = gWishFutureKnock.futureSightMove[battler]; party = GetSideParty(GetBattlerSide(gBattlerAttacker)); @@ -5888,7 +5887,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !IsBattlerAlive(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) { - gBattleStruct->moveDamage[gBattlerAttacker] = gSpecialStatuses[gBattlerTarget].shellBellDmg; + gBattleStruct->moveDamage[gBattlerAttacker] = gBattleStruct->moveDamage[gBattlerTarget]; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AftermathDmg; effect++; @@ -8180,19 +8179,21 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) switch (atkHoldEffect) { case HOLD_EFFECT_SHELL_BELL: - if (gSpecialStatuses[gBattlerAttacker].damagedMons // Need to have done damage + if (gBattleScripting.savedDmg > 0 + && MoveResultHasEffect(battler) && gBattlerAttacker != gBattlerTarget - && gBattleMons[gBattlerAttacker].hp != gBattleMons[gBattlerAttacker].maxHP + && !IsBattlerAtMaxHp(gBattlerAttacker) && IsBattlerAlive(gBattlerAttacker) + && gMovesInfo[gCurrentMove].effect != EFFECT_FUTURE_SIGHT + && gMovesInfo[gCurrentMove].effect != EFFECT_PAIN_SPLIT && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) { gLastUsedItem = atkItem; gPotentialItemEffectBattler = gBattlerAttacker; gBattleScripting.battler = gBattlerAttacker; - gBattleStruct->moveDamage[gBattlerAttacker] = (gSpecialStatuses[gBattlerTarget].shellBellDmg / atkHoldEffectParam) * -1; + gBattleStruct->moveDamage[gBattlerAttacker] = (gBattleScripting.savedDmg / atkHoldEffectParam) * -1; if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) gBattleStruct->moveDamage[gBattlerAttacker] = -1; - gSpecialStatuses[gBattlerTarget].shellBellDmg = 0; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ItemHealHP_Ret; effect = ITEM_HP_CHANGE; @@ -8200,11 +8201,11 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_LIFE_ORB: if (IsBattlerAlive(gBattlerAttacker) + && (IsBattlerTurnDamaged(gBattlerTarget) || gBattleStruct->moveDamage[gBattlerTarget]) // Needs the second check in case of Substitute && !(TestIfSheerForceAffected(gBattlerAttacker, gCurrentMove)) && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && !gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage - && gSpecialStatuses[gBattlerAttacker].damagedMons) + && !gSpecialStatuses[gBattlerAttacker].preventLifeOrbDamage) { gBattleStruct->moveDamage[gBattlerAttacker] = GetNonDynamaxMaxHP(gBattlerAttacker) / 10; if (gBattleStruct->moveDamage[gBattlerAttacker] == 0) @@ -8212,7 +8213,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) effect = ITEM_HP_CHANGE; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ItemHurtRet; - gLastUsedItem = gBattleMons[gBattlerAttacker].item; + gLastUsedItem = atkItem; } break; case HOLD_EFFECT_THROAT_SPRAY: // Does NOT need to be a damaging move diff --git a/test/battle/hold_effect/life_orb.c b/test/battle/hold_effect/life_orb.c new file mode 100644 index 0000000000..e69de29bb2 diff --git a/test/battle/hold_effect/shell_bell.c b/test/battle/hold_effect/shell_bell.c new file mode 100644 index 0000000000..8f03ca4a0f --- /dev/null +++ b/test/battle/hold_effect/shell_bell.c @@ -0,0 +1,141 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gItemsInfo[ITEM_SHELL_BELL].holdEffect == HOLD_EFFECT_SHELL_BELL); +} + +#define HITS 5 +SINGLE_BATTLE_TEST("Shell Bell recovers 1/8 of HP from after the last hit from all hits of a multi hit move") +{ + s16 multiHitDamage[HITS]; + s16 totalDamage = 0; + s16 shellBellRecovery = 0; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); Item(ITEM_SHELL_BELL); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_BULLET_SEED); } + } SCENE { + for (u32 i = 0; i < HITS; i++) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_BULLET_SEED, player); + HP_BAR(opponent, captureDamage: &multiHitDamage[i]); + totalDamage += multiHitDamage[i]; + } + HP_BAR(player, captureDamage: &shellBellRecovery); + } THEN { + EXPECT_EQ(totalDamage / 8, -1 * shellBellRecovery); + } +} +#undef HITS + +SINGLE_BATTLE_TEST("Shell Bell recovers no HP if the move did no damage") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); Item(ITEM_SHELL_BELL); } + OPPONENT(SPECIES_WOBBUFFET) { HP(1); }; + } WHEN { + TURN { MOVE(player, MOVE_FALSE_SWIPE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FALSE_SWIPE, player); + HP_BAR(opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(player); + } + } +} + +SINGLE_BATTLE_TEST("Shell Bell activates if it hits a Substitute") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); Item(ITEM_SHELL_BELL); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_SUBSTITUTE); MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SUBSTITUTE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + // HP_BAR(opponent); // When you hit a sub the hp bar check doesn't work. Not sure if this is a bug + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Shell Bell activates after Absorb") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); Item(ITEM_SHELL_BELL); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_ABSORB); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ABSORB, player); + HP_BAR(opponent); + HP_BAR(player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Shell Bell activates after Rough Skin") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Item(ITEM_SHELL_BELL); } + OPPONENT(SPECIES_GIBLE) { Ability(ABILITY_ROUGH_SKIN); } + } WHEN { + TURN { MOVE(player, MOVE_TACKLE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, player); + HP_BAR(opponent); + HP_BAR(player); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(player); + } +} + +SINGLE_BATTLE_TEST("Shell Bell does not activate on Future Sight if the original user is on the field") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); Item(ITEM_SHELL_BELL); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_FUTURE_SIGHT); } + TURN {} + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + MESSAGE("The opposing Wynaut took the Future Sight attack!"); + HP_BAR(opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(player); + } + } +} + +SINGLE_BATTLE_TEST("Shell Bell does not activate on Future Sight if the original user is not on the field") +{ + GIVEN { + PLAYER(SPECIES_WYNAUT); + PLAYER(SPECIES_WOBBUFFET) { HP(1); Item(ITEM_SHELL_BELL); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_FUTURE_SIGHT); } + TURN { SWITCH(player, 1); } + TURN {} + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + MESSAGE("The opposing Wynaut took the Future Sight attack!"); + HP_BAR(opponent); + NONE_OF { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(player); + } + } +} + +TO_DO_BATTLE_TEST("If a Pokémon steals a Shell Bell with Thief or Covet, it will recover HP for the use of that move that stole the Shell Bell") +TO_DO_BATTLE_TEST("If a Pokémon steals a Shell Bell with Magician, it will recover HP for the use of that move that stole the Shell Bell") From bb781f21a1652a3667bd908c467e6d5618e368d7 Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 8 Jan 2025 10:27:00 +0000 Subject: [PATCH 37/85] Arbitrary trainer scripts + map script/trigger softlock prevention (#5033) Script_RunImmediatelyUntilEffect runs a script until either a specified effect may occur or it reaches an end. All existing script commands and natives, and some specials, call Script_RequestEffects which allows us to analyze them. Any downstream script commands/natives/specials will be statically known not to call Script_RequestEffects and treated as if they have all effects. Manually tagging them with requests_effects=1 and calling Script_RequestEffects will make them analyzable. Using these, we're able to execute scripts until they either exit with no effect, or would possibly have an effect. This allows us to: 1. Not run on frame map scripts or triggers if they would have no effect. 2. Immediately run triggers if they only affect flags/vars. This removes the lag frames when biking into the Cycling Road, for example. 3. Migrate on load/on transition/on resume/on return to field/on dive warp scripts onto the global script context if they would block (approximated via SCREFF_HARDWARE). 4. Support arbitrary control flow in trainer scripts. The trainer does not see the player if the script has no effect, and the trainer will use whichever trainerbattle command is branched to. 5. Support arbitrary scripts in trainer scripts. cant_see and cant_see_if_* commands have been introduced so that scripts are able to do something when the player interacts with the trainer even if that trainer wouldn't see them. --- asm/macros/event.inc | 158 +++++--- constants/gba_constants.inc | 3 + data/maps/Route110/scripts.inc | 1 + data/script_cmd_table.inc | 469 ++++++++++++------------ data/scripts/trainer_script.inc | 6 + data/specials.inc | 13 +- include/event_scripts.h | 1 + include/script.h | 112 +++++- include/test/overworld_script.h | 11 + src/battle_ai_main.c | 2 + src/battle_main.c | 4 + src/difficulty.c | 10 + src/event_object_movement.c | 22 +- src/fake_rtc.c | 7 + src/field_control_avatar.c | 9 +- src/field_player_avatar.c | 2 + src/main.c | 4 +- src/overworld.c | 5 + src/scrcmd.c | 613 ++++++++++++++++++++++++++++++-- src/script.c | 150 +++++++- src/script_pokemon_util.c | 22 ++ src/trainer_see.c | 74 ++-- test/script.c | 116 ++++++ 23 files changed, 1475 insertions(+), 339 deletions(-) create mode 100644 test/script.c diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 2bb2027cb1..6c1547fafc 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -251,15 +251,26 @@ .endm @ Calls the native C function stored at func. - .macro callnative func:req + @ 'callnative's should set 'requests_effects=1' if the native + @ contains a call to 'Script_RequestEffects', which allows them + @ to be analyzed by 'RunScriptImmediatelyUntilEffect'. + .macro callnative func:req, requests_effects=0 .byte 0x23 + .if \requests_effects == 0 .4byte \func + .else + .4byte \func + ROM_SIZE + .endif .endm @ Replaces the script with the function stored at func. Execution returns to the bytecode script when func returns TRUE. - .macro gotonative func:req + .macro gotonative func:req, requests_effects=0 .byte 0x24 + .if \requests_effects == 0 .4byte \func + .else + .4byte \func + ROM_SIZE + .endif .endm @ Calls a function listed in the table in data/specials.inc. @@ -997,9 +1008,9 @@ @ 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, ggMaxFactor, teraType - callnative ScrCmd_createmon + callnative ScrCmd_createmon, requests_effects=1 .byte 0 - .byte 6 @ PARTY_SIZE - assign to first empty slot + .byte PARTY_SIZE @ assign to first empty slot .set givemon_flags, 0 .2byte \species .2byte \level @@ -1057,7 +1068,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, ggMaxFactor, teraType - callnative ScrCmd_createmon + callnative ScrCmd_createmon, requests_effects=1 .byte \side @ 0 - player, 1 - opponent .byte \slot @ 0-5 .set givemon_flags, 0 @@ -2103,7 +2114,7 @@ .endm .macro setdynamicaifunc func:req - callnative ScriptSetDynamicAiFunc + callnative ScriptSetDynamicAiFunc, requests_effects=1 .4byte \func .endm @@ -2112,7 +2123,7 @@ @ The rest of the arguments are the stat change values to each stat. @ For example, giving the first opponent +1 to atk and -2 to speed would be: settotemboost B_POSITION_OPPONENT_LEFT, 1, 0, -2 .macro settotemboost battler:req, atk=0,def=0,speed=0,spatk=0,spdef=0,acc=0,evas=0 - callnative ScriptSetTotemBoost + callnative ScriptSetTotemBoost, requests_effects=1 .2byte \battler .2byte \atk .2byte \def @@ -2183,21 +2194,21 @@ .macro ai_vs_ai_battle trainer1:req, trainer2:req setflag B_FLAG_AI_VS_AI_BATTLE setvar VAR_0x8004, \trainer1 - callnative CreateTrainerPartyForPlayer + callnative CreateTrainerPartyForPlayer, requests_effects=1 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 + callnative CanHyperTrain, requests_effects=1 .byte \stat .2byte \slot .endm @ Hyper Trains a stat. .macro hypertrain stat:req, slot:req - callnative HyperTrain + callnative HyperTrain, requests_effects=1 .byte \stat .2byte \slot .endm @@ -2205,7 +2216,7 @@ @ Sets VAR_RESULT to TRUE if the Pokemon has the Gigantamax Factor, @ or to FALSE otherwise. .macro hasgigantamaxfactor slot:req - callnative HasGigantamaxFactor + callnative HasGigantamaxFactor, requests_effects=1 .2byte \slot .endm @@ -2213,7 +2224,7 @@ @ Fails for Melmetal (vanilla behavior). @ Sets VAR_RESULT to TRUE if it succeeds, and FALSE otherwise. .macro togglegigantamaxfactor slot:req - callnative ToggleGigantamaxFactor + callnative ToggleGigantamaxFactor, requests_effects=1 .2byte \slot .endm @@ -2251,27 +2262,27 @@ @ Inflicts \status1 to the Pokémon in \slot. @ If \slot is greater or equal than PARTY_SIZE, the status is inflicted on each of the Player's Pokémon. .macro setstatus1 status1:req, slot:req - callnative Script_SetStatus1 + callnative Script_SetStatus1, requests_effects=1 .2byte \status1 .2byte \slot .endm @ Sets VAR_RESULT to the Pokémon in \slot's Tera Type .macro checkteratype slot:req - callnative CheckTeraType + callnative CheckTeraType, requests_effects=1 .2byte \slot .endm @ Sets the Pokémon in \slot's Tera Type .macro setteratype type:req, slot:req - callnative SetTeraType + callnative SetTeraType, requests_effects=1 .byte \type .2byte \slot .endm @ Saves species and forms of Daycare Pokémon to specific vars. Saves the amount of Daycare mon to VAR_RESULT. .macro getdaycaregfx varSpecies1:req varSpecies2:req varForm1:req varForm2:req - callnative GetDaycareGraphics + callnative GetDaycareGraphics, requests_effects=1 .2byte \varSpecies1 .2byte \varSpecies2 .2byte \varForm1 @@ -2280,12 +2291,12 @@ @ Plays the cry of the first alive party member. .macro playfirstmoncry - callnative PlayFirstMonCry + callnative PlayFirstMonCry, requests_effects=1 .endm @ Buffers the nickname of the first alive party member. .macro bufferlivemonnickname out:req - callnative BufferFirstLiveMonNickname + callnative BufferFirstLiveMonNickname, requests_effects=1 .byte \out .endm @@ -2296,13 +2307,13 @@ @ Checks if Field move is being used by the current follower. .macro isfollowerfieldmoveuser var:req - callnative IsFollowerFieldMoveUser + callnative IsFollowerFieldMoveUser, requests_effects=1 .2byte \var .endm @ Saves the direction from where source object event would need to turn to to face the target into the specified var. .macro getdirectiontoface var:req, sourceId:req, targetId:req - callnative GetDirectionToFaceScript + callnative GetDirectionToFaceScript, requests_effects=1 .2byte \var .byte \sourceId .byte \targetId @@ -2311,50 +2322,50 @@ @ set the wild double battle flag @ can be used in conjunection with createmon to set up a wild battle with 2 player mons vs. 1 enemy mon .macro setwilddoubleflag - callnative ScriptSetDoubleBattleFlag + callnative ScriptSetDoubleBattleFlag, requests_effects=1 .endm @ When OW_USE_FAKE_RTC and OW_FLAG_PAUSE_TIME is assigned, this macro will stop the flow of time. .macro pausefakertc - callnative Script_PauseFakeRtc + callnative Script_PauseFakeRtc, requests_effects=1 .endm @ When OW_USE_FAKE_RTC and OW_FLAG_PAUSE_TIME is assigned, this macro will resume the flow of time. .macro resumefakertc - callnative Script_ResumeFakeRtc + callnative Script_ResumeFakeRtc, requests_effects=1 .endm @ When OW_USE_FAKE_RTC and OW_FLAG_PAUSE_TIME is assigned, this macro will resume the flow of time if paused, and stop the flow of time otherwise. .macro togglefakertc - callnative Script_ToggleFakeRtc + callnative Script_ToggleFakeRtc, requests_effects=1 .endm @ ============================ @ @ ITEM DESCRIPTION HEADER MACROS @ Used with OW_SHOW_ITEM_DESCRIPTIONS config .macro showitemdescription - callnative ScriptShowItemDescription + callnative ScriptShowItemDescription, requests_effects=1 .byte 0 .endm .macro showberrydescription - callnative ScriptShowItemDescription + callnative ScriptShowItemDescription, requests_effects=1 .byte 1 .endm .macro hideitemdescription - callnative ScriptHideItemDescription + callnative ScriptHideItemDescription, requests_effects=1 .endm @ Remove all of specified item from the player's bag and return the number of removed items to VAR_RESULT .macro removeallitem itemId:req - callnative ScrCmd_removeallitem + callnative ScrCmd_removeallitem, requests_effects=1 .2byte \itemId .endm @ Stores the position of the given object in destX and destY. Mode CURRENT_POSITION will take the object's current position. Mode TEMPLATE_POSITION will take the object's template position. .macro getobjectxy localId:req, posType:req, destX:req, destY:req - callnative ScrCmd_getobjectxy + callnative ScrCmd_getobjectxy, request_effects=1 .2byte \localId .2byte \posType .2byte \destX @@ -2362,7 +2373,7 @@ .endm .macro getobjecttemplatexy localId:req, posType = TEMPLATE_POSITION, destX:req, destY:req - callnative ScrCmd_getobjectxy + callnative ScrCmd_getobjectxy, request_effects=1 .2byte \localId .2byte \posType .2byte \destX @@ -2370,7 +2381,7 @@ .endm .macro getobjectcurrentxy localId:req, posType = CURRENT_POSITION, destX:req, destY:req - callnative ScrCmd_getobjectxy + callnative ScrCmd_getobjectxy, request_effects=1 .2byte \localId .2byte \posType .2byte \destX @@ -2379,7 +2390,7 @@ @ Return TRUE to dest if there is an object at the position x and y. .macro checkobjectat x:req, y:req, dest = VAR_RESULT - callnative ScrCmd_checkobjectat + callnative ScrCmd_checkobjectat, request_effects=1 .2byte \x .2byte \y .2byte \dest @@ -2387,28 +2398,28 @@ @ Returns the state of the Pokedex Seen Flag to VAR_RESULT for the Pokemon with speciesId .macro getseenmon species:req - callnative Scrcmd_getsetpokedexflag + callnative Scrcmd_getsetpokedexflag, request_effects=1 .2byte \species .2byte FLAG_GET_SEEN .endm @ Returns the state of the Pokedex Caught Flag to VAR_RESULT for the Pokemon with speciesId .macro getcaughtmon species:req - callnative Scrcmd_getsetpokedexflag + callnative Scrcmd_getsetpokedexflag, request_effects=1 .2byte \species .2byte FLAG_GET_CAUGHT .endm @ Sets the Pokedex Seen Flag for the Pokemon with speciesId .macro setseenmon species:req - callnative Scrcmd_getsetpokedexflag + callnative Scrcmd_getsetpokedexflag, request_effects=1 .2byte \species .2byte FLAG_SET_SEEN .endm @ Sets the Pokedex Caught Flag for the Pokemon with speciesId .macro setcaughtmon species:req - callnative Scrcmd_getsetpokedexflag + callnative Scrcmd_getsetpokedexflag, request_effects=1 .2byte \species .2byte FLAG_SET_CAUGHT .endm @@ -2418,10 +2429,10 @@ .if \mode == OPEN_PARTY_SCREEN special ChoosePartyMon waitstate - callnative Scrcmd_checkspecies_choose + callnative Scrcmd_checkspecies_choose, request_effects=1 .2byte \speciesId .else - callnative Scrcmd_checkspecies + callnative Scrcmd_checkspecies, request_effects=1 .2byte \speciesId .endif .endm @@ -2432,24 +2443,85 @@ @ Gets the facing direction of a given event object and stores it in the variable dest. .macro getobjectfacingdirection localId:req, dest:req - callnative Scrcmd_getobjectfacingdirection + callnative Scrcmd_getobjectfacingdirection, request_effects=1 .2byte \localId .2byte \dest .endm .macro increasedifficulty - callnative Script_IncreaseDifficulty + callnative Script_IncreaseDifficulty, requests_effects=1 .endm .macro decreasedifficulty - callnative Script_DecreaseDifficulty + callnative Script_DecreaseDifficulty, requests_effects=1 .endm .macro getdifficulty var:req - callnative Script_GetDifficulty + callnative Script_GetDifficulty, requests_effects=1 .endm .macro setdifficulty difficulty:req - callnative Script_SetDifficulty + callnative Script_SetDifficulty, requests_effects=1 .byte \difficulty .endm + + @ Makes the trainer unable to see the player if executed. + @ This is a no-op if the player interacts with the trainer. + .macro cant_see_if, condition:req + callnative Script_EndTrainerCanSeeIf, requests_effects=1 + .byte \condition + .endm + + .macro cant_see + cant_see_if_unset 0 @ flag 0 is always FALSE. + .endm + + .macro cant_see_if_unset, flag:req + checkflag \flag + cant_see_if FALSE + .endm + + .macro cant_see_if_set, flag:req + checkflag \flag + cant_see_if TRUE + .endm + + .macro cant_see_if_trainerflag_unset, trainer:req + checktrainerflag \trainer + cant_see_if FALSE + .endm + + .macro cant_see_if_trainerflag_set, trainer:req + checktrainerflag \trainer + cant_see_if TRUE + .endm + + .macro cant_see_if_lt, a:req, b:req + compare \a, \b + cant_see_if 0 + .endm + + .macro cant_see_if_eq, a:req, b:req + compare \a, \b + cant_see_if 1 + .endm + + .macro cant_see_if_gt, a:req, b:req + compare \a, \b + cant_see_if 2 + .endm + + .macro cant_see_if_le, a:req, b:req + compare \a, \b + cant_see_if 3 + .endm + + .macro cant_see_if_ge, a:req, b:req + compare \a, \b + cant_see_if 4 + .endm + + .macro cant_see_if_ne, a:req, b:req + compare \a, \b + cant_see_if 5 + .endm diff --git a/constants/gba_constants.inc b/constants/gba_constants.inc index 9f51b0f02b..febb1244d0 100644 --- a/constants/gba_constants.inc +++ b/constants/gba_constants.inc @@ -29,6 +29,9 @@ .set OAM, 0x7000000 + .set ROM, 0x8000000 + .set ROM_SIZE, 0x2000000 + .set SOUND_INFO_PTR, 0x3007FF0 .set INTR_CHECK, 0x3007FF8 .set INTR_VECTOR, 0x3007FFC diff --git a/data/maps/Route110/scripts.inc b/data/maps/Route110/scripts.inc index 8447604aca..7c494a586d 100644 --- a/data/maps/Route110/scripts.inc +++ b/data/maps/Route110/scripts.inc @@ -11,6 +11,7 @@ Route110_MapScripts:: Route110_OnResume: special UpdateCyclingRoadState + msgbox Route110_Text_WeCantTalkAboutAquaActivities, MSGBOX_SIGN end Route110_OnTransition: diff --git a/data/script_cmd_table.inc b/data/script_cmd_table.inc index 711b118cc6..61046e6cb4 100644 --- a/data/script_cmd_table.inc +++ b/data/script_cmd_table.inc @@ -1,234 +1,245 @@ +@ 'requests_effects' should be set to 1 if the command contains a call +@ to 'Script_RequestEffects', which allows it to be analyzed with +@ 'RunScriptImmediatelyUntilEffect'. +.macro cmd func:req, requests_effects=0 + .if \requests_effects == 0 + .4byte \func + .else + .4byte \func + ROM_SIZE + .endif +.endm + .align 2 gScriptCmdTable:: - .4byte ScrCmd_nop @ 0x00 - .4byte ScrCmd_nop1 @ 0x01 - .4byte ScrCmd_end @ 0x02 - .4byte ScrCmd_return @ 0x03 - .4byte ScrCmd_call @ 0x04 - .4byte ScrCmd_goto @ 0x05 - .4byte ScrCmd_goto_if @ 0x06 - .4byte ScrCmd_call_if @ 0x07 - .4byte ScrCmd_gotostd @ 0x08 - .4byte ScrCmd_callstd @ 0x09 - .4byte ScrCmd_gotostd_if @ 0x0a - .4byte ScrCmd_callstd_if @ 0x0b - .4byte ScrCmd_returnram @ 0x0c - .4byte ScrCmd_endram @ 0x0d - .4byte ScrCmd_setmysteryeventstatus @ 0x0e - .4byte ScrCmd_loadword @ 0x0f - .4byte ScrCmd_loadbyte @ 0x10 - .4byte ScrCmd_setptr @ 0x11 - .4byte ScrCmd_loadbytefromptr @ 0x12 - .4byte ScrCmd_setptrbyte @ 0x13 - .4byte ScrCmd_copylocal @ 0x14 - .4byte ScrCmd_copybyte @ 0x15 - .4byte ScrCmd_setvar @ 0x16 - .4byte ScrCmd_addvar @ 0x17 - .4byte ScrCmd_subvar @ 0x18 - .4byte ScrCmd_copyvar @ 0x19 - .4byte ScrCmd_setorcopyvar @ 0x1a - .4byte ScrCmd_compare_local_to_local @ 0x1b - .4byte ScrCmd_compare_local_to_value @ 0x1c - .4byte ScrCmd_compare_local_to_ptr @ 0x1d - .4byte ScrCmd_compare_ptr_to_local @ 0x1e - .4byte ScrCmd_compare_ptr_to_value @ 0x1f - .4byte ScrCmd_compare_ptr_to_ptr @ 0x20 - .4byte ScrCmd_compare_var_to_value @ 0x21 - .4byte ScrCmd_compare_var_to_var @ 0x22 - .4byte ScrCmd_callnative @ 0x23 - .4byte ScrCmd_gotonative @ 0x24 - .4byte ScrCmd_special @ 0x25 - .4byte ScrCmd_specialvar @ 0x26 - .4byte ScrCmd_waitstate @ 0x27 - .4byte ScrCmd_delay @ 0x28 - .4byte ScrCmd_setflag @ 0x29 - .4byte ScrCmd_clearflag @ 0x2a - .4byte ScrCmd_checkflag @ 0x2b - .4byte ScrCmd_initclock @ 0x2c - .4byte ScrCmd_dotimebasedevents @ 0x2d - .4byte ScrCmd_gettime @ 0x2e - .4byte ScrCmd_playse @ 0x2f - .4byte ScrCmd_waitse @ 0x30 - .4byte ScrCmd_playfanfare @ 0x31 - .4byte ScrCmd_waitfanfare @ 0x32 - .4byte ScrCmd_playbgm @ 0x33 - .4byte ScrCmd_savebgm @ 0x34 - .4byte ScrCmd_fadedefaultbgm @ 0x35 - .4byte ScrCmd_fadenewbgm @ 0x36 - .4byte ScrCmd_fadeoutbgm @ 0x37 - .4byte ScrCmd_fadeinbgm @ 0x38 - .4byte ScrCmd_warp @ 0x39 - .4byte ScrCmd_warpsilent @ 0x3a - .4byte ScrCmd_warpdoor @ 0x3b - .4byte ScrCmd_warphole @ 0x3c - .4byte ScrCmd_warpteleport @ 0x3d - .4byte ScrCmd_setwarp @ 0x3e - .4byte ScrCmd_setdynamicwarp @ 0x3f - .4byte ScrCmd_setdivewarp @ 0x40 - .4byte ScrCmd_setholewarp @ 0x41 - .4byte ScrCmd_getplayerxy @ 0x42 - .4byte ScrCmd_getpartysize @ 0x43 - .4byte ScrCmd_additem @ 0x44 - .4byte ScrCmd_removeitem @ 0x45 - .4byte ScrCmd_checkitemspace @ 0x46 - .4byte ScrCmd_checkitem @ 0x47 - .4byte ScrCmd_checkitemtype @ 0x48 - .4byte ScrCmd_addpcitem @ 0x49 - .4byte ScrCmd_checkpcitem @ 0x4a - .4byte ScrCmd_adddecoration @ 0x4b - .4byte ScrCmd_removedecoration @ 0x4c - .4byte ScrCmd_checkdecor @ 0x4d - .4byte ScrCmd_checkdecorspace @ 0x4e - .4byte ScrCmd_applymovement @ 0x4f - .4byte ScrCmd_applymovementat @ 0x50 - .4byte ScrCmd_waitmovement @ 0x51 - .4byte ScrCmd_waitmovementat @ 0x52 - .4byte ScrCmd_removeobject @ 0x53 - .4byte ScrCmd_removeobjectat @ 0x54 - .4byte ScrCmd_addobject @ 0x55 - .4byte ScrCmd_addobjectat @ 0x56 - .4byte ScrCmd_setobjectxy @ 0x57 - .4byte ScrCmd_showobjectat @ 0x58 - .4byte ScrCmd_hideobjectat @ 0x59 - .4byte ScrCmd_faceplayer @ 0x5a - .4byte ScrCmd_turnobject @ 0x5b - .4byte ScrCmd_trainerbattle @ 0x5c - .4byte ScrCmd_dotrainerbattle @ 0x5d - .4byte ScrCmd_gotopostbattlescript @ 0x5e - .4byte ScrCmd_gotobeatenscript @ 0x5f - .4byte ScrCmd_checktrainerflag @ 0x60 - .4byte ScrCmd_settrainerflag @ 0x61 - .4byte ScrCmd_cleartrainerflag @ 0x62 - .4byte ScrCmd_setobjectxyperm @ 0x63 - .4byte ScrCmd_copyobjectxytoperm @ 0x64 - .4byte ScrCmd_setobjectmovementtype @ 0x65 - .4byte ScrCmd_waitmessage @ 0x66 - .4byte ScrCmd_message @ 0x67 - .4byte ScrCmd_closemessage @ 0x68 - .4byte ScrCmd_lockall @ 0x69 - .4byte ScrCmd_lock @ 0x6a - .4byte ScrCmd_releaseall @ 0x6b - .4byte ScrCmd_release @ 0x6c - .4byte ScrCmd_waitbuttonpress @ 0x6d - .4byte ScrCmd_yesnobox @ 0x6e - .4byte ScrCmd_multichoice @ 0x6f - .4byte ScrCmd_multichoicedefault @ 0x70 - .4byte ScrCmd_multichoicegrid @ 0x71 - .4byte ScrCmd_drawbox @ 0x72 - .4byte ScrCmd_erasebox @ 0x73 - .4byte ScrCmd_drawboxtext @ 0x74 - .4byte ScrCmd_showmonpic @ 0x75 - .4byte ScrCmd_hidemonpic @ 0x76 - .4byte ScrCmd_showcontestpainting @ 0x77 - .4byte ScrCmd_braillemessage @ 0x78 - .4byte ScrCmd_nop1 @ 0x79 - .4byte ScrCmd_giveegg @ 0x7a - .4byte ScrCmd_setmonmove @ 0x7b - .4byte ScrCmd_checkpartymove @ 0x7c - .4byte ScrCmd_bufferspeciesname @ 0x7d - .4byte ScrCmd_bufferleadmonspeciesname @ 0x7e - .4byte ScrCmd_bufferpartymonnick @ 0x7f - .4byte ScrCmd_bufferitemname @ 0x80 - .4byte ScrCmd_bufferdecorationname @ 0x81 - .4byte ScrCmd_buffermovename @ 0x82 - .4byte ScrCmd_buffernumberstring @ 0x83 - .4byte ScrCmd_bufferstdstring @ 0x84 - .4byte ScrCmd_bufferstring @ 0x85 - .4byte ScrCmd_pokemart @ 0x86 - .4byte ScrCmd_pokemartdecoration @ 0x87 - .4byte ScrCmd_pokemartdecoration2 @ 0x88 - .4byte ScrCmd_playslotmachine @ 0x89 - .4byte ScrCmd_setberrytree @ 0x8a - .4byte ScrCmd_choosecontestmon @ 0x8b - .4byte ScrCmd_startcontest @ 0x8c - .4byte ScrCmd_showcontestresults @ 0x8d - .4byte ScrCmd_contestlinktransfer @ 0x8e - .4byte ScrCmd_random @ 0x8f - .4byte ScrCmd_addmoney @ 0x90 - .4byte ScrCmd_removemoney @ 0x91 - .4byte ScrCmd_checkmoney @ 0x92 - .4byte ScrCmd_showmoneybox @ 0x93 - .4byte ScrCmd_hidemoneybox @ 0x94 - .4byte ScrCmd_updatemoneybox @ 0x95 - .4byte ScrCmd_getpokenewsactive @ 0x96 - .4byte ScrCmd_fadescreen @ 0x97 - .4byte ScrCmd_fadescreenspeed @ 0x98 - .4byte ScrCmd_setflashlevel @ 0x99 - .4byte ScrCmd_animateflash @ 0x9a - .4byte ScrCmd_messageautoscroll @ 0x9b - .4byte ScrCmd_dofieldeffect @ 0x9c - .4byte ScrCmd_setfieldeffectargument @ 0x9d - .4byte ScrCmd_waitfieldeffect @ 0x9e - .4byte ScrCmd_setrespawn @ 0x9f - .4byte ScrCmd_checkplayergender @ 0xa0 - .4byte ScrCmd_playmoncry @ 0xa1 - .4byte ScrCmd_setmetatile @ 0xa2 - .4byte ScrCmd_resetweather @ 0xa3 - .4byte ScrCmd_setweather @ 0xa4 - .4byte ScrCmd_doweather @ 0xa5 - .4byte ScrCmd_setstepcallback @ 0xa6 - .4byte ScrCmd_setmaplayoutindex @ 0xa7 - .4byte ScrCmd_setobjectsubpriority @ 0xa8 - .4byte ScrCmd_resetobjectsubpriority @ 0xa9 - .4byte ScrCmd_createvobject @ 0xaa - .4byte ScrCmd_turnvobject @ 0xab - .4byte ScrCmd_opendoor @ 0xac - .4byte ScrCmd_closedoor @ 0xad - .4byte ScrCmd_waitdooranim @ 0xae - .4byte ScrCmd_setdooropen @ 0xaf - .4byte ScrCmd_setdoorclosed @ 0xb0 - .4byte ScrCmd_addelevmenuitem @ 0xb1 - .4byte ScrCmd_showelevmenu @ 0xb2 - .4byte ScrCmd_checkcoins @ 0xb3 - .4byte ScrCmd_addcoins @ 0xb4 - .4byte ScrCmd_removecoins @ 0xb5 - .4byte ScrCmd_setwildbattle @ 0xb6 - .4byte ScrCmd_dowildbattle @ 0xb7 - .4byte ScrCmd_setvaddress @ 0xb8 - .4byte ScrCmd_vgoto @ 0xb9 - .4byte ScrCmd_vcall @ 0xba - .4byte ScrCmd_vgoto_if @ 0xbb - .4byte ScrCmd_vcall_if @ 0xbc - .4byte ScrCmd_vmessage @ 0xbd - .4byte ScrCmd_vbuffermessage @ 0xbe - .4byte ScrCmd_vbufferstring @ 0xbf - .4byte ScrCmd_showcoinsbox @ 0xc0 - .4byte ScrCmd_hidecoinsbox @ 0xc1 - .4byte ScrCmd_updatecoinsbox @ 0xc2 - .4byte ScrCmd_incrementgamestat @ 0xc3 - .4byte ScrCmd_setescapewarp @ 0xc4 - .4byte ScrCmd_waitmoncry @ 0xc5 - .4byte ScrCmd_bufferboxname @ 0xc6 - .4byte ScrCmd_nop1 @ 0xc7 - .4byte ScrCmd_nop1 @ 0xc8 - .4byte ScrCmd_nop1 @ 0xc9 - .4byte ScrCmd_nop1 @ 0xca - .4byte ScrCmd_nop1 @ 0xcb - .4byte ScrCmd_nop1 @ 0xcc - .4byte ScrCmd_setmodernfatefulencounter @ 0xcd - .4byte ScrCmd_checkmodernfatefulencounter @ 0xce - .4byte ScrCmd_trywondercardscript @ 0xcf - .4byte ScrCmd_nop1 @ 0xd0 - .4byte ScrCmd_warpspinenter @ 0xd1 - .4byte ScrCmd_setmonmetlocation @ 0xd2 - .4byte ScrCmd_moverotatingtileobjects @ 0xd3 - .4byte ScrCmd_turnrotatingtileobjects @ 0xd4 - .4byte ScrCmd_initrotatingtilepuzzle @ 0xd5 - .4byte ScrCmd_freerotatingtilepuzzle @ 0xd6 - .4byte ScrCmd_warpmossdeepgym @ 0xd7 - .4byte ScrCmd_selectapproachingtrainer @ 0xd8 - .4byte ScrCmd_lockfortrainer @ 0xd9 - .4byte ScrCmd_closebraillemessage @ 0xda - .4byte ScrCmd_messageinstant @ 0xdb - .4byte ScrCmd_fadescreenswapbuffers @ 0xdc - .4byte ScrCmd_buffertrainerclassname @ 0xdd - .4byte ScrCmd_buffertrainername @ 0xde - .4byte ScrCmd_pokenavcall @ 0xdf - .4byte ScrCmd_warpwhitefade @ 0xe0 - .4byte ScrCmd_buffercontestname @ 0xe1 - .4byte ScrCmd_bufferitemnameplural @ 0xe2 - .4byte ScrCmd_dynmultichoice @ 0xe3 - .4byte ScrCmd_dynmultipush @ 0xe4 + cmd ScrCmd_nop, requests_effects=1 @ 0x00 + cmd ScrCmd_nop1, requests_effects=1 @ 0x01 + cmd ScrCmd_end, requests_effects=1 @ 0x02 + cmd ScrCmd_return, requests_effects=1 @ 0x03 + cmd ScrCmd_call, requests_effects=1 @ 0x04 + cmd ScrCmd_goto, requests_effects=1 @ 0x05 + cmd ScrCmd_goto_if, requests_effects=1 @ 0x06 + cmd ScrCmd_call_if, requests_effects=1 @ 0x07 + cmd ScrCmd_gotostd, requests_effects=1 @ 0x08 + cmd ScrCmd_callstd, requests_effects=1 @ 0x09 + cmd ScrCmd_gotostd_if, requests_effects=1 @ 0x0a + cmd ScrCmd_callstd_if, requests_effects=1 @ 0x0b + cmd ScrCmd_returnram, requests_effects=1 @ 0x0c + cmd ScrCmd_endram, requests_effects=1 @ 0x0d + cmd ScrCmd_setmysteryeventstatus, requests_effects=1 @ 0x0e + cmd ScrCmd_loadword, requests_effects=1 @ 0x0f + cmd ScrCmd_loadbyte, requests_effects=1 @ 0x10 + cmd ScrCmd_setptr, requests_effects=1 @ 0x11 + cmd ScrCmd_loadbytefromptr, requests_effects=1 @ 0x12 + cmd ScrCmd_setptrbyte, requests_effects=1 @ 0x13 + cmd ScrCmd_copylocal, requests_effects=1 @ 0x14 + cmd ScrCmd_copybyte, requests_effects=1 @ 0x15 + cmd ScrCmd_setvar, requests_effects=1 @ 0x16 + cmd ScrCmd_addvar, requests_effects=1 @ 0x17 + cmd ScrCmd_subvar, requests_effects=1 @ 0x18 + cmd ScrCmd_copyvar, requests_effects=1 @ 0x19 + cmd ScrCmd_setorcopyvar, requests_effects=1 @ 0x1a + cmd ScrCmd_compare_local_to_local, requests_effects=1 @ 0x1b + cmd ScrCmd_compare_local_to_value, requests_effects=1 @ 0x1c + cmd ScrCmd_compare_local_to_ptr, requests_effects=1 @ 0x1d + cmd ScrCmd_compare_ptr_to_local, requests_effects=1 @ 0x1e + cmd ScrCmd_compare_ptr_to_value, requests_effects=1 @ 0x1f + cmd ScrCmd_compare_ptr_to_ptr, requests_effects=1 @ 0x20 + cmd ScrCmd_compare_var_to_value, requests_effects=1 @ 0x21 + cmd ScrCmd_compare_var_to_var, requests_effects=1 @ 0x22 + cmd ScrCmd_callnative, requests_effects=1 @ 0x23 + cmd ScrCmd_gotonative, requests_effects=1 @ 0x24 + cmd ScrCmd_special, requests_effects=1 @ 0x25 + cmd ScrCmd_specialvar, requests_effects=1 @ 0x26 + cmd ScrCmd_waitstate, requests_effects=1 @ 0x27 + cmd ScrCmd_delay, requests_effects=1 @ 0x28 + cmd ScrCmd_setflag, requests_effects=1 @ 0x29 + cmd ScrCmd_clearflag, requests_effects=1 @ 0x2a + cmd ScrCmd_checkflag, requests_effects=1 @ 0x2b + cmd ScrCmd_initclock, requests_effects=1 @ 0x2c + cmd ScrCmd_dotimebasedevents, requests_effects=1 @ 0x2d + cmd ScrCmd_gettime, requests_effects=1 @ 0x2e + cmd ScrCmd_playse, requests_effects=1 @ 0x2f + cmd ScrCmd_waitse, requests_effects=1 @ 0x30 + cmd ScrCmd_playfanfare, requests_effects=1 @ 0x31 + cmd ScrCmd_waitfanfare, requests_effects=1 @ 0x32 + cmd ScrCmd_playbgm, requests_effects=1 @ 0x33 + cmd ScrCmd_savebgm, requests_effects=1 @ 0x34 + cmd ScrCmd_fadedefaultbgm, requests_effects=1 @ 0x35 + cmd ScrCmd_fadenewbgm, requests_effects=1 @ 0x36 + cmd ScrCmd_fadeoutbgm, requests_effects=1 @ 0x37 + cmd ScrCmd_fadeinbgm, requests_effects=1 @ 0x38 + cmd ScrCmd_warp, requests_effects=1 @ 0x39 + cmd ScrCmd_warpsilent, requests_effects=1 @ 0x3a + cmd ScrCmd_warpdoor, requests_effects=1 @ 0x3b + cmd ScrCmd_warphole, requests_effects=1 @ 0x3c + cmd ScrCmd_warpteleport, requests_effects=1 @ 0x3d + cmd ScrCmd_setwarp, requests_effects=1 @ 0x3e + cmd ScrCmd_setdynamicwarp, requests_effects=1 @ 0x3f + cmd ScrCmd_setdivewarp, requests_effects=1 @ 0x40 + cmd ScrCmd_setholewarp, requests_effects=1 @ 0x41 + cmd ScrCmd_getplayerxy, requests_effects=1 @ 0x42 + cmd ScrCmd_getpartysize, requests_effects=1 @ 0x43 + cmd ScrCmd_additem, requests_effects=1 @ 0x44 + cmd ScrCmd_removeitem, requests_effects=1 @ 0x45 + cmd ScrCmd_checkitemspace, requests_effects=1 @ 0x46 + cmd ScrCmd_checkitem, requests_effects=1 @ 0x47 + cmd ScrCmd_checkitemtype, requests_effects=1 @ 0x48 + cmd ScrCmd_addpcitem, requests_effects=1 @ 0x49 + cmd ScrCmd_checkpcitem, requests_effects=1 @ 0x4a + cmd ScrCmd_adddecoration, requests_effects=1 @ 0x4b + cmd ScrCmd_removedecoration, requests_effects=1 @ 0x4c + cmd ScrCmd_checkdecor, requests_effects=1 @ 0x4d + cmd ScrCmd_checkdecorspace, requests_effects=1 @ 0x4e + cmd ScrCmd_applymovement, requests_effects=1 @ 0x4f + cmd ScrCmd_applymovementat, requests_effects=1 @ 0x50 + cmd ScrCmd_waitmovement, requests_effects=1 @ 0x51 + cmd ScrCmd_waitmovementat, requests_effects=1 @ 0x52 + cmd ScrCmd_removeobject, requests_effects=1 @ 0x53 + cmd ScrCmd_removeobjectat, requests_effects=1 @ 0x54 + cmd ScrCmd_addobject, requests_effects=1 @ 0x55 + cmd ScrCmd_addobjectat, requests_effects=1 @ 0x56 + cmd ScrCmd_setobjectxy, requests_effects=1 @ 0x57 + cmd ScrCmd_showobjectat, requests_effects=1 @ 0x58 + cmd ScrCmd_hideobjectat, requests_effects=1 @ 0x59 + cmd ScrCmd_faceplayer, requests_effects=1 @ 0x5a + cmd ScrCmd_turnobject, requests_effects=1 @ 0x5b + cmd ScrCmd_trainerbattle, requests_effects=1 @ 0x5c + cmd ScrCmd_dotrainerbattle, requests_effects=1 @ 0x5d + cmd ScrCmd_gotopostbattlescript, requests_effects=1 @ 0x5e + cmd ScrCmd_gotobeatenscript, requests_effects=1 @ 0x5f + cmd ScrCmd_checktrainerflag, requests_effects=1 @ 0x60 + cmd ScrCmd_settrainerflag, requests_effects=1 @ 0x61 + cmd ScrCmd_cleartrainerflag, requests_effects=1 @ 0x62 + cmd ScrCmd_setobjectxyperm, requests_effects=1 @ 0x63 + cmd ScrCmd_copyobjectxytoperm, requests_effects=1 @ 0x64 + cmd ScrCmd_setobjectmovementtype, requests_effects=1 @ 0x65 + cmd ScrCmd_waitmessage, requests_effects=1 @ 0x66 + cmd ScrCmd_message, requests_effects=1 @ 0x67 + cmd ScrCmd_closemessage, requests_effects=1 @ 0x68 + cmd ScrCmd_lockall, requests_effects=1 @ 0x69 + cmd ScrCmd_lock, requests_effects=1 @ 0x6a + cmd ScrCmd_releaseall, requests_effects=1 @ 0x6b + cmd ScrCmd_release, requests_effects=1 @ 0x6c + cmd ScrCmd_waitbuttonpress, requests_effects=1 @ 0x6d + cmd ScrCmd_yesnobox, requests_effects=1 @ 0x6e + cmd ScrCmd_multichoice, requests_effects=1 @ 0x6f + cmd ScrCmd_multichoicedefault, requests_effects=1 @ 0x70 + cmd ScrCmd_multichoicegrid, requests_effects=1 @ 0x71 + cmd ScrCmd_drawbox, requests_effects=1 @ 0x72 + cmd ScrCmd_erasebox, requests_effects=1 @ 0x73 + cmd ScrCmd_drawboxtext, requests_effects=1 @ 0x74 + cmd ScrCmd_showmonpic, requests_effects=1 @ 0x75 + cmd ScrCmd_hidemonpic, requests_effects=1 @ 0x76 + cmd ScrCmd_showcontestpainting, requests_effects=1 @ 0x77 + cmd ScrCmd_braillemessage, requests_effects=1 @ 0x78 + cmd ScrCmd_nop1, requests_effects=1 @ 0x79 + cmd ScrCmd_giveegg, requests_effects=1 @ 0x7a + cmd ScrCmd_setmonmove, requests_effects=1 @ 0x7b + cmd ScrCmd_checkpartymove, requests_effects=1 @ 0x7c + cmd ScrCmd_bufferspeciesname, requests_effects=1 @ 0x7d + cmd ScrCmd_bufferleadmonspeciesname, requests_effects=1 @ 0x7e + cmd ScrCmd_bufferpartymonnick, requests_effects=1 @ 0x7f + cmd ScrCmd_bufferitemname, requests_effects=1 @ 0x80 + cmd ScrCmd_bufferdecorationname, requests_effects=1 @ 0x81 + cmd ScrCmd_buffermovename, requests_effects=1 @ 0x82 + cmd ScrCmd_buffernumberstring, requests_effects=1 @ 0x83 + cmd ScrCmd_bufferstdstring, requests_effects=1 @ 0x84 + cmd ScrCmd_bufferstring, requests_effects=1 @ 0x85 + cmd ScrCmd_pokemart, requests_effects=1 @ 0x86 + cmd ScrCmd_pokemartdecoration, requests_effects=1 @ 0x87 + cmd ScrCmd_pokemartdecoration2, requests_effects=1 @ 0x88 + cmd ScrCmd_playslotmachine, requests_effects=1 @ 0x89 + cmd ScrCmd_setberrytree, requests_effects=1 @ 0x8a + cmd ScrCmd_choosecontestmon, requests_effects=1 @ 0x8b + cmd ScrCmd_startcontest, requests_effects=1 @ 0x8c + cmd ScrCmd_showcontestresults, requests_effects=1 @ 0x8d + cmd ScrCmd_contestlinktransfer, requests_effects=1 @ 0x8e + cmd ScrCmd_random, requests_effects=1 @ 0x8f + cmd ScrCmd_addmoney, requests_effects=1 @ 0x90 + cmd ScrCmd_removemoney, requests_effects=1 @ 0x91 + cmd ScrCmd_checkmoney, requests_effects=1 @ 0x92 + cmd ScrCmd_showmoneybox, requests_effects=1 @ 0x93 + cmd ScrCmd_hidemoneybox, requests_effects=1 @ 0x94 + cmd ScrCmd_updatemoneybox, requests_effects=1 @ 0x95 + cmd ScrCmd_getpokenewsactive, requests_effects=1 @ 0x96 + cmd ScrCmd_fadescreen, requests_effects=1 @ 0x97 + cmd ScrCmd_fadescreenspeed, requests_effects=1 @ 0x98 + cmd ScrCmd_setflashlevel, requests_effects=1 @ 0x99 + cmd ScrCmd_animateflash, requests_effects=1 @ 0x9a + cmd ScrCmd_messageautoscroll, requests_effects=1 @ 0x9b + cmd ScrCmd_dofieldeffect, requests_effects=1 @ 0x9c + cmd ScrCmd_setfieldeffectargument, requests_effects=1 @ 0x9d + cmd ScrCmd_waitfieldeffect, requests_effects=1 @ 0x9e + cmd ScrCmd_setrespawn, requests_effects=1 @ 0x9f + cmd ScrCmd_checkplayergender, requests_effects=1 @ 0xa0 + cmd ScrCmd_playmoncry, requests_effects=1 @ 0xa1 + cmd ScrCmd_setmetatile, requests_effects=1 @ 0xa2 + cmd ScrCmd_resetweather, requests_effects=1 @ 0xa3 + cmd ScrCmd_setweather, requests_effects=1 @ 0xa4 + cmd ScrCmd_doweather, requests_effects=1 @ 0xa5 + cmd ScrCmd_setstepcallback, requests_effects=1 @ 0xa6 + cmd ScrCmd_setmaplayoutindex, requests_effects=1 @ 0xa7 + cmd ScrCmd_setobjectsubpriority, requests_effects=1 @ 0xa8 + cmd ScrCmd_resetobjectsubpriority, requests_effects=1 @ 0xa9 + cmd ScrCmd_createvobject, requests_effects=1 @ 0xaa + cmd ScrCmd_turnvobject, requests_effects=1 @ 0xab + cmd ScrCmd_opendoor, requests_effects=1 @ 0xac + cmd ScrCmd_closedoor, requests_effects=1 @ 0xad + cmd ScrCmd_waitdooranim, requests_effects=1 @ 0xae + cmd ScrCmd_setdooropen, requests_effects=1 @ 0xaf + cmd ScrCmd_setdoorclosed, requests_effects=1 @ 0xb0 + cmd ScrCmd_addelevmenuitem, requests_effects=1 @ 0xb1 + cmd ScrCmd_showelevmenu, requests_effects=1 @ 0xb2 + cmd ScrCmd_checkcoins, requests_effects=1 @ 0xb3 + cmd ScrCmd_addcoins, requests_effects=1 @ 0xb4 + cmd ScrCmd_removecoins, requests_effects=1 @ 0xb5 + cmd ScrCmd_setwildbattle, requests_effects=1 @ 0xb6 + cmd ScrCmd_dowildbattle, requests_effects=1 @ 0xb7 + cmd ScrCmd_setvaddress, requests_effects=1 @ 0xb8 + cmd ScrCmd_vgoto, requests_effects=1 @ 0xb9 + cmd ScrCmd_vcall, requests_effects=1 @ 0xba + cmd ScrCmd_vgoto_if, requests_effects=1 @ 0xbb + cmd ScrCmd_vcall_if, requests_effects=1 @ 0xbc + cmd ScrCmd_vmessage, requests_effects=1 @ 0xbd + cmd ScrCmd_vbuffermessage, requests_effects=1 @ 0xbe + cmd ScrCmd_vbufferstring, requests_effects=1 @ 0xbf + cmd ScrCmd_showcoinsbox, requests_effects=1 @ 0xc0 + cmd ScrCmd_hidecoinsbox, requests_effects=1 @ 0xc1 + cmd ScrCmd_updatecoinsbox, requests_effects=1 @ 0xc2 + cmd ScrCmd_incrementgamestat, requests_effects=1 @ 0xc3 + cmd ScrCmd_setescapewarp, requests_effects=1 @ 0xc4 + cmd ScrCmd_waitmoncry, requests_effects=1 @ 0xc5 + cmd ScrCmd_bufferboxname, requests_effects=1 @ 0xc6 + cmd ScrCmd_nop1, requests_effects=1 @ 0xc7 + cmd ScrCmd_nop1, requests_effects=1 @ 0xc8 + cmd ScrCmd_nop1, requests_effects=1 @ 0xc9 + cmd ScrCmd_nop1, requests_effects=1 @ 0xca + cmd ScrCmd_nop1, requests_effects=1 @ 0xcb + cmd ScrCmd_nop1, requests_effects=1 @ 0xcc + cmd ScrCmd_setmodernfatefulencounter, requests_effects=1 @ 0xcd + cmd ScrCmd_checkmodernfatefulencounter, requests_effects=1 @ 0xce + cmd ScrCmd_trywondercardscript, requests_effects=1 @ 0xcf + cmd ScrCmd_nop1, requests_effects=1 @ 0xd0 + cmd ScrCmd_warpspinenter, requests_effects=1 @ 0xd1 + cmd ScrCmd_setmonmetlocation, requests_effects=1 @ 0xd2 + cmd ScrCmd_moverotatingtileobjects, requests_effects=1 @ 0xd3 + cmd ScrCmd_turnrotatingtileobjects, requests_effects=1 @ 0xd4 + cmd ScrCmd_initrotatingtilepuzzle, requests_effects=1 @ 0xd5 + cmd ScrCmd_freerotatingtilepuzzle, requests_effects=1 @ 0xd6 + cmd ScrCmd_warpmossdeepgym, requests_effects=1 @ 0xd7 + cmd ScrCmd_selectapproachingtrainer, requests_effects=1 @ 0xd8 + cmd ScrCmd_lockfortrainer, requests_effects=1 @ 0xd9 + cmd ScrCmd_closebraillemessage, requests_effects=1 @ 0xda + cmd ScrCmd_messageinstant, requests_effects=1 @ 0xdb + cmd ScrCmd_fadescreenswapbuffers, requests_effects=1 @ 0xdc + cmd ScrCmd_buffertrainerclassname, requests_effects=1 @ 0xdd + cmd ScrCmd_buffertrainername, requests_effects=1 @ 0xde + cmd ScrCmd_pokenavcall, requests_effects=1 @ 0xdf + cmd ScrCmd_warpwhitefade, requests_effects=1 @ 0xe0 + cmd ScrCmd_buffercontestname, requests_effects=1 @ 0xe1 + cmd ScrCmd_bufferitemnameplural, requests_effects=1 @ 0xe2 + cmd ScrCmd_dynmultichoice, requests_effects=1 @ 0xe3 + cmd ScrCmd_dynmultipush, requests_effects=1 @ 0xe4 gScriptCmdTableEnd:: .4byte ScrCmd_nop diff --git a/data/scripts/trainer_script.inc b/data/scripts/trainer_script.inc index c0998aef8e..aad79334ab 100644 --- a/data/scripts/trainer_script.inc +++ b/data/scripts/trainer_script.inc @@ -20,3 +20,9 @@ EventScript_GotoTrainerScript:: gotobeatenscript releaseall end + +EventScript_ObjectApproachPlayer:: + lock + special DoTrainerApproach + waitstate + gotonative LoadTrainerObjectScript diff --git a/data/specials.inc b/data/specials.inc index 4d2bea3d33..9bf3734491 100644 --- a/data/specials.inc +++ b/data/specials.inc @@ -1,9 +1,16 @@ -.macro def_special ptr +@ 'requests_effects' should be set to 1 if the special contains a call +@ to 'Script_RequestEffects', which allows it to be analyzed with +@ 'RunScriptImmediatelyUntilEffect'. +.macro def_special ptr:req, requests_effects=0 .global SPECIAL_\ptr .set SPECIAL_\ptr, __special__ .set __special__, __special__ + 1 + .if \requests_effects == 0 .4byte \ptr - .endm + .else + .4byte \ptr + ROM_SIZE + .endif +.endm .set __special__, 0 .align 2 @@ -297,7 +304,7 @@ gSpecials:: def_special WaitWeather def_special BufferEReaderTrainerName def_special GetSlotMachineId - def_special GetPlayerFacingDirection + def_special GetPlayerFacingDirection, requests_effects=TRUE def_special FoundAbandonedShipRoom1Key def_special FoundAbandonedShipRoom2Key def_special FoundAbandonedShipRoom4Key diff --git a/include/event_scripts.h b/include/event_scripts.h index 133d9fa98b..782576a30a 100644 --- a/include/event_scripts.h +++ b/include/event_scripts.h @@ -36,6 +36,7 @@ extern const u8 EventScript_TryDoDoubleTrainerBattle[]; extern const u8 EventScript_TryDoNormalTrainerBattle[]; extern const u8 EventScript_TryDoDoubleRematchBattle[]; extern const u8 EventScript_TryDoRematchBattle[]; +extern const u8 EventScript_ObjectApproachPlayer[]; extern const u8 BerryTreeScript[]; diff --git a/include/script.h b/include/script.h index 1f3c4f7afb..68e0c9e20e 100644 --- a/include/script.h +++ b/include/script.h @@ -1,6 +1,8 @@ #ifndef GUARD_SCRIPT_H #define GUARD_SCRIPT_H +#include + struct ScriptContext; typedef bool8 (*ScrCmdFunc)(struct ScriptContext *); @@ -11,6 +13,7 @@ struct ScriptContext u8 stackDepth; u8 mode; u8 comparisonResult; + bool8 breakOnTrainerBattle; u8 (*nativePtr)(void); const u8 *scriptPtr; const u8 *stack[20]; @@ -39,12 +42,13 @@ void ScriptContext_Init(void); bool8 ScriptContext_IsEnabled(void); bool8 ScriptContext_RunScript(void); void ScriptContext_SetupScript(const u8 *ptr); +void ScriptContext_ContinueScript(struct ScriptContext *ctx); void ScriptContext_Stop(void); void ScriptContext_Enable(void); void RunScriptImmediately(const u8 *ptr); -u8 *MapHeaderGetScriptTable(u8 tag); +const u8 *MapHeaderGetScriptTable(u8 tag); void MapHeaderRunScriptType(u8 tag); -u8 *MapHeaderCheckScriptTable(u8 tag); +const u8 *MapHeaderCheckScriptTable(u8 tag); void RunOnLoadMapScript(void); void RunOnTransitionMapScript(void); void RunOnResumeMapScript(void); @@ -66,4 +70,108 @@ void SetMovingNpcId(u16 npcId); extern u8 gMsgIsSignPost; extern u8 gMsgBoxIsCancelable; +/* Script effects analysis. + * + * 'RunScriptImmediatelyUntilEffect' executes a script until it reaches + * the first command which calls 'Script_RequestEffects' with an + * effect in 'effects' in which case it returns 'TRUE' and stores the + * current state in 'ctx'; or until it reaches an 'end'/'return' in + * which case it returns 'FALSE'. + * + * 'Script_HasNoEffect' wraps 'RunScriptImmediatelyUntilEffect' and + * returns 'TRUE' if the script exits without an effect on the save or + * the hardware, or 'FALSE' if it would have an effect (the effect is + * not performed). + * + * Commands, natives, and specials which call 'Script_RequestEffects' + * must be explicitly tagged with 'requests_effects=1', and must call + * the function before any of those effects occur. An untagged function + * could cause any effect, so execution is stopped to be safe. If the + * code has no effects it must call 'Script_RequestEffects(SCREFF_V1)' + * to note that explicitly. + * + * Regular variables are in the save (so should use 'SCREFF_SAVE'), but + * special variables are not in the save, so 'Script_RequestWriteVar' is + * provided to only request the 'SCREFF_SAVE' effect for a non-special + * variable. + * + * The 'effects' parameter to 'RunScriptImmediatelyUntilEffect' and + * 'Script_RequestEffects' must be the bitwise or of an effects version + * (currently 'SCREFF_V1') and any number of effects. For example + * 'Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE)'. */ + +enum // effects +{ + SCREFF_SAVE = 1 << 0, // writes to the save. + SCREFF_HARDWARE = 1 << 1, // writes to a hardware register. + SCREFF_TRAINERBATTLE = 1 << 2, // 'trainerbattle' command. +}; + +enum // effects versions +{ + SCREFF_V1 = ~7, +}; + +extern struct ScriptEffectContext *gScriptEffectContext; + +bool32 RunScriptImmediatelyUntilEffect_Internal(u32 effects, const u8 *ptr, struct ScriptContext *ctx); +bool32 Script_HasNoEffect(const u8 *ptr); +void Script_GotoBreak_Internal(void); +void Script_RequestEffects_Internal(u32 effects); +void Script_RequestWriteVar_Internal(u32 varId); + +static inline bool32 Script_IsAnalyzingEffects(void) +{ + return gScriptEffectContext != NULL; +} + +#define RunScriptImmediatelyUntilEffect(effects, ptr, ctx) \ + ({ \ + _Static_assert((effects) & 0x80000000, "RunScriptImmediatelyUntilEffect requires an effects version"); \ + RunScriptImmediatelyUntilEffect_Internal(effects, ptr, ctx); \ + }) + +/* Optimize 'Script_RequestEffects' to a no-op if it would have no + * effect. 'Script_RequestEffects' must be called in all commands and + * natives/specials with 'request_effects=TRUE' even if it would have + * no effect to future-proof against new effects. */ +#define Script_RequestEffects(effects) \ + ({ \ + _Static_assert((effects) & 0x80000000, "Script_RequestEffects requires an effects version"); \ + if ((effects) != SCREFF_V1) \ + if (Script_IsAnalyzingEffects()) \ + Script_RequestEffects_Internal(effects); \ + }) + +/* Optimize 'Script_RequestWriteVar' to a no-op if it would have no + * effect. */ +#define Script_RequestWriteVar(varId) \ + ({ \ + if (Script_IsAnalyzingEffects()) \ + Script_RequestWriteVar_Internal(varId); \ + }) + +static inline void Script_CheckEffectInstrumentedSpecial(u32 specialId) +{ + typedef u16 (*SpecialFunc)(void); + extern const SpecialFunc gSpecials[]; + // In ROM mirror 1. + if (Script_IsAnalyzingEffects() && (((uintptr_t)gSpecials[specialId]) & 0xE000000) != 0xA000000) + Script_GotoBreak_Internal(); +} + +static inline void Script_CheckEffectInstrumentedGotoNative(bool8 (*func)(void)) +{ + // In ROM mirror 1. + if (Script_IsAnalyzingEffects() && (((uintptr_t)func) & 0xE000000) != 0xA000000) + Script_GotoBreak_Internal(); +} + +static inline void Script_CheckEffectInstrumentedCallNative(void (*func)(struct ScriptContext *)) +{ + // In ROM mirror 1. + if (Script_IsAnalyzingEffects() && (((uintptr_t)func) & 0xE000000) != 0xA000000) + Script_GotoBreak_Internal(); +} + #endif // GUARD_SCRIPT_H diff --git a/include/test/overworld_script.h b/include/test/overworld_script.h index e2f65930f5..9b85f82ac3 100644 --- a/include/test/overworld_script.h +++ b/include/test/overworld_script.h @@ -42,6 +42,17 @@ #define RUN_OVERWORLD_SCRIPT(...) RunScriptImmediately(OVERWORLD_SCRIPT(__VA_ARGS__)) +// Make important constants available. +// TODO: Find a better approach to this. +asm(".set FALSE, 0\n" + ".set TRUE, 1\n" + ".set PARTY_SIZE, " STR(PARTY_SIZE) "\n" + ".set VARS_START, " STR(VARS_START) "\n" + ".set VARS_END, " STR(VARS_END) "\n" + ".set SPECIAL_VARS_START, " STR(SPECIAL_VARS_START) "\n" + ".set SPECIAL_VARS_END, " STR(SPECIAL_VARS_END) "\n"); +asm(".include \"constants/gba_constants.inc\"\n"); + // Make overworld script macros available. asm(".include \"asm/macros/event.inc\"\n"); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 828b7b7c94..61e27ddb5a 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -5353,6 +5353,8 @@ static s32 AI_DynamicFunc(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) void ScriptSetDynamicAiFunc(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + AiScoreFunc func = (AiScoreFunc)ScriptReadWord(ctx); sDynamicAiFunc = func; } diff --git a/src/battle_main.c b/src/battle_main.c index 1938cef20c..ebc391983a 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -2060,6 +2060,8 @@ static u8 CreateNPCTrainerParty(struct Pokemon *party, u16 trainerNum, bool8 fir void CreateTrainerPartyForPlayer(void) { + Script_RequestEffects(SCREFF_V1); + ZeroPlayerPartyMons(); gPartnerTrainerId = gSpecialVar_0x8004; CreateNPCTrainerPartyFromTrainer(gPlayerParty, GetTrainerStructFromId(gSpecialVar_0x8004), TRUE, BATTLE_TYPE_TRAINER); @@ -6135,6 +6137,8 @@ void ScriptSetTotemBoost(struct ScriptContext *ctx) u32 stat; u32 i; + Script_RequestEffects(SCREFF_V1); + for (i = 0; i < (NUM_BATTLE_STATS - 1); i++) { stat = VarGet(ScriptReadHalfword(ctx)); diff --git a/src/difficulty.c b/src/difficulty.c index bf7caca313..470c7fb3fd 100644 --- a/src/difficulty.c +++ b/src/difficulty.c @@ -64,6 +64,9 @@ void Script_IncreaseDifficulty(void) if (currentDifficulty++ > DIFFICULTY_MAX) return; + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(B_VAR_DIFFICULTY); + SetCurrentDifficultyLevel(currentDifficulty); } @@ -79,11 +82,15 @@ void Script_DecreaseDifficulty(void) if (!currentDifficulty) return; + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(B_VAR_DIFFICULTY); + SetCurrentDifficultyLevel(--currentDifficulty); } void Script_GetDifficulty(void) { + Script_RequestEffects(SCREFF_V1); gSpecialVar_Result = GetCurrentDifficultyLevel(); } @@ -91,5 +98,8 @@ void Script_SetDifficulty(struct ScriptContext *ctx) { enum DifficultyLevel desiredDifficulty = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(B_VAR_DIFFICULTY); + SetCurrentDifficultyLevel(desiredDifficulty); } diff --git a/src/event_object_movement.c b/src/event_object_movement.c index 9392a81d86..581cd94620 100644 --- a/src/event_object_movement.c +++ b/src/event_object_movement.c @@ -6012,9 +6012,15 @@ u8 GetDirectionToFace(s16 x, s16 y, s16 targetX, s16 targetY) // Uses the above, but script accessible, and uses localIds void GetDirectionToFaceScript(struct ScriptContext *ctx) { - u16 *var = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); u8 sourceId = GetObjectEventIdByLocalId(ScriptReadByte(ctx)); u8 targetId = GetObjectEventIdByLocalId(ScriptReadByte(ctx)); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + + u16 *var = GetVarPointer(varId); + if (var == NULL) return; if (sourceId >= OBJECT_EVENTS_COUNT || targetId >= OBJECT_EVENTS_COUNT) @@ -6030,7 +6036,12 @@ void GetDirectionToFaceScript(struct ScriptContext *ctx) // Intended to be called before the field effect itself void IsFollowerFieldMoveUser(struct ScriptContext *ctx) { - u16 *var = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + + u16 *var = GetVarPointer(varId); u16 userIndex = gFieldEffectArguments[0]; // field move user index struct Pokemon *follower = GetFirstLiveMon(); struct ObjectEvent *obj = GetFollowerObject(); @@ -10995,6 +11006,13 @@ void GetDaycareGraphics(struct ScriptContext *ctx) u8 form; u8 shiny; s32 i; + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varGfx[0]); + Script_RequestWriteVar(varGfx[1]); + Script_RequestWriteVar(varForm[0]); + Script_RequestWriteVar(varForm[1]); + for (i = 0; i < 2; i++) { GetMonInfo((struct Pokemon *) &gSaveBlock1Ptr->daycare.mons[i].mon, &specGfx, &form, &shiny); diff --git a/src/fake_rtc.c b/src/fake_rtc.c index f3f3b74c39..4dbf7837ba 100644 --- a/src/fake_rtc.c +++ b/src/fake_rtc.c @@ -5,6 +5,7 @@ #include "rtc.h" #include "fake_rtc.h" #include "event_data.h" +#include "script.h" struct Time *FakeRtc_GetCurrentTime(void) { @@ -90,15 +91,21 @@ STATIC_ASSERT((OW_FLAG_PAUSE_TIME == 0 || OW_USE_FAKE_RTC == TRUE), FakeRtcMustB void Script_PauseFakeRtc(void) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + FlagSet(OW_FLAG_PAUSE_TIME); } void Script_ResumeFakeRtc(void) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + FlagClear(OW_FLAG_PAUSE_TIME); } void Script_ToggleFakeRtc(void) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + FlagToggle(OW_FLAG_PAUSE_TIME); } diff --git a/src/field_control_avatar.c b/src/field_control_avatar.c index eabbc202c8..d87c7ca010 100644 --- a/src/field_control_avatar.c +++ b/src/field_control_avatar.c @@ -275,7 +275,7 @@ static u16 GetPlayerCurMetatileBehavior(int runningState) static bool8 TryStartInteractionScript(struct MapPosition *position, u16 metatileBehavior, u8 direction) { const u8 *script = GetInteractionScript(position, metatileBehavior, direction); - if (script == NULL) + if (script == NULL || Script_HasNoEffect(script)) return FALSE; // Don't play interaction sound for certain scripts. @@ -590,7 +590,12 @@ static bool8 TryStartCoordEventScript(struct MapPosition *position) if (script == NULL) return FALSE; - ScriptContext_SetupScript(script); + + struct ScriptContext ctx; + if (!RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_HARDWARE, script, &ctx)) + return FALSE; + + ScriptContext_ContinueScript(&ctx); return TRUE; } diff --git a/src/field_player_avatar.c b/src/field_player_avatar.c index 9abb81a18e..2aed46627c 100644 --- a/src/field_player_avatar.c +++ b/src/field_player_avatar.c @@ -1236,6 +1236,8 @@ u8 player_get_pos_including_state_based_drift(s16 *x, s16 *y) u8 GetPlayerFacingDirection(void) { + Script_RequestEffects(SCREFF_V1); + return gObjectEvents[gPlayerAvatar.objectEventId].facingDirection; } diff --git a/src/main.c b/src/main.c index 39b4f7e7a7..c2758ee227 100644 --- a/src/main.c +++ b/src/main.c @@ -93,7 +93,9 @@ void AgbMain() { *(vu16 *)BG_PLTT = RGB_WHITE; // Set the backdrop to white on startup InitGpuRegManager(); - REG_WAITCNT = WAITCNT_PREFETCH_ENABLE | WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3; + REG_WAITCNT = WAITCNT_PREFETCH_ENABLE + | WAITCNT_WS0_S_1 | WAITCNT_WS0_N_3 + | WAITCNT_WS1_S_1 | WAITCNT_WS1_N_3; InitKeys(); InitIntrHandlers(); m4aSoundInit(); diff --git a/src/overworld.c b/src/overworld.c index 443d10295b..05c04d0fba 100644 --- a/src/overworld.c +++ b/src/overworld.c @@ -3386,6 +3386,9 @@ static u8 ReformatItemDescription(u16 item, u8 *dest) void ScriptShowItemDescription(struct ScriptContext *ctx) { u8 headerType = ScriptReadByte(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + struct WindowTemplate template; u16 item = gSpecialVar_0x8006; u8 textY; @@ -3425,6 +3428,8 @@ void ScriptShowItemDescription(struct ScriptContext *ctx) void ScriptHideItemDescription(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + DestroyItemIconSprite(); if (!GetSetItemObtained(gSpecialVar_0x8006, FLAG_GET_ITEM_OBTAINED)) diff --git a/src/scrcmd.c b/src/scrcmd.c index 2471f3b595..54585aa503 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -101,16 +101,22 @@ static u8 *const sScriptStringVars[] = bool8 ScrCmd_nop(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + return FALSE; } bool8 ScrCmd_nop1(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + return FALSE; } bool8 ScrCmd_end(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + FlagClear(FLAG_SAFE_FOLLOWER_MOVEMENT); StopScript(ctx); return FALSE; @@ -120,6 +126,9 @@ bool8 ScrCmd_gotonative(struct ScriptContext *ctx) { bool8 (*addr)(void) = (bool8 (*)(void))ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + Script_CheckEffectInstrumentedGotoNative(addr); + SetupNativeScript(ctx, addr); return TRUE; } @@ -128,15 +137,24 @@ bool8 ScrCmd_special(struct ScriptContext *ctx) { u16 index = ScriptReadHalfword(ctx); + Script_RequestEffects(SCREFF_V1); + Script_CheckEffectInstrumentedSpecial(index); + gSpecials[index](); return FALSE; } bool8 ScrCmd_specialvar(struct ScriptContext *ctx) { - u16 *var = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + u16 index = ScriptReadHalfword(ctx); + u16 *ptr = GetVarPointer(varId); - *var = gSpecials[ScriptReadHalfword(ctx)](); + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + Script_CheckEffectInstrumentedSpecial(index); + + *ptr = gSpecials[index](); return FALSE; } @@ -144,12 +162,17 @@ bool8 ScrCmd_callnative(struct ScriptContext *ctx) { NativeFunc func = (NativeFunc)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + Script_CheckEffectInstrumentedCallNative(func); + func(ctx); return FALSE; } bool8 ScrCmd_waitstate(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ScriptContext_Stop(); return TRUE; } @@ -158,12 +181,16 @@ bool8 ScrCmd_goto(struct ScriptContext *ctx) { const u8 *ptr = (const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + ScriptJump(ctx, ptr); return FALSE; } bool8 ScrCmd_return(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + ScriptReturn(ctx); return FALSE; } @@ -172,6 +199,8 @@ bool8 ScrCmd_call(struct ScriptContext *ctx) { const u8 *ptr = (const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + ScriptCall(ctx, ptr); return FALSE; } @@ -181,6 +210,8 @@ bool8 ScrCmd_goto_if(struct ScriptContext *ctx) u8 condition = ScriptReadByte(ctx); const u8 *ptr = (const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) ScriptJump(ctx, ptr); return FALSE; @@ -191,6 +222,8 @@ bool8 ScrCmd_call_if(struct ScriptContext *ctx) u8 condition = ScriptReadByte(ctx); const u8 *ptr = (const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) ScriptCall(ctx, ptr); return FALSE; @@ -201,6 +234,8 @@ bool8 ScrCmd_setvaddress(struct ScriptContext *ctx) u32 addr1 = (u32)ctx->scriptPtr - 1; u32 addr2 = ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + sAddressOffset = addr2 - addr1; return FALSE; } @@ -209,6 +244,8 @@ bool8 ScrCmd_vgoto(struct ScriptContext *ctx) { u32 addr = ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + ScriptJump(ctx, (u8 *)(addr - sAddressOffset)); return FALSE; } @@ -217,6 +254,8 @@ bool8 ScrCmd_vcall(struct ScriptContext *ctx) { u32 addr = ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + ScriptCall(ctx, (u8 *)(addr - sAddressOffset)); return FALSE; } @@ -226,6 +265,8 @@ bool8 ScrCmd_vgoto_if(struct ScriptContext *ctx) u8 condition = ScriptReadByte(ctx); const u8 *ptr = (const u8 *)(ScriptReadWord(ctx) - sAddressOffset); + Script_RequestEffects(SCREFF_V1); + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) ScriptJump(ctx, ptr); return FALSE; @@ -236,6 +277,8 @@ bool8 ScrCmd_vcall_if(struct ScriptContext *ctx) u8 condition = ScriptReadByte(ctx); const u8 *ptr = (const u8 *)(ScriptReadWord(ctx) - sAddressOffset); + Script_RequestEffects(SCREFF_V1); + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) ScriptCall(ctx, ptr); return FALSE; @@ -246,6 +289,8 @@ bool8 ScrCmd_gotostd(struct ScriptContext *ctx) u8 index = ScriptReadByte(ctx); const u8 **ptr = &gStdScripts[index]; + Script_RequestEffects(SCREFF_V1); + if (ptr < gStdScripts_End) ScriptJump(ctx, *ptr); return FALSE; @@ -256,6 +301,8 @@ bool8 ScrCmd_callstd(struct ScriptContext *ctx) u8 index = ScriptReadByte(ctx); const u8 **ptr = &gStdScripts[index]; + Script_RequestEffects(SCREFF_V1); + if (ptr < gStdScripts_End) ScriptCall(ctx, *ptr); return FALSE; @@ -266,6 +313,8 @@ bool8 ScrCmd_gotostd_if(struct ScriptContext *ctx) u8 condition = ScriptReadByte(ctx); u8 index = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) { const u8 **ptr = &gStdScripts[index]; @@ -280,6 +329,8 @@ bool8 ScrCmd_callstd_if(struct ScriptContext *ctx) u8 condition = ScriptReadByte(ctx); u8 index = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + if (sScriptConditionTable[condition][ctx->comparisonResult] == 1) { const u8 **ptr = &gStdScripts[index]; @@ -291,12 +342,16 @@ bool8 ScrCmd_callstd_if(struct ScriptContext *ctx) bool8 ScrCmd_returnram(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + ScriptJump(ctx, gRamScriptRetAddr); return FALSE; } bool8 ScrCmd_endram(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + FlagClear(FLAG_SAFE_FOLLOWER_MOVEMENT); ClearRamScript(); StopScript(ctx); @@ -307,6 +362,8 @@ bool8 ScrCmd_setmysteryeventstatus(struct ScriptContext *ctx) { u8 status = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + SetMysteryEventScriptStatus(status); return FALSE; } @@ -315,6 +372,8 @@ bool8 ScrCmd_loadword(struct ScriptContext *ctx) { u8 index = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->data[index] = ScriptReadWord(ctx); return FALSE; } @@ -323,6 +382,8 @@ bool8 ScrCmd_loadbytefromptr(struct ScriptContext *ctx) { u8 index = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->data[index] = *(const u8 *)ScriptReadWord(ctx); return FALSE; } @@ -331,6 +392,9 @@ bool8 ScrCmd_setptr(struct ScriptContext *ctx) { u8 value = ScriptReadByte(ctx); + // TODO: Check if 'ptr' is within a save block? + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + *(u8 *)ScriptReadWord(ctx) = value; return FALSE; } @@ -339,6 +403,8 @@ bool8 ScrCmd_loadbyte(struct ScriptContext *ctx) { u8 index = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->data[index] = ScriptReadByte(ctx); return FALSE; } @@ -347,6 +413,9 @@ bool8 ScrCmd_setptrbyte(struct ScriptContext *ctx) { u8 index = ScriptReadByte(ctx); + // TODO: Check if 'ptr' is within a save block? + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + *(u8 *)ScriptReadWord(ctx) = ctx->data[index]; return FALSE; } @@ -356,6 +425,8 @@ bool8 ScrCmd_copylocal(struct ScriptContext *ctx) u8 destIndex = ScriptReadByte(ctx); u8 srcIndex = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->data[destIndex] = ctx->data[srcIndex]; return FALSE; } @@ -363,27 +434,46 @@ bool8 ScrCmd_copylocal(struct ScriptContext *ctx) bool8 ScrCmd_copybyte(struct ScriptContext *ctx) { u8 *ptr = (u8 *)ScriptReadWord(ctx); + + // TODO: Check if 'ptr' is within a save block? + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + *ptr = *(const u8 *)ScriptReadWord(ctx); return FALSE; } bool8 ScrCmd_setvar(struct ScriptContext *ctx) { - u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + u16 *ptr = GetVarPointer(varId); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + *ptr = ScriptReadHalfword(ctx); return FALSE; } bool8 ScrCmd_copyvar(struct ScriptContext *ctx) { - u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + u16 *ptr = GetVarPointer(varId); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + *ptr = *GetVarPointer(ScriptReadHalfword(ctx)); return FALSE; } bool8 ScrCmd_setorcopyvar(struct ScriptContext *ctx) { - u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + u16 *ptr = GetVarPointer(varId); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + *ptr = VarGet(ScriptReadHalfword(ctx)); return FALSE; } @@ -402,6 +492,8 @@ bool8 ScrCmd_compare_local_to_local(struct ScriptContext *ctx) const u8 value1 = ctx->data[ScriptReadByte(ctx)]; const u8 value2 = ctx->data[ScriptReadByte(ctx)]; + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = Compare(value1, value2); return FALSE; } @@ -411,6 +503,8 @@ bool8 ScrCmd_compare_local_to_value(struct ScriptContext *ctx) const u8 value1 = ctx->data[ScriptReadByte(ctx)]; const u8 value2 = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = Compare(value1, value2); return FALSE; } @@ -420,6 +514,8 @@ bool8 ScrCmd_compare_local_to_ptr(struct ScriptContext *ctx) const u8 value1 = ctx->data[ScriptReadByte(ctx)]; const u8 value2 = *(const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = Compare(value1, value2); return FALSE; } @@ -429,6 +525,8 @@ bool8 ScrCmd_compare_ptr_to_local(struct ScriptContext *ctx) const u8 value1 = *(const u8 *)ScriptReadWord(ctx); const u8 value2 = ctx->data[ScriptReadByte(ctx)]; + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = Compare(value1, value2); return FALSE; } @@ -438,6 +536,8 @@ bool8 ScrCmd_compare_ptr_to_value(struct ScriptContext *ctx) const u8 value1 = *(const u8 *)ScriptReadWord(ctx); const u8 value2 = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = Compare(value1, value2); return FALSE; } @@ -447,6 +547,8 @@ bool8 ScrCmd_compare_ptr_to_ptr(struct ScriptContext *ctx) const u8 value1 = *(const u8 *)ScriptReadWord(ctx); const u8 value2 = *(const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = Compare(value1, value2); return FALSE; } @@ -456,6 +558,8 @@ bool8 ScrCmd_compare_var_to_value(struct ScriptContext *ctx) const u16 value1 = *GetVarPointer(ScriptReadHalfword(ctx)); const u16 value2 = ScriptReadHalfword(ctx); + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = Compare(value1, value2); return FALSE; } @@ -465,6 +569,8 @@ bool8 ScrCmd_compare_var_to_var(struct ScriptContext *ctx) const u16 *ptr1 = GetVarPointer(ScriptReadHalfword(ctx)); const u16 *ptr2 = GetVarPointer(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = Compare(*ptr1, *ptr2); return FALSE; } @@ -474,14 +580,24 @@ bool8 ScrCmd_compare_var_to_var(struct ScriptContext *ctx) // in the contest scripts to `subvar VAR_*, 1`, else contests will break. bool8 ScrCmd_addvar(struct ScriptContext *ctx) { - u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + u16 *ptr = GetVarPointer(varId); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + *ptr += ScriptReadHalfword(ctx); return FALSE; } bool8 ScrCmd_subvar(struct ScriptContext *ctx) { - u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + u16 *ptr = GetVarPointer(varId); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + *ptr -= VarGet(ScriptReadHalfword(ctx)); return FALSE; } @@ -490,6 +606,8 @@ bool8 ScrCmd_random(struct ScriptContext *ctx) { u16 max = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = Random() % max; return FALSE; } @@ -499,6 +617,8 @@ bool8 ScrCmd_additem(struct ScriptContext *ctx) u16 itemId = VarGet(ScriptReadHalfword(ctx)); u32 quantity = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + gSpecialVar_Result = AddBagItem(itemId, quantity); return FALSE; } @@ -508,6 +628,8 @@ bool8 ScrCmd_removeitem(struct ScriptContext *ctx) u16 itemId = VarGet(ScriptReadHalfword(ctx)); u32 quantity = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + gSpecialVar_Result = RemoveBagItem(itemId, quantity); return FALSE; } @@ -517,6 +639,8 @@ bool8 ScrCmd_checkitemspace(struct ScriptContext *ctx) u16 itemId = VarGet(ScriptReadHalfword(ctx)); u32 quantity = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = CheckBagHasSpace(itemId, quantity); return FALSE; } @@ -526,6 +650,8 @@ bool8 ScrCmd_checkitem(struct ScriptContext *ctx) u16 itemId = VarGet(ScriptReadHalfword(ctx)); u32 quantity = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = CheckBagHasItem(itemId, quantity); return FALSE; } @@ -534,6 +660,8 @@ bool8 ScrCmd_checkitemtype(struct ScriptContext *ctx) { u16 itemId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = GetPocketByItemId(itemId); return FALSE; } @@ -543,6 +671,8 @@ bool8 ScrCmd_addpcitem(struct ScriptContext *ctx) u16 itemId = VarGet(ScriptReadHalfword(ctx)); u16 quantity = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + gSpecialVar_Result = AddPCItem(itemId, quantity); return FALSE; } @@ -552,6 +682,8 @@ bool8 ScrCmd_checkpcitem(struct ScriptContext *ctx) u16 itemId = VarGet(ScriptReadHalfword(ctx)); u16 quantity = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = CheckPCHasItem(itemId, quantity); return FALSE; } @@ -560,6 +692,8 @@ bool8 ScrCmd_adddecoration(struct ScriptContext *ctx) { u32 decorId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + gSpecialVar_Result = DecorationAdd(decorId); return FALSE; } @@ -568,6 +702,8 @@ bool8 ScrCmd_removedecoration(struct ScriptContext *ctx) { u32 decorId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + gSpecialVar_Result = DecorationRemove(decorId); return FALSE; } @@ -576,6 +712,8 @@ bool8 ScrCmd_checkdecorspace(struct ScriptContext *ctx) { u32 decorId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = DecorationCheckSpace(decorId); return FALSE; } @@ -584,44 +722,68 @@ bool8 ScrCmd_checkdecor(struct ScriptContext *ctx) { u32 decorId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = CheckHasDecoration(decorId); return FALSE; } bool8 ScrCmd_setflag(struct ScriptContext *ctx) { - FlagSet(ScriptReadHalfword(ctx)); + u32 flagId = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + + FlagSet(flagId); return FALSE; } bool8 ScrCmd_clearflag(struct ScriptContext *ctx) { - FlagClear(ScriptReadHalfword(ctx)); + u32 flagId = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + + FlagClear(flagId); return FALSE; } bool8 ScrCmd_checkflag(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = FlagGet(ScriptReadHalfword(ctx)); return FALSE; } bool8 ScrCmd_incrementgamestat(struct ScriptContext *ctx) { - IncrementGameStat(ScriptReadByte(ctx)); + u32 statId = ScriptReadByte(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + + IncrementGameStat(statId); return FALSE; } bool8 ScrCmd_animateflash(struct ScriptContext *ctx) { - AnimateFlash(ScriptReadByte(ctx)); + u32 level = ScriptReadByte(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + + AnimateFlash(level); ScriptContext_Stop(); return TRUE; } bool8 ScrCmd_setflashlevel(struct ScriptContext *ctx) { - SetFlashLevel(VarGet(ScriptReadHalfword(ctx))); + u32 level = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + + SetFlashLevel(level); return FALSE; } @@ -635,7 +797,11 @@ static bool8 IsPaletteNotActive(void) bool8 ScrCmd_fadescreen(struct ScriptContext *ctx) { - FadeScreen(ScriptReadByte(ctx), 0); + u32 mode = ScriptReadByte(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + + FadeScreen(mode, 0); SetupNativeScript(ctx, IsPaletteNotActive); return TRUE; } @@ -645,6 +811,8 @@ bool8 ScrCmd_fadescreenspeed(struct ScriptContext *ctx) u8 mode = ScriptReadByte(ctx); u8 speed = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + FadeScreen(mode, speed); SetupNativeScript(ctx, IsPaletteNotActive); return TRUE; @@ -654,6 +822,8 @@ bool8 ScrCmd_fadescreenswapbuffers(struct ScriptContext *ctx) { u8 mode = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + switch (mode) { case FADE_TO_BLACK: @@ -683,7 +853,11 @@ static bool8 RunPauseTimer(void) bool8 ScrCmd_delay(struct ScriptContext *ctx) { - sPauseCounter = ScriptReadHalfword(ctx); + u32 frames = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + + sPauseCounter = frames; SetupNativeScript(ctx, RunPauseTimer); return TRUE; } @@ -693,18 +867,24 @@ bool8 ScrCmd_initclock(struct ScriptContext *ctx) u8 hour = VarGet(ScriptReadHalfword(ctx)); u8 minute = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + RtcInitLocalTimeOffset(hour, minute); return FALSE; } bool8 ScrCmd_dotimebasedevents(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + DoTimeBasedEvents(); return FALSE; } bool8 ScrCmd_gettime(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + RtcCalcLocalTime(); gSpecialVar_0x8000 = gLocalTime.hours; gSpecialVar_0x8001 = gLocalTime.minutes; @@ -716,25 +896,35 @@ bool8 ScrCmd_setweather(struct ScriptContext *ctx) { u16 weather = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetSavedWeather(weather); return FALSE; } bool8 ScrCmd_resetweather(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetSavedWeatherFromCurrMapHeader(); return FALSE; } bool8 ScrCmd_doweather(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + DoCurrentWeather(); return FALSE; } bool8 ScrCmd_setstepcallback(struct ScriptContext *ctx) { - ActivatePerStepCallback(ScriptReadByte(ctx)); + u32 callbackId = ScriptReadByte(ctx); + + Script_RequestEffects(SCREFF_V1); + + ActivatePerStepCallback(callbackId); return FALSE; } @@ -742,6 +932,8 @@ bool8 ScrCmd_setmaplayoutindex(struct ScriptContext *ctx) { u16 value = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + SetCurrentMapLayout(value); return FALSE; } @@ -754,6 +946,8 @@ bool8 ScrCmd_warp(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + SetWarpDestination(mapGroup, mapNum, warpId, x, y); DoWarp(); ResetInitialPlayerAvatarState(); @@ -768,6 +962,8 @@ bool8 ScrCmd_warpsilent(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + SetWarpDestination(mapGroup, mapNum, warpId, x, y); DoDiveWarp(); ResetInitialPlayerAvatarState(); @@ -782,6 +978,8 @@ bool8 ScrCmd_warpdoor(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + SetWarpDestination(mapGroup, mapNum, warpId, x, y); DoDoorWarp(); ResetInitialPlayerAvatarState(); @@ -795,6 +993,8 @@ bool8 ScrCmd_warphole(struct ScriptContext *ctx) s16 x; s16 y; + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + PlayerGetDestCoords(&x, &y); if (mapGroup == MAP_GROUP(UNDEFINED) && mapNum == MAP_NUM(UNDEFINED)) SetWarpDestinationToFixedHoleWarp(x - MAP_OFFSET, y - MAP_OFFSET); @@ -814,6 +1014,8 @@ bool8 ScrCmd_warpteleport(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + SetWarpDestination(mapGroup, mapNum, warpId, x, y); DoTeleportTileWarp(); ResetInitialPlayerAvatarState(); @@ -828,6 +1030,8 @@ bool8 ScrCmd_warpmossdeepgym(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + SetWarpDestination(mapGroup, mapNum, warpId, x, y); DoMossdeepGymWarp(); ResetInitialPlayerAvatarState(); @@ -842,6 +1046,8 @@ bool8 ScrCmd_setwarp(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + SetWarpDestination(mapGroup, mapNum, warpId, x, y); return FALSE; } @@ -854,6 +1060,8 @@ bool8 ScrCmd_setdynamicwarp(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetDynamicWarpWithCoords(0, mapGroup, mapNum, warpId, x, y); return FALSE; } @@ -866,6 +1074,8 @@ bool8 ScrCmd_setdivewarp(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + SetFixedDiveWarp(mapGroup, mapNum, warpId, x, y); return FALSE; } @@ -878,6 +1088,8 @@ bool8 ScrCmd_setholewarp(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + SetFixedHoleWarp(mapGroup, mapNum, warpId, x, y); return FALSE; } @@ -890,14 +1102,22 @@ bool8 ScrCmd_setescapewarp(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetEscapeWarp(mapGroup, mapNum, warpId, x, y); return FALSE; } bool8 ScrCmd_getplayerxy(struct ScriptContext *ctx) { - u16 *pX = GetVarPointer(ScriptReadHalfword(ctx)); - u16 *pY = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varIdX = ScriptReadHalfword(ctx); + u32 varIdY = ScriptReadHalfword(ctx); + u16 *pX = GetVarPointer(varIdX); + u16 *pY = GetVarPointer(varIdY); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varIdX); + Script_RequestWriteVar(varIdY); *pX = gSaveBlock1Ptr->pos.x; *pY = gSaveBlock1Ptr->pos.y; @@ -906,13 +1126,19 @@ bool8 ScrCmd_getplayerxy(struct ScriptContext *ctx) bool8 ScrCmd_getpartysize(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = CalculatePlayerPartyCount(); return FALSE; } bool8 ScrCmd_playse(struct ScriptContext *ctx) { - PlaySE(ScriptReadHalfword(ctx)); + u32 songId = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + + PlaySE(songId); return FALSE; } @@ -926,13 +1152,19 @@ static bool8 WaitForSoundEffectFinish(void) bool8 ScrCmd_waitse(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetupNativeScript(ctx, WaitForSoundEffectFinish); return TRUE; } bool8 ScrCmd_playfanfare(struct ScriptContext *ctx) { - PlayFanfare(ScriptReadHalfword(ctx)); + u32 songId = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + + PlayFanfare(songId); return FALSE; } @@ -943,6 +1175,8 @@ static bool8 WaitForFanfareFinish(void) bool8 ScrCmd_waitfanfare(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetupNativeScript(ctx, WaitForFanfareFinish); return TRUE; } @@ -952,6 +1186,8 @@ bool8 ScrCmd_playbgm(struct ScriptContext *ctx) u16 songId = ScriptReadHalfword(ctx); bool8 save = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + if (save == TRUE) Overworld_SetSavedMusic(songId); PlayNewMapMusic(songId); @@ -960,18 +1196,24 @@ bool8 ScrCmd_playbgm(struct ScriptContext *ctx) bool8 ScrCmd_savebgm(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + Overworld_SetSavedMusic(ScriptReadHalfword(ctx)); return FALSE; } bool8 ScrCmd_fadedefaultbgm(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + Overworld_ChangeMusicToDefault(); return FALSE; } bool8 ScrCmd_fadenewbgm(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + Overworld_ChangeMusicTo(ScriptReadHalfword(ctx)); return FALSE; } @@ -980,6 +1222,8 @@ bool8 ScrCmd_fadeoutbgm(struct ScriptContext *ctx) { u8 speed = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + if (speed != 0) FadeOutBGMTemporarily(4 * speed); else @@ -992,6 +1236,8 @@ bool8 ScrCmd_fadeinbgm(struct ScriptContext *ctx) { u8 speed = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + if (speed != 0) FadeInBGM(4 * speed); else @@ -1005,6 +1251,8 @@ bool8 ScrCmd_applymovement(struct ScriptContext *ctx) const u8 *movementScript = (const u8 *)ScriptReadWord(ctx); struct ObjectEvent *objEvent; + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + // When applying script movements to follower, it may have frozen animation that must be cleared if (localId == OBJ_EVENT_ID_FOLLOWER && (objEvent = GetFollowerObject()) && objEvent->frozen) { @@ -1037,6 +1285,8 @@ bool8 ScrCmd_applymovementat(struct ScriptContext *ctx) u8 mapGroup = ScriptReadByte(ctx); u8 mapNum = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + gObjectEvents[GetObjectEventIdByLocalId(localId)].directionOverwrite = DIR_NONE; ScriptMovement_StartObjectMovementScript(localId, mapNum, mapGroup, movementScript); sMovingNpcId = localId; @@ -1061,6 +1311,8 @@ bool8 ScrCmd_waitmovement(struct ScriptContext *ctx) { u16 localId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (localId != 0) sMovingNpcId = localId; sMovingNpcMapGroup = gSaveBlock1Ptr->location.mapGroup; @@ -1075,6 +1327,8 @@ bool8 ScrCmd_waitmovementat(struct ScriptContext *ctx) u8 mapGroup; u8 mapNum; + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (localId != 0) sMovingNpcId = localId; mapGroup = ScriptReadByte(ctx); @@ -1089,6 +1343,8 @@ bool8 ScrCmd_removeobject(struct ScriptContext *ctx) { u16 localId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + RemoveObjectEventByLocalIdAndMap(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); return FALSE; } @@ -1099,6 +1355,8 @@ bool8 ScrCmd_removeobjectat(struct ScriptContext *ctx) u8 mapGroup = ScriptReadByte(ctx); u8 mapNum = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + RemoveObjectEventByLocalIdAndMap(objectId, mapNum, mapGroup); return FALSE; } @@ -1107,6 +1365,8 @@ bool8 ScrCmd_addobject(struct ScriptContext *ctx) { u16 objectId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + TrySpawnObjectEvent(objectId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); return FALSE; } @@ -1117,6 +1377,8 @@ bool8 ScrCmd_addobjectat(struct ScriptContext *ctx) u8 mapGroup = ScriptReadByte(ctx); u8 mapNum = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + TrySpawnObjectEvent(objectId, mapNum, mapGroup); return FALSE; } @@ -1127,6 +1389,8 @@ bool8 ScrCmd_setobjectxy(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + TryMoveObjectEventToMapCoords(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, x, y); return FALSE; } @@ -1137,6 +1401,8 @@ bool8 ScrCmd_setobjectxyperm(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetObjEventTemplateCoords(localId, x, y); return FALSE; } @@ -1145,6 +1411,8 @@ bool8 ScrCmd_copyobjectxytoperm(struct ScriptContext *ctx) { u16 localId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + TryOverrideObjectEventTemplateCoords(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup); return FALSE; } @@ -1155,6 +1423,8 @@ bool8 ScrCmd_showobjectat(struct ScriptContext *ctx) u8 mapGroup = ScriptReadByte(ctx); u8 mapNum = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetObjectInvisibility(localId, mapNum, mapGroup, FALSE); return FALSE; } @@ -1165,6 +1435,8 @@ bool8 ScrCmd_hideobjectat(struct ScriptContext *ctx) u8 mapGroup = ScriptReadByte(ctx); u8 mapNum = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetObjectInvisibility(localId, mapNum, mapGroup, TRUE); return FALSE; } @@ -1176,6 +1448,8 @@ bool8 ScrCmd_setobjectsubpriority(struct ScriptContext *ctx) u8 mapNum = ScriptReadByte(ctx); u8 priority = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetObjectSubpriority(localId, mapNum, mapGroup, priority + 83); return FALSE; } @@ -1186,12 +1460,16 @@ bool8 ScrCmd_resetobjectsubpriority(struct ScriptContext *ctx) u8 mapGroup = ScriptReadByte(ctx); u8 mapNum = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ResetObjectSubpriority(localId, mapNum, mapGroup); return FALSE; } bool8 ScrCmd_faceplayer(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (gObjectEvents[gSelectedObjectEvent].active) ObjectEventFaceOppositeDirection(&gObjectEvents[gSelectedObjectEvent], GetPlayerFacingDirection()); return FALSE; @@ -1202,6 +1480,8 @@ bool8 ScrCmd_turnobject(struct ScriptContext *ctx) u16 localId = VarGet(ScriptReadHalfword(ctx)); u8 direction = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ObjectEventTurnByLocalIdAndMap(localId, gSaveBlock1Ptr->location.mapNum, gSaveBlock1Ptr->location.mapGroup, direction); return FALSE; } @@ -1211,6 +1491,8 @@ bool8 ScrCmd_setobjectmovementtype(struct ScriptContext *ctx) u16 localId = VarGet(ScriptReadHalfword(ctx)); u8 movementType = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetObjEventTemplateMovementType(localId, movementType); return FALSE; } @@ -1224,6 +1506,8 @@ bool8 ScrCmd_createvobject(struct ScriptContext *ctx) u8 elevation = ScriptReadByte(ctx); u8 direction = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + CreateVirtualObject(graphicsId, virtualObjId, x, y, elevation, direction); return FALSE; } @@ -1233,6 +1517,8 @@ bool8 ScrCmd_turnvobject(struct ScriptContext *ctx) u8 virtualObjId = ScriptReadByte(ctx); u8 direction = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + TurnVirtualObject(virtualObjId, direction); return FALSE; } @@ -1241,6 +1527,11 @@ bool8 ScrCmd_turnvobject(struct ScriptContext *ctx) // The player is frozen after waiting for their current movement to finish. bool8 ScrCmd_lockall(struct ScriptContext *ctx) { + // As a special case, skip this during analysis. + if (Script_IsAnalyzingEffects()) + return FALSE; + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (IsOverworldLinkActive()) { return FALSE; @@ -1257,6 +1548,11 @@ bool8 ScrCmd_lockall(struct ScriptContext *ctx) // The player and selected object are frozen after waiting for their current movement to finish. bool8 ScrCmd_lock(struct ScriptContext *ctx) { + // As a special case, skip this during analysis. + if (Script_IsAnalyzingEffects()) + return FALSE; + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (IsOverworldLinkActive()) { return FALSE; @@ -1285,6 +1581,11 @@ bool8 ScrCmd_lock(struct ScriptContext *ctx) bool8 ScrCmd_releaseall(struct ScriptContext *ctx) { + // As a special case, skip this during analysis. + if (Script_IsAnalyzingEffects()) + return FALSE; + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + u8 playerObjectId; struct ObjectEvent *followerObject = GetFollowerObject(); // Release follower from movement iff it exists and is in the shadowing state @@ -1302,6 +1603,11 @@ bool8 ScrCmd_releaseall(struct ScriptContext *ctx) bool8 ScrCmd_release(struct ScriptContext *ctx) { + // As a special case, skip this during analysis. + if (Script_IsAnalyzingEffects()) + return FALSE; + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + u8 playerObjectId; struct ObjectEvent *followerObject = GetFollowerObject(); // Release follower from movement iff it exists and is in the shadowing state @@ -1323,6 +1629,8 @@ bool8 ScrCmd_message(struct ScriptContext *ctx) { const u8 *msg = (const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (msg == NULL) msg = (const u8 *)ctx->data[0]; ShowFieldMessage(msg); @@ -1333,6 +1641,8 @@ bool8 ScrCmd_pokenavcall(struct ScriptContext *ctx) { const u8 *msg = (const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (msg == NULL) msg = (const u8 *)ctx->data[0]; ShowPokenavFieldMessage(msg); @@ -1343,6 +1653,8 @@ bool8 ScrCmd_messageautoscroll(struct ScriptContext *ctx) { const u8 *msg = (const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (msg == NULL) msg = (const u8 *)ctx->data[0]; gTextFlags.autoScroll = TRUE; @@ -1356,6 +1668,8 @@ bool8 ScrCmd_messageinstant(struct ScriptContext *ctx) { const u8 *msg = (const u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (msg == NULL) msg = (const u8 *)ctx->data[0]; LoadMessageBoxAndBorderGfx(); @@ -1366,12 +1680,16 @@ bool8 ScrCmd_messageinstant(struct ScriptContext *ctx) bool8 ScrCmd_waitmessage(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetupNativeScript(ctx, IsFieldMessageBoxHidden); return TRUE; } bool8 ScrCmd_closemessage(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + HideFieldMessageBox(); return FALSE; } @@ -1387,6 +1705,8 @@ static bool8 WaitForAorBPress(void) bool8 ScrCmd_waitbuttonpress(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetupNativeScript(ctx, WaitForAorBPress); return TRUE; } @@ -1396,6 +1716,8 @@ bool8 ScrCmd_yesnobox(struct ScriptContext *ctx) u8 left = ScriptReadByte(ctx); u8 top = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (ScriptMenu_YesNo(left, top) == TRUE) { ScriptContext_Stop(); @@ -1442,6 +1764,8 @@ bool8 ScrCmd_dynmultichoice(struct ScriptContext *ctx) u32 argc = ScriptReadByte(ctx); struct ListMenuItem *items; + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (argc == 0) return FALSE; @@ -1491,9 +1815,12 @@ bool8 ScrCmd_dynmultichoice(struct ScriptContext *ctx) bool8 ScrCmd_dynmultipush(struct ScriptContext *ctx) { - u8 *nameBuffer = Alloc(100); const u8 *name = (const u8*) ScriptReadWord(ctx); u32 id = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + + u8 *nameBuffer = Alloc(100); struct ListMenuItem item; StringExpandPlaceholders(nameBuffer, name); item.name = nameBuffer; @@ -1509,6 +1836,8 @@ bool8 ScrCmd_multichoice(struct ScriptContext *ctx) u8 multichoiceId = ScriptReadByte(ctx); bool8 ignoreBPress = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (ScriptMenu_Multichoice(left, top, multichoiceId, ignoreBPress) == TRUE) { ScriptContext_Stop(); @@ -1528,6 +1857,8 @@ bool8 ScrCmd_multichoicedefault(struct ScriptContext *ctx) u8 defaultChoice = ScriptReadByte(ctx); bool8 ignoreBPress = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (ScriptMenu_MultichoiceWithDefault(left, top, multichoiceId, ignoreBPress, defaultChoice) == TRUE) { ScriptContext_Stop(); @@ -1558,6 +1889,8 @@ bool8 ScrCmd_multichoicegrid(struct ScriptContext *ctx) u8 numColumns = ScriptReadByte(ctx); bool8 ignoreBPress = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (ScriptMenu_MultichoiceGrid(left, top, multichoiceId, ignoreBPress, numColumns) == TRUE) { ScriptContext_Stop(); @@ -1601,12 +1934,16 @@ bool8 ScrCmd_showmonpic(struct ScriptContext *ctx) u8 x = ScriptReadByte(ctx); u8 y = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ScriptMenu_ShowPokemonPic(species, x, y); return FALSE; } bool8 ScrCmd_hidemonpic(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + // The hide function returns a pointer to a function // that returns true once the pic is hidden bool8 (*func)(void) = ScriptMenu_HidePokemonPic(); @@ -1621,6 +1958,8 @@ bool8 ScrCmd_showcontestpainting(struct ScriptContext *ctx) { u8 contestWinnerId = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + // Artist's painting is temporary and already has its data loaded if (contestWinnerId != CONTEST_WINNER_ARTIST) SetContestWinnerForPainting(contestWinnerId); @@ -1633,6 +1972,9 @@ bool8 ScrCmd_showcontestpainting(struct ScriptContext *ctx) bool8 ScrCmd_braillemessage(struct ScriptContext *ctx) { u8 *ptr = (u8 *)ScriptReadWord(ctx); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + struct WindowTemplate winTemplate; s32 i; u8 width, height; @@ -1686,6 +2028,8 @@ bool8 ScrCmd_braillemessage(struct ScriptContext *ctx) bool8 ScrCmd_closebraillemessage(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + CloseBrailleWindow(); return FALSE; } @@ -1694,6 +2038,8 @@ bool8 ScrCmd_vmessage(struct ScriptContext *ctx) { u32 msg = ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ShowFieldMessage((u8 *)(msg - sAddressOffset)); return FALSE; } @@ -1703,6 +2049,8 @@ bool8 ScrCmd_bufferspeciesname(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 species = VarGet(ScriptReadHalfword(ctx)) & OBJ_EVENT_GFX_SPECIES_MASK; // ignore possible shiny / form bits + Script_RequestEffects(SCREFF_V1); + StringCopy(sScriptStringVars[stringVarIndex], GetSpeciesName(species)); return FALSE; } @@ -1711,6 +2059,8 @@ bool8 ScrCmd_bufferleadmonspeciesname(struct ScriptContext *ctx) { u8 stringVarIndex = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + u8 *dest = sScriptStringVars[stringVarIndex]; u8 partyIndex = GetLeadMonIndex(); u32 species = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPECIES, NULL); @@ -1722,6 +2072,8 @@ void BufferFirstLiveMonNickname(struct ScriptContext *ctx) { u8 stringVarIndex = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + GetMonData(GetFirstLiveMon(), MON_DATA_NICKNAME, sScriptStringVars[stringVarIndex]); StringGet_Nickname(sScriptStringVars[stringVarIndex]); } @@ -1731,6 +2083,8 @@ bool8 ScrCmd_bufferpartymonnick(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 partyIndex = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, sScriptStringVars[stringVarIndex]); StringGet_Nickname(sScriptStringVars[stringVarIndex]); return FALSE; @@ -1741,6 +2095,8 @@ bool8 ScrCmd_bufferitemname(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 itemId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + CopyItemName(itemId, sScriptStringVars[stringVarIndex]); return FALSE; } @@ -1751,6 +2107,8 @@ bool8 ScrCmd_bufferitemnameplural(struct ScriptContext *ctx) u16 itemId = VarGet(ScriptReadHalfword(ctx)); u16 quantity = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + CopyItemNameHandlePlural(itemId, sScriptStringVars[stringVarIndex], quantity); return FALSE; } @@ -1760,6 +2118,8 @@ bool8 ScrCmd_bufferdecorationname(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 decorId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + StringCopy(sScriptStringVars[stringVarIndex], gDecorations[decorId].name); return FALSE; } @@ -1769,6 +2129,8 @@ bool8 ScrCmd_buffermovename(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 moveId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + StringCopy(sScriptStringVars[stringVarIndex], GetMoveName(moveId)); return FALSE; } @@ -1779,6 +2141,8 @@ bool8 ScrCmd_buffernumberstring(struct ScriptContext *ctx) u16 num = VarGet(ScriptReadHalfword(ctx)); u8 numDigits = CountDigits(num); + Script_RequestEffects(SCREFF_V1); + ConvertIntToDecimalStringN(sScriptStringVars[stringVarIndex], num, STR_CONV_MODE_LEFT_ALIGN, numDigits); return FALSE; } @@ -1788,6 +2152,8 @@ bool8 ScrCmd_bufferstdstring(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 index = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + StringCopy(sScriptStringVars[stringVarIndex], gStdStrings[index]); return FALSE; } @@ -1797,6 +2163,8 @@ bool8 ScrCmd_buffercontestname(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 category = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + BufferContestName(sScriptStringVars[stringVarIndex], category); return FALSE; } @@ -1806,6 +2174,8 @@ bool8 ScrCmd_bufferstring(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); const u8 *text = (u8 *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + StringCopy(sScriptStringVars[stringVarIndex], text); return FALSE; } @@ -1814,6 +2184,8 @@ bool8 ScrCmd_vbuffermessage(struct ScriptContext *ctx) { const u8 *ptr = (u8 *)(ScriptReadWord(ctx) - sAddressOffset); + Script_RequestEffects(SCREFF_V1); + StringExpandPlaceholders(gStringVar4, ptr); return FALSE; } @@ -1823,6 +2195,8 @@ bool8 ScrCmd_vbufferstring(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u32 addr = ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1); + const u8 *src = (u8 *)(addr - sAddressOffset); u8 *dest = sScriptStringVars[stringVarIndex]; StringCopy(dest, src); @@ -1834,6 +2208,8 @@ bool8 ScrCmd_bufferboxname(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 boxId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + StringCopy(sScriptStringVars[stringVarIndex], GetBoxNamePtr(boxId)); return FALSE; } @@ -1842,6 +2218,8 @@ bool8 ScrCmd_giveegg(struct ScriptContext *ctx) { u16 species = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + gSpecialVar_Result = ScriptGiveEgg(species); return FALSE; } @@ -1852,6 +2230,8 @@ bool8 ScrCmd_setmonmove(struct ScriptContext *ctx) u8 slot = ScriptReadByte(ctx); u16 move = ScriptReadHalfword(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + ScriptSetMonMoveSlot(partyIndex, move, slot); return FALSE; } @@ -1861,6 +2241,8 @@ bool8 ScrCmd_checkpartymove(struct ScriptContext *ctx) u8 i; u16 moveId = ScriptReadHalfword(ctx); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = PARTY_SIZE; for (i = 0; i < PARTY_SIZE; i++) { @@ -1883,7 +2265,11 @@ bool8 ScrCmd_addmoney(struct ScriptContext *ctx) u8 ignore = ScriptReadByte(ctx); if (!ignore) + { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + AddMoney(&gSaveBlock1Ptr->money, amount); + } return FALSE; } @@ -1893,7 +2279,11 @@ bool8 ScrCmd_removemoney(struct ScriptContext *ctx) u8 ignore = ScriptReadByte(ctx); if (!ignore) + { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + RemoveMoney(&gSaveBlock1Ptr->money, amount); + } return FALSE; } @@ -1903,7 +2293,11 @@ bool8 ScrCmd_checkmoney(struct ScriptContext *ctx) u8 ignore = ScriptReadByte(ctx); if (!ignore) + { + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = IsEnoughMoney(&gSaveBlock1Ptr->money, amount); + } return FALSE; } @@ -1914,12 +2308,18 @@ bool8 ScrCmd_showmoneybox(struct ScriptContext *ctx) u8 ignore = ScriptReadByte(ctx); if (!ignore) + { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + DrawMoneyBox(GetMoney(&gSaveBlock1Ptr->money), x, y); + } return FALSE; } bool8 ScrCmd_hidemoneybox(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + /*u8 x = ScriptReadByte(ctx); u8 y = ScriptReadByte(ctx);*/ @@ -1934,7 +2334,11 @@ bool8 ScrCmd_updatemoneybox(struct ScriptContext *ctx) u8 ignore = ScriptReadByte(ctx); if (!ignore) + { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ChangeAmountInMoneyBox(GetMoney(&gSaveBlock1Ptr->money)); + } return FALSE; } @@ -1943,6 +2347,8 @@ bool8 ScrCmd_showcoinsbox(struct ScriptContext *ctx) u8 x = ScriptReadByte(ctx); u8 y = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ShowCoinsWindow(GetCoins(), x, y); return FALSE; } @@ -1952,6 +2358,8 @@ bool8 ScrCmd_hidecoinsbox(struct ScriptContext *ctx) u8 UNUSED x = ScriptReadByte(ctx); u8 UNUSED y = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + HideCoinsWindow(); return FALSE; } @@ -1961,30 +2369,40 @@ bool8 ScrCmd_updatecoinsbox(struct ScriptContext *ctx) u8 UNUSED x = ScriptReadByte(ctx); u8 UNUSED y = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + PrintCoinsString(GetCoins()); return FALSE; } bool8 ScrCmd_trainerbattle(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_TRAINERBATTLE); + ctx->scriptPtr = BattleSetup_ConfigureTrainerBattle(ctx->scriptPtr); return FALSE; } bool8 ScrCmd_dotrainerbattle(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + BattleSetup_StartTrainerBattle(); return TRUE; } bool8 ScrCmd_gotopostbattlescript(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + ctx->scriptPtr = BattleSetup_GetScriptAddrAfterBattle(); return FALSE; } bool8 ScrCmd_gotobeatenscript(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + ctx->scriptPtr = BattleSetup_GetTrainerPostBattleScript(); return FALSE; } @@ -1993,6 +2411,8 @@ bool8 ScrCmd_checktrainerflag(struct ScriptContext *ctx) { u16 index = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + ctx->comparisonResult = HasTrainerBeenFought(index); return FALSE; } @@ -2001,6 +2421,8 @@ bool8 ScrCmd_settrainerflag(struct ScriptContext *ctx) { u16 index = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetTrainerFlag(index); return FALSE; } @@ -2009,6 +2431,8 @@ bool8 ScrCmd_cleartrainerflag(struct ScriptContext *ctx) { u16 index = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + ClearTrainerFlag(index); return FALSE; } @@ -2022,6 +2446,8 @@ bool8 ScrCmd_setwildbattle(struct ScriptContext *ctx) u8 level2 = ScriptReadByte(ctx); u16 item2 = ScriptReadHalfword(ctx); + Script_RequestEffects(SCREFF_V1); + if(species2 == SPECIES_NONE) { CreateScriptedWildMon(species, level, item); @@ -2038,6 +2464,8 @@ bool8 ScrCmd_setwildbattle(struct ScriptContext *ctx) bool8 ScrCmd_dowildbattle(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (sIsScriptedWildDouble == FALSE) BattleSetup_StartScriptedWildBattle(); else @@ -2052,6 +2480,8 @@ bool8 ScrCmd_pokemart(struct ScriptContext *ctx) { const void *ptr = (void *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + CreatePokemartMenu(ptr); ScriptContext_Stop(); return TRUE; @@ -2061,6 +2491,8 @@ bool8 ScrCmd_pokemartdecoration(struct ScriptContext *ctx) { const void *ptr = (void *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + CreateDecorationShop1Menu(ptr); ScriptContext_Stop(); return TRUE; @@ -2071,6 +2503,8 @@ bool8 ScrCmd_pokemartdecoration2(struct ScriptContext *ctx) { const void *ptr = (void *)ScriptReadWord(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + CreateDecorationShop2Menu(ptr); ScriptContext_Stop(); return TRUE; @@ -2080,6 +2514,8 @@ bool8 ScrCmd_playslotmachine(struct ScriptContext *ctx) { u8 machineId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + PlaySlotMachine(machineId, CB2_ReturnToFieldContinueScriptPlayMapMusic); ScriptContext_Stop(); return TRUE; @@ -2091,6 +2527,8 @@ bool8 ScrCmd_setberrytree(struct ScriptContext *ctx) u8 berry = ScriptReadByte(ctx); u8 growthStage = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + if (berry == 0) PlantBerryTree(treeId, berry, growthStage, FALSE); else @@ -2102,12 +2540,16 @@ bool8 ScrCmd_getpokenewsactive(struct ScriptContext *ctx) { u16 newsKind = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = IsPokeNewsActive(newsKind); return FALSE; } bool8 ScrCmd_choosecontestmon(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ChooseContestMon(); ScriptContext_Stop(); return TRUE; @@ -2116,6 +2558,8 @@ bool8 ScrCmd_choosecontestmon(struct ScriptContext *ctx) bool8 ScrCmd_startcontest(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + StartContest(); ScriptContext_Stop(); return TRUE; @@ -2123,6 +2567,8 @@ bool8 ScrCmd_startcontest(struct ScriptContext *ctx) bool8 ScrCmd_showcontestresults(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ShowContestResults(); ScriptContext_Stop(); return TRUE; @@ -2130,6 +2576,8 @@ bool8 ScrCmd_showcontestresults(struct ScriptContext *ctx) bool8 ScrCmd_contestlinktransfer(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + ContestLinkTransfer(gSpecialVar_ContestCategory); ScriptContext_Stop(); return TRUE; @@ -2139,6 +2587,8 @@ bool8 ScrCmd_dofieldeffect(struct ScriptContext *ctx) { u16 effectId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + sFieldEffectScriptId = effectId; FieldEffectStart(sFieldEffectScriptId); return FALSE; @@ -2148,6 +2598,8 @@ bool8 ScrCmd_setfieldeffectargument(struct ScriptContext *ctx) { u8 argNum = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1); + gFieldEffectArguments[argNum] = (s16)VarGet(ScriptReadHalfword(ctx)); return FALSE; } @@ -2162,7 +2614,11 @@ static bool8 WaitForFieldEffectFinish(void) bool8 ScrCmd_waitfieldeffect(struct ScriptContext *ctx) { - sFieldEffectScriptId = VarGet(ScriptReadHalfword(ctx)); + u32 scriptId = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + + sFieldEffectScriptId = scriptId; SetupNativeScript(ctx, WaitForFieldEffectFinish); return TRUE; } @@ -2171,12 +2627,16 @@ bool8 ScrCmd_setrespawn(struct ScriptContext *ctx) { u16 healLocationId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetLastHealLocationWarp(healLocationId); return FALSE; } bool8 ScrCmd_checkplayergender(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = gSaveBlock2Ptr->playerGender; return FALSE; } @@ -2186,17 +2646,23 @@ bool8 ScrCmd_playmoncry(struct ScriptContext *ctx) u16 species = VarGet(ScriptReadHalfword(ctx)); u16 mode = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + PlayCry_Script(species, mode); return FALSE; } void PlayFirstMonCry(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + PlayCry_Script(GetMonData(GetFirstLiveMon(), MON_DATA_SPECIES), CRY_MODE_NORMAL); } bool8 ScrCmd_waitmoncry(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetupNativeScript(ctx, IsCryFinished); return TRUE; } @@ -2208,6 +2674,8 @@ bool8 ScrCmd_setmetatile(struct ScriptContext *ctx) u16 metatileId = VarGet(ScriptReadHalfword(ctx)); bool16 isImpassable = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + x += MAP_OFFSET; y += MAP_OFFSET; if (!isImpassable) @@ -2222,6 +2690,8 @@ bool8 ScrCmd_opendoor(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + x += MAP_OFFSET; y += MAP_OFFSET; PlaySE(GetDoorSoundEffect(x, y)); @@ -2234,6 +2704,8 @@ bool8 ScrCmd_closedoor(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + x += MAP_OFFSET; y += MAP_OFFSET; FieldAnimateDoorClose(x, y); @@ -2250,6 +2722,8 @@ static bool8 IsDoorAnimationStopped(void) bool8 ScrCmd_waitdooranim(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + SetupNativeScript(ctx, IsDoorAnimationStopped); return TRUE; } @@ -2259,6 +2733,8 @@ bool8 ScrCmd_setdooropen(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + x += MAP_OFFSET; y += MAP_OFFSET; FieldSetDoorOpened(x, y); @@ -2270,6 +2746,8 @@ bool8 ScrCmd_setdoorclosed(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + x += MAP_OFFSET; y += MAP_OFFSET; FieldSetDoorClosed(x, y); @@ -2298,7 +2776,12 @@ bool8 ScrCmd_showelevmenu(struct ScriptContext *ctx) bool8 ScrCmd_checkcoins(struct ScriptContext *ctx) { - u16 *ptr = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + u16 *ptr = GetVarPointer(varId); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + *ptr = GetCoins(); return FALSE; } @@ -2307,6 +2790,8 @@ bool8 ScrCmd_addcoins(struct ScriptContext *ctx) { u16 coins = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + if (AddCoins(coins) == TRUE) gSpecialVar_Result = FALSE; else @@ -2318,6 +2803,8 @@ bool8 ScrCmd_removecoins(struct ScriptContext *ctx) { u16 coins = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + if (RemoveCoins(coins) == TRUE) gSpecialVar_Result = FALSE; else @@ -2329,12 +2816,16 @@ bool8 ScrCmd_moverotatingtileobjects(struct ScriptContext *ctx) { u16 puzzleNumber = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + sMovingNpcId = MoveRotatingTileObjects(puzzleNumber); return FALSE; } bool8 ScrCmd_turnrotatingtileobjects(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + TurnRotatingTileObjects(); return FALSE; } @@ -2343,24 +2834,35 @@ bool8 ScrCmd_initrotatingtilepuzzle(struct ScriptContext *ctx) { u16 isTrickHouse = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + InitRotatingTilePuzzle(isTrickHouse); return FALSE; } bool8 ScrCmd_freerotatingtilepuzzle(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + FreeRotatingTilePuzzle(); return FALSE; } bool8 ScrCmd_selectapproachingtrainer(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + gSelectedObjectEvent = GetCurrentApproachingTrainerObjectEventId(); return FALSE; } bool8 ScrCmd_lockfortrainer(struct ScriptContext *ctx) { + // As a special case, skip this during analysis. + if (Script_IsAnalyzingEffects()) + return FALSE; + Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); + if (IsOverworldLinkActive()) { return FALSE; @@ -2382,6 +2884,8 @@ bool8 ScrCmd_setmodernfatefulencounter(struct ScriptContext *ctx) bool8 isModernFatefulEncounter = TRUE; u16 partyIndex = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + SetMonData(&gPlayerParty[partyIndex], MON_DATA_MODERN_FATEFUL_ENCOUNTER, &isModernFatefulEncounter); return FALSE; } @@ -2390,6 +2894,8 @@ bool8 ScrCmd_checkmodernfatefulencounter(struct ScriptContext *ctx) { u16 partyIndex = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = GetMonData(&gPlayerParty[partyIndex], MON_DATA_MODERN_FATEFUL_ENCOUNTER, NULL); return FALSE; } @@ -2400,6 +2906,8 @@ bool8 ScrCmd_trywondercardscript(struct ScriptContext *ctx) if (script) { + Script_RequestEffects(SCREFF_V1); + gRamScriptRetAddr = ctx->scriptPtr; ScriptJump(ctx, script); } @@ -2416,6 +2924,8 @@ bool8 ScrCmd_warpspinenter(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + SetWarpDestination(mapGroup, mapNum, warpId, x, y); SetSpinStartFacingDir(GetPlayerFacingDirection()); DoSpinEnterWarp(); @@ -2428,6 +2938,8 @@ bool8 ScrCmd_setmonmetlocation(struct ScriptContext *ctx) u16 partyIndex = VarGet(ScriptReadHalfword(ctx)); u8 location = ScriptReadByte(ctx); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + if (partyIndex < PARTY_SIZE) SetMonData(&gPlayerParty[partyIndex], MON_DATA_MET_LOCATION, &location); return FALSE; @@ -2444,6 +2956,8 @@ bool8 ScrCmd_buffertrainerclassname(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 trainerClassId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + StringCopy(sScriptStringVars[stringVarIndex], GetTrainerClassNameFromId(trainerClassId)); return FALSE; } @@ -2453,6 +2967,8 @@ bool8 ScrCmd_buffertrainername(struct ScriptContext *ctx) u8 stringVarIndex = ScriptReadByte(ctx); u16 trainerClassId = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + StringCopy(sScriptStringVars[stringVarIndex], GetTrainerNameFromId(trainerClassId)); return FALSE; } @@ -2470,6 +2986,8 @@ bool8 ScrCmd_warpwhitefade(struct ScriptContext *ctx) u16 x = VarGet(ScriptReadHalfword(ctx)); u16 y = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE); + SetWarpDestination(mapGroup, mapNum, warpId, x, y); DoWhiteFadeWarp(); ResetInitialPlayerAvatarState(); @@ -2478,12 +2996,17 @@ bool8 ScrCmd_warpwhitefade(struct ScriptContext *ctx) void ScriptSetDoubleBattleFlag(struct ScriptContext *ctx) { + Script_RequestEffects(SCREFF_V1); + sIsScriptedWildDouble = TRUE; } bool8 ScrCmd_removeallitem(struct ScriptContext *ctx) { u32 itemId = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + u32 count = CountTotalItemQuantityInBag(itemId); gSpecialVar_Result = count; RemoveBagItem(itemId, count); @@ -2495,8 +3018,15 @@ bool8 ScrCmd_getobjectxy(struct ScriptContext *ctx) { u32 localId = VarGet(ScriptReadHalfword(ctx)); u32 useTemplate = VarGet(ScriptReadHalfword(ctx)); - u16 *pX = GetVarPointer(ScriptReadHalfword(ctx)); - u16 *pY = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varIdX = ScriptReadHalfword(ctx); + u32 varIdY = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varIdX); + Script_RequestWriteVar(varIdY); + + u16 *pX = GetVarPointer(varIdX); + u16 *pY = GetVarPointer(varIdY); GetObjectPosition(pX, pY, localId, useTemplate); return FALSE; @@ -2506,7 +3036,12 @@ bool8 ScrCmd_checkobjectat(struct ScriptContext *ctx) { u32 x = VarGet(ScriptReadHalfword(ctx)) + 7; u32 y = VarGet(ScriptReadHalfword(ctx)) + 7; - u16 *varPointer = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + + u16 *varPointer = GetVarPointer(varId); *varPointer = CheckObjectAtXY(x, y); @@ -2516,7 +3051,13 @@ bool8 ScrCmd_checkobjectat(struct ScriptContext *ctx) bool8 Scrcmd_getsetpokedexflag(struct ScriptContext *ctx) { u32 speciesId = SpeciesToNationalPokedexNum(VarGet(ScriptReadHalfword(ctx))); - bool32 desiredFlag = VarGet(ScriptReadHalfword(ctx)); + u32 desiredFlag = VarGet(ScriptReadHalfword(ctx)); + + if (desiredFlag == FLAG_SET_CAUGHT || desiredFlag == FLAG_SET_SEEN) + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + else + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = GetSetPokedexFlag(speciesId, desiredFlag); if (desiredFlag == FLAG_SET_CAUGHT) @@ -2528,6 +3069,9 @@ bool8 Scrcmd_getsetpokedexflag(struct ScriptContext *ctx) bool8 Scrcmd_checkspecies(struct ScriptContext *ctx) { u32 givenSpecies = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = CheckPartyHasSpecies(givenSpecies); return FALSE; @@ -2536,6 +3080,9 @@ bool8 Scrcmd_checkspecies(struct ScriptContext *ctx) bool8 Scrcmd_checkspecies_choose(struct ScriptContext *ctx) { u32 givenSpecies = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = (GetMonData(&gPlayerParty[gSpecialVar_0x8004], MON_DATA_SPECIES) == givenSpecies); return FALSE; @@ -2544,9 +3091,21 @@ bool8 Scrcmd_checkspecies_choose(struct ScriptContext *ctx) bool8 Scrcmd_getobjectfacingdirection(struct ScriptContext *ctx) { u32 objectId = VarGet(ScriptReadHalfword(ctx)); - u16 *varPointer = GetVarPointer(ScriptReadHalfword(ctx)); + u32 varId = ScriptReadHalfword(ctx); + + Script_RequestEffects(SCREFF_V1); + Script_RequestWriteVar(varId); + + u16 *varPointer = GetVarPointer(varId); *varPointer = gObjectEvents[GetObjectEventIdByLocalId(objectId)].facingDirection; return FALSE; } + +void Script_EndTrainerCanSeeIf(struct ScriptContext *ctx) +{ + u8 condition = ScriptReadByte(ctx); + if (ctx->breakOnTrainerBattle && sScriptConditionTable[condition][ctx->comparisonResult] == 1) + StopScript(ctx); +} diff --git a/src/script.c b/src/script.c index e6e2aa264d..b2730fb97f 100644 --- a/src/script.c +++ b/src/script.c @@ -2,6 +2,8 @@ #include "script.h" #include "event_data.h" #include "mystery_gift.h" +#include "random.h" +#include "trainer_see.h" #include "util.h" #include "constants/event_objects.h" #include "constants/map_scripts.h" @@ -50,6 +52,8 @@ void InitScriptContext(struct ScriptContext *ctx, void *cmdTable, void *cmdTable for (i = 0; i < (int)ARRAY_COUNT(ctx->stack); i++) ctx->stack[i] = NULL; + + ctx->breakOnTrainerBattle = FALSE; } u8 SetupBytecodeScript(struct ScriptContext *ctx, const u8 *ptr) @@ -258,6 +262,14 @@ void ScriptContext_SetupScript(const u8 *ptr) sGlobalScriptContextStatus = CONTEXT_RUNNING; } +// Moves a script from a local context to the global context and enables it. +void ScriptContext_ContinueScript(struct ScriptContext *ctx) +{ + sGlobalScriptContext = *ctx; + LockPlayerFieldControls(); + sGlobalScriptContextStatus = CONTEXT_RUNNING; +} + // Puts the script into waiting mode; usually called from a wait* script command. void ScriptContext_Stop(void) { @@ -281,7 +293,7 @@ void RunScriptImmediately(const u8 *ptr) while (RunScriptCommand(&sImmediateScriptContext) == TRUE); } -u8 *MapHeaderGetScriptTable(u8 tag) +const u8 *MapHeaderGetScriptTable(u8 tag) { const u8 *mapScripts = gMapHeader.mapScripts; @@ -303,14 +315,18 @@ u8 *MapHeaderGetScriptTable(u8 tag) void MapHeaderRunScriptType(u8 tag) { - u8 *ptr = MapHeaderGetScriptTable(tag); + const u8 *ptr = MapHeaderGetScriptTable(tag); if (ptr) - RunScriptImmediately(ptr); + { + struct ScriptContext ctx; + if (RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_HARDWARE, ptr, &ctx)) + ScriptContext_ContinueScript(&ctx); + } } -u8 *MapHeaderCheckScriptTable(u8 tag) +const u8 *MapHeaderCheckScriptTable(u8 tag) { - u8 *ptr = MapHeaderGetScriptTable(tag); + const u8 *ptr = MapHeaderGetScriptTable(tag); if (!ptr) return NULL; @@ -332,7 +348,12 @@ u8 *MapHeaderCheckScriptTable(u8 tag) // Run map script if vars are equal if (VarGet(varIndex1) == VarGet(varIndex2)) - return T2_READ_PTR(ptr); + { + const u8 *mapScript = T2_READ_PTR(ptr); + if (!Script_HasNoEffect(mapScript)) + return mapScript; + } + ptr += 4; } } @@ -364,7 +385,7 @@ void RunOnDiveWarpMapScript(void) bool8 TryRunOnFrameMapScript(void) { - u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_FRAME_TABLE); + const u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_FRAME_TABLE); if (!ptr) return FALSE; @@ -375,7 +396,7 @@ bool8 TryRunOnFrameMapScript(void) void TryRunOnWarpIntoMapScript(void) { - u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_WARP_INTO_MAP_TABLE); + const u8 *ptr = MapHeaderCheckScriptTable(MAP_SCRIPT_ON_WARP_INTO_MAP_TABLE); if (ptr) RunScriptImmediately(ptr); } @@ -504,3 +525,116 @@ void InitRamScript_NoObjectEvent(u8 *script, u16 scriptSize) InitRamScript(script, scriptSize, MAP_GROUP(UNDEFINED), MAP_NUM(UNDEFINED), NO_OBJECT); #endif //FREE_MYSTERY_EVENT_BUFFERS } + +bool8 LoadTrainerObjectScript(void) +{ + sGlobalScriptContext.scriptPtr = gApproachingTrainers[gNoOfApproachingTrainers - 1].trainerScriptPtr; + return TRUE; +} + +struct ScriptEffectContext { + u32 breakOn; + intptr_t breakTo[5]; + const u8 *nextCmd; +}; + +struct ScriptEffectContext *gScriptEffectContext = NULL; + +static bool32 Script_IsEffectInstrumentedCommand(ScrCmdFunc func) +{ + // In ROM mirror 1. + return (((uintptr_t)func) & 0xE000000) == 0xA000000; +} + +/* 'setjmp' and 'longjmp' cause link errors, so we use + * '__builtin_setjmp' and '__builtin_longjmp' instead. + * See https://gcc.gnu.org/onlinedocs/gcc/Nonlocal-Gotos.html */ +static bool32 RunScriptImmediatelyUntilEffect_InternalLoop(struct ScriptContext *ctx) +{ + if (__builtin_setjmp(gScriptEffectContext->breakTo) == 0) + { + while (TRUE) + { + u32 cmdCode; + ScrCmdFunc *func; + + gScriptEffectContext->nextCmd = ctx->scriptPtr; + + if (!ctx->scriptPtr) + return FALSE; + + cmdCode = *ctx->scriptPtr; + ctx->scriptPtr++; + func = &ctx->cmdTable[cmdCode]; + + // Invalid script command. + if (func >= ctx->cmdTableEnd) + return TRUE; + + if (!Script_IsEffectInstrumentedCommand(*func)) + return TRUE; + + // Command which waits for a frame. + if ((*func)(ctx)) + { + gScriptEffectContext->nextCmd = ctx->scriptPtr; + return TRUE; + } + } + } + else + { + return TRUE; + } +} + +void Script_GotoBreak_Internal(void) +{ + __builtin_longjmp(gScriptEffectContext->breakTo, 1); +} + +bool32 RunScriptImmediatelyUntilEffect_Internal(u32 effects, const u8 *ptr, struct ScriptContext *ctx) +{ + bool32 result; + struct ScriptEffectContext seCtx; + seCtx.breakOn = effects & 0x7FFFFFFF; + + if (ctx == NULL) + ctx = &sImmediateScriptContext; + + InitScriptContext(ctx, gScriptCmdTable, gScriptCmdTableEnd); + if (effects & SCREFF_TRAINERBATTLE) + ctx->breakOnTrainerBattle = TRUE; + SetupBytecodeScript(ctx, ptr); + + rng_value_t rngValue = gRngValue; + gScriptEffectContext = &seCtx; + result = RunScriptImmediatelyUntilEffect_InternalLoop(ctx); + gScriptEffectContext = NULL; + gRngValue = rngValue; + + if (result) + ctx->scriptPtr = seCtx.nextCmd; + + return result; +} + +bool32 Script_HasNoEffect(const u8 *ptr) +{ + return !RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE, ptr, NULL); +} + +void Script_RequestEffects_Internal(u32 effects) +{ + if (gScriptEffectContext->breakOn & effects) + __builtin_longjmp(gScriptEffectContext->breakTo, 1); +} + +void Script_RequestWriteVar_Internal(u32 varId) +{ + if (varId == 0) + return; + if (SPECIAL_VARS_START <= varId && varId <= SPECIAL_VARS_END) + return; + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); +} diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index fc248435a9..94c7d7d8fa 100644 --- a/src/script_pokemon_util.c +++ b/src/script_pokemon_util.c @@ -240,6 +240,9 @@ void CanHyperTrain(struct ScriptContext *ctx) { u32 stat = ScriptReadByte(ctx); u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1); + if (stat < NUM_STATS && partyIndex < PARTY_SIZE && !GetMonData(&gPlayerParty[partyIndex], MON_DATA_HYPER_TRAINED_HP + stat) @@ -257,6 +260,9 @@ void HyperTrain(struct ScriptContext *ctx) { u32 stat = ScriptReadByte(ctx); u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + if (stat < NUM_STATS && partyIndex < PARTY_SIZE) { bool32 data = TRUE; @@ -268,6 +274,9 @@ void HyperTrain(struct ScriptContext *ctx) void HasGigantamaxFactor(struct ScriptContext *ctx) { u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + + Script_RequestEffects(SCREFF_V1); + if (partyIndex < PARTY_SIZE) gSpecialVar_Result = GetMonData(&gPlayerParty[partyIndex], MON_DATA_GIGANTAMAX_FACTOR); else @@ -278,6 +287,8 @@ void ToggleGigantamaxFactor(struct ScriptContext *ctx) { u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + gSpecialVar_Result = FALSE; if (partyIndex < PARTY_SIZE) @@ -298,6 +309,8 @@ void CheckTeraType(struct ScriptContext *ctx) { u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = TYPE_NONE; if (partyIndex < PARTY_SIZE) @@ -309,6 +322,8 @@ void SetTeraType(struct ScriptContext *ctx) u32 type = ScriptReadByte(ctx); u32 partyIndex = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + if (type < NUMBER_OF_MON_TYPES && partyIndex < PARTY_SIZE) SetMonData(&gPlayerParty[partyIndex], MON_DATA_TERA_TYPE, &type); } @@ -542,6 +557,11 @@ void ScrCmd_createmon(struct ScriptContext *ctx) u8 ivs[NUM_STATS] = {hpIv, atkIv, defIv, speedIv, spAtkIv, spDefIv}; u16 moves[MAX_MON_MOVES] = {move1, move2, move3, move4}; + if (side == 0) + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + else + Script_RequestEffects(SCREFF_V1); + gSpecialVar_Result = ScriptGiveMonParameterized(side, slot, species, level, item, ball, nature, abilityNum, gender, evs, ivs, moves, isShiny, ggMaxFactor, teraType); } @@ -580,6 +600,8 @@ void Script_SetStatus1(struct ScriptContext *ctx) u32 status1 = VarGet(ScriptReadHalfword(ctx)); u32 slot = VarGet(ScriptReadHalfword(ctx)); + Script_RequestEffects(SCREFF_V1 | SCREFF_SAVE); + if (slot >= PARTY_SIZE) { u16 species; diff --git a/src/trainer_see.c b/src/trainer_see.c index 2582637aa1..12c6cba612 100644 --- a/src/trainer_see.c +++ b/src/trainer_see.c @@ -2,6 +2,7 @@ #include "battle_setup.h" #include "event_data.h" #include "event_object_movement.h" +#include "event_scripts.h" #include "field_effect.h" #include "field_player_avatar.h" #include "pokemon.h" @@ -375,6 +376,16 @@ bool8 CheckForTrainersWantingBattle(void) continue; numTrainers = CheckTrainer(i); + if (numTrainers == 0xFF) // non-trainerbatle script + { + u32 objectEventId = gApproachingTrainers[gNoOfApproachingTrainers - 1].objectEventId; + gSelectedObjectEvent = objectEventId; + gSpecialVar_LastTalked = gObjectEvents[objectEventId].localId; + ScriptContext_SetupScript(EventScript_ObjectApproachPlayer); + LockPlayerFieldControls(); + return TRUE; + } + if (numTrainers == 2) break; @@ -417,14 +428,33 @@ bool8 CheckForTrainersWantingBattle(void) static u8 CheckTrainer(u8 objectEventId) { - const u8 *scriptPtr; + const u8 *scriptPtr, *trainerBattlePtr; u8 numTrainers = 1; - u8 approachDistance; + + u8 approachDistance = GetTrainerApproachDistance(&gObjectEvents[objectEventId]); + if (approachDistance == 0) + return 0; if (InTrainerHill() == TRUE) - scriptPtr = GetTrainerHillTrainerScript(); + { + trainerBattlePtr = scriptPtr = GetTrainerHillTrainerScript(); + } else - scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); + { + trainerBattlePtr = scriptPtr = GetObjectEventScriptPointerByObjectEventId(objectEventId); + struct ScriptContext ctx; + if (RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_SAVE | SCREFF_HARDWARE | SCREFF_TRAINERBATTLE, scriptPtr, &ctx)) + { + if (*ctx.scriptPtr == 0x5c) // trainerbattle + trainerBattlePtr = ctx.scriptPtr; + else + trainerBattlePtr = NULL; + } + else + { + return 0; // no effect + } + } if (InBattlePyramid()) { @@ -436,36 +466,36 @@ static u8 CheckTrainer(u8 objectEventId) if (GetHillTrainerFlag(objectEventId)) return 0; } - else + else if (trainerBattlePtr) { - if (GetTrainerFlagFromScriptPointer(scriptPtr)) + if (GetTrainerFlagFromScriptPointer(trainerBattlePtr)) return 0; } - - approachDistance = GetTrainerApproachDistance(&gObjectEvents[objectEventId]); - - if (approachDistance != 0) + else { - if (scriptPtr[1] == TRAINER_BATTLE_DOUBLE - || scriptPtr[1] == TRAINER_BATTLE_REMATCH_DOUBLE - || scriptPtr[1] == TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE) + numTrainers = 0xFF; + } + + if (trainerBattlePtr) + { + if (trainerBattlePtr[1] == TRAINER_BATTLE_DOUBLE + || trainerBattlePtr[1] == TRAINER_BATTLE_REMATCH_DOUBLE + || trainerBattlePtr[1] == TRAINER_BATTLE_CONTINUE_SCRIPT_DOUBLE) { if (GetMonsStateToDoubles_2() != PLAYER_HAS_TWO_USABLE_MONS) return 0; numTrainers = 2; } - - gApproachingTrainers[gNoOfApproachingTrainers].objectEventId = objectEventId; - gApproachingTrainers[gNoOfApproachingTrainers].trainerScriptPtr = scriptPtr; - gApproachingTrainers[gNoOfApproachingTrainers].radius = approachDistance; - InitTrainerApproachTask(&gObjectEvents[objectEventId], approachDistance - 1); - gNoOfApproachingTrainers++; - - return numTrainers; } - return 0; + gApproachingTrainers[gNoOfApproachingTrainers].objectEventId = objectEventId; + gApproachingTrainers[gNoOfApproachingTrainers].trainerScriptPtr = scriptPtr; + gApproachingTrainers[gNoOfApproachingTrainers].radius = approachDistance; + InitTrainerApproachTask(&gObjectEvents[objectEventId], approachDistance - 1); + gNoOfApproachingTrainers++; + + return numTrainers; } static u8 GetTrainerApproachDistance(struct ObjectEvent *trainerObj) diff --git a/test/script.c b/test/script.c new file mode 100644 index 0000000000..5f185d72cf --- /dev/null +++ b/test/script.c @@ -0,0 +1,116 @@ +#include "global.h" +#include "test/test.h" +#include "test/overworld_script.h" +#include "script.h" +#include "constants/decorations.h" +#include "constants/moves.h" + +TEST("Script_HasNoEffect control flow") +{ + const u8 *script = OVERWORLD_SCRIPT( + nop; + nop1; + checkflag FLAG_TEMP_1; + checktrainerflag 0; + compare VAR_TEMP_0, 0; + goto_if_eq GoneTo; + GoneTo: + call Sub; + call_if_eq Sub; + end; + + Sub: + goto SubRet; + SubRet: + return; + ); + EXPECT(Script_HasNoEffect(script)); +} + +TEST("Script_HasNoEffect variables") +{ + // Writes to special variables are not considered player-visible + // because their values are indeterminate if the player has control. + const u8 *writeSpecial = OVERWORLD_SCRIPT( + setvar VAR_0x8000, 1; + addvar VAR_0x8000, 1; + subvar VAR_0x8000, VAR_TEMP_0; + copyvar VAR_0x8000, VAR_TEMP_0; + setorcopyvar VAR_0x8000, VAR_TEMP_0; + specialvar VAR_RESULT, GetPlayerFacingDirection; + getplayerxy VAR_0x8000, VAR_0x8001; + getpartysize; + checkitemspace ITEM_POTION, 1; + checkitem ITEM_POTION, 1; + checkitemtype ITEM_POTION; + checkpcitem ITEM_POTION, 1; + checkdecorspace DECOR_SNORLAX_DOLL; + checkdecor DECOR_SNORLAX_DOLL; + checkpartymove MOVE_CELEBRATE; + random 2; + checkmoney 5000; + getpokenewsactive POKENEWS_LILYCOVE; + checkplayergender; + checkcoins VAR_RESULT; + checkmodernfatefulencounter 0; + end; + ); + + // Writes to other variables are considered player-visible because + // their values are preserved even while the player has control. + const u8 *setVariable = OVERWORLD_SCRIPT( + setvar VAR_TEMP_0, 1; + end; + ); + + const u8 *addVariable = OVERWORLD_SCRIPT( + addvar VAR_TEMP_0, 1; + end; + ); + + const u8 *subVariable = OVERWORLD_SCRIPT( + subvar VAR_TEMP_0, 1; + end; + ); + + const u8 *copyVariable = OVERWORLD_SCRIPT( + copyvar VAR_TEMP_0, VAR_RESULT; + end; + ); + + const u8 *setorcopyVariable = OVERWORLD_SCRIPT( + setorcopyvar VAR_TEMP_0, VAR_RESULT; + end; + ); + + const u8 *specialvarVariable = OVERWORLD_SCRIPT( + specialvar VAR_TEMP_0, GetPlayerFacingDirection; + end; + ); + + const u8 *getPlayerXYVariable1 = OVERWORLD_SCRIPT( + getplayerxy VAR_TEMP_0, VAR_RESULT; + end; + ); + + const u8 *getPlayerXYVariable2 = OVERWORLD_SCRIPT( + getplayerxy VAR_RESULT, VAR_TEMP_0; + end; + ); + + const u8 *checkCoinsVariable = OVERWORLD_SCRIPT( + checkcoins VAR_TEMP_0; + end; + ); + + EXPECT(Script_HasNoEffect(writeSpecial)); + EXPECT(!Script_HasNoEffect(setVariable)); + EXPECT(!Script_HasNoEffect(addVariable)); + EXPECT(!Script_HasNoEffect(subVariable)); + EXPECT(!Script_HasNoEffect(copyVariable)); + EXPECT(!Script_HasNoEffect(setorcopyVariable)); + EXPECT(!Script_HasNoEffect(specialvarVariable)); + EXPECT(!Script_HasNoEffect(getPlayerXYVariable1)); + EXPECT(!Script_HasNoEffect(getPlayerXYVariable2)); + EXPECT(!Script_HasNoEffect(checkCoinsVariable)); +} From b5f539ed21dc5044b779e16054388dce35b77a04 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Wed, 8 Jan 2025 08:00:20 -0500 Subject: [PATCH 38/85] Rename AI_FLAG_PREFER_STRONGEST_MOVE (#5972) --- docs/tutorials/ai_flags.md | 2 +- include/constants/battle_ai.h | 2 +- src/battle_ai_main.c | 8 ++++---- src/battle_debug.c | 6 +++--- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/docs/tutorials/ai_flags.md b/docs/tutorials/ai_flags.md index 7b77305c13..4d0b7ca6aa 100644 --- a/docs/tutorials/ai_flags.md +++ b/docs/tutorials/ai_flags.md @@ -67,7 +67,7 @@ AI will generally behave more recklessly. This AI enables the following behaviou * Switch offensively mid battle rather than defensively (if using `AI_FLAG_SMART_MON_CHOICES`) * Prioritize Explosion moves -## `AI_FLAG_PREFER_STRONGEST_MOVE` +## `AI_FLAG_TRY_TO_2HKO` Adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. Keep in mind that this is a weaker form of `AI_FLAG_TRY_TO_FAINT` at scoring OHKOs as it does not take into account who is attacking first, it does however handle 2HKOs. diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index df6069ead9..5057a04152 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -31,7 +31,7 @@ #define AI_FLAG_CHECK_VIABILITY (1 << 2) // AI damaging moves and move effects to determine the best available move in the current situation. #define AI_FLAG_FORCE_SETUP_FIRST_TURN (1 << 3) // AI will prioritize using setup moves on the first turn at the expensve of all else. AI_FLAG_CHECK_VIABILITY will instead do this when the AI determines it makes sense. #define AI_FLAG_RISKY (1 << 4) // AI will generally behave more recklessly, prioritizing damage over accuracy, explosions, etc. -#define AI_FLAG_PREFER_STRONGEST_MOVE (1 << 5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. +#define AI_FLAG_TRY_TO_2HKO (1 << 5) // AI adds score bonus to any move the AI has that either OHKOs or 2HKOs the player. #define AI_FLAG_PREFER_BATON_PASS (1 << 6) // AI prefers raising its own stats and setting for / using Baton Pass. #define AI_FLAG_DOUBLE_BATTLE (1 << 7) // Automatically set for double battles, handles AI behaviour with partner. #define AI_FLAG_HP_AWARE (1 << 8) // AI will favour certain move effects based on how much remaining HP it and the player's mon have. diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 538b0e4732..ea8a4bb91f 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -48,7 +48,7 @@ static s32 AI_TryToFaint(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_ForceSetupFirstTurn(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); -static s32 AI_PreferStrongestMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); +static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_PreferBatonPass(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_HPAware(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_Roaming(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); @@ -66,7 +66,7 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) = [2] = AI_CheckViability, // AI_FLAG_CHECK_VIABILITY [3] = AI_ForceSetupFirstTurn, // AI_FLAG_FORCE_SETUP_FIRST_TURN [4] = AI_Risky, // AI_FLAG_RISKY - [5] = AI_PreferStrongestMove, // AI_FLAG_PREFER_STRONGEST_MOVE + [5] = AI_TryTo2HKO, // AI_FLAG_TRY_TO_2HKO [6] = AI_PreferBatonPass, // AI_FLAG_PREFER_BATON_PASS [7] = AI_DoubleBattle, // AI_FLAG_DOUBLE_BATTLE [8] = AI_HPAware, // AI_FLAG_HP_AWARE @@ -136,7 +136,7 @@ static u32 GetWildAiFlags(void) if (avgLevel >= 20) flags |= AI_FLAG_CHECK_VIABILITY; if (avgLevel >= 60) - flags |= AI_FLAG_PREFER_STRONGEST_MOVE; + flags |= AI_FLAG_TRY_TO_2HKO; if (avgLevel >= 80) flags |= AI_FLAG_HP_AWARE; @@ -4897,7 +4897,7 @@ static s32 AI_Risky(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } // Adds score bonus to best powered move -static s32 AI_PreferStrongestMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) +static s32 AI_TryTo2HKO(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (IS_TARGETING_PARTNER(battlerAtk, battlerDef)) return score; diff --git a/src/battle_debug.c b/src/battle_debug.c index b03ef194f0..c4fef859f4 100644 --- a/src/battle_debug.c +++ b/src/battle_debug.c @@ -220,7 +220,7 @@ enum LIST_AI_CHECK_VIABILITY, LIST_AI_SETUP_FIRST_TURN, LIST_AI_RISKY, - LIST_AI_PREFER_STRONGEST_MOVE, + LIST_AI_TRY_TO_2HKO, LIST_AI_PREFER_BATON_PASS, LIST_AI_DOUBLE_BATTLE, LIST_AI_HP_AWARE, @@ -385,7 +385,7 @@ static const u8 sText_TryToFaint[] = _("Try to Faint"); static const u8 sText_CheckViability[] = _("Check Viability"); static const u8 sText_SetUpFirstTurn[] = _("Setup First Turn"); static const u8 sText_Risky[] = _("Risky"); -static const u8 sText_PreferStrongestMove[] = _("Prefer Strongest Move"); +static const u8 sText_TryTo2HKO[] = _("Try to 2HKO"); static const u8 sText_PreferBatonPass[] = _("Prefer Baton Pass"); static const u8 sText_DoubleBattle[] = _("Double Battle"); static const u8 sText_HpAware[] = _("HP Aware"); @@ -628,7 +628,7 @@ static const struct ListMenuItem sAIListItems[] = {sText_CheckViability, LIST_AI_CHECK_VIABILITY}, {sText_SetUpFirstTurn, LIST_AI_SETUP_FIRST_TURN}, {sText_Risky, LIST_AI_RISKY}, - {sText_PreferStrongestMove, LIST_AI_PREFER_STRONGEST_MOVE}, + {sText_TryTo2HKO, LIST_AI_TRY_TO_2HKO}, {sText_PreferBatonPass, LIST_AI_PREFER_BATON_PASS}, {sText_DoubleBattle, LIST_AI_DOUBLE_BATTLE}, {sText_HpAware, LIST_AI_HP_AWARE}, From 4c4137d6003b3388c0514b70c5af55e2282f223d Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 8 Jan 2025 18:26:35 +0000 Subject: [PATCH 39/85] Revert #5033 change to MapHeaderRunScriptType (#5975) --- src/script.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/src/script.c b/src/script.c index b2730fb97f..7111f3228d 100644 --- a/src/script.c +++ b/src/script.c @@ -317,11 +317,7 @@ void MapHeaderRunScriptType(u8 tag) { const u8 *ptr = MapHeaderGetScriptTable(tag); if (ptr) - { - struct ScriptContext ctx; - if (RunScriptImmediatelyUntilEffect(SCREFF_V1 | SCREFF_HARDWARE, ptr, &ctx)) - ScriptContext_ContinueScript(&ctx); - } + RunScriptImmediately(ptr); } const u8 *MapHeaderCheckScriptTable(u8 tag) From 81d877339ce1ae048426733bb820c9daf6e9919a Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Wed, 8 Jan 2025 12:36:50 -0800 Subject: [PATCH 40/85] Removed OW_AUTO_SIGNPOST (#5974) --- include/config/overworld.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/config/overworld.h b/include/config/overworld.h index bc65470751..5a6cb1e955 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -3,7 +3,6 @@ // Movement config #define OW_RUNNING_INDOORS GEN_LATEST // In Gen4+, players are allowed to run indoors. -#define OW_AUTO_SIGNPOST FALSE // When enabled, if the tile that the player is facing has MB_SIGNPOST, MB_POKEMART_SIGN, or MB_POKEMON_CENTER_SIGN, the player will automatically read the signpost, as seen in FRLG. #define SLOW_MOVEMENT_ON_STAIRS FALSE // If enabled, the player will move slower up/down stairs like in FR // Other settings From e264fa6fc087674266c890535caae5d097aca45e Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Thu, 9 Jan 2025 01:14:38 +0100 Subject: [PATCH 41/85] Removed OW_AUTO_SIGNPOST (#5978) --- include/config/overworld.h | 1 - 1 file changed, 1 deletion(-) diff --git a/include/config/overworld.h b/include/config/overworld.h index 464024025b..be56ccb26f 100644 --- a/include/config/overworld.h +++ b/include/config/overworld.h @@ -3,7 +3,6 @@ // Movement config #define OW_RUNNING_INDOORS GEN_LATEST // In Gen4+, players are allowed to run indoors. -#define OW_AUTO_SIGNPOST FALSE // When enabled, if the tile that the player is facing has MB_SIGNPOST, MB_POKEMART_SIGN, or MB_POKEMON_CENTER_SIGN, the player will automatically read the signpost, as seen in FRLG. #define SLOW_MOVEMENT_ON_STAIRS FALSE // If enabled, the player will move slower up/down stairs like in FR // Other settings From e244d942cce5018a14f3b2910cb5689432cf2666 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Thu, 9 Jan 2025 14:01:00 +0100 Subject: [PATCH 42/85] CreateFacilityMon error: 'personality' may be used uninitialized (#5981) --- src/battle_tower.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_tower.c b/src/battle_tower.c index 6f80823b98..3f614cf294 100644 --- a/src/battle_tower.c +++ b/src/battle_tower.c @@ -1567,7 +1567,7 @@ void CreateFacilityMon(const struct TrainerMon *fmon, u16 level, u8 fixedIV, u32 { u8 ball = (fmon->ball == 0xFF) ? Random() % POKEBALL_COUNT : fmon->ball; u16 move; - u32 personality, ability, friendship, j; + u32 personality = 0, ability, friendship, j; if (fmon->gender == TRAINER_MON_MALE) { From 83979375d38f33978d77a30b0fb47f64086fa6c8 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Thu, 9 Jan 2025 15:19:07 +0100 Subject: [PATCH 43/85] Don't write to NULL in TryFindHiddenPokemon (#5983) --- src/dexnav.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/dexnav.c b/src/dexnav.c index c3d8e3b992..9247ff77a3 100644 --- a/src/dexnav.c +++ b/src/dexnav.c @@ -2499,7 +2499,8 @@ bool8 TryFindHiddenPokemon(void) || FlagGet(FLAG_SYS_DEXNAV_SEARCH) || GetFlashLevel() > 0) { - (*stepPtr) = 0; + if (stepPtr != NULL) + (*stepPtr) = 0; return FALSE; } From 1551a33069be4d8a55902f68e5de9dc437e8984d Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Thu, 9 Jan 2025 20:28:09 +0000 Subject: [PATCH 44/85] Fix leftover test change from #5033 (#5987) --- data/maps/Route110/scripts.inc | 1 - 1 file changed, 1 deletion(-) diff --git a/data/maps/Route110/scripts.inc b/data/maps/Route110/scripts.inc index 7c494a586d..8447604aca 100644 --- a/data/maps/Route110/scripts.inc +++ b/data/maps/Route110/scripts.inc @@ -11,7 +11,6 @@ Route110_MapScripts:: Route110_OnResume: special UpdateCyclingRoadState - msgbox Route110_Text_WeCantTalkAboutAquaActivities, MSGBOX_SIGN end Route110_OnTransition: From 25d678f1e7603fbd5c0156b68f0419555f90c8b3 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Fri, 10 Jan 2025 10:53:27 +0100 Subject: [PATCH 45/85] PlayerHandleStatusXor - change u8 to u32 (#5988) --- src/battle_controller_player.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 059836561c..e56207507b 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -2236,7 +2236,7 @@ void PlayerHandleExpUpdate(u32 battler) static void PlayerHandleStatusXor(u32 battler) { - u8 val = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_STATUS) ^ gBattleResources->bufferA[battler][1]; + u32 val = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_STATUS) ^ gBattleResources->bufferA[battler][1]; SetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_STATUS, &val); PlayerBufferExecCompleted(battler); From ab49aaf3b15b87e7746f7f30e909b2a8db82dabe Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:58:51 +0100 Subject: [PATCH 46/85] Dynamic move type was ignored in doubles for spread moves (#5984) --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 41b61f6014..f7ea083c60 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3809,7 +3809,7 @@ static void CancellerMultiTargetMoves(u32 *effect) } else { - CalcTypeEffectivenessMultiplier(gCurrentMove, GetMoveType(gCurrentMove), gBattlerAttacker, battlerDef, GetBattlerAbility(battlerDef), TRUE); + CalcTypeEffectivenessMultiplier(gCurrentMove, GetBattleMoveType(gCurrentMove), gBattlerAttacker, battlerDef, GetBattlerAbility(battlerDef), TRUE); } } if (moveTarget == MOVE_TARGET_BOTH) From 75a2d419e11e462fefbc1c048485828ece4fde0c Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 10 Jan 2025 16:59:37 +0100 Subject: [PATCH 47/85] Follo up for Innards Out / Future Sight interaction (#5967) --- include/battle.h | 2 +- src/battle_script_commands.c | 8 +++----- src/battle_util.c | 5 +++-- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/include/battle.h b/include/battle.h index 99c86181f6..c762e7f766 100644 --- a/include/battle.h +++ b/include/battle.h @@ -310,7 +310,7 @@ struct WishFutureKnock u8 wishPartyId[MAX_BATTLERS_COUNT]; u8 weatherDuration; u8 knockedOffMons[NUM_BATTLE_SIDES]; // Each battler is represented by a bit. - u8 futureSightDmg[MAX_BATTLERS_COUNT]; + s16 futureSightDmg; }; struct AI_SavedBattleMon diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 19b095333c..81891831f4 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2460,10 +2460,8 @@ static void Cmd_datahpupdate(void) gSpecialStatuses[battler].shellBellDmg = gHpDealt; // Record damage for foreseen moves - if (gWishFutureKnock.futureSightDmg[battler] == 0 - && gMovesInfo[gWishFutureKnock.futureSightMove[battler]].effect == EFFECT_FUTURE_SIGHT) - gWishFutureKnock.futureSightDmg[battler] = gHpDealt; - + gWishFutureKnock.futureSightDmg = gHpDealt; + // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are // used in combination as general damage trackers for other purposes. specialDmg is additionally used // to help determine if a fire move should defrost the target. @@ -13964,7 +13962,7 @@ static void Cmd_trysetfutureattack(void) gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; gWishFutureKnock.futureSightCounter[gBattlerTarget] = 3; - gWishFutureKnock.futureSightDmg[gBattlerTarget] = 0; + gWishFutureKnock.futureSightDmg = 0; if (gCurrentMove == MOVE_DOOM_DESIRE) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; diff --git a/src/battle_util.c b/src/battle_util.c index c35c072b77..8d87bcccf5 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5808,9 +5808,10 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { //no Innards Out effect if Future Sight user is currently not on field if (gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == gBattlerPartyIndexes[gBattlerAttacker] - || gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == BATTLE_PARTNER(gBattlerPartyIndexes[gBattlerAttacker])) + || gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == BATTLE_PARTNER(gBattlerPartyIndexes[gBattlerAttacker])) { - gBattleMoveDamage = gWishFutureKnock.futureSightDmg[gBattlerTarget]; + gBattleMoveDamage = gWishFutureKnock.futureSightDmg; + gWishFutureKnock.futureSightDmg = 0; BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_AftermathDmg; effect++; From 3c7708fae4327edac08e44b74f380ccd63fd2cbb Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Fri, 10 Jan 2025 17:00:30 +0100 Subject: [PATCH 48/85] Remove out of bounds gSprites access in move relearner (#5991) --- src/move_relearner.c | 1 - 1 file changed, 1 deletion(-) diff --git a/src/move_relearner.c b/src/move_relearner.c index 1e66702695..7930ba15b6 100644 --- a/src/move_relearner.c +++ b/src/move_relearner.c @@ -1007,7 +1007,6 @@ void MoveRelearnerShowHideCategoryIcon(s32 moveId) DestroySprite(&gSprites[sMoveRelearnerStruct->categoryIconSpriteId]); sMoveRelearnerStruct->categoryIconSpriteId = 0xFF; - gSprites[sMoveRelearnerStruct->categoryIconSpriteId].invisible = TRUE; } else { From 0fefb444debebdd09bbbcdeb9b0a134fc74aadc2 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Fri, 10 Jan 2025 19:07:32 -0300 Subject: [PATCH 49/85] Multiple removals of hardcoded move IDs (#5964) --- include/battle_ai_util.h | 3 ++- include/battle_util.h | 4 ++-- include/constants/battle.h | 7 ++++++ src/battle_ai_main.c | 43 ++++++++++++++-------------------- src/battle_ai_switch_items.c | 4 ++-- src/battle_ai_util.c | 41 ++++++++++++++++++++++---------- src/battle_controller_player.c | 15 ++++++------ src/battle_script_commands.c | 4 ++-- src/battle_util.c | 8 +++---- 9 files changed, 72 insertions(+), 57 deletions(-) diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 7cfc28e5d6..4a47b63503 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -123,7 +123,7 @@ bool32 HasMoveWithMoveEffectExcept(u32 battlerId, u32 moveEffect, u32 exception) bool32 HasMoveThatLowersOwnStats(u32 battlerId); bool32 HasMoveWithLowAccuracy(u32 battlerAtk, u32 battlerDef, u32 accCheck, bool32 ignoreStatus, u32 atkAbility, u32 defAbility, u32 atkHoldEffect, u32 defHoldEffect); bool32 HasAnyKnownMove(u32 battlerId); -bool32 IsAromaVeilProtectedMove(u32 move); +bool32 IsAromaVeilProtectedEffect(u32 moveEffect); bool32 IsNonVolatileStatusMoveEffect(u32 moveEffect); bool32 IsMoveRedirectionPrevented(u32 move, u32 atkAbility); bool32 IsMoveEncouragedToHit(u32 battlerAtk, u32 battlerDef, u32 move); @@ -182,6 +182,7 @@ bool32 PartnerHasSameMoveEffectWithoutTarget(u32 battlerAtkPartner, u32 move, u3 bool32 PartnerMoveEffectIsStatusSameTarget(u32 battlerAtkPartner, u32 battlerDef, u32 partnerMove); bool32 IsMoveEffectWeather(u32 move); bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove); +bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, u32 effectCheck); bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck); bool32 PartnerMoveIsSameAsAttacker(u32 battlerAtkPartner, u32 battlerDef, u32 move, u32 partnerMove); bool32 PartnerMoveIsSameNoTarget(u32 battlerAtkPartner, u32 move, u32 partnerMove); diff --git a/include/battle_util.h b/include/battle_util.h index 5ab3c3495b..5ab72967dc 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -248,8 +248,8 @@ uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); uq4_12_t GetTypeModifier(u32 atkType, u32 defType); uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType); -s32 GetStealthHazardDamage(u8 hazardType, u32 battler); -s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp); +s32 GetStealthHazardDamage(enum TypeSideHazard hazardType, u32 battler); +s32 GetStealthHazardDamageByTypesAndHP(enum TypeSideHazard hazardType, u8 type1, u8 type2, u32 maxHp); bool32 CanMegaEvolve(u32 battler); bool32 CanUltraBurst(u32 battler); void ActivateMegaEvolution(u32 battler); diff --git a/include/constants/battle.h b/include/constants/battle.h index eeccd83144..561d4f81e5 100644 --- a/include/constants/battle.h +++ b/include/constants/battle.h @@ -253,6 +253,13 @@ #define SIDE_STATUS_SCREEN_ANY (SIDE_STATUS_REFLECT | SIDE_STATUS_LIGHTSCREEN | SIDE_STATUS_AURORA_VEIL) #define SIDE_STATUS_PLEDGE_ANY (SIDE_STATUS_RAINBOW | SIDE_STATUS_SEA_OF_FIRE | SIDE_STATUS_SWAMP) +// Used for damaging entry hazards based on type +enum TypeSideHazard +{ + TYPE_SIDE_HAZARD_POINTED_STONES = TYPE_ROCK, + TYPE_SIDE_HAZARD_SHARP_STEEL = TYPE_STEEL, +}; + // Field affecting statuses. #define STATUS_FIELD_MAGIC_ROOM (1 << 0) #define STATUS_FIELD_TRICK_ROOM (1 << 1) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 61e27ddb5a..d856fae81f 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -809,7 +809,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) RETURN_SCORE_MINUS(10); break; case ABILITY_AROMA_VEIL: - if (IsAromaVeilProtectedMove(move)) + if (IsAromaVeilProtectedEffect(moveEffect)) RETURN_SCORE_MINUS(10); break; case ABILITY_SWEET_VEIL: @@ -902,7 +902,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) RETURN_SCORE_MINUS(10); break; case ABILITY_AROMA_VEIL: - if (IsAromaVeilProtectedMove(move)) + if (IsAromaVeilProtectedEffect(moveEffect)) RETURN_SCORE_MINUS(10); break; } @@ -947,12 +947,13 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) weather = AI_GetWeather(aiData); if (weather & B_WEATHER_PRIMAL_ANY) { - switch (move) + switch (moveEffect) { - case MOVE_SUNNY_DAY: - case MOVE_RAIN_DANCE: - case MOVE_HAIL: - case MOVE_SANDSTORM: + case EFFECT_SUNNY_DAY: + case EFFECT_RAIN_DANCE: + case EFFECT_HAIL: + case EFFECT_SNOWSCAPE: + case EFFECT_SANDSTORM: RETURN_SCORE_MINUS(30); } @@ -2020,7 +2021,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); // Don't Fly/dig/etc if opponent is going to fly/dig/etc after you if (BattlerWillFaintFromWeather(battlerAtk, aiData->abilities[battlerAtk]) - && (move == MOVE_FLY || move == MOVE_BOUNCE)) + && GetMoveTwoTurnAttackStatus(move) == STATUS3_ON_AIR) ADJUST_SCORE(-10); // Attacker will faint while in the air break; case EFFECT_HEALING_WISH: //healing wish, lunar dance @@ -2258,7 +2259,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } break; case EFFECT_TRICK_ROOM: - if (PartnerMoveIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, MOVE_TRICK_ROOM)) + if (PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TRICK_ROOM)) { ADJUST_SCORE(-10); } @@ -2367,17 +2368,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; } case EFFECT_THIRD_TYPE: - switch (move) - { - case MOVE_TRICK_OR_TREAT: - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GHOST) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) || GetActiveGimmick(battlerDef) == GIMMICK_TERA) - ADJUST_SCORE(-10); - break; - case MOVE_FORESTS_CURSE: - if (IS_BATTLER_OF_TYPE(battlerDef, TYPE_GRASS) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) || GetActiveGimmick(battlerDef) == GIMMICK_TERA) - ADJUST_SCORE(-10); - break; - } + if (IS_BATTLER_OF_TYPE(battlerDef, GetMoveArgType(move)) || PartnerMoveIsSameAsAttacker(BATTLE_PARTNER(battlerAtk), battlerDef, move, aiData->partnerMove) || GetActiveGimmick(battlerDef) == GIMMICK_TERA) + ADJUST_SCORE(-10); break; case EFFECT_HEAL_PULSE: // and floral healing if (!IS_TARGETING_PARTNER(battlerAtk, battlerDef)) // Don't heal enemies @@ -2489,7 +2481,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_TAILWIND: if (gSideTimers[GetBattlerSide(battlerAtk)].tailwindTimer != 0 - || PartnerMoveIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, MOVE_TAILWIND) + || PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_TAILWIND) || (gFieldStatuses & STATUS_FIELD_TRICK_ROOM && gFieldTimers.trickRoomTimer > 1)) // Trick Room active and not ending this turn ADJUST_SCORE(-10); break; @@ -2566,9 +2558,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) break; case EFFECT_TAKE_HEART: if ((!(gBattleMons[battlerAtk].status1 & STATUS1_ANY) - || PartnerMoveIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, MOVE_JUNGLE_HEALING) - || PartnerMoveIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, MOVE_HEAL_BELL) - || PartnerMoveIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, MOVE_AROMATHERAPY)) + || PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_JUNGLE_HEALING) + || PartnerMoveEffectIs(BATTLE_PARTNER(battlerAtk), aiData->partnerMove, EFFECT_HEAL_BELL)) && !BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPATK) && !BattlerStatCanRise(battlerAtk, aiData->abilities[battlerAtk], STAT_SPDEF)) ADJUST_SCORE(-10); @@ -3893,9 +3884,9 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) break; case EFFECT_FOLLOW_ME: if (isDoubleBattle - && move != MOVE_SPOTLIGHT + && GetMoveTarget(move) == MOVE_TARGET_USER && !IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) - && (move != MOVE_RAGE_POWDER || IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) // Rage Powder doesn't affect powder immunities + && (!IsPowderMove(move) || IsAffectedByPowder(battlerDef, aiData->abilities[battlerDef], aiData->holdEffects[battlerDef])) // Rage Powder doesn't affect powder immunities && IsBattlerAlive(BATTLE_PARTNER(battlerAtk))) { u32 predictedMoveOnPartner = gLastMoves[BATTLE_PARTNER(battlerAtk)]; diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 7de2e897a5..8a8fe367ac 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -1283,10 +1283,10 @@ static u32 GetSwitchinHazardsDamage(u32 battler, struct BattlePokemon *battleMon { // Stealth Rock if ((hazardFlags & SIDE_STATUS_STEALTH_ROCK) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) - hazardDamage += GetStealthHazardDamageByTypesAndHP(GetMoveType(MOVE_STEALTH_ROCK), defType1, defType2, battleMon->maxHP); + hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_POINTED_STONES, defType1, defType2, battleMon->maxHP); // G-Max Steelsurge if ((hazardFlags & SIDE_STATUS_STEELSURGE) && heldItemEffect != HOLD_EFFECT_HEAVY_DUTY_BOOTS) - hazardDamage += GetStealthHazardDamageByTypesAndHP(GetMoveType(MOVE_G_MAX_STEELSURGE), defType1, defType2, battleMon->maxHP); + hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_SHARP_STEEL, defType1, defType2, battleMon->maxHP); // Spikes if ((hazardFlags & SIDE_STATUS_SPIKES) && IsMonGrounded(heldItemEffect, ability, defType1, defType2)) { diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 7b7621d312..7306237de4 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -1434,16 +1434,16 @@ u32 AI_GetWeather(struct AiLogicData *aiData) return gBattleWeather; } -bool32 IsAromaVeilProtectedMove(u32 move) +bool32 IsAromaVeilProtectedEffect(u32 moveEffect) { - switch (move) + switch (moveEffect) { - case MOVE_DISABLE: - case MOVE_ATTRACT: - case MOVE_ENCORE: - case MOVE_TORMENT: - case MOVE_TAUNT: - case MOVE_HEAL_BLOCK: + case EFFECT_DISABLE: + case EFFECT_ATTRACT: + case EFFECT_ENCORE: + case EFFECT_TORMENT: + case EFFECT_TAUNT: + case EFFECT_HEAL_BLOCK: return TRUE; default: return FALSE; @@ -1498,8 +1498,9 @@ bool32 IsMoveRedirectionPrevented(u32 move, u32 atkAbility) if (AI_THINKING_STRUCT->aiFlags[sBattler_AI] & AI_FLAG_NEGATE_UNAWARE) return FALSE; - if (move == MOVE_SKY_DROP - || move == MOVE_SNIPE_SHOT + u32 effect = GetMoveEffect(move); + if (effect == EFFECT_SKY_DROP + || effect == EFFECT_SNIPE_SHOT || atkAbility == ABILITY_PROPELLER_TAIL || atkAbility == ABILITY_STALWART) return TRUE; @@ -2725,7 +2726,7 @@ static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) u32 ability = GetMonAbility(mon); // we know our own party data u32 holdEffect; u32 species = GetMonData(mon, MON_DATA_SPECIES); - u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES); + u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STEELSURGE | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES); s32 hazardDamage = 0; u32 type1 = gSpeciesInfo[species].types[0]; u32 type2 = gSpeciesInfo[species].types[1]; @@ -2744,7 +2745,9 @@ static bool32 PartyBattlerShouldAvoidHazards(u32 currBattler, u32 switchBattler) return FALSE; if (flags & SIDE_STATUS_STEALTH_ROCK) - hazardDamage += GetStealthHazardDamageByTypesAndHP(GetMoveType(MOVE_STEALTH_ROCK), type1, type2, maxHp); + hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_POINTED_STONES, type1, type2, maxHp); + if ((flags & SIDE_STATUS_STEELSURGE)) + hazardDamage += GetStealthHazardDamageByTypesAndHP(TYPE_SIDE_HAZARD_SHARP_STEEL, type1, type2, maxHp); if (flags & SIDE_STATUS_SPIKES && ((type1 != TYPE_FLYING && type2 != TYPE_FLYING && ability != ABILITY_LEVITATE && holdEffect != HOLD_EFFECT_AIR_BALLOON) @@ -3171,7 +3174,7 @@ static u32 FindMoveUsedXTurnsAgo(u32 battlerId, u32 x) bool32 IsWakeupTurn(u32 battler) { // Check if rest was used 2 turns ago - if ((gBattleMons[battler].status1 & STATUS1_SLEEP) == 1 && FindMoveUsedXTurnsAgo(battler, 2) == MOVE_REST) + if ((gBattleMons[battler].status1 & STATUS1_SLEEP) == 1 && GetMoveEffect(FindMoveUsedXTurnsAgo(battler, 2)) == EFFECT_REST) return TRUE; else // no way to know return FALSE; @@ -3431,6 +3434,18 @@ bool32 PartnerMoveEffectIsTerrain(u32 battlerAtkPartner, u32 partnerMove) return FALSE; } +//PARTNER_MOVE_EFFECT_IS +bool32 PartnerMoveEffectIs(u32 battlerAtkPartner, u32 partnerMove, u32 effectCheck) +{ + if (!IsDoubleBattle()) + return FALSE; + + if (partnerMove != MOVE_NONE && GetMoveEffect(partnerMove) == effectCheck) + return TRUE; + + return FALSE; +} + //PARTNER_MOVE_IS_TAILWIND_TRICKROOM bool32 PartnerMoveIs(u32 battlerAtkPartner, u32 partnerMove, u32 moveCheck) { diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 1eac4dbe26..1e154981dd 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1711,18 +1711,19 @@ static void MoveSelectionDisplayPpNumber(u32 battler) static void MoveSelectionDisplayMoveType(u32 battler) { u8 *txtPtr, *end; - u8 type; u32 speciesId; struct ChooseMoveStruct *moveInfo = (struct ChooseMoveStruct *)(&gBattleResources->bufferA[battler][4]); txtPtr = StringCopy(gDisplayedStringBattle, gText_MoveInterfaceType); - type = GetMoveType(moveInfo->moves[gMoveSelectionCursor[battler]]); + u32 move = moveInfo->moves[gMoveSelectionCursor[battler]]; + u32 type = GetMoveType(move); + u32 effect = GetMoveEffect(move); - if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_TERA_BLAST) + if (effect == EFFECT_TERA_BLAST) { if (IsGimmickSelected(battler, GIMMICK_TERA) || GetActiveGimmick(battler) == GIMMICK_TERA) type = GetBattlerTeraType(battler); } - else if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_IVY_CUDGEL) + else if (effect == EFFECT_IVY_CUDGEL) { speciesId = gBattleMons[battler].species; @@ -1731,12 +1732,12 @@ static void MoveSelectionDisplayMoveType(u32 battler) || speciesId == SPECIES_OGERPON_CORNERSTONE || speciesId == SPECIES_OGERPON_CORNERSTONE_TERA) type = gBattleMons[battler].types[1]; } - else if (GetMoveCategory(moveInfo->moves[gMoveSelectionCursor[battler]]) == DAMAGE_CATEGORY_STATUS + else if (GetMoveCategory(move) == DAMAGE_CATEGORY_STATUS && (GetActiveGimmick(battler) == GIMMICK_DYNAMAX || IsGimmickSelected(battler, GIMMICK_DYNAMAX))) { type = TYPE_NORMAL; // Max Guard is always a Normal-type move } - else if (moveInfo->moves[gMoveSelectionCursor[battler]] == MOVE_TERA_STARSTORM) + else if (effect == EFFECT_TERA_STARSTORM) { if (gBattleMons[battler].species == SPECIES_TERAPAGOS_STELLAR || (IsGimmickSelected(battler, GIMMICK_TERA) && gBattleMons[battler].species == SPECIES_TERAPAGOS_TERASTAL)) @@ -1745,7 +1746,7 @@ static void MoveSelectionDisplayMoveType(u32 battler) else if (P_SHOW_DYNAMIC_TYPES) // Non-vanilla changes to battle UI showing dynamic types { struct Pokemon *mon = &gPlayerParty[gBattlerPartyIndexes[battler]]; - type = CheckDynamicMoveType(mon, moveInfo->moves[gMoveSelectionCursor[battler]], battler); + type = CheckDynamicMoveType(mon, move, battler); } end = StringCopy(txtPtr, gTypesInfo[type].name); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ba606632f7..536291661a 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7755,7 +7755,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) { gDisableStructs[battler].stealthRockDone = TRUE; - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(GetMoveType(MOVE_STEALTH_ROCK), battler); + gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_ROCK, battler); if (gBattleStruct->moveDamage[battler] != 0) SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG); @@ -7814,7 +7814,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) { gDisableStructs[battler].steelSurgeDone = TRUE; - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(GetMoveType(MOVE_G_MAX_STEELSURGE), battler); + gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_STEEL, battler); if (gBattleStruct->moveDamage[battler] != 0) SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG); diff --git a/src/battle_util.c b/src/battle_util.c index f7ea083c60..59478ba97e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10829,14 +10829,14 @@ uq4_12_t GetTypeModifier(u32 atkType, u32 defType) return gTypeEffectivenessTable[atkType][defType]; } -s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp) +s32 GetStealthHazardDamageByTypesAndHP(enum TypeSideHazard hazardType, u8 type1, u8 type2, u32 maxHp) { s32 dmg = 0; uq4_12_t modifier = UQ_4_12(1.0); - modifier = uq4_12_multiply(modifier, GetTypeModifier(hazardType, type1)); + modifier = uq4_12_multiply(modifier, GetTypeModifier((u8)hazardType, type1)); if (type2 != type1) - modifier = uq4_12_multiply(modifier, GetTypeModifier(hazardType, type2)); + modifier = uq4_12_multiply(modifier, GetTypeModifier((u8)hazardType, type2)); switch (modifier) { @@ -10873,7 +10873,7 @@ s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 ma return dmg; } -s32 GetStealthHazardDamage(u8 hazardType, u32 battler) +s32 GetStealthHazardDamage(enum TypeSideHazard hazardType, u32 battler) { u8 type1 = gBattleMons[battler].types[0]; u8 type2 = gBattleMons[battler].types[1]; From f8151f0be594d2f116c750b9ed0e6bb1a797e6ac Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Fri, 10 Jan 2025 18:14:15 -0500 Subject: [PATCH 50/85] Missed two uses of new hazard type enum (#5996) --- src/battle_script_commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 536291661a..368e08db23 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -7755,7 +7755,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) { gDisableStructs[battler].stealthRockDone = TRUE; - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_ROCK, battler); + gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_POINTED_STONES, battler); if (gBattleStruct->moveDamage[battler] != 0) SetDmgHazardsBattlescript(battler, B_MSG_STEALTHROCKDMG); @@ -7814,7 +7814,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) && GetBattlerAbility(battler) != ABILITY_MAGIC_GUARD) { gDisableStructs[battler].steelSurgeDone = TRUE; - gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_STEEL, battler); + gBattleStruct->moveDamage[battler] = GetStealthHazardDamage(TYPE_SIDE_HAZARD_SHARP_STEEL, battler); if (gBattleStruct->moveDamage[battler] != 0) SetDmgHazardsBattlescript(battler, B_MSG_SHARPSTEELDMG); From 71cf1bfaa7f6fe43c445c730f62b82496f4cf9b7 Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Fri, 10 Jan 2025 23:25:04 -0800 Subject: [PATCH 51/85] Updated Makefile to allow for the creation of specific tests (#5993) --- Makefile | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Makefile b/Makefile index 656b0847dd..0d2ef1d240 100644 --- a/Makefile +++ b/Makefile @@ -29,6 +29,9 @@ endif ifeq (debug,$(MAKECMDGOALS)) DEBUG := 1 endif +ifeq ($(TESTELF),$(MAKECMDGOALS)) + TEST := 1 +endif # Default make rule all: rom From c33c38e0207bfae4c2d5a6e688c40ec04574f67a Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 11 Jan 2025 05:57:39 -0300 Subject: [PATCH 52/85] Remove form change function footguns (#5995) --- include/pokemon.h | 4 ++-- src/battle_dynamax.c | 4 ++-- src/battle_script_commands.c | 2 +- src/battle_util.c | 19 ++++++++++--------- src/clock.c | 5 +++-- src/daycare.c | 6 +++--- src/party_menu.c | 13 ++++++++----- src/pokemon.c | 26 ++++++++++++++------------ src/pokemon_storage_system.c | 2 +- 9 files changed, 44 insertions(+), 37 deletions(-) diff --git a/include/pokemon.h b/include/pokemon.h index f855b27ea5..32ec73fecf 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -783,8 +783,8 @@ void DestroyMonSpritesGfxManager(u8 managerId); u8 *MonSpritesGfxManager_GetSpritePtr(u8 managerId, u8 spriteNum); u16 GetFormSpeciesId(u16 speciesId, u8 formId); u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId); -u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); -u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg); +u32 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg); +u32 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg); bool32 DoesSpeciesHaveFormChangeMethod(u16 species, u16 method); u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove); void RemoveIVIndexFromList(u8 *ivs, u8 selectedIv); diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 050bee3d14..f355b67d99 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -254,12 +254,12 @@ static u16 GetTypeBasedMaxMove(u32 battler, u32 type) // Gigantamax check u32 i; u32 species = gBattleMons[battler].species; - u32 targetSpecies = SPECIES_NONE; + u32 targetSpecies = species; if (!gSpeciesInfo[species].isGigantamax) targetSpecies = GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_GIGANTAMAX); - if (targetSpecies != SPECIES_NONE) + if (targetSpecies != species) species = targetSpecies; if (gSpeciesInfo[species].isGigantamax) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 368e08db23..2c50f26d9d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -11102,7 +11102,7 @@ static void Cmd_various(void) case VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL: { VARIOUS_ARGS(const u8 *jumpInstr); - if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) == SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) == gBattleMons[battler].species) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; diff --git a/src/battle_util.c b/src/battle_util.c index 59478ba97e..fef04096a4 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -6609,7 +6609,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 bool32 TryPrimalReversion(u32 battler) { if (GetBattlerHoldEffect(battler, FALSE) == HOLD_EFFECT_PRIMAL_ORB - && GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != SPECIES_NONE) + && GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_PRIMAL_REVERSION) != gBattleMons[battler].species) { gBattleScripting.battler = battler; BattleScriptPushCursorAndCallback(BattleScript_PrimalReversion); @@ -10946,11 +10946,11 @@ bool32 CanMegaEvolve(u32 battler) return FALSE; // Check if there is an entry in the form change table for regular Mega Evolution and battler is holding Mega Stone. - if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM) != SPECIES_NONE && holdEffect == HOLD_EFFECT_MEGA_STONE) + if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_ITEM) != gBattleMons[battler].species && holdEffect == HOLD_EFFECT_MEGA_STONE) return TRUE; // Check if there is an entry in the form change table for Wish Mega Evolution. - if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != gBattleMons[battler].species) return TRUE; // No checks passed, the mon CAN'T mega evolve. @@ -10980,7 +10980,7 @@ bool32 CanUltraBurst(u32 battler) return FALSE; // Check if there is an entry in the form change table for Ultra Burst and battler is holding a Z-Crystal. - if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_ULTRA_BURST) != SPECIES_NONE && holdEffect == HOLD_EFFECT_Z_CRYSTAL) + if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_ULTRA_BURST) != gBattleMons[battler].species && holdEffect == HOLD_EFFECT_Z_CRYSTAL) return TRUE; // No checks passed, the mon CAN'T ultra burst. @@ -10991,7 +10991,7 @@ void ActivateMegaEvolution(u32 battler) { gLastUsedItem = gBattleMons[battler].item; SetActiveGimmick(battler, GIMMICK_MEGA); - if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != SPECIES_NONE) + if (GetBattleFormChangeTargetSpecies(battler, FORM_CHANGE_BATTLE_MEGA_EVOLUTION_MOVE) != gBattleMons[battler].species) BattleScriptExecute(BattleScript_WishMegaEvolution); else BattleScriptExecute(BattleScript_MegaEvolution); @@ -11040,8 +11040,8 @@ bool32 IsBattlerInTeraForm(u32 battler) u16 GetBattleFormChangeTargetSpecies(u32 battler, u16 method) { u32 i; - u16 targetSpecies = SPECIES_NONE; - u16 species = gBattleMons[battler].species; + u32 species = gBattleMons[battler].species; + u32 targetSpecies = species; const struct FormChange *formChanges = GetSpeciesFormChanges(species); struct Pokemon *mon = &GetBattlerParty(battler)[gBattlerPartyIndexes[battler]]; u16 heldItem; @@ -11170,15 +11170,16 @@ bool32 TryBattleFormChange(u32 battler, u32 method) u32 monId = gBattlerPartyIndexes[battler]; u32 side = GetBattlerSide(battler); struct Pokemon *party = GetBattlerParty(battler); + u32 currentSpecies = GetMonData(&party[monId], MON_DATA_SPECIES); u32 targetSpecies; if (!CanBattlerFormChange(battler, method)) return FALSE; targetSpecies = GetBattleFormChangeTargetSpecies(battler, method); - if (targetSpecies == SPECIES_NONE) + if (targetSpecies == currentSpecies) targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); - if (targetSpecies != SPECIES_NONE) + if (targetSpecies != currentSpecies) { // Saves the original species on the first form change. if (gBattleStruct->changedSpecies[side][monId] == SPECIES_NONE) diff --git a/src/clock.c b/src/clock.c index 54c9422bbe..d122fc782c 100644 --- a/src/clock.c +++ b/src/clock.c @@ -83,9 +83,10 @@ static void FormChangeTimeUpdate() for (i = 0; i < PARTY_SIZE; i++) { struct Pokemon *mon = &gPlayerParty[i]; - u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_TIME_OF_DAY, 0); + u32 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_TIME_OF_DAY, 0); + u32 currentSpecies = GetMonData(mon, MON_DATA_SPECIES); - if (targetSpecies != SPECIES_NONE) + if (targetSpecies != currentSpecies) { SetMonData(mon, MON_DATA_SPECIES, &targetSpecies); CalculateMonStats(mon); diff --git a/src/daycare.c b/src/daycare.c index 83dd24af07..26b86ec1e2 100644 --- a/src/daycare.c +++ b/src/daycare.c @@ -330,8 +330,8 @@ static void ApplyDaycareExperience(struct Pokemon *mon) static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon) { - u16 species; - u16 newSpecies; + u32 species; + u32 newSpecies; u32 experience; struct Pokemon pokemon; @@ -340,7 +340,7 @@ static u16 TakeSelectedPokemonFromDaycare(struct DaycareMon *daycareMon) BoxMonToMon(&daycareMon->mon, &pokemon); newSpecies = GetFormChangeTargetSpecies(&pokemon, FORM_CHANGE_WITHDRAW, 0); - if (newSpecies != SPECIES_NONE) + if (newSpecies != species) { SetMonData(&pokemon, MON_DATA_SPECIES, &newSpecies); CalculateMonStats(&pokemon); diff --git a/src/party_menu.c b/src/party_menu.c index 416bbd7898..af447ac990 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -6442,9 +6442,10 @@ static void Task_TryItemUseFormChange(u8 taskId) bool32 TryItemUseFormChange(u8 taskId, TaskFunc task) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; - u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_USE, gSpecialVar_ItemId); + u32 currentSpecies = GetMonData(mon, MON_DATA_SPECIES); + u32 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_USE, gSpecialVar_ItemId); - if (targetSpecies != SPECIES_NONE) + if (targetSpecies != currentSpecies) { gPartyMenuUseExitCallback = TRUE; SetWordTaskArg(taskId, tNextFunc, (u32)task); @@ -6490,12 +6491,13 @@ void ItemUseCB_RotomCatalog(u8 taskId, TaskFunc task) bool32 TryMultichoiceFormChange(u8 taskId) { struct Pokemon *mon = &gPlayerParty[gPartyMenu.slotId]; + u32 currentSpecies = GetMonData(mon, MON_DATA_SPECIES); u32 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_USE_MULTICHOICE, gSpecialVar_ItemId); PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[0]); PartyMenuRemoveWindow(&sPartyMenuInternal->windowId[1]); - if (targetSpecies != SPECIES_NONE) + if (targetSpecies != currentSpecies) { gPartyMenuUseExitCallback = TRUE; SetWordTaskArg(taskId, tNextFunc, (u32)Task_ClosePartyMenuAfterText); @@ -6582,8 +6584,9 @@ static void CursorCb_ChangeAbility(u8 taskId) void TryItemHoldFormChange(struct Pokemon *mon) { - u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_HOLD, 0); - if (targetSpecies != SPECIES_NONE) + u32 currentSpecies = GetMonData(mon, MON_DATA_SPECIES); + u32 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_ITEM_HOLD, 0); + if (targetSpecies != currentSpecies) { PlayCry_NormalNoDucking(targetSpecies, 0, CRY_VOLUME_RS, CRY_VOLUME_RS); SetMonData(mon, MON_DATA_SPECIES, &targetSpecies); diff --git a/src/pokemon.c b/src/pokemon.c index bb590abd63..5fa53dd2e8 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -6529,17 +6529,18 @@ u8 GetFormIdFromFormSpeciesId(u16 formSpeciesId) return targetFormId; } -u16 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg) +// Returns the current species if no form change is possible +u32 GetFormChangeTargetSpecies(struct Pokemon *mon, u16 method, u32 arg) { return GetFormChangeTargetSpeciesBoxMon(&mon->box, method, arg); } -// Returns SPECIES_NONE if no form change is possible -u16 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg) +// Returns the current species if no form change is possible +u32 GetFormChangeTargetSpeciesBoxMon(struct BoxPokemon *boxMon, u16 method, u32 arg) { u32 i; - u16 targetSpecies = SPECIES_NONE; - u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); + u32 species = GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL); + u32 targetSpecies = species; const struct FormChange *formChanges = GetSpeciesFormChanges(species); u16 heldItem; u32 ability; @@ -6762,18 +6763,18 @@ bool32 SpeciesHasGenderDifferences(u16 species) bool32 TryFormChange(u32 monId, u32 side, u16 method) { struct Pokemon *party = (side == B_SIDE_PLAYER) ? gPlayerParty : gEnemyParty; - u16 targetSpecies; if (GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG, 0) == SPECIES_NONE || GetMonData(&party[monId], MON_DATA_SPECIES_OR_EGG, 0) == SPECIES_EGG) return FALSE; - targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); + u32 currentSpecies = GetMonData(&party[monId], MON_DATA_SPECIES); + u32 targetSpecies = GetFormChangeTargetSpecies(&party[monId], method, 0); - if (targetSpecies == SPECIES_NONE && gBattleStruct != NULL) + if (targetSpecies == currentSpecies && gBattleStruct != NULL && gBattleStruct->changedSpecies[side][monId] != SPECIES_NONE) targetSpecies = gBattleStruct->changedSpecies[side][monId]; - if (targetSpecies != SPECIES_NONE) + if (targetSpecies != currentSpecies) { TryToSetBattleFormChangeMoves(&party[monId], method); SetMonData(&party[monId], MON_DATA_SPECIES, &targetSpecies); @@ -6962,9 +6963,10 @@ void UpdateDaysPassedSinceFormChange(u16 days) for (i = 0; i < PARTY_SIZE; i++) { struct Pokemon *mon = &gPlayerParty[i]; + u32 currentSpecies = GetMonData(mon, MON_DATA_SPECIES); u8 daysSinceFormChange; - if (!GetMonData(mon, MON_DATA_SPECIES, 0)) + if (currentSpecies == SPECIES_NONE) continue; daysSinceFormChange = GetMonData(mon, MON_DATA_DAYS_SINCE_FORM_CHANGE, 0); @@ -6980,9 +6982,9 @@ void UpdateDaysPassedSinceFormChange(u16 days) if (daysSinceFormChange == 0) { - u16 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_DAYS_PASSED, 0); + u32 targetSpecies = GetFormChangeTargetSpecies(mon, FORM_CHANGE_DAYS_PASSED, 0); - if (targetSpecies != SPECIES_NONE) + if (targetSpecies != currentSpecies) { SetMonData(mon, MON_DATA_SPECIES, &targetSpecies); CalculateMonStats(mon); diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index e34c4d8e37..4498832743 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -6965,7 +6965,7 @@ static void ReshowDisplayMon(void) void SetMonFormPSS(struct BoxPokemon *boxMon) { u16 targetSpecies = GetFormChangeTargetSpeciesBoxMon(boxMon, FORM_CHANGE_ITEM_HOLD, 0); - if (targetSpecies != SPECIES_NONE) + if (targetSpecies != GetBoxMonData(boxMon, MON_DATA_SPECIES, NULL)) { SetBoxMonData(boxMon, MON_DATA_SPECIES, &targetSpecies); UpdateSpeciesSpritePSS(boxMon); From 21bc5cfd30af4a6ba654f0ae13720fa939afad84 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 11 Jan 2025 06:07:47 -0300 Subject: [PATCH 53/85] Debug menu and `createmon` additions/cleanup (#5994) --- asm/macros/event.inc | 16 +- include/constants/weather.h | 1 + src/debug.c | 539 ++++++++++++++---------------------- src/script_pokemon_util.c | 14 +- test/pokemon.c | 7 +- 5 files changed, 230 insertions(+), 347 deletions(-) diff --git a/asm/macros/event.inc b/asm/macros/event.inc index 6c1547fafc..b9c5d875b3 100644 --- a/asm/macros/event.inc +++ b/asm/macros/event.inc @@ -1007,7 +1007,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, ggMaxFactor, teraType + .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 callnative ScrCmd_createmon, requests_effects=1 .byte 0 .byte PARTY_SIZE @ assign to first empty slot @@ -1036,8 +1036,9 @@ .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 \ggMaxFactor; .set givemon_flags, givemon_flags | (1 << 22); .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 .4byte givemon_flags .ifnb \item; .2byte \item; .endif .ifnb \ball; .2byte \ball; .endif @@ -1061,13 +1062,14 @@ .ifnb \move3; .2byte \move3; .endif .ifnb \move4; .2byte \move4; .endif .ifnb \isShiny; .2byte \isShiny; .endif - .ifnb \ggMaxFactor; .2byte \ggMaxFactor; .endif + .ifnb \gmaxFactor; .2byte \gmaxFactor; .endif .ifnb \teraType; .2byte \teraType; .endif + .ifnb \dmaxLevel; .2byte \dmaxLevel; .endif .endm @ 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, ggMaxFactor, teraType + .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 callnative ScrCmd_createmon, requests_effects=1 .byte \side @ 0 - player, 1 - opponent .byte \slot @ 0-5 @@ -1096,8 +1098,9 @@ .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 \ggMaxFactor; .set givemon_flags, givemon_flags | (1 << 22); .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 .4byte givemon_flags .ifnb \item; .2byte \item; .endif .ifnb \ball; .2byte \ball; .endif @@ -1121,8 +1124,9 @@ .ifnb \move3; .2byte \move3; .endif .ifnb \move4; .2byte \move4; .endif .ifnb \isShiny; .2byte \isShiny; .endif - .ifnb \ggMaxFactor; .2byte \ggMaxFactor; .endif + .ifnb \gmaxFactor; .2byte \gmaxFactor; .endif .ifnb \teraType; .2byte \teraType; .endif + .ifnb \dmaxLevel; .2byte \dmaxLevel; .endif .endm @ Gives the player an Egg of the specified species. diff --git a/include/constants/weather.h b/include/constants/weather.h index c4a23a18bc..32dc97a1a2 100644 --- a/include/constants/weather.h +++ b/include/constants/weather.h @@ -19,6 +19,7 @@ #define WEATHER_ABNORMAL 15 // The alternating weather during Groudon/Kyogre conflict #define WEATHER_ROUTE119_CYCLE 20 #define WEATHER_ROUTE123_CYCLE 21 +#define WEATHER_COUNT 22 // These are used in maps' coord_weather_event entries. // They are not a one-to-one mapping with the engine's diff --git a/src/debug.c b/src/debug.c index 9e24846d6a..267c5d5ab9 100644 --- a/src/debug.c +++ b/src/debug.c @@ -293,6 +293,9 @@ struct DebugMonData u8 mon_ev_speed; u8 mon_ev_satk; u8 mon_ev_sdef; + u8 teraType; + u8 dynamaxLevel:7; + u8 gmaxFactor:1; }; struct DebugMenuListData @@ -434,6 +437,9 @@ static void DebugAction_Give_Pokemon_SelectLevel(u8 taskId); static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId); static void DebugAction_Give_Pokemon_SelectNature(u8 taskId); static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId); +static void DebugAction_Give_Pokemon_SelectTeraType(u8 taskId); +static void DebugAction_Give_Pokemon_SelectDynamaxLevel(u8 taskId); +static void DebugAction_Give_Pokemon_SelectGigantamaxFactor(u8 taskId); static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId); static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId); static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId); @@ -631,6 +637,9 @@ static const u8 sDebugText_PokemonLevel[] = _("Level:{CLEAR_TO 90}\n static const u8 sDebugText_PokemonShiny[] = _("Shiny:{CLEAR_TO 90}\n {STR_VAR_2}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{CLEAR_TO 90}"); static const u8 sDebugText_PokemonNature[] = _("Nature ID: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); static const u8 sDebugText_PokemonAbility[] = _("Ability Num: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonTeraType[] = _("Tera Type: {STR_VAR_3}{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonDynamaxLevel[] = _("Dmax Lvl:{CLEAR_TO 90}\n{STR_VAR_1}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); +static const u8 sDebugText_PokemonGmaxFactor[] = _("Gmax Factor:{CLEAR_TO 90}\n {STR_VAR_2}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{CLEAR_TO 90}"); static const u8 sDebugText_PokemonIVs[] = _("All IVs:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); static const u8 sDebugText_PokemonEVs[] = _("All EVs:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); static const u8 sDebugText_IV_HP[] = _("IV HP:{CLEAR_TO 90}\n {STR_VAR_3}{CLEAR_TO 90}\n{CLEAR_TO 90}\n{STR_VAR_2}{CLEAR_TO 90}"); @@ -1242,6 +1251,32 @@ static void Debug_DestroyMenu_Full_Script(u8 taskId, const u8 *script) ScriptContext_SetupScript(script); } +static void Debug_HandleInput_Numeric(u8 taskId, s32 min, s32 max, u32 digits) +{ + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > max) + gTasks[taskId].tInput = max; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < min) + gTasks[taskId].tInput = min; + } + if (JOY_NEW(DPAD_LEFT)) + { + if (gTasks[taskId].tDigit > 0) + gTasks[taskId].tDigit -= 1; + } + if (JOY_NEW(DPAD_RIGHT)) + { + if (gTasks[taskId].tDigit < digits - 1) + gTasks[taskId].tDigit += 1; + } +} + static void DebugAction_Cancel(u8 taskId) { Debug_DestroyMenu_Full(taskId); @@ -1951,28 +1986,7 @@ static void DebugAction_Util_Warp_SelectMapGroup(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > LAST_MAP_GROUP) - gTasks[taskId].tInput = LAST_MAP_GROUP; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 0) - gTasks[taskId].tInput = 0; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < 2) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 0, LAST_MAP_GROUP, 3); ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); ConvertIntToDecimalStringN(gStringVar2, LAST_MAP_GROUP, STR_CONV_MODE_LEADING_ZEROS, 3); @@ -2012,28 +2026,7 @@ static void DebugAction_Util_Warp_SelectMap(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > max_value - 1) - gTasks[taskId].tInput = max_value - 1; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 0) - gTasks[taskId].tInput = 0; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < 2) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 0, max_value - 1, 3); ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, (max_value >= 100) ? 3 : 2); ConvertIntToDecimalStringN(gStringVar2, MAP_GROUP_COUNT[gTasks[taskId].tMapGroup] - 1, STR_CONV_MODE_LEADING_ZEROS, (max_value >= 100) ? 3 : 2); @@ -2257,29 +2250,7 @@ static void DebugAction_Util_Weather_SelectId(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > WEATHER_ROUTE123_CYCLE) - gTasks[taskId].tInput = WEATHER_ROUTE123_CYCLE; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < WEATHER_NONE) - gTasks[taskId].tInput = WEATHER_NONE; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < 2) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, WEATHER_NONE, WEATHER_COUNT - 1, 3); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); @@ -2474,34 +2445,8 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) return; } - if (JOY_NEW(DPAD_UP)) - { - PlaySE(SE_SELECT); - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput >= FLAGS_COUNT) - gTasks[taskId].tInput = FLAGS_COUNT - 1; - } - if (JOY_NEW(DPAD_DOWN)) - { - PlaySE(SE_SELECT); - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 1) - gTasks[taskId].tInput = 1; - } - if (JOY_NEW(DPAD_LEFT)) - { - PlaySE(SE_SELECT); - gTasks[taskId].tDigit -= 1; - if (gTasks[taskId].tDigit < 0) - gTasks[taskId].tDigit = 0; - } - if (JOY_NEW(DPAD_RIGHT)) - { - PlaySE(SE_SELECT); - gTasks[taskId].tDigit += 1; - if (gTasks[taskId].tDigit > DEBUG_NUMBER_DIGITS_FLAGS - 1) - gTasks[taskId].tDigit = DEBUG_NUMBER_DIGITS_FLAGS - 1; - } + PlaySE(SE_SELECT); + Debug_HandleInput_Numeric(taskId, 1, FLAGS_COUNT - 1, DEBUG_NUMBER_DIGITS_FLAGS); if (JOY_NEW(DPAD_ANY) || JOY_NEW(A_BUTTON)) { @@ -2553,30 +2498,7 @@ static void DebugAction_FlagsVars_Vars(u8 taskId) static void DebugAction_FlagsVars_Select(u8 taskId) { - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > VARS_END) - gTasks[taskId].tInput = VARS_END; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < VARS_START) - gTasks[taskId].tInput = VARS_START; - } - if (JOY_NEW(DPAD_LEFT)) - { - gTasks[taskId].tDigit -= 1; - if (gTasks[taskId].tDigit < 0) - gTasks[taskId].tDigit = 0; - } - if (JOY_NEW(DPAD_RIGHT)) - { - gTasks[taskId].tDigit += 1; - if (gTasks[taskId].tDigit > DEBUG_NUMBER_DIGITS_VARIABLES - 1) - gTasks[taskId].tDigit = DEBUG_NUMBER_DIGITS_VARIABLES - 1; - } + Debug_HandleInput_Numeric(taskId, VARS_START, VARS_END, DEBUG_NUMBER_DIGITS_VARIABLES); if (JOY_NEW(DPAD_ANY)) { @@ -2999,29 +2921,7 @@ static void DebugAction_Give_Item_SelectId(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput >= ITEMS_COUNT) - gTasks[taskId].tInput = ITEMS_COUNT - 1; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 1) - gTasks[taskId].tInput = 1; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < DEBUG_NUMBER_DIGITS_ITEMS - 1) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 1, ITEMS_COUNT - 1, DEBUG_NUMBER_DIGITS_ITEMS); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); u8* end = CopyItemName(gTasks[taskId].tInput, gStringVar1); @@ -3074,29 +2974,7 @@ static void DebugAction_Give_Item_SelectQuantity(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > MAX_BAG_ITEM_CAPACITY) - gTasks[taskId].tInput = MAX_BAG_ITEM_CAPACITY; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 1) - gTasks[taskId].tInput = 1; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < MAX_ITEM_DIGITS) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 1, MAX_BAG_ITEM_CAPACITY, MAX_ITEM_DIGITS); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEM_QUANTITY); @@ -3139,6 +3017,9 @@ static void ResetMonDataStruct(struct DebugMonData *sDebugMonData) sDebugMonData->isShiny = FALSE; sDebugMonData->nature = 0; sDebugMonData->abilityNum = 0; + sDebugMonData->teraType = TYPE_NONE; + sDebugMonData->dynamaxLevel = 0; + sDebugMonData->gmaxFactor = FALSE; sDebugMonData->mon_iv_hp = 0; sDebugMonData->mon_iv_atk = 0; sDebugMonData->mon_iv_def = 0; @@ -3244,29 +3125,7 @@ static void DebugAction_Give_Pokemon_SelectId(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput >= NUM_SPECIES) - gTasks[taskId].tInput = NUM_SPECIES - 1; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 1) - gTasks[taskId].tInput = 1; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < DEBUG_NUMBER_DIGITS_ITEMS - 1) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 1, NUM_SPECIES - 1, DEBUG_NUMBER_DIGITS_ITEMS); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); u8 *end = StringCopy(gStringVar1, GetSpeciesName(gTasks[taskId].tInput)); //CopyItemName(gTasks[taskId].tInput, gStringVar1); @@ -3312,29 +3171,7 @@ static void DebugAction_Give_Pokemon_SelectLevel(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > MAX_LEVEL) - gTasks[taskId].tInput = MAX_LEVEL; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 1) - gTasks[taskId].tInput = 1; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < 2) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 1, MAX_LEVEL, 3); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); @@ -3429,8 +3266,8 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId) if (JOY_NEW(DPAD_UP)) { gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > NUM_NATURES-1) - gTasks[taskId].tInput = NUM_NATURES-1; + if (gTasks[taskId].tInput > NUM_NATURES - 1) + gTasks[taskId].tInput = NUM_NATURES - 1; } if (JOY_NEW(DPAD_DOWN)) { @@ -3516,6 +3353,132 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) gTasks[taskId].tInput = 0; gTasks[taskId].tDigit = 0; + 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, gTypesInfo[0].name); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonTeraType); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectTeraType; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_SelectTeraType(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + + if (JOY_NEW(DPAD_UP)) + { + gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput > NUMBER_OF_MON_TYPES - 1) + gTasks[taskId].tInput = NUMBER_OF_MON_TYPES - 1; + } + if (JOY_NEW(DPAD_DOWN)) + { + gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; + if (gTasks[taskId].tInput < 0) + gTasks[taskId].tInput = 0; + } + + 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, gTypesInfo[gTasks[taskId].tInput].name); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonTeraType); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + sDebugMonData->teraType = gTasks[taskId].tInput; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonDynamaxLevel); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectDynamaxLevel; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_SelectDynamaxLevel(u8 taskId) +{ + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + Debug_HandleInput_Numeric(taskId, 0, MAX_DYNAMAX_LEVEL, 2); + + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); + ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); + StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonDynamaxLevel); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + sDebugMonData->dynamaxLevel = gTasks[taskId].tInput; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 0); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonGmaxFactor); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + + gTasks[taskId].func = DebugAction_Give_Pokemon_SelectGigantamaxFactor; + } + else if (JOY_NEW(B_BUTTON)) + { + PlaySE(SE_SELECT); + Free(sDebugMonData); + FreeMonIconPalettes(); + FreeAndDestroyMonIconSprite(&gSprites[gTasks[taskId].tSpriteId]); + DebugAction_DestroyExtraWindow(taskId); + } +} + +static void DebugAction_Give_Pokemon_SelectGigantamaxFactor(u8 taskId) +{ + static const u8 *txtStr; + + if (JOY_NEW(DPAD_ANY)) + { + PlaySE(SE_SELECT); + gTasks[taskId].tInput ^= JOY_NEW(DPAD_UP | DPAD_DOWN) > 0; + txtStr = (gTasks[taskId].tInput == TRUE) ? sDebugText_True : sDebugText_False; + StringCopyPadded(gStringVar2, txtStr, CHAR_SPACE, 15); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 0); + StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); + StringExpandPlaceholders(gStringVar4, sDebugText_PokemonGmaxFactor); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); + } + + if (JOY_NEW(A_BUTTON)) + { + sDebugMonData->gmaxFactor = gTasks[taskId].tInput; + gTasks[taskId].tInput = 0; + gTasks[taskId].tDigit = 0; + StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); @@ -3537,29 +3500,7 @@ static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > MAX_PER_STAT_IVS) - gTasks[taskId].tInput = MAX_PER_STAT_IVS; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 0) - gTasks[taskId].tInput = 0; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < 2) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 0, MAX_PER_STAT_IVS, 3); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); @@ -3687,29 +3628,7 @@ static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > MAX_PER_STAT_EVS) - gTasks[taskId].tInput = MAX_PER_STAT_EVS; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 0) - gTasks[taskId].tInput = 0; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < 3) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 0, MAX_PER_STAT_EVS, 4); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); @@ -3849,29 +3768,7 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId) if (JOY_NEW(DPAD_ANY)) { PlaySE(SE_SELECT); - - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput >= MOVES_COUNT) - gTasks[taskId].tInput = MOVES_COUNT - 1; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 0) - gTasks[taskId].tInput = 0; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < 3) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 0, MOVES_COUNT - 1, 4); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); u8 *end = StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); @@ -3983,6 +3880,9 @@ static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://githu bool8 isShiny = sDebugMonData->isShiny; u8 nature = sDebugMonData->nature; u8 abilityNum = sDebugMonData->abilityNum; + u32 teraType = sDebugMonData->teraType; + u32 dmaxLevel = sDebugMonData->dynamaxLevel; + u32 gmaxFactor = sDebugMonData->gmaxFactor; moves[0] = sDebugMonData->mon_move_0; moves[1] = sDebugMonData->mon_move_1; moves[2] = sDebugMonData->mon_move_2; @@ -4003,16 +3903,27 @@ 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); + CreateMonWithNature(&mon, species, level, USE_RANDOM_IVS, nature); //Shininess SetMonData(&mon, MON_DATA_IS_SHINY, &isShiny); + // Gigantamax factor + SetMonData(&mon, MON_DATA_GIGANTAMAX_FACTOR, &gmaxFactor); + + // Dynamax Level + SetMonData(&mon, MON_DATA_DYNAMAX_LEVEL, &dmaxLevel); + + // tera type + if (teraType >= NUMBER_OF_MON_TYPES) + teraType = TYPE_NONE; + SetMonData(&mon, MON_DATA_TERA_TYPE, &teraType); + //IVs for (i = 0; i < NUM_STATS; i++) { iv_val = IVs[i]; - if (iv_val != 32 && iv_val != 0xFF) + if (iv_val != USE_RANDOM_IVS && iv_val != 0xFF) SetMonData(&mon, MON_DATA_HP_IV + i, &iv_val); } @@ -4027,18 +3938,18 @@ static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://githu //Moves for (i = 0; i < MAX_MON_MOVES; i++) { - if (moves[i] == 0 || moves[i] == 0xFF || moves[i] >= MOVES_COUNT) + if (moves[i] == MOVE_NONE || moves[i] == 0xFF || moves[i] >= MOVES_COUNT) continue; SetMonMoveSlot(&mon, moves[i], i); } //Ability - if (abilityNum == 0xFF || GetAbilityBySpecies(species, abilityNum) == 0) + if (abilityNum == 0xFF || GetAbilityBySpecies(species, abilityNum) == ABILITY_NONE) { do { - abilityNum = Random() % 3; // includes hidden abilities - } while (GetAbilityBySpecies(species, abilityNum) == 0); + abilityNum = Random() % NUM_ABILITY_SLOTS; // includes hidden abilities + } while (GetAbilityBySpecies(species, abilityNum) == ABILITY_NONE); } SetMonData(&mon, MON_DATA_ABILITY_NUM, &abilityNum); @@ -4056,7 +3967,9 @@ static void DebugAction_Give_Pokemon_ComplexCreateMon(u8 taskId) //https://githu } if (i >= PARTY_SIZE) + { sentToPc = CopyMonToPC(&mon); + } else { sentToPc = MON_GIVEN_TO_PARTY; @@ -4314,31 +4227,10 @@ static void DebugAction_Sound_SE_SelectId(u8 taskId) { if (JOY_NEW(DPAD_ANY)) { - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > END_SE) - gTasks[taskId].tInput = END_SE; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < 1) - gTasks[taskId].tInput = 1; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < DEBUG_NUMBER_DIGITS_ITEMS - 1) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, 1, END_SE, DEBUG_NUMBER_DIGITS_ITEMS); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - StringCopyPadded(gStringVar1, sSENames[gTasks[taskId].tInput-1], CHAR_SPACE, 35); + StringCopyPadded(gStringVar1, sSENames[gTasks[taskId].tInput - 1], CHAR_SPACE, 35); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); StringExpandPlaceholders(gStringVar4, sDebugText_Sound_SFX_ID); AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); @@ -4396,31 +4288,10 @@ static void DebugAction_Sound_MUS_SelectId(u8 taskId) { if (JOY_NEW(DPAD_ANY)) { - if (JOY_NEW(DPAD_UP)) - { - gTasks[taskId].tInput += sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput > END_MUS) - gTasks[taskId].tInput = END_MUS; - } - if (JOY_NEW(DPAD_DOWN)) - { - gTasks[taskId].tInput -= sPowersOfTen[gTasks[taskId].tDigit]; - if (gTasks[taskId].tInput < START_MUS) - gTasks[taskId].tInput = START_MUS; - } - if (JOY_NEW(DPAD_LEFT)) - { - if (gTasks[taskId].tDigit > 0) - gTasks[taskId].tDigit -= 1; - } - if (JOY_NEW(DPAD_RIGHT)) - { - if (gTasks[taskId].tDigit < DEBUG_NUMBER_DIGITS_ITEMS - 1) - gTasks[taskId].tDigit += 1; - } + Debug_HandleInput_Numeric(taskId, START_MUS, END_MUS, DEBUG_NUMBER_DIGITS_ITEMS); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - StringCopyPadded(gStringVar1, sBGMNames[gTasks[taskId].tInput-START_MUS], CHAR_SPACE, 35); + StringCopyPadded(gStringVar1, sBGMNames[gTasks[taskId].tInput - START_MUS], CHAR_SPACE, 35); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); StringExpandPlaceholders(gStringVar4, sDebugText_Sound_Music_ID); AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); diff --git a/src/script_pokemon_util.c b/src/script_pokemon_util.c index 94c7d7d8fa..77ce6411db 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 ggMaxFactor, u8 teraType) +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) { u16 nationalDexNum; int sentToPc; @@ -367,7 +367,10 @@ static u32 ScriptGiveMonParameterized(u8 side, u8 slot, u16 species, u8 level, u SetMonData(&mon, MON_DATA_IS_SHINY, &isShiny); // gigantamax factor - SetMonData(&mon, MON_DATA_GIGANTAMAX_FACTOR, &ggMaxFactor); + SetMonData(&mon, MON_DATA_GIGANTAMAX_FACTOR, &gmaxFactor); + + // Dynamax Level + SetMonData(&mon, MON_DATA_DYNAMAX_LEVEL, &dmaxLevel); // tera type if (teraType >= NUMBER_OF_MON_TYPES) @@ -476,7 +479,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); + 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); } #define PARSE_FLAG(n, default_) (flags & (1 << (n))) ? VarGet(ScriptReadHalfword(ctx)) : (default_) @@ -550,8 +553,9 @@ void ScrCmd_createmon(struct ScriptContext *ctx) u16 move3 = PARSE_FLAG(19, MOVE_NONE); u16 move4 = PARSE_FLAG(20, MOVE_NONE); bool8 isShiny = PARSE_FLAG(21, FALSE); - bool8 ggMaxFactor = PARSE_FLAG(22, FALSE); + 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}; @@ -562,7 +566,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, ggMaxFactor, teraType); + gSpecialVar_Result = ScriptGiveMonParameterized(side, slot, species, level, item, ball, nature, abilityNum, gender, evs, ivs, moves, isShiny, gmaxFactor, teraType, dmaxLevel); } #undef PARSE_FLAG diff --git a/test/pokemon.c b/test/pokemon.c index 00b08ebb79..4469fe677d 100644 --- a/test/pokemon.c +++ b/test/pokemon.c @@ -275,7 +275,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_TACKLE, move2=MOVE_SPLASH, move3=MOVE_CELEBRATE, move4=MOVE_EXPLOSION, isShiny=TRUE, ggMaxFactor=TRUE, teraType=TYPE_FIRE; + 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_TACKLE, move2=MOVE_SPLASH, move3=MOVE_CELEBRATE, move4=MOVE_EXPLOSION, isShiny=TRUE, gmaxFactor=TRUE, teraType=TYPE_FIRE, dmaxLevel=7; ); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_WOBBUFFET); @@ -304,6 +304,7 @@ TEST("givemon [all]") EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_IS_SHINY), TRUE); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_GIGANTAMAX_FACTOR), TRUE); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_TERA_TYPE), TYPE_FIRE); + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_DYNAMAX_LEVEL), 7); } TEST("givemon [vars]") @@ -336,9 +337,10 @@ TEST("givemon [vars]") VarSet(VAR_TEMP_9, TRUE); 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, ggMaxFactor=VAR_TEMP_A, teraType=VAR_TEMP_B; + 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; ); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_SPECIES), SPECIES_WOBBUFFET); @@ -367,6 +369,7 @@ TEST("givemon [vars]") EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_IS_SHINY), TRUE); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_GIGANTAMAX_FACTOR), TRUE); EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_TERA_TYPE), TYPE_FIRE); + EXPECT_EQ(GetMonData(&gPlayerParty[0], MON_DATA_DYNAMAX_LEVEL), 7); } TEST("checkteratype/setteratype work") From 6e5f40d506405af3e9a0621dcc91c13c12e7db47 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 11 Jan 2025 11:12:22 +0100 Subject: [PATCH 54/85] Introduces BattlerState struct for the Battle Engine (#5954) --- include/battle.h | 54 +++++++++++++++---------- include/battle_util.h | 3 ++ src/battle_ai_main.c | 2 +- src/battle_ai_switch_items.c | 4 +- src/battle_ai_util.c | 4 +- src/battle_arena.c | 5 +-- src/battle_interface.c | 22 +++++++--- src/battle_main.c | 59 ++++++++++----------------- src/battle_script_commands.c | 78 ++++++++++++++++++------------------ src/battle_util.c | 68 +++++++++++++++++++++---------- 10 files changed, 166 insertions(+), 133 deletions(-) diff --git a/include/battle.h b/include/battle.h index 05c3b3a822..673da55299 100644 --- a/include/battle.h +++ b/include/battle.h @@ -137,6 +137,7 @@ struct DisableStruct u8 terrainAbilityDone:1; u8 usedProteanLibero:1; u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) + u8 boosterEnergyActivates:1; }; struct ProtectStruct @@ -235,6 +236,8 @@ struct SpecialStatus u8 teraShellAbilityDone:1; u8 criticalHit:1; // End of byte + u8 enduredDamage:1; + u8 padding:7; }; struct SideTimer @@ -621,8 +624,32 @@ enum BattleIntroStates BATTLE_INTRO_STATE_SET_DEX_AND_BATTLE_VARS }; +struct BattlerState +{ + u8 targetsDone[MAX_BATTLERS_COUNT]; + + u32 commandingDondozo:1; + u32 absentBattlerFlags:1; + u32 focusPunchBattlers:1; + u32 multipleSwitchInBattlers:1; + u32 alreadyStatusedMoveAttempt:1; // For example when using Thunder Wave on an already paralyzed Pokémon. + u32 activeAbilityPopUps:1; + u32 lastMoveFailed:1; // For Stomping Tantrum + u32 forcedSwitch:1; + u32 storedHealingWish:1; + u32 storedLunarDance:1; + u32 usedEjectItem:1; + u32 sleepClauseEffectExempt:1; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore) + u32 usedMicleBerry:1; + u32 pursuitTarget:1; + u32 padding:17; + // End of Word +}; + +// Cleared at the beginning of the battle. Fields need to be cleared when needed manually otherwise. struct BattleStruct { + struct BattlerState battlerState[MAX_BATTLERS_COUNT]; u8 turnEffectsTracker; u8 turnEffectsBattlerId; u8 turnCountersTracker; @@ -640,7 +667,6 @@ struct BattleStruct u8 wildVictorySong; u8 dynamicMoveType; u8 wrappedBy[MAX_BATTLERS_COUNT]; - u8 focusPunchBattlers; // as bits u8 battlerPreventingSwitchout; u8 moneyMultiplier:6; u8 moneyMultiplierItem:1; @@ -681,9 +707,9 @@ struct BattleStruct u8 hpScale; u16 synchronizeMoveEffect; u8 anyMonHasTransformed:1; // Only used in battle_tv.c - u8 multipleSwitchInBattlers:4; // One bit per battler u8 multipleSwitchInState:2; u8 multipleSwitchInCursor:3; + u8 padding1:2; u8 multipleSwitchInSortedBattlers[MAX_BATTLERS_COUNT]; void (*savedCallback)(void); u16 usedHeldItems[PARTY_SIZE][NUM_BATTLE_SIDES]; // For each party member and side. For harvest, recycle @@ -720,7 +746,6 @@ struct BattleStruct u16 arenaStartHp[2]; u8 arenaLostPlayerMons; // Bits for party member, lost as in referee's decision, not by fainting. u8 arenaLostOpponentMons; - u8 alreadyStatusedMoveAttempt; // As bits for battlers; For example when using Thunder Wave on an already paralyzed Pokémon. u8 debugBattler; u8 magnitudeBasePower; u8 presentBasePower; @@ -730,7 +755,6 @@ struct BattleStruct u8 savedTargetCount:4; u8 savedAttackerCount:4; bool8 ateBoost[MAX_BATTLERS_COUNT]; - u8 activeAbilityPopUps; // as bits for each battler u8 abilityPopUpSpriteIds[MAX_BATTLERS_COUNT][2]; // two per battler struct ZMoveData zmove; struct DynamaxData dynamax; @@ -739,7 +763,6 @@ struct BattleStruct enum BattleIntroStates introState:8; u8 ateBerry[2]; // array id determined by side, each party pokemon as bit u8 stolenStats[NUM_BATTLE_STATS]; // hp byte is used for which stats to raise, other inform about by how many stages - u8 lastMoveFailed; // as bits for each battler, for the sake of Stomping Tantrum u8 lastMoveTarget[MAX_BATTLERS_COUNT]; // The last target on which each mon used a move, for the sake of Instruct u16 tracedAbility[MAX_BATTLERS_COUNT]; u16 hpBefore[MAX_BATTLERS_COUNT]; // Hp of battlers before using a move. For Berserk and Anger Shell. @@ -754,8 +777,6 @@ struct BattleStruct u16 changedSpecies[NUM_BATTLE_SIDES][PARTY_SIZE]; // For forms when multiple mons can change into the same pokemon. u8 quickClawBattlerId; struct LostItem itemLost[NUM_BATTLE_SIDES][PARTY_SIZE]; // Pokemon that had items consumed or stolen (two bytes per party member per side) - u8 forcedSwitch:4; // For each battler - u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects u8 blunderPolicy:1; // should blunder policy activate u8 swapDamageCategory:1; // Photon Geyser, Shell Side Arm, Light That Burns the Sky u8 bouncedMoveIsUsed:1; @@ -773,10 +794,7 @@ struct BattleStruct u8 hitSwitchTargetFailed:1; u8 effectsBeforeUsingMoveDone:1; // Mega Evo and Focus Punch/Shell Trap effects. u8 spriteIgnore0Hp:1; - u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit. u8 battleBondTransformed[NUM_BATTLE_SIDES]; // Bitfield for each party. - u8 storedHealingWish:4; // Each battler as a bit. - u8 storedLunarDance:4; // Each battler as a bit. u8 bonusCritStages[MAX_BATTLERS_COUNT]; // G-Max Chi Strike boosts crit stages of allies. u8 itemPartyIndex[MAX_BATTLERS_COUNT]; u8 itemMoveIndex[MAX_BATTLERS_COUNT]; @@ -795,7 +813,6 @@ struct BattleStruct u32 aiDelayTimer; // Counts number of frames AI takes to choose an action. u32 aiDelayFrames; // Number of frames it took to choose an action. u8 timesGotHit[NUM_BATTLE_SIDES][PARTY_SIZE]; - u8 enduredDamage; u8 transformZeroToHero[NUM_BATTLE_SIDES]; u8 stickySyrupdBy[MAX_BATTLERS_COUNT]; u8 intrepidSwordBoost[NUM_BATTLE_SIDES]; @@ -806,18 +823,13 @@ struct BattleStruct u8 quickDrawRandom[MAX_BATTLERS_COUNT]; u8 shellSideArmCategory[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; u8 speedTieBreaks; // MAX_BATTLERS_COUNT! values. - u8 boosterEnergyActivates; u8 categoryOverride; // for Z-Moves and Max Moves - u8 commandingDondozo; u16 commanderActive[MAX_BATTLERS_COUNT]; u32 stellarBoostFlags[NUM_BATTLE_SIDES]; // stored as a bitfield of flags for all types for each side - u8 redCardActivates:1; - u8 padding1:7; - u8 usedEjectItem; u8 monCausingSleepClause[NUM_BATTLE_SIDES]; // Stores which pokemon on a given side is causing Sleep Clause to be active as the mon's index in the party - u8 sleepClauseEffectExempt:4; // Stores whether effect should be exempt from triggering Sleep Clause (Effect Spore) - u8 usedMicleBerry:4; - u8 pursuitTarget:4; // Each battler as a bit. + u8 additionalEffectsCounter:4; // A counter for the additionalEffects applied by the current move in Cmd_setadditionaleffects + u8 redCardActivates:1; + u8 padding2:2; // padding in the middle so pursuit fields are together u8 pursuitSwitchByMove:1; u8 pursuitStoredSwitch; // Stored id for the Pursuit target's switch s32 battlerExpReward; @@ -833,7 +845,7 @@ struct BattleStruct u8 calculatedSpreadMoveAccuracy:1; u8 printedStrongWindsWeakenedAttack:1; u8 numSpreadTargets:2; - u8 padding2:2; + u8 padding3:2; }; // The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider, @@ -1190,7 +1202,7 @@ static inline bool32 IsBattlerTurnDamaged(u32 battler) { return gSpecialStatuses[battler].physicalDmg != 0 || gSpecialStatuses[battler].specialDmg != 0 - || gBattleStruct->enduredDamage & (1u << battler); + || gSpecialStatuses[battler].enduredDamage; } static inline bool32 IsBattlerAtMaxHp(u32 battler) diff --git a/include/battle_util.h b/include/battle_util.h index 5ab72967dc..57beae337e 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -339,5 +339,8 @@ void ClearDamageCalcResults(void); u32 DoesDestinyBondFail(u32 battler); bool32 IsMoveEffectBlockedByTarget(u32 ability); u32 NumAffectedSpreadMoveTargets(void); +bool32 IsPursuitTargetSet(void); +void ClearPursuitValuesIfSet(u32 battler); +void ClearPursuitValues(void); #endif // GUARD_BATTLE_UTIL_H diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d856fae81f..b4b1909237 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -734,7 +734,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsTwoTurnNotSemiInvulnerableMove(battlerAtk, move) && CanTargetFaintAi(battlerDef, battlerAtk)) RETURN_SCORE_MINUS(10); - if (gBattleStruct->commandingDondozo & (1u << battlerDef)) + if (gBattleStruct->battlerState[battlerDef].commandingDondozo) RETURN_SCORE_MINUS(20); // check if negates type diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 8a8fe367ac..7522c7ec05 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -40,11 +40,11 @@ static void InitializeSwitchinCandidate(struct Pokemon *mon) static bool32 IsAceMon(u32 battler, u32 monPartyId) { if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_ACE_POKEMON - && !(gBattleStruct->forcedSwitch & (1u << battler)) + && !gBattleStruct->battlerState[battler].forcedSwitch && monPartyId == CalculateEnemyPartyCountInSide(battler)-1) return TRUE; if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON - && !(gBattleStruct->forcedSwitch & (1u << battler)) + && !gBattleStruct->battlerState[battler].forcedSwitch && (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2)) return TRUE; return FALSE; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 7306237de4..c9a3ae07b2 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -430,7 +430,7 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy if (battlerDef == BATTLE_PARTNER(battlerAtk)) battlerDefAbility = aiData->abilities[battlerDef]; - if (gBattleStruct->commandingDondozo & (1u << battlerDef)) + if (gBattleStruct->battlerState[battlerDef].commandingDondozo) return TRUE; if (CanAbilityBlockMove(battlerAtk, battlerDef, move, aiData->abilities[battlerDef])) @@ -1511,7 +1511,7 @@ bool32 IsSemiInvulnerable(u32 battlerDef, u32 move) { if (gStatuses3[battlerDef] & STATUS3_PHANTOM_FORCE) return TRUE; - else if (gBattleStruct->commandingDondozo & (1u << battlerDef)) + else if (gBattleStruct->battlerState[battlerDef].commandingDondozo) return TRUE; else if (!MoveDamagesAirborne(move) && gStatuses3[battlerDef] & STATUS3_ON_AIR) return TRUE; diff --git a/src/battle_arena.c b/src/battle_arena.c index ff406a37df..dd0f0c1bbd 100644 --- a/src/battle_arena.c +++ b/src/battle_arena.c @@ -386,10 +386,9 @@ void BattleArena_AddSkillPoints(u8 battler) if (gHitMarker & HITMARKER_OBEYS) { - u8 *failedMoveBits = &gBattleStruct->alreadyStatusedMoveAttempt; - if (*failedMoveBits & (1u << battler)) + if (gBattleStruct->battlerState[battler].alreadyStatusedMoveAttempt) { - *failedMoveBits &= ~((1u << battler)); + gBattleStruct->battlerState[battler].alreadyStatusedMoveAttempt = FALSE; skillPoints[battler] -= 2; } else if (gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_NO_EFFECT) diff --git a/src/battle_interface.c b/src/battle_interface.c index 5c514a0d80..196f338495 100644 --- a/src/battle_interface.c +++ b/src/battle_interface.c @@ -2695,6 +2695,17 @@ static void RestoreOverwrittenPixels(u8 *tiles) Free(buffer); } +static inline bool32 IsAnyAbilityPopUpActive(void) +{ + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (gBattleStruct->battlerState[battler].activeAbilityPopUps) + return TRUE; + } + + return FALSE; +} + void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle) { const s16 (*coords)[2]; @@ -2713,12 +2724,13 @@ void CreateAbilityPopUp(u8 battlerId, u32 ability, bool32 isDoubleBattle) return; } - if (!gBattleStruct->activeAbilityPopUps) + if (!IsAnyAbilityPopUpActive()) { LoadSpriteSheet(&sSpriteSheet_AbilityPopUp); LoadSpritePalette(&sSpritePalette_AbilityPopUp); } - gBattleStruct->activeAbilityPopUps |= 1u << battlerId; + + gBattleStruct->battlerState[battlerId].activeAbilityPopUps = TRUE; battlerPosition = GetBattlerPosition(battlerId); if (isDoubleBattle) @@ -2809,7 +2821,7 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite) ||(sprite->tRightToLeft && (sprite->x -= 4) <= sprite->tOriginalX - ABILITY_POP_UP_POS_X_SLIDE) ) { - gBattleStruct->activeAbilityPopUps &= ~(1u << sprite->tBattlerId); + gBattleStruct->battlerState[sprite->tBattlerId].activeAbilityPopUps = FALSE; DestroySprite(sprite); } } @@ -2823,7 +2835,7 @@ static void SpriteCb_AbilityPopUp(struct Sprite *sprite) void DestroyAbilityPopUp(u8 battlerId) { - if (gBattleStruct->activeAbilityPopUps & (1u << battlerId)) + if (gBattleStruct->battlerState[battlerId].activeAbilityPopUps) { gSprites[gBattleStruct->abilityPopUpSpriteIds[battlerId][0]].tFrames = 0; gSprites[gBattleStruct->abilityPopUpSpriteIds[battlerId][1]].tFrames = 0; @@ -2835,7 +2847,7 @@ static void Task_FreeAbilityPopUpGfx(u8 taskId) { if (!gSprites[gTasks[taskId].tSpriteId1].inUse && !gSprites[gTasks[taskId].tSpriteId2].inUse - && !gBattleStruct->activeAbilityPopUps) + && !IsAnyAbilityPopUpActive()) { FreeSpriteTilesByTag(ABILITY_POP_UP_TAG); FreeSpritePaletteByTag(ABILITY_POP_UP_TAG); diff --git a/src/battle_main.c b/src/battle_main.c index ebc391983a..e0072829e0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3133,10 +3133,8 @@ static void BattleStartClearSetData(void) gBattleStruct->swapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky gBattleStruct->categoryOverride = FALSE; // used for Z-Moves and Max Moves - gBattleStruct->pursuitTarget = 0; - gBattleStruct->pursuitSwitchByMove = FALSE; - gBattleStruct->pursuitStoredSwitch = 0; + ClearPursuitValues(); gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing gCategoryIconSpriteId = 0xFF; @@ -3243,17 +3241,11 @@ void SwitchInClearSetData(u32 battler) gBattleStruct->lastTakenMoveFrom[battler][1] = 0; gBattleStruct->lastTakenMoveFrom[battler][2] = 0; gBattleStruct->lastTakenMoveFrom[battler][3] = 0; - gBattleStruct->lastMoveFailed &= ~(1u << battler); + gBattleStruct->battlerState[battler].lastMoveFailed = FALSE; gBattleStruct->palaceFlags &= ~(1u << battler); - gBattleStruct->boosterEnergyActivates &= ~(1u << battler); gBattleStruct->canPickupItem &= ~(1u << battler); - if (gBattleStruct->pursuitTarget & (1u << battler)) - { - gBattleStruct->pursuitTarget = 0; - gBattleStruct->pursuitSwitchByMove = FALSE; - gBattleStruct->pursuitStoredSwitch = 0; - } + ClearPursuitValuesIfSet(battler); for (i = 0; i < ARRAY_COUNT(gSideTimers); i++) { @@ -3278,7 +3270,7 @@ void SwitchInClearSetData(u32 battler) // Reset damage to prevent things like red card activating if the switched-in mon is holding it gSpecialStatuses[battler].physicalDmg = 0; gSpecialStatuses[battler].specialDmg = 0; - gBattleStruct->enduredDamage &= ~(1u << battler); + gSpecialStatuses[battler].enduredDamage = FALSE; // Reset Eject Button / Eject Pack switch detection AI_DATA->ejectButtonSwitch = FALSE; @@ -3383,16 +3375,9 @@ const u8* FaintClearSetData(u32 battler) gBattleStruct->lastTakenMoveFrom[battler][1] = 0; gBattleStruct->lastTakenMoveFrom[battler][2] = 0; gBattleStruct->lastTakenMoveFrom[battler][3] = 0; - - if (gBattleStruct->pursuitTarget & (1u << battler)) - { - gBattleStruct->pursuitTarget = 0; - gBattleStruct->pursuitSwitchByMove = FALSE; - gBattleStruct->pursuitStoredSwitch = 0; - } - gBattleStruct->palaceFlags &= ~(1u << battler); - gBattleStruct->boosterEnergyActivates &= ~(1u << battler); + + ClearPursuitValuesIfSet(battler); if (gBattleStruct->commanderActive[battler] != SPECIES_NONE) { @@ -3953,10 +3938,10 @@ static void TryDoEventsBeforeFirstTurn(void) *(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE; gChosenActionByBattler[i] = B_ACTION_NONE; gChosenMoveByBattler[i] = MOVE_NONE; + gBattleStruct->battlerState[i].absentBattlerFlags = gAbsentBattlerFlags & (1u << i); } TurnValuesCleanUp(FALSE); SpecialStatusesClear(); - *(&gBattleStruct->absentBattlerFlags) = gAbsentBattlerFlags; BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG); AssignUsableGimmicks(); gBattleMainFunc = HandleTurnActionSelectionState; @@ -4070,12 +4055,12 @@ void BattleTurnPassed(void) { gChosenActionByBattler[i] = B_ACTION_NONE; gChosenMoveByBattler[i] = MOVE_NONE; + gBattleStruct->battlerState[i].absentBattlerFlags = gAbsentBattlerFlags & (1u << i); } for (i = 0; i < MAX_BATTLERS_COUNT; i++) *(gBattleStruct->monToSwitchIntoId + i) = PARTY_SIZE; - *(&gBattleStruct->absentBattlerFlags) = gAbsentBattlerFlags; BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG); AssignUsableGimmicks(); SetShellSideArmCategory(); @@ -4259,10 +4244,10 @@ static void HandleTurnActionSelectionState(void) *(gBattleStruct->monToSwitchIntoId + battler) = PARTY_SIZE; if (gBattleTypeFlags & BATTLE_TYPE_MULTI || (position & BIT_FLANK) == B_FLANK_LEFT - || gBattleStruct->absentBattlerFlags & (1u << GetBattlerAtPosition(BATTLE_PARTNER(position))) + || gBattleStruct->battlerState[GetBattlerAtPosition(BATTLE_PARTNER(position))].absentBattlerFlags || gBattleCommunication[GetBattlerAtPosition(BATTLE_PARTNER(position))] == STATE_WAIT_ACTION_CONFIRMED) { - if ((gBattleStruct->absentBattlerFlags & (1u << battler)) || (gBattleStruct->commandingDondozo & (1u << battler))) + if (gBattleStruct->battlerState[battler].absentBattlerFlags || gBattleStruct->battlerState[battler].commandingDondozo) { gChosenActionByBattler[battler] = B_ACTION_NOTHING_FAINTED; if (!(gBattleTypeFlags & BATTLE_TYPE_MULTI)) @@ -4637,7 +4622,7 @@ static void HandleTurnActionSelectionState(void) if (((gBattleTypeFlags & BATTLE_TYPE_MULTI) || !IsDoubleBattle()) || (position & BIT_FLANK) != B_FLANK_LEFT - || (*(&gBattleStruct->absentBattlerFlags) & (1u << GetBattlerAtPosition(BATTLE_PARTNER(position))))) + || gBattleStruct->battlerState[GetBattlerAtPosition(BATTLE_PARTNER(position))].absentBattlerFlags) { BtlController_EmitLinkStandbyMsg(battler, BUFFER_A, LINK_STANDBY_MSG_STOP_BOUNCE, i); } @@ -4803,9 +4788,9 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect) speed *= 2; else if (ability == ABILITY_SLOW_START && gDisableStructs[battler].slowStartTimer != 0) speed /= 2; - else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gBattleStruct->boosterEnergyActivates & (1u << battler))) + else if (ability == ABILITY_PROTOSYNTHESIS && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && ((gBattleWeather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gDisableStructs[battler].boosterEnergyActivates)) speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; - else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battler))) + else if (ability == ABILITY_QUARK_DRIVE && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) && (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battler].boosterEnergyActivates)) speed = (GetHighestStatId(battler) == STAT_SPEED) ? (speed * 150) / 100 : speed; // stat stages @@ -5186,9 +5171,10 @@ static void TurnValuesCleanUp(bool8 var0) gBattleMons[i].status2 &= ~STATUS2_SUBSTITUTE; if (!(gStatuses3[i] & STATUS3_COMMANDER)) - gBattleStruct->commandingDondozo &= ~(1u << i); + gBattleStruct->battlerState[i].commandingDondozo = FALSE; gSpecialStatuses[i].parentalBondState = PARENTAL_BOND_OFF; + gBattleStruct->battlerState[i].usedEjectItem = FALSE; } gSideStatuses[B_SIDE_PLAYER] &= ~(SIDE_STATUS_QUICK_GUARD | SIDE_STATUS_WIDE_GUARD | SIDE_STATUS_CRAFTY_SHIELD | SIDE_STATUS_MAT_BLOCK); @@ -5196,11 +5182,8 @@ static void TurnValuesCleanUp(bool8 var0) gSideTimers[B_SIDE_PLAYER].followmeTimer = 0; gSideTimers[B_SIDE_OPPONENT].followmeTimer = 0; - gBattleStruct->usedEjectItem = 0; - gBattleStruct->pursuitTarget = 0; - gBattleStruct->pursuitSwitchByMove = FALSE; - gBattleStruct->pursuitStoredSwitch = 0; gBattleStruct->pledgeMove = FALSE; // combined pledge move may not have been used due to a canceller + ClearPursuitValues(); ClearDamageCalcResults(); } @@ -5264,12 +5247,12 @@ static bool32 TryDoMoveEffectsBeforeMoves(void) SortBattlersBySpeed(battlers, FALSE); for (i = 0; i < gBattlersCount; i++) { - if (!(gBattleStruct->focusPunchBattlers & (1u << battlers[i])) + if (!gBattleStruct->battlerState[battlers[i]].focusPunchBattlers && !(gBattleMons[battlers[i]].status1 & STATUS1_SLEEP) && !(gDisableStructs[battlers[i]].truantCounter) && !(gProtectStructs[battlers[i]].noValidMoves)) { - gBattleStruct->focusPunchBattlers |= 1u << battlers[i]; + gBattleStruct->battlerState[battlers[i]].focusPunchBattlers = TRUE; gBattlerAttacker = battlers[i]; switch (GetMoveEffect(gChosenMoveByBattler[gBattlerAttacker])) { @@ -5390,9 +5373,9 @@ static void CheckChangingTurnOrderEffects(void) gCurrentActionFuncId = gActionsByTurnOrder[0]; gBattleStruct->dynamicMoveType = 0; gBattleStruct->effectsBeforeUsingMoveDone = FALSE; - gBattleStruct->focusPunchBattlers = 0; for (i = 0; i < MAX_BATTLERS_COUNT; i++) { + gBattleStruct->battlerState[i].focusPunchBattlers = FALSE; gBattleStruct->ateBoost[i] = FALSE; gSpecialStatuses[i].gemBoost = FALSE; } @@ -5412,7 +5395,7 @@ static void RunTurnActionsFunctions(void) // Mega Evolve / Focus Punch-like moves after switching, items, running, but before using a move. if (gCurrentActionFuncId == B_ACTION_USE_MOVE && !gBattleStruct->effectsBeforeUsingMoveDone) { - if (!gBattleStruct->pursuitTarget) + if (!IsPursuitTargetSet()) { if (TryDoGimmicksBeforeMoves()) return; @@ -5690,7 +5673,7 @@ static void FreeResetData_ReturnToOvOrDoEvolutions(void) IncrementDexNavChain(); else gSaveBlock3Ptr->dexNavChain = 0; - + gDexNavBattle = FALSE; ResetSpriteData(); if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 2c50f26d9d..29b075e855 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1166,9 +1166,9 @@ static void Cmd_attackcanceler(void) s32 i; - if (gBattleStruct->usedEjectItem & (1u << gBattlerAttacker)) + if (gBattleStruct->battlerState[gBattlerAttacker].usedEjectItem) { - gBattleStruct->usedEjectItem = 0; + gBattleStruct->battlerState[gBattlerAttacker].usedEjectItem = FALSE; gCurrentActionFuncId = B_ACTION_TRY_FINISH; return; } @@ -1432,7 +1432,7 @@ static bool32 AccuracyCalcHelper(u32 move, u32 battler) { effect = TRUE; } - else if (gBattleStruct->pursuitTarget & (1u << battler)) + else if (gBattleStruct->battlerState[battler].pursuitTarget) { effect = TRUE; } @@ -1581,7 +1581,7 @@ u32 GetTotalAccuracy(u32 battlerAtk, u32 battlerDef, u32 move, u32 atkAbility, u break; } - if (gBattleStruct->usedMicleBerry & 1u << battlerAtk) + if (gBattleStruct->battlerState[battlerAtk].usedMicleBerry) { if (atkAbility == ABILITY_RIPEN) calc = (calc * 140) / 100; // ripen gives 40% acc boost @@ -2128,7 +2128,7 @@ static void Cmd_adjustdamage(void) if (DoesDisguiseBlockMove(battlerDef, gCurrentMove)) { - gBattleStruct->enduredDamage |= 1u << battlerDef; + gSpecialStatuses[battlerDef].enduredDamage = TRUE; continue; } if (GetBattlerAbility(battlerDef) == ABILITY_ICE_FACE && IsBattleMovePhysical(gCurrentMove) && gBattleMons[battlerDef].species == SPECIES_EISCUE) @@ -2182,7 +2182,7 @@ static void Cmd_adjustdamage(void) // Handle reducing the dmg to 1 hp. gBattleStruct->moveDamage[battlerDef] = gBattleMons[battlerDef].hp - 1; - gBattleStruct->enduredDamage |= 1u << battlerDef; + gSpecialStatuses[battlerDef].enduredDamage = TRUE; if (gProtectStructs[battlerDef].endured) { @@ -3209,7 +3209,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) if (i != gBattlersCount) break; - if (!CanBeSlept(gEffectBattler, GetBattlerAbility(gEffectBattler), BLOCKED_BY_SLEEP_CLAUSE) && !(gBattleStruct->sleepClauseEffectExempt & (1u << gEffectBattler))) + if (!CanBeSlept(gEffectBattler, GetBattlerAbility(gEffectBattler), BLOCKED_BY_SLEEP_CLAUSE) && !gBattleStruct->battlerState[gEffectBattler].sleepClauseEffectExempt) break; cancelMultiTurnMovesResult = CancelMultiTurnMoves(gEffectBattler); @@ -5895,7 +5895,7 @@ static u32 GetNextTarget(u32 moveTarget, bool32 excludeCurrent) if (battler != gBattlerAttacker && !(excludeCurrent && battler == gBattlerTarget) && IsBattlerAlive(battler) - && !(gBattleStruct->targetsDone[gBattlerAttacker] & (1u << battler)) + && !gBattleStruct->battlerState[gBattlerAttacker].targetsDone[battler] && (GetBattlerSide(battler) != GetBattlerSide(gBattlerAttacker) || moveTarget == MOVE_TARGET_FOES_AND_ALLY)) break; } @@ -6396,9 +6396,9 @@ static void Cmd_moveend(void) if ((gBattleStruct->moveResultFlags[gBattlerTarget] & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE)) || (gBattleMons[gBattlerAttacker].status2 & (STATUS2_FLINCHED)) || gProtectStructs[gBattlerAttacker].prlzImmobility) - gBattleStruct->lastMoveFailed |= 1u << gBattlerAttacker; + gBattleStruct->battlerState[gBattlerAttacker].lastMoveFailed = TRUE; else - gBattleStruct->lastMoveFailed &= ~(1u << gBattlerAttacker); + gBattleStruct->battlerState[gBattlerAttacker].lastMoveFailed = FALSE; // Set ShellTrap to activate after the attacker's turn if target was hit by a physical move. if (GetMoveEffect(gChosenMoveByBattler[gBattlerTarget]) == EFFECT_SHELL_TRAP @@ -6436,7 +6436,7 @@ static void Cmd_moveend(void) } u32 originalEffect = GetMoveEffect(originallyUsedMove); if (!(gAbsentBattlerFlags & (1u << gBattlerAttacker)) - && !(gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker)) + && !gBattleStruct->battlerState[gBattlerAttacker].absentBattlerFlags && originalEffect != EFFECT_BATON_PASS && originalEffect != EFFECT_HEALING_WISH) { if (gHitMarker & HITMARKER_OBEYS) @@ -6480,7 +6480,7 @@ static void Cmd_moveend(void) break; case MOVEEND_MIRROR_MOVE: // mirror move if (!(gAbsentBattlerFlags & (1u << gBattlerAttacker)) - && !(gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker)) + && !gBattleStruct->battlerState[gBattlerAttacker].absentBattlerFlags && !IsMoveMirrorMoveBanned(originallyUsedMove) && gHitMarker & HITMARKER_OBEYS && gBattlerAttacker != gBattlerTarget @@ -6500,7 +6500,7 @@ static void Cmd_moveend(void) && MoveResultHasEffect(gBattlerTarget)) gProtectStructs[gBattlerAttacker].targetAffected = TRUE; - gBattleStruct->targetsDone[gBattlerAttacker] |= 1u << gBattlerTarget; + gBattleStruct->battlerState[gBattlerAttacker].targetsDone[gBattlerTarget] = TRUE; if (!(gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) && IsDoubleBattle() && !gProtectStructs[gBattlerAttacker].chargingTurn @@ -6531,9 +6531,9 @@ static void Cmd_moveend(void) u8 originalBounceTarget = gBattlerAttacker; gBattleStruct->bouncedMoveIsUsed = FALSE; gBattlerAttacker = gBattleStruct->attackerBeforeBounce; - gBattleStruct->targetsDone[gBattlerAttacker] |= 1u << originalBounceTarget; - gBattleStruct->targetsDone[originalBounceTarget] = 0; - + gBattleStruct->battlerState[gBattlerAttacker].targetsDone[originalBounceTarget] = TRUE; + for (i = 0; i < gBattlersCount; i++) + gBattleStruct->battlerState[originalBounceTarget].targetsDone[i] = FALSE; nextTarget = GetNextTarget(moveTarget, FALSE); if (nextTarget != MAX_BATTLERS_COUNT) { @@ -6703,7 +6703,7 @@ static void Cmd_moveend(void) gBattlescriptCurrInstr = BattleScript_MoveEnd; // Prevent user switch-in selection effect = TRUE; BattleScriptPushCursor(); - gBattleStruct->usedEjectItem |= 1u << battler; + gBattleStruct->battlerState[battler].usedEjectItem = TRUE; if (ejectButtonBattlers & (1u << battler)) { gBattlescriptCurrInstr = BattleScript_EjectButtonActivates; @@ -6972,7 +6972,6 @@ static void Cmd_moveend(void) DebugPrintfLevel(MGBA_LOG_WARN, "savedTargetCount is greater than 0! More calls to SaveBattlerTarget than RestoreBattlerTarget!"); // #endif } - gBattleStruct->targetsDone[gBattlerAttacker] = 0; gProtectStructs[gBattlerAttacker].targetAffected = FALSE; gProtectStructs[gBattlerAttacker].shellTrap = FALSE; gBattleStruct->ateBoost[gBattlerAttacker] = FALSE; @@ -6988,12 +6987,11 @@ static void Cmd_moveend(void) gBattleStruct->categoryOverride = FALSE; gBattleStruct->bouncedMoveIsUsed = FALSE; gBattleStruct->snatchedMoveIsUsed = FALSE; - gBattleStruct->enduredDamage = 0; gBattleStruct->additionalEffectsCounter = 0; gBattleStruct->poisonPuppeteerConfusion = FALSE; gBattleStruct->fickleBeamBoosted = FALSE; gBattleStruct->redCardActivates = FALSE; - gBattleStruct->usedMicleBerry &= ~(1u << gBattlerAttacker); + gBattleStruct->battlerState[gBattlerAttacker].usedMicleBerry = FALSE; if (gHitMarker & HITMARKER_UNABLE_TO_USE_MOVE) gBattleStruct->pledgeMove = FALSE; if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE) @@ -7005,6 +7003,8 @@ static void Cmd_moveend(void) for (i = 0; i < gBattlersCount; i++) { + gBattleStruct->battlerState[gBattlerAttacker].targetsDone[i] = FALSE; + if (gBattleStruct->commanderActive[i] != SPECIES_NONE && !IsBattlerAlive(i)) { u32 partner = BATTLE_PARTNER(i); @@ -7017,7 +7017,7 @@ static void Cmd_moveend(void) gBattleScripting.moveendState++; break; case MOVEEND_PURSUIT_NEXT_ACTION: - if (gBattleStruct->pursuitTarget & (1u << gBattlerTarget)) + if (gBattleStruct->battlerState[gBattlerTarget].pursuitTarget) { u32 storedTarget = gBattlerTarget; if (SetTargetToNextPursuiter(gBattlerTarget)) @@ -7034,9 +7034,7 @@ static void Cmd_moveend(void) else gBattlescriptCurrInstr = BattleScript_DoSwitchOut; *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = gBattleStruct->pursuitStoredSwitch; - gBattleStruct->pursuitTarget = 0; - gBattleStruct->pursuitSwitchByMove = FALSE; - gBattleStruct->pursuitStoredSwitch = 0; + ClearPursuitValues(); effect = TRUE; } } @@ -7719,20 +7717,20 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) } // Healing Wish activates before hazards. // Starting from Gen8 - it heals only pokemon which can be healed. In gens 5,6,7 the effect activates anyways. - else if (((gBattleStruct->storedHealingWish & (1u << battler)) || (gBattleStruct->storedLunarDance & (1u << battler))) + else if ((gBattleStruct->battlerState[battler].storedHealingWish || gBattleStruct->battlerState[battler].storedLunarDance) && (gBattleMons[battler].hp != gBattleMons[battler].maxHP || gBattleMons[battler].status1 != 0 || B_HEALING_WISH_SWITCH < GEN_8)) { - if (gBattleStruct->storedHealingWish & (1u << battler)) + if (gBattleStruct->battlerState[battler].storedHealingWish) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_HealingWishActivates; - gBattleStruct->storedHealingWish &= ~(1u << battler); + gBattleStruct->battlerState[battler].storedHealingWish = FALSE; } else // Lunar Dance { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_LunarDanceActivates; - gBattleStruct->storedLunarDance &= ~(1u << battler); + gBattleStruct->battlerState[battler].storedLunarDance = FALSE; } } else if (!(gDisableStructs[battler].spikesDone) @@ -7881,7 +7879,7 @@ static bool32 DoSwitchInEffectsForBattler(u32 battler) gBattleStruct->hpOnSwitchout[GetBattlerSide(i)] = gBattleMons[i].hp; } - gBattleStruct->forcedSwitch &= ~(1u << battler); + gBattleStruct->battlerState[battler].forcedSwitch = FALSE; return FALSE; } @@ -7897,7 +7895,7 @@ static void Cmd_switchineffects(void) { // Multiple mons fainted and are being switched-in. Their abilities/hazards will play according to speed ties. case BS_FAINTED_MULTIPLE_1: // Saves the battlers. - gBattleStruct->multipleSwitchInBattlers |= 1 << battler; + gBattleStruct->battlerState[battler].multipleSwitchInBattlers = TRUE; UpdateSentMonFlags(battler); // Increment fainted battler. @@ -7926,14 +7924,16 @@ static void Cmd_switchineffects(void) for (; gBattleStruct->multipleSwitchInCursor < gBattlersCount; gBattleStruct->multipleSwitchInCursor++) { gBattlerFainted = gBattleStruct->multipleSwitchInSortedBattlers[gBattleStruct->multipleSwitchInCursor]; - if (gBattleStruct->multipleSwitchInBattlers & (1 << (gBattlerFainted))) + if (gBattleStruct->battlerState[gBattlerFainted].multipleSwitchInBattlers) { if (DoSwitchInEffectsForBattler(gBattlerFainted)) return; } } // All battlers done, end - gBattleStruct->multipleSwitchInBattlers = 0; + for (i = 0; i < gBattlersCount; i++) + gBattleStruct->battlerState[i].multipleSwitchInBattlers = FALSE; + gBattleStruct->multipleSwitchInState = 0; gBattlescriptCurrInstr = cmd->nextInstr; } @@ -10048,7 +10048,7 @@ static void Cmd_various(void) case VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT: { VARIOUS_ARGS(); - gBattleStruct->alreadyStatusedMoveAttempt |= 1u << battler; + gBattleStruct->battlerState[battler].alreadyStatusedMoveAttempt = TRUE; break; } case VARIOUS_PALACE_TRY_ESCAPE_STATUS: @@ -12486,7 +12486,7 @@ static void Cmd_forcerandomswitch(void) { *(gBattleStruct->battlerPartyIndexes + gBattlerTarget) = gBattlerPartyIndexes[gBattlerTarget]; gBattlescriptCurrInstr = BattleScript_RoarSuccessSwitch; - gBattleStruct->forcedSwitch |= 1u << gBattlerTarget; + gBattleStruct->battlerState[gBattlerTarget].forcedSwitch = TRUE; *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = validMons[RandomUniform(RNG_FORCE_RANDOM_SWITCH, 0, validMonsCount - 1)]; if (!IsMultiBattle()) @@ -14021,7 +14021,7 @@ static void Cmd_jumpifnopursuitswitchdmg(void) if (SetTargetToNextPursuiter(gBattlerAttacker)) { ChangeOrderTargetAfterAttacker(); - gBattleStruct->pursuitTarget = 1u << gBattlerAttacker; + gBattleStruct->battlerState[gBattlerAttacker].pursuitTarget = TRUE; gBattleStruct->pursuitSwitchByMove = gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE; gBattleStruct->pursuitStoredSwitch = gBattleStruct->monToSwitchIntoId[gBattlerAttacker]; *(gBattleStruct->moveTarget + gBattlerTarget) = gBattlerAttacker; @@ -17619,11 +17619,11 @@ void BS_JumpIfSleepClause(void) // Can freely sleep own partner if (IsDoubleBattle() && IsSleepClauseEnabled() && GetBattlerSide(gBattlerAttacker) == GetBattlerSide(gBattlerTarget)) { - gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerTarget); + gBattleStruct->battlerState[gBattlerTarget].sleepClauseEffectExempt = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; return; } - gBattleStruct->sleepClauseEffectExempt &= ~(1u << gBattlerTarget); + gBattleStruct->battlerState[gBattlerTarget].sleepClauseEffectExempt = FALSE; // Can't sleep if clause is active otherwise if (IsSleepClauseActiveForSide(GetBattlerSide(gBattlerTarget))) gBattlescriptCurrInstr = cmd->jumpInstr; @@ -17795,9 +17795,9 @@ void BS_StoreHealingWish(void) u32 battler = GetBattlerForBattleScript(cmd->battler); if (gCurrentMove == MOVE_LUNAR_DANCE) - gBattleStruct->storedLunarDance |= 1u << battler; + gBattleStruct->battlerState[battler].storedLunarDance = TRUE; else - gBattleStruct->storedHealingWish |= 1u << battler; + gBattleStruct->battlerState[battler].storedHealingWish = TRUE; gBattlescriptCurrInstr = cmd->nextInstr; } diff --git a/src/battle_util.c b/src/battle_util.c index fef04096a4..88918320da 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -223,7 +223,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) || ability == ABILITY_PROPELLER_TAIL || ability == ABILITY_STALWART) return FALSE; - if (effect == EFFECT_PURSUIT && gBattleStruct->pursuitTarget) + if (effect == EFFECT_PURSUIT && IsPursuitTargetSet()) return FALSE; if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE))) @@ -239,8 +239,8 @@ void HandleAction_UseMove(void) u16 moveTarget; gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; - if (gBattleStruct->absentBattlerFlags & (1u << gBattlerAttacker) - || gBattleStruct->commandingDondozo & (1u << gBattlerAttacker) + if (gBattleStruct->battlerState[gBattlerAttacker].absentBattlerFlags + || gBattleStruct->battlerState[gBattlerAttacker].commandingDondozo || !IsBattlerAlive(gBattlerAttacker)) { gCurrentActionFuncId = B_ACTION_FINISHED; @@ -334,7 +334,7 @@ void HandleAction_UseMove(void) } else if (IsDoubleBattle() && gSideTimers[side].followmeTimer == 0 - && !(gBattleStruct->pursuitTarget & (1u << *(gBattleStruct->moveTarget + gBattlerAttacker))) + && !gBattleStruct->battlerState[*(gBattleStruct->moveTarget + gBattlerAttacker)].pursuitTarget && (!IsBattleMoveStatus(gCurrentMove) || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS)) && ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) || (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) @@ -815,7 +815,7 @@ void HandleAction_ActionFinished(void) gBattleScripting.multihitMoveEffect = 0; gBattleResources->battleScriptsStack->size = 0; - if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !gBattleStruct->pursuitTarget) + if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !IsPursuitTargetSet()) { // i starts at `gCurrentTurnActionNumber` because we don't want to recalculate turn order for mon that have already // taken action. It's been previously increased, which we want in order to not recalculate the turn of the mon that just finished its action @@ -3280,7 +3280,7 @@ static void CancellerObedience(u32 *effect) break; case DISOBEYS_FALL_ASLEEP: if (IsSleepClauseEnabled()) - gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker); + gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE; gBattlescriptCurrInstr = BattleScript_IgnoresAndFallsAsleep; gBattleStruct->moveResultFlags[gBattlerTarget] |= MOVE_RESULT_MISSED; break; @@ -5244,7 +5244,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 SaveBattlerAttacker(gBattlerAttacker); gSpecialStatuses[battler].switchInAbilityDone = TRUE; gBattlerAttacker = partner; - gBattleStruct->commandingDondozo |= 1u << battler; + gBattleStruct->battlerState[battler].commandingDondozo = TRUE; gBattleStruct->commanderActive[partner] = gBattleMons[battler].species; gStatuses3[battler] |= STATUS3_COMMANDER; if (gBattleMons[battler].status2 & STATUS2_CONFUSION @@ -5930,7 +5930,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsMoveMakingContact(move, gBattlerAttacker)) { if (IsSleepClauseEnabled()) - gBattleStruct->sleepClauseEffectExempt |= (1u << gBattlerAttacker); + gBattleStruct->battlerState[gBattlerAttacker].sleepClauseEffectExempt = TRUE; gBattleScripting.moveEffect = MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_SLEEP; PREPARE_ABILITY_BUFFER(gBattleTextBuff1, gLastUsedAbility); BattleScriptPushCursor(); @@ -6556,7 +6556,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gDisableStructs[battler].weatherAbilityDone && (gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) - && !(gBattleStruct->boosterEnergyActivates & (1u << battler))) + && !gDisableStructs[battler].boosterEnergyActivates) { gDisableStructs[battler].weatherAbilityDone = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); @@ -6585,7 +6585,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (!gDisableStructs[battler].terrainAbilityDone && gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && !(gBattleMons[battler].status2 & STATUS2_TRANSFORMED) - && !(gBattleStruct->boosterEnergyActivates & (1u << battler))) + && !gDisableStructs[battler].boosterEnergyActivates) { gDisableStructs[battler].terrainAbilityDone = TRUE; PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); @@ -7046,7 +7046,7 @@ static u32 TrySetMicleBerry(u32 battler, u32 itemId, enum ItemEffect caseID) { if (HasEnoughHpToEatBerry(battler, 4, itemId)) { - gBattleStruct->usedMicleBerry |= 1u << battler; + gBattleStruct->battlerState[battler].usedMicleBerry = TRUE; if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) { BattleScriptExecute(BattleScript_MicleBerryActivateEnd2); @@ -7305,7 +7305,7 @@ static u32 TryConsumeMirrorHerb(u32 battler, enum ItemEffect caseID) static inline u32 TryBoosterEnergy(u32 battler, enum ItemEffect caseID) { - if (gBattleStruct->boosterEnergyActivates & (1u << battler) || gBattleMons[battler].status2 & STATUS2_TRANSFORMED) + if (gDisableStructs[battler].boosterEnergyActivates || gBattleMons[battler].status2 & STATUS2_TRANSFORMED) return ITEM_NO_EFFECT; if (((GetBattlerAbility(battler) == ABILITY_PROTOSYNTHESIS) && !((gBattleWeather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT)) @@ -7313,7 +7313,7 @@ static inline u32 TryBoosterEnergy(u32 battler, enum ItemEffect caseID) { PREPARE_STAT_BUFFER(gBattleTextBuff1, GetHighestStatId(battler)); gBattlerAbility = gBattleScripting.battler = battler; - gBattleStruct->boosterEnergyActivates |= 1u << battler; + gDisableStructs[battler].boosterEnergyActivates = TRUE; if (caseID == ITEMEFFECT_ON_SWITCH_IN_FIRST_TURN || caseID == ITEMEFFECT_NORMAL) { BattleScriptExecute(BattleScript_BoosterEnergyEnd2); @@ -9133,7 +9133,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData basePower *= 2; break; case EFFECT_PURSUIT: - if (gBattleStruct->pursuitTarget & (1u << battlerDef)) + if (gBattleStruct->battlerState[battlerDef].pursuitTarget) basePower *= 2; break; case EFFECT_NATURAL_GIFT: @@ -9362,7 +9362,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * modifier = uq4_12_multiply(modifier, UQ_4_12(0.5)); break; case EFFECT_STOMPING_TANTRUM: - if (gBattleStruct->lastMoveFailed & (1u << battlerAtk)) + if (gBattleStruct->battlerState[battlerAtk].lastMoveFailed) modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); break; case EFFECT_MAGNITUDE: @@ -9550,7 +9550,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * case ABILITY_PROTOSYNTHESIS: { u8 defHighestStat = GetHighestStatId(battlerDef); - if (((weather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gBattleStruct->boosterEnergyActivates & (1u << battlerDef)) + if (((weather & B_WEATHER_SUN && WEATHER_HAS_EFFECT) || gDisableStructs[battlerDef].boosterEnergyActivates) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); @@ -9559,7 +9559,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * case ABILITY_QUARK_DRIVE: { u8 defHighestStat = GetHighestStatId(battlerDef); - if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battlerDef)) + if ((gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerDef].boosterEnergyActivates) && ((IsBattleMovePhysical(move) && defHighestStat == STAT_DEF) || (IsBattleMoveSpecial(move) && defHighestStat == STAT_SPDEF)) && !(gBattleMons[battlerDef].status2 & STATUS2_TRANSFORMED)) modifier = uq4_12_multiply(modifier, UQ_4_12(0.7)); @@ -9829,7 +9829,7 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) { u32 atkHighestStat = GetHighestStatId(battlerAtk); - if (((weather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT) || gBattleStruct->boosterEnergyActivates & (1u << battlerAtk)) + if (((weather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT) || gDisableStructs[battlerAtk].boosterEnergyActivates) { if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); @@ -9840,7 +9840,7 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u if (!(gBattleMons[battlerAtk].status2 & STATUS2_TRANSFORMED)) { u32 atkHighestStat = GetHighestStatId(battlerAtk); - if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gBattleStruct->boosterEnergyActivates & (1u << battlerAtk)) + if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN || gDisableStructs[battlerAtk].boosterEnergyActivates) { if ((IsBattleMovePhysical(move) && atkHighestStat == STAT_ATK) || (IsBattleMoveSpecial(move) && atkHighestStat == STAT_SPATK)) modifier = uq4_12_multiply(modifier, UQ_4_12(1.3)); @@ -12147,9 +12147,9 @@ u32 GetBattleMoveType(u32 move) void TryActivateSleepClause(u32 battler, u32 indexInParty) { - if (gBattleStruct->sleepClauseEffectExempt & (1u << battler)) + if (gBattleStruct->battlerState[battler].sleepClauseEffectExempt) { - gBattleStruct->sleepClauseEffectExempt &= ~(1u << battler); + gBattleStruct->battlerState[battler].sleepClauseEffectExempt = FALSE; return; } @@ -12205,7 +12205,7 @@ bool32 DoesDestinyBondFail(u32 battler) { if (B_DESTINY_BOND_FAIL >= GEN_7 && GetMoveEffect(gLastResultingMoves[battler]) == EFFECT_DESTINY_BOND - && !(gBattleStruct->lastMoveFailed & (1u << battler))) + && !gBattleStruct->battlerState[battler].lastMoveFailed) return TRUE; return FALSE; } @@ -12243,3 +12243,27 @@ u32 NumAffectedSpreadMoveTargets(void) return targetCount; } + +bool32 IsPursuitTargetSet(void) +{ + for (u32 battler = 0; battler < gBattlersCount; battler++) + { + if (gBattleStruct->battlerState[battler].pursuitTarget) + return TRUE; + } + return FALSE; +} + +void ClearPursuitValues(void) +{ + for (u32 i = 0; i < gBattlersCount; i++) + gBattleStruct->battlerState[i].pursuitTarget = FALSE; + gBattleStruct->pursuitSwitchByMove = FALSE; + gBattleStruct->pursuitStoredSwitch = 0; +} + +void ClearPursuitValuesIfSet(u32 battler) +{ + if (gBattleStruct->battlerState[battler].pursuitTarget) + ClearPursuitValues(); +} From f15d89893ec2e955dad2d15b83548c9ca49245ee Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sat, 11 Jan 2025 12:14:31 +0100 Subject: [PATCH 55/85] Allow Party Menu with 0 Pokemon (#5997) --- include/constants/party_menu.h | 1 + src/data/party_menu.h | 1 + src/party_menu.c | 10 ++++++++-- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/include/constants/party_menu.h b/include/constants/party_menu.h index 1f37f3416c..e997dd566d 100644 --- a/include/constants/party_menu.h +++ b/include/constants/party_menu.h @@ -81,6 +81,7 @@ #define PARTY_MSG_ALREADY_HOLDING_ONE 26 #define PARTY_MSG_WHICH_APPLIANCE 27 #define PARTY_MSG_CHOOSE_SECOND_FUSION 28 +#define PARTY_MSG_NO_POKEMON 29 #define PARTY_MSG_NONE 127 // IDs for DisplayPartyPokemonDescriptionText, to display a message in the party pokemon's box diff --git a/src/data/party_menu.h b/src/data/party_menu.h index e6cb13ee6d..168387dbf4 100644 --- a/src/data/party_menu.h +++ b/src/data/party_menu.h @@ -659,6 +659,7 @@ static const u8 *const sActionStringTable[] = [PARTY_MSG_ALREADY_HOLDING_ONE] = gText_AlreadyHoldingOne, [PARTY_MSG_WHICH_APPLIANCE] = gText_WhichAppliance, [PARTY_MSG_CHOOSE_SECOND_FUSION] = gText_NextFusionMon, + [PARTY_MSG_NO_POKEMON] = COMPOUND_STRING("You have no POKéMON."), }; static const u8 *const sDescriptionStringTable[] = diff --git a/src/party_menu.c b/src/party_menu.c index af447ac990..bda62ba3d1 100644 --- a/src/party_menu.c +++ b/src/party_menu.c @@ -551,6 +551,9 @@ static void InitPartyMenu(u8 menuType, u8 layout, u8 partyAction, bool8 keepCurs else if (gPartyMenu.slotId > PARTY_SIZE - 1 || GetMonData(&gPlayerParty[gPartyMenu.slotId], MON_DATA_SPECIES) == SPECIES_NONE) gPartyMenu.slotId = 0; + if (gPlayerPartyCount == 0) + gPartyMenu.slotId = PARTY_SIZE + 1; // Cancel + gTextFlags.autoScroll = 0; CalculatePlayerPartyCount(); SetMainCallback2(CB2_InitPartyMenu); @@ -982,7 +985,7 @@ static void RenderPartyMenuBox(u8 slot) PutWindowTilemap(sPartyMenuBoxes[slot].windowId); ScheduleBgCopyTilemapToVram(2); } - else + else if (gPlayerPartyCount != 0) { if (GetMonData(&gPlayerParty[slot], MON_DATA_SPECIES) == SPECIES_NONE) { @@ -1656,7 +1659,7 @@ static u16 PartyMenuButtonHandler(s8 *slotPtr) if (JOY_NEW(START_BUTTON)) return START_BUTTON; - if (movementDir) + if (movementDir && gPlayerPartyCount != 0) { UpdateCurrentPartySelection(slotPtr, movementDir); return 0; @@ -2667,6 +2670,9 @@ void DisplayPartyMenuStdMessage(u32 stringId) stringId = PARTY_MSG_CHOOSE_MON_AND_CONFIRM; else if (!ShouldUseChooseMonText()) stringId = PARTY_MSG_CHOOSE_MON_OR_CANCEL; + + if (gPlayerPartyCount == 0) + stringId = PARTY_MSG_NO_POKEMON; } DrawStdFrameWithCustomTileAndPalette(*windowPtr, FALSE, 0x4F, 13); StringExpandPlaceholders(gStringVar4, sActionStringTable[stringId]); From bfa9d905e1bde63bc0d7f5f95891ec302567a7d6 Mon Sep 17 00:00:00 2001 From: DizzyEggg Date: Sat, 11 Jan 2025 13:30:11 +0100 Subject: [PATCH 56/85] Free some IWRAM (#6000) --- src/battle_anim_dragon.c | 5 ----- src/digit_obj_util.c | 6 +++--- src/ereader_screen.c | 3 --- src/link.c | 28 ---------------------------- src/pokedex_area_screen.c | 10 +++++----- 5 files changed, 8 insertions(+), 44 deletions(-) mode change 100755 => 100644 src/ereader_screen.c mode change 100755 => 100644 src/pokedex_area_screen.c diff --git a/src/battle_anim_dragon.c b/src/battle_anim_dragon.c index f3ee2a3818..55ecd5d0c1 100644 --- a/src/battle_anim_dragon.c +++ b/src/battle_anim_dragon.c @@ -14,8 +14,6 @@ static void AnimSpinningDracoMeteor(struct Sprite *sprite); static void AnimSpinningDracoMeteorFinish(struct Sprite *sprite); static void AnimDracoMeteorRock_Step(struct Sprite *sprite); -EWRAM_DATA static u16 sUnusedOverheatData[7] = {0}; - static const union AnimCmd sAnim_OutrageOverheatFire_0[] = { ANIMCMD_FRAME(0, 4), @@ -601,7 +599,6 @@ static void UpdateDragonDanceScanlineEffect(struct Task *task) void AnimOverheatFlame(struct Sprite *sprite) { - int i; int yAmplitude = (gBattleAnimArgs[2] * 3) / 5; sprite->x = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); sprite->y = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[4]; @@ -611,8 +608,6 @@ void AnimOverheatFlame(struct Sprite *sprite) sprite->y += sprite->data[2] * gBattleAnimArgs[0]; sprite->data[3] = gBattleAnimArgs[3]; sprite->callback = AnimOverheatFlame_Step; - for (i = 0; i < 7; i++) - sUnusedOverheatData[i] = sprite->data[i]; } static void AnimOverheatFlame_Step(struct Sprite *sprite) diff --git a/src/digit_obj_util.c b/src/digit_obj_util.c index f66dc80cb7..f9e3ed1c01 100644 --- a/src/digit_obj_util.c +++ b/src/digit_obj_util.c @@ -239,9 +239,9 @@ static void DrawNumObjsLeadingZeros(struct DigitPrinter *objWork, s32 num, bool3 static void DrawNumObjsMinusInFront(struct DigitPrinter *objWork, s32 num, bool32 sign) { u32 pow10 = objWork->pow10; - static int oamId; - static int curDigit; - static int firstDigit; + int oamId; + int curDigit; + int firstDigit; oamId = objWork->firstOamId; curDigit = 0; diff --git a/src/ereader_screen.c b/src/ereader_screen.c old mode 100755 new mode 100644 index 556acf8e3c..ef1f45d49a --- a/src/ereader_screen.c +++ b/src/ereader_screen.c @@ -40,9 +40,6 @@ struct EReaderData static void Task_EReader(u8); -// This belongs in COMMON somewhere between party_menu and ereader_screen, but it's unused so it's unclear where. -COMMON_DATA UNUSED u8 gUnknownSpace[64] = {0}; - COMMON_DATA struct EReaderData gEReaderData = {0}; extern const u8 gMultiBootProgram_EReader_Start[]; diff --git a/src/link.c b/src/link.c index ef928e8d62..501aacad2c 100644 --- a/src/link.c +++ b/src/link.c @@ -55,10 +55,7 @@ struct LinkTestBGInfo static struct BlockTransfer sBlockSend; static struct BlockTransfer sBlockRecv[MAX_LINK_PLAYERS]; static u32 sBlockSendDelayCounter; -static bool32 sDummy1; // Never read -static bool8 sDummy2; // Never assigned, read in unused function static u32 sPlayerDataExchangeStatus; -static bool32 sDummy3; // Never read static u8 sLinkTestLastBlockSendPos; static u8 sLinkTestLastBlockRecvPos[MAX_LINK_PLAYERS]; static u8 sNumVBlanksWithoutSerialIntr; @@ -73,15 +70,11 @@ COMMON_DATA u32 gLinkDebugSeed = 0; COMMON_DATA struct LinkPlayerBlock gLocalLinkPlayerBlock = {0}; COMMON_DATA bool8 gLinkErrorOccurred = 0; COMMON_DATA u32 gLinkDebugFlags = 0; -COMMON_DATA u32 gLinkFiller1 = 0; COMMON_DATA bool8 gRemoteLinkPlayersNotReceived[MAX_LINK_PLAYERS] = {0}; COMMON_DATA u8 gBlockReceivedStatus[MAX_LINK_PLAYERS] = {0}; -COMMON_DATA u32 gLinkFiller2 = 0; COMMON_DATA u16 gLinkHeldKeys = 0; COMMON_DATA u16 ALIGNED(4) gRecvCmds[MAX_RFU_PLAYERS][CMD_LENGTH] = {0}; COMMON_DATA u32 gLinkStatus = 0; -COMMON_DATA bool8 gLinkDummy1 = 0; // Never read -COMMON_DATA bool8 gLinkDummy2 = 0; // Never read COMMON_DATA bool8 gReadyToExitStandby[MAX_LINK_PLAYERS] = {0}; COMMON_DATA bool8 gReadyToCloseLink[MAX_LINK_PLAYERS] = {0}; COMMON_DATA u16 gReadyCloseLinkType = 0; // Never read @@ -96,9 +89,6 @@ COMMON_DATA void (*gLinkCallback)(void) = NULL; COMMON_DATA u8 gShouldAdvanceLinkState = 0; COMMON_DATA u16 gLinkTestBlockChecksums[MAX_LINK_PLAYERS] = {0}; COMMON_DATA u8 gBlockRequestType = 0; -COMMON_DATA u32 gLinkFiller3 = 0; -COMMON_DATA u32 gLinkFiller4 = 0; -COMMON_DATA u32 gLinkFiller5 = 0; COMMON_DATA u8 gLastSendQueueCount = 0; COMMON_DATA struct Link gLink = {0}; COMMON_DATA u8 gLastRecvQueueCount = 0; @@ -310,7 +300,6 @@ static void UNUSED LinkTestScreen(void) AnimateSprites(); BuildOamBuffer(); UpdatePaletteFade(); - sDummy3 = FALSE; InitLocalLinkPlayer(); CreateTask(Task_PrintTestData, 0); SetMainCallback2(CB2_LinkTest); @@ -378,9 +367,6 @@ void OpenLink(void) gSuppressLinkErrorMessage = FALSE; ResetBlockReceivedFlags(); ResetBlockSend(); - sDummy1 = FALSE; - gLinkDummy2 = FALSE; - gLinkDummy1 = FALSE; gReadyCloseLinkType = 0; CreateTask(Task_TriggerHandshake, 2); } @@ -552,10 +538,8 @@ static void ProcessRecvCmds(u8 unused) gLinkPartnersHeldKeys[i] = gRecvCmds[i][1]; break; case LINKCMD_DUMMY_1: - gLinkDummy2 = TRUE; break; case LINKCMD_DUMMY_2: - gLinkDummy2 = TRUE; break; case LINKCMD_INIT_BLOCK: { @@ -1376,11 +1360,6 @@ bool8 IsLinkMaster(void) return EXTRACT_MASTER(gLinkStatus); } -static u8 UNUSED GetDummy2(void) -{ - return sDummy2; -} - void SetCloseLinkCallbackAndType(u16 type) { if (gWirelessCommType == TRUE) @@ -1392,7 +1371,6 @@ void SetCloseLinkCallbackAndType(u16 type) if (gLinkCallback == NULL) { gLinkCallback = LinkCB_ReadyCloseLink; - gLinkDummy1 = FALSE; gReadyCloseLinkType = type; } } @@ -1413,7 +1391,6 @@ void SetCloseLinkCallback(void) else { gLinkCallback = LinkCB_ReadyCloseLink; - gLinkDummy1 = FALSE; gReadyCloseLinkType = 0; } } @@ -1449,7 +1426,6 @@ static void LinkCB_WaitCloseLink(void) gLinkVSyncDisabled = TRUE; CloseLink(); gLinkCallback = NULL; - gLinkDummy1 = TRUE; } } @@ -1469,7 +1445,6 @@ void SetCloseLinkCallbackHandleJP(void) else { gLinkCallback = LinkCB_ReadyCloseLinkWithJP; - gLinkDummy1 = FALSE; gReadyCloseLinkType = 0; } } @@ -1511,7 +1486,6 @@ static void LinkCB_WaitCloseLinkWithJP(void) gLinkVSyncDisabled = TRUE; CloseLink(); gLinkCallback = NULL; - gLinkDummy1 = TRUE; } } @@ -1525,8 +1499,6 @@ void SetLinkStandbyCallback(void) { if (gLinkCallback == NULL) gLinkCallback = LinkCB_Standby; - - gLinkDummy1 = FALSE; } } diff --git a/src/pokedex_area_screen.c b/src/pokedex_area_screen.c old mode 100755 new mode 100644 index a3bbafa926..dd45335afb --- a/src/pokedex_area_screen.c +++ b/src/pokedex_area_screen.c @@ -718,11 +718,11 @@ static void ResetPokedexAreaMapBg(void) static void CreateAreaMarkerSprites(void) { u8 spriteId; - static s16 x; - static s16 y; - static s16 i; - static s16 mapSecId; - static s16 numSprites; + s16 x; + s16 y; + s16 i; + s16 mapSecId; + s16 numSprites; LoadSpriteSheet(&sAreaMarkerSpriteSheet); LoadSpritePalette(&sAreaMarkerSpritePalette); From 8427d47ea5616410560be573f7280125e595c674 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sat, 11 Jan 2025 09:36:00 -0300 Subject: [PATCH 57/85] Fixed Gimmick tests failing when running first (#6001) --- test/battle/gimmick/dynamax.c | 2 -- test/test_runner_battle.c | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/test/battle/gimmick/dynamax.c b/test/battle/gimmick/dynamax.c index 0e3ae532bf..91773b01bc 100644 --- a/test/battle/gimmick/dynamax.c +++ b/test/battle/gimmick/dynamax.c @@ -458,7 +458,6 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Max Moves deal 1/4 damage through protect", s16 da } } -// This test will fail if it's the first test a thread runs SINGLE_BATTLE_TEST("(DYNAMAX) Max Moves don't bypass Max Guard") { GIVEN { @@ -1536,7 +1535,6 @@ SINGLE_BATTLE_TEST("(DYNAMAX) Moxie clones can be triggered by Max Moves faintin } } -// This test will fail if it's the first test a thread runs SINGLE_BATTLE_TEST("(DYNAMAX) Max Attacks prints a message when hitting into Max Guard") { GIVEN { diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index 9484e6df6c..5340ddb4c9 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -2117,7 +2117,7 @@ void MoveGetIdAndSlot(s32 battlerId, struct MoveContext *ctx, u32 *moveId, u32 * u32 item = GetMonData(mon, MON_DATA_HELD_ITEM); u32 holdEffect = ItemId_GetHoldEffect(item); u32 species = GetMonData(mon, MON_DATA_SPECIES); - u32 side = GetBattlerSide(battlerId); + u32 side = battlerId & BIT_SIDE; // Check invalid item usage. INVALID_IF(ctx->gimmick == GIMMICK_MEGA && holdEffect != HOLD_EFFECT_MEGA_STONE && species != SPECIES_RAYQUAZA, "Cannot Mega Evolve without a Mega Stone"); From 8f34c7639553fb90ae0aaad00fc88b2b8b392c04 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 11 Jan 2025 13:39:10 +0100 Subject: [PATCH 58/85] Removes Resource Flags and moves fields to DisableStruct (#5945) --- include/battle.h | 31 ++++++++++++------------------- src/battle_ai_main.c | 2 +- src/battle_main.c | 12 ++++-------- src/battle_script_commands.c | 27 ++++++++++++++------------- src/battle_util.c | 23 +++++++++++------------ src/battle_util2.c | 2 -- test/battle/ability/flash_fire.c | 28 ++++++++++++++++++++++++++++ 7 files changed, 70 insertions(+), 55 deletions(-) create mode 100644 test/battle/ability/flash_fire.c diff --git a/include/battle.h b/include/battle.h index 70ce4485de..cfe9b2f682 100644 --- a/include/battle.h +++ b/include/battle.h @@ -68,20 +68,6 @@ #define BATTLE_BUFFER_LINK_SIZE 0x1000 -struct ResourceFlags -{ - u32 flags[MAX_BATTLERS_COUNT]; -}; - -#define RESOURCE_FLAG_FLASH_FIRE 0x1 -#define RESOURCE_FLAG_ROOST 0x2 -#define RESOURCE_FLAG_UNBURDEN 0x4 -#define RESOURCE_FLAG_UNUSED 0x8 -#define RESOURCE_FLAG_UNUSED_2 0x10 -#define RESOURCE_FLAG_EMERGENCY_EXIT 0x20 -#define RESOURCE_FLAG_NEUTRALIZING_GAS 0x40 -#define RESOURCE_FLAG_ICE_FACE 0x80 - struct DisableStruct { u32 transformedMonPersonality; @@ -118,6 +104,7 @@ struct DisableStruct u8 laserFocusTimer; u8 throatChopTimer; u8 wrapTurns; + u8 syrupBombTimer; u8 tormentTimer:4; // used for G-Max Meltdown u8 usedMoves:4; u8 truantCounter:1; @@ -130,16 +117,23 @@ struct DisableStruct u8 toxicSpikesDone:1; u8 stickyWebDone:1; u8 stealthRockDone:1; - u8 syrupBombTimer; - u8 syrupBombIsShiny:1; - u8 steelSurgeDone:1; u8 weatherAbilityDone:1; u8 terrainAbilityDone:1; + u8 syrupBombIsShiny:1; + u8 steelSurgeDone:1; u8 usedProteanLibero:1; + u8 flashFireBoosted:1; u16 overwrittenAbility; // abilities overwritten during battle (keep separate from battle history in case of switching) u8 boosterEnergyActivates:1; + u8 roostActive:1; + u8 unbrudenActive:1; + u8 startEmergencyExit:1; + u8 neutralizingGas:1; + u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case + u8 padding:2; }; +// Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects struct ProtectStruct { u32 protected:1; @@ -193,9 +187,9 @@ struct ProtectStruct u32 specialDmg; u8 physicalBattlerId; u8 specialBattlerId; - }; +// Cleared at the start of HandleAction_ActionFinished struct SpecialStatus { s32 physicalDmg; @@ -416,7 +410,6 @@ struct StatsArray struct BattleResources { struct SecretBase* secretBase; - struct ResourceFlags *flags; struct BattleScriptsStack* battleScriptsStack; struct BattleCallbacksStack* battleCallbackStack; struct StatsArray* beforeLvlUp; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 1dc3867f21..0fefd71fbd 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2826,7 +2826,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case ABILITY_FLASH_FIRE: if (moveType == TYPE_FIRE && HasMoveWithType(battlerAtkPartner, TYPE_FIRE) - && !(gBattleResources->flags->flags[battlerAtkPartner] & RESOURCE_FLAG_FLASH_FIRE)) + && !gDisableStructs[battlerAtkPartner].flashFireBoosted) { RETURN_SCORE_PLUS(WEAK_EFFECT); } diff --git a/src/battle_main.c b/src/battle_main.c index e0072829e0..5dba22a160 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3049,7 +3049,6 @@ static void BattleStartClearSetData(void) gLastHitBy[i] = 0xFF; gLockedMoves[i] = MOVE_NONE; gLastPrintedMoves[i] = MOVE_NONE; - gBattleResources->flags->flags[i] = 0; gPalaceSelectionBattleScripts[i] = 0; gBattleStruct->lastTakenMove[i] = MOVE_NONE; gBattleStruct->choicedMove[i] = MOVE_NONE; @@ -3263,7 +3262,6 @@ void SwitchInClearSetData(u32 battler) } gBattleStruct->choicedMove[battler] = MOVE_NONE; - gBattleResources->flags->flags[battler] = 0; gCurrentMove = MOVE_NONE; gBattleStruct->arenaTurnCounter = 0xFF; @@ -3404,8 +3402,6 @@ const u8* FaintClearSetData(u32 battler) gBattleStruct->lastTakenMoveFrom[i][battler] = 0; } - gBattleResources->flags->flags[battler] = 0; - gBattleMons[battler].types[0] = gSpeciesInfo[gBattleMons[battler].species].types[0]; gBattleMons[battler].types[1] = gSpeciesInfo[gBattleMons[battler].species].types[1]; gBattleMons[battler].types[2] = TYPE_MYSTERY; @@ -4818,7 +4814,7 @@ u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect) // various effects if (gSideStatuses[GetBattlerSide(battler)] & SIDE_STATUS_TAILWIND) speed *= 2; - if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_UNBURDEN) + if (gDisableStructs[battler].unbrudenActive) speed *= 2; // paralysis drop @@ -5972,11 +5968,11 @@ u32 GetDynamicMoveType(struct Pokemon *mon, u32 move, u32 battler, u8 *ateBoost) u32 teraType; if (GetActiveGimmick(battler) == GIMMICK_TERA && ((teraType = GetMonData(mon, MON_DATA_TERA_TYPE)) != TYPE_STELLAR)) return teraType; - else if (type1 != TYPE_MYSTERY && !(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST && type1 == TYPE_FLYING)) + else if (type1 != TYPE_MYSTERY && !(gDisableStructs[battler].roostActive && type1 == TYPE_FLYING)) return type1; - else if (type2 != TYPE_MYSTERY && !(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST && type2 == TYPE_FLYING)) + else if (type2 != TYPE_MYSTERY && !(gDisableStructs[battler].roostActive && type2 == TYPE_FLYING)) return type2; - else if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST) + else if (gDisableStructs[battler].roostActive) return (B_ROOST_PURE_FLYING >= GEN_5 ? TYPE_NORMAL : TYPE_MYSTERY); else if (type3 != TYPE_MYSTERY) return type3; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 22252fdec3..529d00d507 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2137,7 +2137,7 @@ static void Cmd_adjustdamage(void) gBattleStruct->moveResultFlags[battlerDef] &= ~(MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_NOT_VERY_EFFECTIVE); gBattleStruct->moveDamage[battlerDef] = 0; RecordAbilityBattle(gBattlerTarget, ABILITY_ICE_FACE); - gBattleResources->flags->flags[battlerDef] |= RESOURCE_FLAG_ICE_FACE; + gDisableStructs[battlerDef].iceFaceActivationPrevention = TRUE; // Form change will be done after attack animation in Cmd_resultmessage. continue; } @@ -2807,9 +2807,9 @@ static void Cmd_resultmessage(void) // TODO: Convert this to a proper FORM_CHANGE type. // Do Ice Face form change which was set up in Cmd_adjustdamage. - if (gBattleResources->flags->flags[gBattlerTarget] & RESOURCE_FLAG_ICE_FACE) + if (gDisableStructs[gBattlerTarget].iceFaceActivationPrevention) { - gBattleResources->flags->flags[gBattlerTarget] &= ~(RESOURCE_FLAG_ICE_FACE); + gDisableStructs[gBattlerTarget].iceFaceActivationPrevention = FALSE; gBattleMons[gBattlerTarget].species = SPECIES_EISCUE_NOICE; gBattleScripting.battler = gBattlerTarget; // For STRINGID_PKMNTRANSFORMED BattleScriptPushCursor(); @@ -3062,7 +3062,7 @@ static void CheckSetUnburden(u8 battler) { if (GetBattlerAbility(battler) == ABILITY_UNBURDEN) { - gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_UNBURDEN; + gDisableStructs[battler].unbrudenActive = TRUE; RecordAbilityBattle(battler, ABILITY_UNBURDEN); } } @@ -3084,7 +3084,8 @@ void StealTargetItem(u8 battlerStealer, u8 battlerItem) { RecordItemEffectBattle(battlerStealer, ItemId_GetHoldEffect(gLastUsedItem)); gBattleMons[battlerStealer].item = gLastUsedItem; - gBattleResources->flags->flags[battlerStealer] &= ~RESOURCE_FLAG_UNBURDEN; + + gDisableStructs[battlerStealer].unbrudenActive = FALSE; BtlController_EmitSetMonData(battlerStealer, BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gLastUsedItem), &gLastUsedItem); // set attacker item MarkBattlerForControllerExec(battlerStealer); } @@ -5586,7 +5587,7 @@ static void Cmd_setroost(void) { CMD_ARGS(); - gBattleResources->flags->flags[gBattlerAttacker] |= RESOURCE_FLAG_ROOST; + gDisableStructs[gBattlerAttacker].roostActive = TRUE; gBattleStruct->roostTypes[gBattlerAttacker][0] = gBattleMons[gBattlerAttacker].types[0]; gBattleStruct->roostTypes[gBattlerAttacker][1] = gBattleMons[gBattlerAttacker].types[1]; @@ -6714,7 +6715,7 @@ static void Cmd_moveend(void) } else // Eject Pack { - if (!(gBattleResources->flags->flags[gBattlerTarget] & RESOURCE_FLAG_EMERGENCY_EXIT) + if (!gDisableStructs[gBattlerTarget].startEmergencyExit && !(gMovesInfo[gCurrentMove].effect == EFFECT_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) { effect = TRUE; @@ -6892,12 +6893,12 @@ static void Cmd_moveend(void) { if (gBattleStruct->redCardActivates) { - gBattleResources->flags->flags[i] &= ~RESOURCE_FLAG_EMERGENCY_EXIT; + gDisableStructs[i].startEmergencyExit = FALSE; continue; } - if (gBattleResources->flags->flags[i] & RESOURCE_FLAG_EMERGENCY_EXIT) + if (gDisableStructs[i].startEmergencyExit) { - gBattleResources->flags->flags[i] &= ~RESOURCE_FLAG_EMERGENCY_EXIT; + gDisableStructs[i].startEmergencyExit = FALSE; gSpecialStatuses[i].emergencyExited = TRUE; gBattlerTarget = gBattlerAbility = i; BattleScriptPushCursor(); @@ -8610,7 +8611,7 @@ static void BestowItem(u32 battlerAtk, u32 battlerDef) gBattleMons[battlerDef].item = gLastUsedItem; BtlController_EmitSetMonData(battlerDef, BUFFER_A, REQUEST_HELDITEM_BATTLE, 0, sizeof(gBattleMons[battlerDef].item), &gBattleMons[battlerDef].item); MarkBattlerForControllerExec(battlerDef); - gBattleResources->flags->flags[battlerDef] &= ~RESOURCE_FLAG_UNBURDEN; + gDisableStructs[battlerDef].unbrudenActive = FALSE; } // Called by Cmd_removeitem. itemId represents the item that was removed, not being given. @@ -14665,8 +14666,8 @@ static void Cmd_tryswapitems(void) } else if (oldItemAtk == ITEM_NONE && *newItemAtk != ITEM_NONE) { - if (GetBattlerAbility(gBattlerAttacker) == ABILITY_UNBURDEN && gBattleResources->flags->flags[gBattlerAttacker] & RESOURCE_FLAG_UNBURDEN) - gBattleResources->flags->flags[gBattlerAttacker] &= ~RESOURCE_FLAG_UNBURDEN; + if (GetBattlerAbility(gBattlerAttacker) == ABILITY_UNBURDEN && gDisableStructs[gBattlerAttacker].unbrudenActive) + gDisableStructs[gBattlerAttacker].unbrudenActive = FALSE; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_ITEM_SWAP_TAKEN; // nothing -> <- target's item } diff --git a/src/battle_util.c b/src/battle_util.c index 9d6ae548ec..d9c72e7d8e 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2782,8 +2782,8 @@ u8 DoBattlerEndTurnEffects(void) gBattleStruct->turnEffectsTracker++; break; case ENDTURN_ROOST: // Return flying type. - if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST) - gBattleResources->flags->flags[battler] &= ~RESOURCE_FLAG_ROOST; + if (gDisableStructs[battler].roostActive) + gDisableStructs[battler].roostActive = FALSE; gBattleStruct->turnEffectsTracker++; break; case ENDTURN_ELECTRIFY: @@ -5590,14 +5590,14 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case MOVE_ABSORBED_BY_BOOST_FLASH_FIRE: gBattleStruct->pledgeMove = FALSE; - if (!(gBattleResources->flags->flags[battler] & RESOURCE_FLAG_FLASH_FIRE)) + if (!gDisableStructs[battler].flashFireBoosted) { gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_FLASH_FIRE_BOOST; if (gProtectStructs[gBattlerAttacker].notFirstStrike) gBattlescriptCurrInstr = BattleScript_FlashFireBoost; else gBattlescriptCurrInstr = BattleScript_FlashFireBoost_PPLoss; - gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_FLASH_FIRE; + gDisableStructs[battler].flashFireBoosted = TRUE; } else { @@ -5704,7 +5704,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 // Not currently held by Sky Drop && !(gStatuses3[battler] & STATUS3_SKY_DROPPED)) { - gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_EMERGENCY_EXIT; + gDisableStructs[battler].startEmergencyExit = TRUE; effect++; } break; @@ -6489,9 +6489,9 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 // Prints message only. separate from ABILITYEFFECT_ON_SWITCHIN bc activates before entry hazards for (i = 0; i < gBattlersCount; i++) { - if (gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !(gBattleResources->flags->flags[i] & RESOURCE_FLAG_NEUTRALIZING_GAS)) + if (gBattleMons[i].ability == ABILITY_NEUTRALIZING_GAS && !gDisableStructs[i].neutralizingGas) { - gBattleResources->flags->flags[i] |= RESOURCE_FLAG_NEUTRALIZING_GAS; + gDisableStructs[i].neutralizingGas = TRUE; gBattlerAbility = i; gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_SWITCHIN_NEUTRALIZING_GAS; BattleScriptPushCursorAndCallback(BattleScript_SwitchInAbilityMsg); @@ -7223,9 +7223,8 @@ static u32 ItemHealHp(u32 battler, u32 itemId, enum ItemEffect caseID, bool32 pe BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_ItemHealHP_RemoveItemRet; } - if (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_EMERGENCY_EXIT - && GetNonDynamaxHP(battler) >= GetNonDynamaxMaxHP(battler) / 2) - gBattleResources->flags->flags[battler] &= ~RESOURCE_FLAG_EMERGENCY_EXIT; + if (gDisableStructs[battler].startEmergencyExit && GetNonDynamaxHP(battler) >= GetNonDynamaxMaxHP(battler) / 2) + gDisableStructs[battler].startEmergencyExit = FALSE; return ITEM_HP_CHANGE; } @@ -9768,7 +9767,7 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(0.5)); break; case ABILITY_FLASH_FIRE: - if (moveType == TYPE_FIRE && gBattleResources->flags->flags[battlerAtk] & RESOURCE_FLAG_FLASH_FIRE) + if (moveType == TYPE_FIRE && gDisableStructs[battlerAtk].flashFireBoosted) modifier = uq4_12_multiply_half_down(modifier, UQ_4_12(1.5)); break; case ABILITY_SWARM: @@ -12065,7 +12064,7 @@ void GetBattlerTypes(u32 battler, bool32 ignoreTera, u32 types[static 3]) types[2] = gBattleMons[battler].types[2]; // Roost. - if (!isTera && (gBattleResources->flags->flags[battler] & RESOURCE_FLAG_ROOST)) + if (!isTera && gDisableStructs[battler].roostActive) { if (types[0] == TYPE_FLYING && types[1] == TYPE_FLYING) types[0] = types[1] = B_ROOST_PURE_FLYING >= GEN_5 ? TYPE_NORMAL : TYPE_MYSTERY; diff --git a/src/battle_util2.c b/src/battle_util2.c index 326acf0e40..6c2d0ff0a9 100644 --- a/src/battle_util2.c +++ b/src/battle_util2.c @@ -25,7 +25,6 @@ void AllocateBattleResources(void) gBattleResources = AllocZeroed(sizeof(*gBattleResources)); gBattleResources->secretBase = AllocZeroed(sizeof(*gBattleResources->secretBase)); - gBattleResources->flags = AllocZeroed(sizeof(*gBattleResources->flags)); gBattleResources->battleScriptsStack = AllocZeroed(sizeof(*gBattleResources->battleScriptsStack)); gBattleResources->battleCallbackStack = AllocZeroed(sizeof(*gBattleResources->battleCallbackStack)); gBattleResources->beforeLvlUp = AllocZeroed(sizeof(*gBattleResources->beforeLvlUp)); @@ -58,7 +57,6 @@ void FreeBattleResources(void) FREE_AND_SET_NULL(gBattleStruct); FREE_AND_SET_NULL(gBattleResources->secretBase); - FREE_AND_SET_NULL(gBattleResources->flags); FREE_AND_SET_NULL(gBattleResources->battleScriptsStack); FREE_AND_SET_NULL(gBattleResources->battleCallbackStack); FREE_AND_SET_NULL(gBattleResources->beforeLvlUp); diff --git a/test/battle/ability/flash_fire.c b/test/battle/ability/flash_fire.c new file mode 100644 index 0000000000..c81967d1af --- /dev/null +++ b/test/battle/ability/flash_fire.c @@ -0,0 +1,28 @@ +#include "global.h" +#include "test/battle.h" + +SINGLE_BATTLE_TEST("Flash Fire boosts fire type moves by 50% but no subsequent increase is applied") +{ + s16 damage[3]; + + GIVEN { + PLAYER(SPECIES_HEATRAN) { Ability(ABILITY_FLASH_FIRE); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_EMBER); MOVE(opponent, MOVE_EMBER); } + TURN { MOVE(player, MOVE_EMBER); MOVE(opponent, MOVE_EMBER); } + TURN { MOVE(player, MOVE_EMBER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); + HP_BAR(opponent, captureDamage: &damage[0]); + ABILITY_POPUP(player, ABILITY_FLASH_FIRE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); + HP_BAR(opponent, captureDamage: &damage[1]); + ABILITY_POPUP(player, ABILITY_FLASH_FIRE); + ANIMATION(ANIM_TYPE_MOVE, MOVE_EMBER, player); + HP_BAR(opponent, captureDamage: &damage[2]); + } THEN { + EXPECT_MUL_EQ(damage[0], UQ_4_12(1.5), damage[1]); + EXPECT_EQ(damage[1], damage[2]); + } +} From 7f2b76d59735d906804da5fbc91b2f75d21af89e Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Sat, 11 Jan 2025 14:29:51 +0000 Subject: [PATCH 59/85] Fix Makefile rules so that test.elf builds in build/test (#6004) --- Makefile | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 011fdaa957..a3a6d82acb 100644 --- a/Makefile +++ b/Makefile @@ -29,9 +29,6 @@ endif ifeq (debug,$(MAKECMDGOALS)) DEBUG := 1 endif -ifeq ($(TESTELF),$(MAKECMDGOALS)) - TEST := 1 -endif # Default make rule all: rom @@ -75,6 +72,9 @@ HEADLESSELF = $(ROM_NAME:.gba=-test-headless.elf) # Pick our active variables ROM := $(ROM_NAME) +ifeq ($(TESTELF),$(MAKECMDGOALS)) + TEST := 1 +endif ifeq ($(TEST), 0) OBJ_DIR := $(OBJ_DIR_NAME) else @@ -83,9 +83,6 @@ endif ifeq ($(DEBUG),1) OBJ_DIR := $(OBJ_DIR_NAME_DEBUG) endif -ifeq ($(TESTELF),$(MAKECMDGOALS)) - TEST := 1 -endif ELF := $(ROM:.gba=.elf) MAP := $(ROM:.gba=.map) SYM := $(ROM:.gba=.sym) @@ -180,7 +177,7 @@ MAKEFLAGS += --no-print-directory # Delete files that weren't built properly .DELETE_ON_ERROR: -RULES_NO_SCAN += libagbsyscall clean clean-assets tidy tidymodern tidycheck generated clean-generated $(TESTELF) +RULES_NO_SCAN += libagbsyscall clean clean-assets tidy tidymodern tidycheck generated clean-generated .PHONY: all rom agbcc modern compare check debug .PHONY: $(RULES_NO_SCAN) From 846734e894b3b48ae46886ebecdde1636de8abc6 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 11 Jan 2025 21:53:15 +0100 Subject: [PATCH 60/85] Ported Makefile fix from upcoming (#6007) Co-authored-by: Hedara --- Makefile | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/Makefile b/Makefile index 0d2ef1d240..5f806e45ec 100644 --- a/Makefile +++ b/Makefile @@ -29,9 +29,6 @@ endif ifeq (debug,$(MAKECMDGOALS)) DEBUG := 1 endif -ifeq ($(TESTELF),$(MAKECMDGOALS)) - TEST := 1 -endif # Default make rule all: rom @@ -75,6 +72,9 @@ HEADLESSELF = $(ROM_NAME:.gba=-test-headless.elf) # Pick our active variables ROM := $(ROM_NAME) +ifeq ($(TESTELF),$(MAKECMDGOALS)) + TEST := 1 +endif ifeq ($(TEST), 0) OBJ_DIR := $(OBJ_DIR_NAME) else @@ -83,9 +83,6 @@ endif ifeq ($(DEBUG),1) OBJ_DIR := $(OBJ_DIR_NAME_DEBUG) endif -ifeq ($(TESTELF),$(MAKECMDGOALS)) - TEST := 1 -endif ELF := $(ROM:.gba=.elf) MAP := $(ROM:.gba=.map) SYM := $(ROM:.gba=.sym) @@ -180,7 +177,7 @@ MAKEFLAGS += --no-print-directory # Delete files that weren't built properly .DELETE_ON_ERROR: -RULES_NO_SCAN += libagbsyscall clean clean-assets tidy tidymodern tidycheck generated clean-generated $(TESTELF) +RULES_NO_SCAN += libagbsyscall clean clean-assets tidy tidymodern tidycheck generated clean-generated .PHONY: all rom agbcc modern compare check debug .PHONY: $(RULES_NO_SCAN) From 10a3ed204464cd2c7f2ae3c7ac2f286c5b86f7cc Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 12 Jan 2025 00:25:17 +0100 Subject: [PATCH 61/85] Use gCurrentMove instead of checking FF move (#5999) --- src/battle_util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/battle_util.c b/src/battle_util.c index 8d87bcccf5..7fdca00026 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5804,7 +5804,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker)) { //special Future Sight handling - if (gMovesInfo[gWishFutureKnock.futureSightMove[battler]].effect == EFFECT_FUTURE_SIGHT) + if (gMovesInfo[gCurrentMove].effect == EFFECT_FUTURE_SIGHT) { //no Innards Out effect if Future Sight user is currently not on field if (gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == gBattlerPartyIndexes[gBattlerAttacker] From ddef67bbb1f414e74a97acd9ce215d6424cff9c5 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 12 Jan 2025 00:25:50 +0100 Subject: [PATCH 62/85] Future Sight Innards Out follow up for upcoming (#5998) --- include/battle.h | 1 - src/battle_script_commands.c | 4 ---- src/battle_util.c | 29 ++++++++++------------------- 3 files changed, 10 insertions(+), 24 deletions(-) diff --git a/include/battle.h b/include/battle.h index cfe9b2f682..d6b5abb7f9 100644 --- a/include/battle.h +++ b/include/battle.h @@ -291,7 +291,6 @@ struct WishFutureKnock u8 wishPartyId[MAX_BATTLERS_COUNT]; u8 weatherDuration; u8 knockedOffMons[NUM_BATTLE_SIDES]; // Each battler is represented by a bit. - s16 futureSightDmg; }; struct AI_SavedBattleMon diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 529d00d507..f5aef7a2c1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2647,9 +2647,6 @@ static void Cmd_datahpupdate(void) u32 effect = GetMoveEffect(gCurrentMove); - // Record damage for foreseen moves - gWishFutureKnock.futureSightDmg = gBattleStruct->moveDamage[battler]; - // Note: While physicalDmg/specialDmg below are only distinguished between for Counter/Mirror Coat, they are // used in combination as general damage trackers for other purposes. specialDmg is additionally used // to help determine if a fire move should defrost the target. @@ -14241,7 +14238,6 @@ static void Cmd_trysetfutureattack(void) gWishFutureKnock.futureSightBattlerIndex[gBattlerTarget] = gBattlerAttacker; gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] = gBattlerPartyIndexes[gBattlerAttacker]; gWishFutureKnock.futureSightCounter[gBattlerTarget] = 3; - gWishFutureKnock.futureSightDmg = 0; if (gCurrentMove == MOVE_DOOM_DESIRE) gBattleCommunication[MULTISTRING_CHOOSER] = B_MSG_DOOM_DESIRE; diff --git a/src/battle_util.c b/src/battle_util.c index d9c72e7d8e..818c22a424 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -5887,27 +5887,18 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !IsBattlerAlive(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker)) { - //special Future Sight handling - if (gMovesInfo[gWishFutureKnock.futureSightMove[battler]].effect == EFFECT_FUTURE_SIGHT) + // Prevent Innards Out effect if Future Sight user is currently not on field + if (GetMoveEffect(gCurrentMove) == EFFECT_FUTURE_SIGHT) { - //no Innards Out effect if Future Sight user is currently not on field - if (gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == gBattlerPartyIndexes[gBattlerAttacker] - || gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] == BATTLE_PARTNER(gBattlerPartyIndexes[gBattlerAttacker])) - { - gBattleStruct->moveDamage[gBattlerAttacker] = gWishFutureKnock.futureSightDmg; - gWishFutureKnock.futureSightDmg = 0; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_AftermathDmg; - effect++; - } - } - else - { - gBattleStruct->moveDamage[gBattlerAttacker] = gBattleStruct->moveDamage[gBattlerTarget]; - BattleScriptPushCursor(); - gBattlescriptCurrInstr = BattleScript_AftermathDmg; - effect++; + if (gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] != gBattlerPartyIndexes[gBattlerAttacker] + && gWishFutureKnock.futureSightPartyIndex[gBattlerTarget] != BATTLE_PARTNER(gBattlerPartyIndexes[gBattlerAttacker])) + break; } + + gBattleStruct->moveDamage[gBattlerAttacker] = gBattleStruct->moveDamage[gBattlerTarget]; + BattleScriptPushCursor(); + gBattlescriptCurrInstr = BattleScript_AftermathDmg; + effect++; } break; case ABILITY_EFFECT_SPORE: From 2da547908ef5aeb99b6d6e88b4aeaa74428bd5a2 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 12 Jan 2025 00:27:31 +0100 Subject: [PATCH 63/85] Fixes Shell Bell inlcuding heal amount from Future Sight when triggered (#5962) --- src/battle_script_commands.c | 4 +++- test/battle/hold_effect/shell_bell.c | 26 ++++++++++++++++++++++++++ 2 files changed, 29 insertions(+), 1 deletion(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 81891831f4..3f49153c7f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2456,7 +2456,9 @@ static void Cmd_datahpupdate(void) } // Record damage for Shell Bell - if (gSpecialStatuses[battler].shellBellDmg == 0 && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE)) + if (gSpecialStatuses[gBattlerTarget].shellBellDmg == IGNORE_SHELL_BELL) + gSpecialStatuses[battler].shellBellDmg = 0; + else if (gSpecialStatuses[battler].shellBellDmg == 0 && !(gHitMarker & HITMARKER_PASSIVE_DAMAGE)) gSpecialStatuses[battler].shellBellDmg = gHpDealt; // Record damage for foreseen moves diff --git a/test/battle/hold_effect/shell_bell.c b/test/battle/hold_effect/shell_bell.c index 9cac6831d9..92625b182a 100644 --- a/test/battle/hold_effect/shell_bell.c +++ b/test/battle/hold_effect/shell_bell.c @@ -34,3 +34,29 @@ SINGLE_BATTLE_TEST("Shell Bell doesn't restore HP for damage dealt by a foreseen } } } + +SINGLE_BATTLE_TEST("Shell Bell does not activate on Future Sight if the original user is on the field") +{ + s16 damage = 0; + s16 healed = 0; + + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); Item(ITEM_SHELL_BELL); } + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, MOVE_FUTURE_SIGHT); } + TURN {} + TURN {} + TURN { MOVE(player, MOVE_DRAGON_RAGE); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FUTURE_SIGHT, player); + MESSAGE("The opposing Wynaut took the Future Sight attack!"); + HP_BAR(opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAGON_RAGE, player); + HP_BAR(opponent, captureDamage: &damage); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player); + HP_BAR(player, captureDamage: &healed); + } THEN { + EXPECT_MUL_EQ(damage, Q_4_12(-0.25), healed); + } +} From 9e8ab3d891ac6919b3177af62ffefadab54bb947 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 12 Jan 2025 00:59:12 +0100 Subject: [PATCH 64/85] Fixes Tera giving boost to dynamic bp moves (#6008) --- src/battle_util.c | 8 ++++++-- test/battle/gimmick/terastal.c | 19 +++++++++++++++++++ 2 files changed, 25 insertions(+), 2 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 7fdca00026..2c53b2282d 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -9244,13 +9244,14 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * u32 battlerDef = damageCalcData->battlerDef; u32 move = damageCalcData->move; u32 moveType = damageCalcData->moveType; + u32 moveEffect = gMovesInfo[move].effect; uq4_12_t holdEffectModifier; uq4_12_t modifier = UQ_4_12(1.0); u32 atkSide = GetBattlerSide(battlerAtk); // move effect - switch (gMovesInfo[move].effect) + switch (moveEffect) { case EFFECT_FACADE: if (gBattleMons[battlerAtk].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_PARALYSIS | STATUS1_FROSTBITE)) @@ -9556,8 +9557,11 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * && (moveType == GetBattlerTeraType(battlerAtk) || (GetBattlerTeraType(battlerAtk) == TYPE_STELLAR && IsTypeStellarBoosted(battlerAtk, moveType))) && uq4_12_multiply_by_int_half_down(modifier, basePower) < 60 + && gMovesInfo[move].power > 1 && gMovesInfo[move].strikeCount < 2 - && gMovesInfo[move].effect != EFFECT_MULTI_HIT + && moveEffect != EFFECT_POWER_BASED_ON_USER_HP + && moveEffect != EFFECT_POWER_BASED_ON_TARGET_HP + && moveEffect != EFFECT_MULTI_HIT && gMovesInfo[move].priority == 0) { return 60; diff --git a/test/battle/gimmick/terastal.c b/test/battle/gimmick/terastal.c index a9e8fca871..42c495829d 100644 --- a/test/battle/gimmick/terastal.c +++ b/test/battle/gimmick/terastal.c @@ -186,6 +186,25 @@ SINGLE_BATTLE_TEST("(TERA) Terastallization's 60 BP floor does not apply to prio } } +SINGLE_BATTLE_TEST("(TERA) Terastallization's 60 BP floor does not apply to dynamic base power moves", s16 damage) +{ + bool32 tera; + PARAMETRIZE { tera = GIMMICK_NONE; } + PARAMETRIZE { tera = GIMMICK_TERA; } + GIVEN { + ASSUME(gMovesInfo[MOVE_WATER_SPOUT].effect == EFFECT_POWER_BASED_ON_USER_HP); + PLAYER(SPECIES_WOBBUFFET) { HP(1); TeraType(TYPE_WATER); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_WATER_SPOUT, gimmick: tera); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_WATER_SPOUT, player); + HP_BAR(opponent, captureDamage: &results[i].damage); + } FINALLY { + EXPECT_EQ(results[0].damage, results[1].damage); + } +} + // Defensive Type Checks SINGLE_BATTLE_TEST("(TERA) Terastallization changes type effectiveness", s16 damage) From 28561bca4a4c8e4efa3416a444a73956350f2764 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 12 Jan 2025 00:59:57 +0100 Subject: [PATCH 65/85] Fixes zmove trigger sprite on b button exit (#6009) --- src/battle_controller_player.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index e56207507b..fcadd22dc7 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -776,6 +776,7 @@ void HandleInputChooseMove(u32 battler) if (gBattleStruct->zmove.viewing) { ReloadMoveNames(battler); + ChangeGimmickTriggerSprite(gBattleStruct->gimmick.triggerSpriteId, gBattleStruct->gimmick.playerSelect); } else { From 15a034a1d942594f6bf4bcc0b2b38394e9a9ce58 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Sun, 12 Jan 2025 05:49:19 -0300 Subject: [PATCH 66/85] Fixed multiple transform/form change graphical issues (#6005) --- asm/macros/battle_script.inc | 3 +- data/battle_scripts_1.s | 24 ++++---- data/battle_scripts_2.s | 2 +- include/battle_controllers.h | 4 +- include/battle_gfx_sfx_util.h | 2 +- include/pokemon.h | 1 + src/battle_anim_mons.c | 50 ++++++---------- src/battle_controllers.c | 20 +++---- src/battle_gfx_sfx_util.c | 104 +++++++++++++++++----------------- src/battle_script_commands.c | 4 +- src/pokemon.c | 10 ++-- 11 files changed, 107 insertions(+), 117 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index fbc724a81e..dbab37af2c 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -478,9 +478,10 @@ .byte \battler .endm - .macro switchinanim battler:req, dontClearSubstitute:req + .macro switchinanim battler:req, dontClearTransform:req, dontClearSubstitute:req .byte 0x4e .byte \battler + .byte \dontClearTransform .byte \dontClearSubstitute .endm diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index bc2f4dea3c..0cd20c7543 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -322,7 +322,7 @@ BattleScript_MoveSwitchOpenPartyScreen: printstring STRINGID_EMPTYSTRING3 waitmessage 1 printstring STRINGID_SWITCHINMON - switchinanim BS_ATTACKER, TRUE + switchinanim BS_ATTACKER, FALSE, TRUE waitstate switchineffects BS_ATTACKER BattleScript_MoveSwitchEnd: @@ -469,7 +469,7 @@ BattleScript_EffectRevivalBlessingSendOut: getswitchedmondata BS_SCRIPTING switchindataupdate BS_SCRIPTING hpthresholds BS_SCRIPTING - switchinanim BS_SCRIPTING, FALSE + switchinanim BS_SCRIPTING, FALSE, FALSE waitstate switchineffects BS_SCRIPTING goto BattleScript_MoveEnd @@ -2390,7 +2390,7 @@ BattleScript_EffectHealingWish:: trytoclearprimalweather flushtextbox printstring STRINGID_SWITCHINMON - switchinanim BS_ATTACKER, TRUE + switchinanim BS_ATTACKER, FALSE, TRUE waitstate switchineffects BS_ATTACKER .endif @@ -4386,7 +4386,7 @@ BattleScript_EffectBatonPass:: trytoclearprimalweather flushtextbox printstring STRINGID_SWITCHINMON - switchinanim BS_ATTACKER, TRUE + switchinanim BS_ATTACKER, FALSE, TRUE waitstate switchineffects BS_ATTACKER goto BattleScript_MoveEnd @@ -5492,7 +5492,7 @@ BattleScript_FaintedMonTryChoose: flushtextbox printstring STRINGID_SWITCHINMON hidepartystatussummary BS_ATTACKER - switchinanim BS_ATTACKER, 0 + switchinanim BS_ATTACKER, FALSE, FALSE waitstate setbyte sSHIFT_SWITCHED, 1 BattleScript_FaintedMonSendOutNew: @@ -5504,7 +5504,7 @@ BattleScript_FaintedMonSendOutNew: flushtextbox printstring STRINGID_SWITCHINMON hidepartystatussummary BS_FAINTED - switchinanim BS_FAINTED, FALSE + switchinanim BS_FAINTED, FALSE, FALSE waitstate resetplayerfainted trytrainerslidelastonmsg BS_FAINTED @@ -5538,7 +5538,7 @@ BattleScript_HandleFaintedMonLoop:: flushtextbox printstring STRINGID_SWITCHINMON hidepartystatussummary BS_FAINTED - switchinanim BS_FAINTED, FALSE + switchinanim BS_FAINTED, FALSE, FALSE waitstate switchineffects BS_FAINTED_MULTIPLE_1 jumpifbytenotequal gBattlerFainted, gBattlersCount, BattleScript_HandleFaintedMonLoop @@ -5763,7 +5763,7 @@ BattleScript_DoSwitchOut:: flushtextbox printstring STRINGID_SWITCHINMON hidepartystatussummary BS_ATTACKER - switchinanim BS_ATTACKER, FALSE + switchinanim BS_ATTACKER, FALSE, FALSE waitstate switchineffects BS_ATTACKER moveendcase MOVEEND_STATUS_IMMUNITY_ABILITIES @@ -6080,7 +6080,7 @@ BattleScript_RoarSuccessSwitch:: switchindataupdate BS_TARGET trytoclearprimalweather flushtextbox - switchinanim BS_TARGET, FALSE + switchinanim BS_TARGET, FALSE, FALSE waitstate printstring STRINGID_PKMNWASDRAGGEDOUT switchineffects BS_TARGET @@ -7648,7 +7648,7 @@ BattleScript_EmergencyExitNoPopUp:: switchindataupdate BS_TARGET hpthresholds BS_TARGET printstring STRINGID_SWITCHINMON - switchinanim BS_TARGET, TRUE + switchinanim BS_TARGET, FALSE, TRUE waitstate switchineffects BS_TARGET BattleScript_EmergencyExitRet: @@ -9617,7 +9617,7 @@ BattleScript_EjectButtonActivates:: trytoclearprimalweather flushtextbox printstring 0x3 - switchinanim BS_SCRIPTING 0x1 + switchinanim BS_SCRIPTING, FALSE, TRUE waitstate switchineffects BS_SCRIPTING BattleScript_EjectButtonEnd: @@ -9981,7 +9981,7 @@ BattleScript_DynamaxBegins:: returnatktoball pause B_WAIT_TIME_SHORT returntoball BS_SCRIPTING, TRUE - switchinanim BS_SCRIPTING, TRUE + switchinanim BS_SCRIPTING, TRUE, TRUE updatedynamax playanimation BS_SCRIPTING, B_ANIM_DYNAMAX_GROWTH waitanimation diff --git a/data/battle_scripts_2.s b/data/battle_scripts_2.s index b68a570664..4db3f350d0 100644 --- a/data/battle_scripts_2.s +++ b/data/battle_scripts_2.s @@ -75,7 +75,7 @@ BattleScript_ItemRestoreHP_Party:: return BattleScript_ItemRestoreHP_SendOutRevivedBattler: - switchinanim BS_SCRIPTING, FALSE + switchinanim BS_SCRIPTING, FALSE, FALSE waitstate switchineffects BS_SCRIPTING end diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 5e92cac763..6bd17f90b9 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -210,7 +210,7 @@ void PrepareBufferDataTransferLink(u32 battler, u32 bufferId, u16 size, u8 *data void BtlController_EmitGetMonData(u32 battler, u32 bufferId, u8 requestId, u8 monToCheck); void BtlController_EmitSetMonData(u32 battler, u32 bufferId, u8 requestId, u8 monToCheck, u8 bytes, void *data); void BtlController_EmitLoadMonSprite(u32 battler, u32 bufferId); -void BtlController_EmitSwitchInAnim(u32 battler, u32 bufferId, u8 partyId, bool8 dontClearSubstituteBit); +void BtlController_EmitSwitchInAnim(u32 battler, u32 bufferId, u8 partyId, bool8 dontClearTransform, bool8 dontClearSubstituteBit); void BtlController_EmitReturnMonToBall(u32 battler, u32 bufferId, bool8 skipAnim); void BtlController_EmitDrawTrainerPic(u32 battler, u32 bufferId); void BtlController_EmitTrainerSlide(u32 battler, u32 bufferId); @@ -255,7 +255,7 @@ void BattleControllerComplete(u32 battler); // Can be used for all the controlle void BtlController_Empty(u32 battler); // Empty command, does nothing, only completes the execution. void BtlController_TerminatorNop(u32 battler); // Dummy function at the end of the table. void BattleControllerDummy(u32 battler); -void StartSendOutAnim(u32 battler, bool32 dontClearSubstituteBit, bool32 doSlideIn); +void StartSendOutAnim(u32 battler, bool32 dontClearTransform, bool32 dontClearSubstituteBit, bool32 doSlideIn); void Controller_WaitForString(u32 battler); void Controller_WaitForHealthBar(u32 battler); diff --git a/include/battle_gfx_sfx_util.h b/include/battle_gfx_sfx_util.h index dd85b2658c..d84af67f35 100644 --- a/include/battle_gfx_sfx_util.h +++ b/include/battle_gfx_sfx_util.h @@ -38,7 +38,7 @@ void SpriteCB_SetInvisible(struct Sprite *sprite); void SetBattlerShadowSpriteCallback(u8 battler, u16 species); void HideBattlerShadowSprite(u8 battler); void FillAroundBattleWindows(void); -void ClearTemporarySpeciesSpriteData(u8 battler, bool8 dontClearSubstitute); +void ClearTemporarySpeciesSpriteData(u32 battler, bool32 dontClearTransform, bool32 dontClearSubstitute); void AllocateMonSpritesGfx(void); void FreeMonSpritesGfx(void); bool32 ShouldPlayNormalMonCry(struct Pokemon *mon); diff --git a/include/pokemon.h b/include/pokemon.h index f5493542ae..706b0cbf65 100644 --- a/include/pokemon.h +++ b/include/pokemon.h @@ -824,6 +824,7 @@ u8 GetItemEffectParamOffset(u32 battler, u16 itemId, u8 effectByte, u8 effectBit u8 *UseStatIncreaseItem(u16 itemId); u8 GetNature(struct Pokemon *mon); u8 GetNatureFromPersonality(u32 personality); +u32 GetGMaxTargetSpecies(u32 species); u16 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 evolutionItem, struct Pokemon *tradePartner); bool8 IsMonPastEvolutionLevel(struct Pokemon *mon); u16 NationalPokedexNumToSpecies(u16 nationalNum); diff --git a/src/battle_anim_mons.c b/src/battle_anim_mons.c index 928f050822..f00626efe8 100644 --- a/src/battle_anim_mons.c +++ b/src/battle_anim_mons.c @@ -2117,24 +2117,26 @@ s16 GetBattlerSpriteCoordAttr(u8 battlerId, u8 attr) } else { + struct Pokemon *mon = GetPartyBattlerData(battlerId); + + spriteInfo = gBattleSpritesDataPtr->battlerData; + if (!spriteInfo[battlerId].transformSpecies) + { + species = GetMonData(mon, MON_DATA_SPECIES); + personality = GetMonData(mon, MON_DATA_PERSONALITY); + } + else + { + species = spriteInfo[battlerId].transformSpecies; + personality = gTransformedPersonalities[battlerId]; + } + + species = SanitizeSpeciesId(species); + if (species == SPECIES_UNOWN) + species = GetUnownSpeciesId(personality); + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) { - spriteInfo = gBattleSpritesDataPtr->battlerData; - if (!spriteInfo[battlerId].transformSpecies) - { - species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); - personality = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY); - } - else - { - species = spriteInfo[battlerId].transformSpecies; - personality = gTransformedPersonalities[battlerId]; - } - - species = SanitizeSpeciesId(species); - if (species == SPECIES_UNOWN) - species = GetUnownSpeciesId(personality); - #if P_GENDER_DIFFERENCES if (gSpeciesInfo[species].backPicFemale != NULL && IsPersonalityFemale(species, personality)) size = gSpeciesInfo[species].backPicSizeFemale; @@ -2146,22 +2148,6 @@ s16 GetBattlerSpriteCoordAttr(u8 battlerId, u8 attr) } else { - spriteInfo = gBattleSpritesDataPtr->battlerData; - if (!spriteInfo[battlerId].transformSpecies) - { - species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_SPECIES); - personality = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PERSONALITY); - } - else - { - species = spriteInfo[battlerId].transformSpecies; - personality = gTransformedPersonalities[battlerId]; - } - - species = SanitizeSpeciesId(species); - if (species == SPECIES_UNOWN) - species = GetUnownSpeciesId(personality); - #if P_GENDER_DIFFERENCES if (gSpeciesInfo[species].frontPicFemale != NULL && IsPersonalityFemale(species, personality)) size = gSpeciesInfo[species].frontPicSizeFemale; diff --git a/src/battle_controllers.c b/src/battle_controllers.c index a5581cf735..727bc8e27f 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -976,12 +976,12 @@ void BtlController_EmitLoadMonSprite(u32 battler, u32 bufferId) PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); } -void BtlController_EmitSwitchInAnim(u32 battler, u32 bufferId, u8 partyId, bool8 dontClearSubstituteBit) +void BtlController_EmitSwitchInAnim(u32 battler, u32 bufferId, u8 partyId, bool8 dontClearTransform, bool8 dontClearSubstituteBit) { gBattleResources->transferBuffer[0] = CONTROLLER_SWITCHINANIM; gBattleResources->transferBuffer[1] = partyId; - gBattleResources->transferBuffer[2] = dontClearSubstituteBit; - gBattleResources->transferBuffer[3] = 5; + gBattleResources->transferBuffer[2] = dontClearTransform; + gBattleResources->transferBuffer[3] = dontClearSubstituteBit; PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); } @@ -2111,13 +2111,13 @@ static bool8 ShouldDoSlideInAnim(void) return TRUE; } -void StartSendOutAnim(u32 battler, bool32 dontClearSubstituteBit, bool32 doSlideIn) +void StartSendOutAnim(u32 battler, bool32 dontClearTransform, bool32 dontClearSubstituteBit, bool32 doSlideIn) { u16 species; u32 side = GetBattlerSide(battler); struct Pokemon *party = GetBattlerParty(battler); - ClearTemporarySpeciesSpriteData(battler, dontClearSubstituteBit); + ClearTemporarySpeciesSpriteData(battler, dontClearTransform, dontClearSubstituteBit); gBattlerPartyIndexes[battler] = gBattleResources->bufferA[battler][1]; species = GetIllusionMonSpecies(battler); if (species == SPECIES_NONE) @@ -2462,11 +2462,11 @@ void BtlController_HandleLoadMonSprite(u32 battler, void (*controllerCallback)(u void BtlController_HandleSwitchInAnim(u32 battler, bool32 isPlayerSide, void (*controllerCallback)(u32 battler)) { if (isPlayerSide) - ClearTemporarySpeciesSpriteData(battler, gBattleResources->bufferA[battler][2]); + ClearTemporarySpeciesSpriteData(battler, gBattleResources->bufferA[battler][2], gBattleResources->bufferA[battler][3]); gBattlerPartyIndexes[battler] = gBattleResources->bufferA[battler][1]; if (isPlayerSide) BattleLoadMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battler]], battler); - StartSendOutAnim(battler, gBattleResources->bufferA[battler][2], FALSE); + StartSendOutAnim(battler, gBattleResources->bufferA[battler][2], gBattleResources->bufferA[battler][3], FALSE); gBattlerControllerFuncs[battler] = controllerCallback; } @@ -2965,17 +2965,17 @@ static void Task_StartSendOutAnim(u8 taskId) if (TwoMonsAtSendOut(battler)) { gBattleResources->bufferA[battler][1] = gBattlerPartyIndexes[battler]; - StartSendOutAnim(battler, FALSE, ShouldDoSlideInAnim()); + StartSendOutAnim(battler, FALSE, FALSE, ShouldDoSlideInAnim()); battlerPartner = battler ^ BIT_FLANK; gBattleResources->bufferA[battlerPartner][1] = gBattlerPartyIndexes[battlerPartner]; BattleLoadMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battlerPartner]], battlerPartner); - StartSendOutAnim(battlerPartner, FALSE, ShouldDoSlideInAnim()); + StartSendOutAnim(battlerPartner, FALSE, FALSE, ShouldDoSlideInAnim()); } else { gBattleResources->bufferA[battler][1] = gBattlerPartyIndexes[battler]; - StartSendOutAnim(battler, FALSE, ShouldDoSlideInAnim()); + StartSendOutAnim(battler, FALSE, FALSE, ShouldDoSlideInAnim()); } gBattlerControllerFuncs[battler] = (void*)(GetWordTaskArg(taskId, tControllerFunc_1)); DestroyTask(taskId); diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 620ef57d94..bbe7924c46 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -609,7 +609,7 @@ bool8 IsBattleSEPlaying(u8 battler) void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) { - u32 monsPersonality, currentPersonality, isShiny, species, paletteOffset, position; + u32 personalityValue, isShiny, species, paletteOffset, position; const void *lzPaletteData; struct Pokemon *illusionMon = GetIllusionMonPtr(battler); if (illusionMon != NULL) @@ -618,48 +618,42 @@ void BattleLoadMonSpriteGfx(struct Pokemon *mon, u32 battler) if (GetMonData(mon, MON_DATA_IS_EGG) || GetMonData(mon, MON_DATA_SPECIES) == SPECIES_NONE) // Don't load GFX of egg pokemon. return; - monsPersonality = GetMonData(mon, MON_DATA_PERSONALITY); isShiny = GetMonData(mon, MON_DATA_IS_SHINY); if (gBattleSpritesDataPtr->battlerData[battler].transformSpecies == SPECIES_NONE) { species = GetMonData(mon, MON_DATA_SPECIES); - currentPersonality = monsPersonality; + personalityValue = GetMonData(mon, MON_DATA_PERSONALITY); } else { species = gBattleSpritesDataPtr->battlerData[battler].transformSpecies; + // If battler has Gigantamax factor, try convert gfx to G-Max version + if (GetActiveGimmick(battler) == GIMMICK_DYNAMAX && GetMonData(mon, MON_DATA_GIGANTAMAX_FACTOR)) + gBattleSpritesDataPtr->battlerData[battler].transformSpecies = species = GetGMaxTargetSpecies(species); + if (B_TRANSFORM_SHINY >= GEN_4) { - currentPersonality = gTransformedPersonalities[battler]; + personalityValue = gTransformedPersonalities[battler]; isShiny = gTransformedShininess[battler]; } else { - currentPersonality = monsPersonality; + personalityValue = GetMonData(mon, MON_DATA_PERSONALITY); } } position = GetBattlerPosition(battler); - if (GetBattlerSide(battler) == B_SIDE_OPPONENT) - { - HandleLoadSpecialPokePic(TRUE, - gMonSpritesGfxPtr->spritesGfx[position], - species, currentPersonality); - } - else - { - HandleLoadSpecialPokePic(FALSE, - gMonSpritesGfxPtr->spritesGfx[position], - species, currentPersonality); - } + HandleLoadSpecialPokePic((GetBattlerSide(battler) == B_SIDE_OPPONENT), + gMonSpritesGfxPtr->spritesGfx[position], + species, personalityValue); paletteOffset = OBJ_PLTT_ID(battler); if (gBattleSpritesDataPtr->battlerData[battler].transformSpecies == SPECIES_NONE) lzPaletteData = GetMonFrontSpritePal(mon); else - lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, currentPersonality); + lzPaletteData = GetMonSpritePalFromSpeciesAndPersonality(species, isShiny, personalityValue); LZDecompressWram(lzPaletteData, gDecompressionBuffer); LoadPalette(gDecompressionBuffer, paletteOffset, PLTT_SIZE_4BPP); @@ -925,8 +919,10 @@ void CopyBattleSpriteInvisibility(u8 battler) void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bool8 trackEnemyPersonality) { u32 personalityValue, position, paletteOffset, targetSpecies; - bool8 isShiny; + bool32 isShiny; const void *lzPaletteData, *src; + struct Pokemon *monAtk = GetPartyBattlerData(battlerAtk); + struct Pokemon *monDef = GetPartyBattlerData(battlerDef); void *dst; if (IsContest()) @@ -944,48 +940,35 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo else { position = GetBattlerPosition(battlerAtk); - - if (GetBattlerSide(battlerDef) == B_SIDE_OPPONENT) - targetSpecies = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_SPECIES); - else - targetSpecies = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_SPECIES); - - if (GetBattlerSide(battlerAtk) == B_SIDE_PLAYER) + if (gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies == SPECIES_NONE) { - if (B_TRANSFORM_SHINY >= GEN_4 && trackEnemyPersonality && !megaEvo) - { - personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_PERSONALITY); - isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_IS_SHINY); - } + // Get base form if its currently Gigantamax + if (IsGigantamaxed(battlerDef)) + targetSpecies = gBattleStruct->changedSpecies[GetBattlerSide(battlerDef)][gBattlerPartyIndexes[battlerDef]]; else - { - personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_IS_SHINY); - } - - HandleLoadSpecialPokePic(FALSE, - gMonSpritesGfxPtr->spritesGfx[position], - targetSpecies, - personalityValue); + targetSpecies = GetMonData(monDef, MON_DATA_SPECIES); + personalityValue = GetMonData(monAtk, MON_DATA_PERSONALITY); + isShiny = GetMonData(monAtk, MON_DATA_IS_SHINY); } else { + targetSpecies = gBattleSpritesDataPtr->battlerData[battlerAtk].transformSpecies; if (B_TRANSFORM_SHINY >= GEN_4 && trackEnemyPersonality && !megaEvo) { - personalityValue = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_PERSONALITY); - isShiny = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerDef]], MON_DATA_IS_SHINY); + personalityValue = GetMonData(monDef, MON_DATA_PERSONALITY); + isShiny = GetMonData(monDef, MON_DATA_IS_SHINY); } else { - personalityValue = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_PERSONALITY); - isShiny = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battlerAtk]], MON_DATA_IS_SHINY); + personalityValue = GetMonData(monAtk, MON_DATA_PERSONALITY); + isShiny = GetMonData(monAtk, MON_DATA_IS_SHINY); } - - HandleLoadSpecialPokePic(TRUE, - gMonSpritesGfxPtr->spritesGfx[position], - targetSpecies, - personalityValue); } + + HandleLoadSpecialPokePic((GetBattlerSide(battlerAtk) != B_SIDE_PLAYER), + gMonSpritesGfxPtr->spritesGfx[position], + targetSpecies, + personalityValue); } src = gMonSpritesGfxPtr->spritesGfx[position]; dst = (void *)(OBJ_VRAM0 + gSprites[gBattlerSpriteIds[battlerAtk]].oam.tileNum * 32); @@ -1005,6 +988,24 @@ void HandleSpeciesGfxDataChange(u8 battlerAtk, u8 battlerDef, bool32 megaEvo, bo } } + // dynamax tint + if (GetActiveGimmick(battlerAtk) == GIMMICK_DYNAMAX) + { + // Calyrex and its forms have a blue dynamax aura instead of red. + if (GET_BASE_SPECIES_ID(targetSpecies) == SPECIES_CALYREX) + BlendPalette(paletteOffset, 16, 4, RGB(12, 0, 31)); + else + BlendPalette(paletteOffset, 16, 4, RGB(31, 0, 12)); + CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, PLTT_SIZEOF(16)); + } + + // Terastallization's tint + if (GetActiveGimmick(battlerAtk) == GIMMICK_TERA) + { + BlendPalette(paletteOffset, 16, 8, GetTeraTypeRGB(GetBattlerTeraType(battlerAtk))); + CpuCopy32(gPlttBufferFaded + paletteOffset, gPlttBufferUnfaded + paletteOffset, PLTT_SIZEOF(16)); + } + gSprites[gBattlerSpriteIds[battlerAtk]].y = GetBattlerSpriteDefault_Y(battlerAtk); StartSpriteAnim(&gSprites[gBattlerSpriteIds[battlerAtk]], 0); } @@ -1384,9 +1385,10 @@ void FillAroundBattleWindows(void) } } -void ClearTemporarySpeciesSpriteData(u8 battler, bool8 dontClearSubstitute) +void ClearTemporarySpeciesSpriteData(u32 battler, bool32 dontClearTransform, bool32 dontClearSubstitute) { - gBattleSpritesDataPtr->battlerData[battler].transformSpecies = SPECIES_NONE; + if (!dontClearTransform) + gBattleSpritesDataPtr->battlerData[battler].transformSpecies = SPECIES_NONE; if (!dontClearSubstitute) ClearBehindSubstituteBit(battler); } diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 3f49153c7f..ffb03a1d73 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -6940,7 +6940,7 @@ static void Cmd_switchinanim(void) { u32 battler; - CMD_ARGS(u8 battler, bool8 dontClearSubstitute); + CMD_ARGS(u8 battler, bool8 dontClearTransform, bool8 dontClearSubstitute); if (gBattleControllerExecFlags) return; @@ -6957,7 +6957,7 @@ static void Cmd_switchinanim(void) gAbsentBattlerFlags &= ~(1u << battler); - BtlController_EmitSwitchInAnim(battler, BUFFER_A, gBattlerPartyIndexes[battler], cmd->dontClearSubstitute); + BtlController_EmitSwitchInAnim(battler, BUFFER_A, gBattlerPartyIndexes[battler], cmd->dontClearTransform, cmd->dontClearSubstitute); MarkBattlerForControllerExec(battler); gBattlescriptCurrInstr = cmd->nextInstr; diff --git a/src/pokemon.c b/src/pokemon.c index d6ed5020b8..01a82d66e0 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3700,7 +3700,7 @@ void CopyPartyMonToBattleData(u32 battlerId, u32 partyIndex) PokemonToBattleMon(&party[partyIndex], &gBattleMons[battlerId]); gBattleStruct->hpOnSwitchout[side] = gBattleMons[battlerId].hp; UpdateSentPokesToOpponentValue(battlerId); - ClearTemporarySpeciesSpriteData(battlerId, FALSE); + ClearTemporarySpeciesSpriteData(battlerId, FALSE, FALSE); } bool8 ExecuteTableBasedItemEffect(struct Pokemon *mon, u16 item, u8 partyIndex, u8 moveIndex) @@ -4407,7 +4407,7 @@ u8 GetNatureFromPersonality(u32 personality) return personality % NUM_NATURES; } -static u32 GetGMaxTargetSpecies(u32 species) +u32 GetGMaxTargetSpecies(u32 species) { const struct FormChange *formChanges = GetSpeciesFormChanges(species); u32 i; @@ -4416,7 +4416,7 @@ static u32 GetGMaxTargetSpecies(u32 species) if (formChanges[i].method == FORM_CHANGE_BATTLE_GIGANTAMAX) return formChanges[i].targetSpecies; } - return SPECIES_NONE; + return species; } u16 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 evolutionItem, struct Pokemon *tradePartner) @@ -4854,8 +4854,8 @@ u16 GetEvolutionTargetSpecies(struct Pokemon *mon, enum EvolutionMode mode, u16 // 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) + && GetGMaxTargetSpecies(species) != species + && GetGMaxTargetSpecies(targetSpecies) == targetSpecies) { return SPECIES_NONE; } From 9c7c94d474aab9266e4ed8abc29bdd8ea2e6da2d Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 12 Jan 2025 10:01:44 +0100 Subject: [PATCH 67/85] Fixed a bunch of move anims (#5936) Co-authored-by: Hedara --- data/battle_anim_scripts.s | 556 ++++++++++++++++----------------- src/battle_anim_dark.c | 4 + src/battle_anim_electric.c | 7 + src/battle_anim_mon_movement.c | 2 +- 4 files changed, 290 insertions(+), 279 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index ae8642feb4..151ab6400a 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -661,22 +661,22 @@ gBattleAnimMove_LuckyChant:: monbg ANIM_DEF_PARTNER setalpha 12, 8 playsewithpan SE_M_PETAL_DANCE, SOUND_PAN_ATTACKER - createsprite gLuckyChantBigStarsSpriteTemplate, 2, 4, 0, -18, 8, 140 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, 16, -18, 8, 100 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, -16, -18, 8, 100 + createsprite gLuckyChantBigStarsSpriteTemplate, ANIM_ATTACKER, 2, 0, -18, 8, 140 + createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 16, -18, 8, 100 + createsprite gLuckyChantSmallStarsSpriteTemplate, 2, -16, -18, 8, 100 delay 15 - createsprite gLuckyChantBigStarsSpriteTemplate 2, 4, 0, -18, 8, 140 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, 32, -18, 8, 100 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, -32, -18, 8, 100 + createsprite gLuckyChantBigStarsSpriteTemplate ANIM_ATTACKER, 2, 0, -18, 8, 140 + createsprite gLuckyChantSmallStarsSpriteTemplate, ANIM_ATTACKER, 2, 32, -18, 8, 100 + createsprite gLuckyChantSmallStarsSpriteTemplate, ANIM_ATTACKER, 2, -32, -18, 8, 100 delay 15 - createsprite gLuckyChantBigStarsSpriteTemplate 2, 4, 0, -18, 8, 140 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, 24, -18, 8, 100 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, -18, -18, 8, 100 + createsprite gLuckyChantBigStarsSpriteTemplate ANIM_ATTACKER, 2, 0, -18, 8, 140 + createsprite gLuckyChantSmallStarsSpriteTemplate, ANIM_ATTACKER, 2, 24, -18, 8, 100 + createsprite gLuckyChantSmallStarsSpriteTemplate, ANIM_ATTACKER, 2, -18, -18, 8, 100 delay 30 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, 16, -18, 0, 100 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, -16, -18, 0, 100 + createsprite gLuckyChantSmallStarsSpriteTemplate, ANIM_ATTACKER, 2, 16, -18, 0, 100 + createsprite gLuckyChantSmallStarsSpriteTemplate, ANIM_ATTACKER, 2, -16, -18, 0, 100 delay 30 - createsprite gLuckyChantSmallStarsSpriteTemplate, 2, 4, 20, -16, 14, 80 + createsprite gLuckyChantSmallStarsSpriteTemplate, ANIM_ATTACKER, 2, 20, -16, 14, 80 waitforvisualfinish clearmonbg ANIM_DEF_PARTNER blendoff @@ -824,7 +824,7 @@ gBattleAnimMove_Punishment:: monbg ANIM_TARGET setalpha 12, 8 playsewithpan 155, SOUND_PAN_TARGET - createsprite gPunishmentSpriteTemplate, 2, 4, 0, 0, 1, 0 + createsprite gPunishmentSpriteTemplate, ANIM_TARGET, 2, 0, 0, 1, 0 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 waitforvisualfinish clearmonbg ANIM_TARGET @@ -834,7 +834,7 @@ gBattleAnimMove_Punishment:: monbg ANIM_TARGET setalpha 12, 8 playsewithpan SE_M_DOUBLE_SLAP, SOUND_PAN_TARGET - createsprite gPunishmentImpactSpriteTemplate 2, 4, 0, 0, 1, 2 + createsprite gPunishmentImpactSpriteTemplate, ANIM_TARGET, 2, 0, 0, 1, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 waitforvisualfinish clearmonbg ANIM_TARGET @@ -848,33 +848,33 @@ gBattleAnimMove_LastResort:: waitbgfadein loadspritegfx ANIM_TAG_IMPACT playsewithpan SE_M_SWIFT, SOUND_PAN_ATTACKER - createsprite gComplexPaletteBlendSpriteTemplate, 2, 7, 2, 4, 2, RGB_WHITE, 10, 0, 0 + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, 2, 4, 2, RGB_WHITE, 10, 0, 0 waitforvisualfinish delay 10 playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER waitplaysewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER, 8 createvisualtask AnimTask_TranslateMonEllipticalRespectSide, 2, ANIM_ATTACKER, 18, 6, 2, 4 waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, 2, 5, 1, 0, 16, 16, RGB_WHITE - createsprite gSlideMonToOffsetSpriteTemplate, 2, 5, 0, 20, 0, 0, 4 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_TARGET, 2, 1, 0, 16, 16, RGB_WHITE + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_TARGET, 2, 0, 20, 0, 0, 4 delay 3 waitforvisualfinish playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET - createsprite gBasicHitSplatSpriteTemplate, 132, 4, -10, 0, 1, 0 - createsprite gSlideMonToOffsetSpriteTemplate, 2, 5, 1, -32, 0, 0, 3 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 132, -10, 0, 1, 0 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_TARGET, 2, 1, -32, 0, 0, 3 waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 4, 8, -256, ANIM_ATTACKER, 0 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 4, 8, -256, ANIM_TARGET, 0 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 0 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 0 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 4, 0, 12, 1 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 - createsprite gSimplePaletteBlendSpriteTemplate, 2, 5, 1, 2, 16, 0, RGB_WHITE + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_TARGET, 2, 1, 2, 16, 0, RGB_WHITE waitforvisualfinish - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 4, 8, -256, ANIM_ATTACKER, 1 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 4, 8, -256, ANIM_TARGET, 1 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_ATTACKER, 1 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 8, -256, ANIM_TARGET, 1 waitforvisualfinish - createsprite gSlideMonToOriginalPosSpriteTemplate, 2, 3, 0, 0, 5 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 5 delay 3 - createsprite gSlideMonToOriginalPosSpriteTemplate, 2, 3, 1, 0, 7 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 2, 1, 0, 7 waitforvisualfinish call UnsetHighSpeedBg end @@ -896,14 +896,14 @@ gBattleAnimMove_WorrySeed:: gBattleAnimMove_SuckerPunch:: loadspritegfx ANIM_TAG_POISON_JAB loadspritegfx ANIM_TAG_IMPACT - createsprite gSlideMonToOffsetSpriteTemplate, 2, 5, 0, 20, 0, 0, 4 - createsprite gSuckerPunchSpriteTemplate, 130, 6, -18, 5, 40, 8, 160, 0 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + createsprite gSuckerPunchSpriteTemplate, ANIM_TARGET, 130, -18, 5, 40, 8, 160, 0 delay 4 - createsprite gBasicHitSplatSpriteTemplate, 130, 4, -8, 8, 1, 2 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 4, 6, 384, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 130, -8, 8, 1, 2 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 6, 384, ANIM_TARGET, 2 playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET waitforvisualfinish - createsprite gSlideMonToOriginalPosSpriteTemplate, 2, 3, 0, 1, 4 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 1, 4 end gBattleAnimMove_ToxicSpikes:: @@ -979,28 +979,28 @@ gBattleAnimGeneral_AquaRingHeal:: createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 23, 1 delay 5 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 10, 10, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 10, 10, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, -15, 0, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, -15, 0, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 20, 10, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 20, 10, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 0, -10, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 0, -10, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, -10, 15, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, -10, 15, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 25, 20, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 25, 20, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, -20, 20, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, -20, 20, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 12, 0, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 12, 0, 25, 0 setalpha 8, 8 playsewithpan SE_M_MILK_DRINK, SOUND_PAN_ATTACKER createsprite gGuardRingSpriteTemplate, 2, 0 @@ -1010,7 +1010,7 @@ gBattleAnimGeneral_AquaRingHeal:: createsprite gGuardRingSpriteTemplate, 2, 0 waitforvisualfinish playsewithpan SE_SHINY, SOUND_PAN_ATTACKER - createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_ATK_SIDE, 0, 2, 10, RGB_WHITE + createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_ATK_SIDE, 0, 2, 0, 10, RGB_WHITE waitforvisualfinish clearmonbg ANIM_ATK_PARTNER blendoff @@ -1020,7 +1020,7 @@ gBattleAnimMove_MagnetRise:: loadspritegfx ANIM_TAG_IMPACT loadspritegfx ANIM_TAG_SPARK_2 delay 0 - createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), -31, 1, 5, 5, RGB(31, 31, 20) + createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), 0, 1, 5, 5, RGB(31, 31, 20) playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER createvisualtask AnimTask_WindUpLunge, 5, ANIM_ATTACKER, -12, 4, 10, 10, 12, 6 createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 32, 24, 190, 12, ANIM_ATTACKER, 1, 0 @@ -1045,11 +1045,11 @@ gBattleAnimMove_MagnetRise:: delay 0 createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 238, 24, 165, 10, ANIM_ATTACKER, 1, 1 delay 0 - createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), -31, 1, 0, 0, RGB(31, 31, 20) + createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), 0, 1, 0, 0, RGB(31, 31, 20) delay 20 - createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), -31, 1, 7, 7, RGB(31, 31, 20) + createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), 0, 1, 7, 7, RGB(31, 31, 20) waitforvisualfinish - createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), -31, 1, 0, 0, RGB(31, 31, 20) + createvisualtask AnimTask_BlendColorCycle, 2, (F_PAL_BG | F_PAL_BATTLERS), 0, 1, 0, 0, RGB(31, 31, 20) waitforvisualfinish end @@ -1090,33 +1090,33 @@ gBattleAnimMove_FlareBlitz:: createvisualtask AnimTask_ShakeMon2, 2, ANIM_TARGET, 4, 0, 22, 1 createvisualtask AnimTask_BlendMonInAndOut, 3, ANIM_TARGET, RGB_RED, 12, 1, 1 createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 1, 0 - createsprite gFireSpreadSpriteTemplate, 0x81, 0, 10, 192, 176, 40 + createsprite gFireSpreadSpriteTemplate, ANIM_TARGET, 129, 0, 10, 192, 176, 40 playsewithpan SE_M_COMET_PUNCH, +63 delay 5 createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 24, 8, 1, 0 createvisualtask AnimTask_BlendMonInAndOut, 3, ANIM_TARGET, RGB_RED, 12, 1, 1 - createsprite gFireSpreadSpriteTemplate, 0x81, 0, 10, -192, 240, 40 + createsprite gFireSpreadSpriteTemplate, ANIM_TARGET, 129, 0, 10, -192, 240, 40 playsewithpan SE_M_COMET_PUNCH, +63 delay 5 createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, -24, -16, 1, 0 createvisualtask AnimTask_BlendMonInAndOut, 3, ANIM_TARGET, RGB_RED, 12, 1, 1 - createsprite gFireSpreadSpriteTemplate, 0x81, 0, 10, 192, -160, 40 + createsprite gFireSpreadSpriteTemplate, ANIM_TARGET, 129, 0, 10, 192, -160, 40 playsewithpan SE_M_COMET_PUNCH, +63 delay 5 createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 8, 4, 1, 0 createvisualtask AnimTask_BlendMonInAndOut, 3, ANIM_TARGET, RGB_RED, 12, 1, 1 - createsprite gFireSpreadSpriteTemplate, 0x81, 0, 10, -192, -112, 40 + createsprite gFireSpreadSpriteTemplate, ANIM_TARGET, 129, 0, 10, -192, -112, 40 playsewithpan SE_M_COMET_PUNCH, +63 delay 5 createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, -16, 19, 1, 0 createvisualtask AnimTask_BlendMonInAndOut, 3, ANIM_TARGET, RGB_RED, 12, 1, 1 - createsprite gFireSpreadSpriteTemplate, 0x81, 0, 10, 160, 48, 40 + createsprite gFireSpreadSpriteTemplate, ANIM_TARGET, 129, 0, 10, 160, 48, 40 playsewithpan SE_M_COMET_PUNCH, +63 delay 5 createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 3, 18, -18, 1, 0 createvisualtask AnimTask_BlendMonInAndOut, 3, ANIM_TARGET, RGB_RED, 12, 1, 1 - createsprite gFireSpreadSpriteTemplate, 0x81, 0, 10, -224, -32, 40 - createsprite gFireSpreadSpriteTemplate, 0x81, 0, 10, 112, -128, 40 + createsprite gFireSpreadSpriteTemplate, ANIM_TARGET, 129, 0, 10, -224, -32, 40 + createsprite gFireSpreadSpriteTemplate, ANIM_TARGET, 129, 0, 10, 112, -128, 40 playsewithpan SE_M_COMET_PUNCH, +63 createvisualtask AnimTask_BlendBattleAnimPal, 10, 4, 2, 0, 0, RGB_BLACK playsewithpan SE_M_COMET_PUNCH, +63 @@ -1138,10 +1138,10 @@ gBattleAnimMove_ForcePalm:: splitbgprio ANIM_TARGET setalpha 12, 8 playsewithpan SE_M_DOUBLE_TEAM, SOUND_PAN_TARGET - createsprite gKarateChopSpriteTemplate, 2, 8, -16, 0, 0, 0, 10, 1, 3, 0 + createsprite gKarateChopSpriteTemplate, ANIM_TARGET, 2, -16, 0, 0, 0, 10, 1, 3, 0 waitforvisualfinish playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET - createsprite gForcePalmSpriteTemplate 3, 4, 0, 0, 1, 2 + createsprite gForcePalmSpriteTemplate, ANIM_TARGET 3, 0, 0, 1, 2 createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 4, 0, 6, 1 waitforvisualfinish clearmonbg ANIM_DEF_PARTNER @@ -1351,45 +1351,45 @@ gBattleAnimMove_AquaTail:: createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 23, 1 delay 5 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 10, 10, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 10, 10, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, -16, 0, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, -16, 0, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 20, 10, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 20, 10, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 0, -10, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 0, -10, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, -10, 15, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, -10, 15, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 25, 20, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 25, 20, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, -20, 20, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, -20, 20, 25, 0 delay 4 playsewithpan SE_M_CRABHAMMER, SOUND_PAN_ATTACKER - createsprite gSmallBubblePairSpriteTemplate, 2, 4, 12, 0, 25, 0 + createsprite gSmallBubblePairSpriteTemplate, ANIM_ATTACKER, 2, 12, 0, 25, 0 waitforvisualfinish loadspritegfx ANIM_TAG_SLAM_HIT_2 loadspritegfx ANIM_TAG_IMPACT - createsprite gHorizontalLungeSpriteTemplate, 2, 2, 4, 6 + createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 6 delay 4 playsewithpan SE_M_VITAL_THROW, SOUND_PAN_TARGET - createsprite gAquaTailKnockOffSpriteTemplate, 130, 2, -16, -16 + createsprite gAquaTailKnockOffSpriteTemplate, ANIM_ATTACKER, 130, -16, -16 delay 8 - createsprite gComplexPaletteBlendSpriteTemplate, 2, 7, 31, 5, 1, RGB_WHITE, 10, 0, 0 - createsprite gAquaTailHitSpriteTemplate, 131, 4, 0, 0, 1, 2 + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_TARGET, 2, 31, 5, 1, RGB_WHITE, 10, 0, 0 + createsprite gAquaTailHitSpriteTemplate, ANIM_TARGET, 131, 0, 0, 1, 2 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET - createsprite gSlideMonToOffsetSpriteTemplate, 2, 5, 1, -12, 10, 0, 3 - createsprite gSlideMonToOriginalPosSpriteTemplate, 2, 3, 0, 0, 5 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_TARGET, 2, ANIM_TARGET, -12, 10, 0, 3 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, ANIM_ATTACKER, 0, 5 delay 3 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 0, 3, 6, 1 delay 5 - createsprite gSlideMonToOriginalPosSpriteTemplate, 2, 3, 1, 0, 6 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 2, ANIM_TARGET, 0, 6 delay 10 waitforvisualfinish clearmonbg ANIM_DEF_PARTNER @@ -1513,7 +1513,7 @@ gBattleAnimMove_DragonPulse:: createsoundtask SoundTask_LoopSEAdjustPanning, SE_M_PSYBEAM2, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 3, 4, 0, 15 call DragonPulseParticle call DragonPulseParticle - createvisualtask AnimTask_SwayMon, 5, 0, 6, 51200, 4, ANIM_TARGET + createvisualtask AnimTask_SwayMon, ANIM_TARGET, 0, 6, 2048, 4, ANIM_TARGET createvisualtask AnimTask_BlendColorCycle, 2, F_PAL_TARGET, 2, 2, 0, 12, RGB(30, 10, 13) call DragonPulseParticle call DragonPulseParticle @@ -1532,7 +1532,7 @@ gBattleAnimMove_DragonPulse:: clearmonbg ANIM_TARGET end DragonPulseParticle: - createsprite gDragonPulseSpriteTemplate, 130, 6, 16, 0, 0, 0, 13, 0 + createsprite gDragonPulseSpriteTemplate, ANIM_ATTACKER, 130, 16, 0, 0, 0, 13, 0 delay 4 return @@ -1541,24 +1541,24 @@ gBattleAnimMove_DragonRush:: loadspritegfx ANIM_TAG_IMPACT loadspritegfx ANIM_TAG_ROCKS loadspritegfx ANIM_TAG_RED_HEART - createsprite gHorizontalLungeSpriteTemplate, 2, 2, 4, 6 + createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 6 delay 4 playsewithpan SE_M_VITAL_THROW, SOUND_PAN_TARGET - createsprite gDragonRushSpriteTemplate, 131, 2, -16, -16 + createsprite gDragonRushSpriteTemplate, ANIM_ATTACKER, 131, -16, -16 delay 8 - createsprite gComplexPaletteBlendSpriteTemplate, 2, 7, 31, 5, 1, RGB_WHITE, 10, 0, 0 - createsprite gBasicHitSplatSpriteTemplate, 3, 4, 0, 0, 1, 1 - createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 5, 1 + createsprite gComplexPaletteBlendSpriteTemplate, ANIM_TARGET, 2, 31, 5, 1, RGB_WHITE, 10, 0, 0 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 3, 0, 0, 1, 1 + createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 5, 1 waitforvisualfinish playsewithpan 131, SOUND_PAN_TARGET - createsprite gRockFragmentSpriteTemplate, 2, 6, 0, 0, 20, 24, 14, 2 - createsprite gRockFragmentSpriteTemplate, 2, 6, 5, 0, -20, 24, 14, 1 - createsprite gRockFragmentSpriteTemplate, 2, 6, 0, 5, 20, -24, 14, 2 - createsprite gRockFragmentSpriteTemplate, 2, 6, -5, 0, 20, 24, 14, 2 - createsprite gRockFragmentSpriteTemplate, 2, 6, 0, -5, 30, 18, 8, 2 - createsprite gRockFragmentSpriteTemplate, 2, 6, 0, 0, 30, -18, 8, 2 - createsprite gRockFragmentSpriteTemplate, 2, 6, 0, 0, -30, 18, 8, 2 - createsprite gRockFragmentSpriteTemplate, 2, 6, 0, 0, -30, -18, 8, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 2, 0, 0, 20, 24, 14, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 2, 5, 0, -20, 24, 14, 1 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 2, 0, 5, 20, -24, 14, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 2, -5, 0, 20, 24, 14, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 2, 0, -5, 30, 18, 8, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 2, 0, 0, 30, -18, 8, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 2, 0, 0, -30, 18, 8, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 2, 0, 0, -30, -18, 8, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 3, 7, 1 waitforvisualfinish clearmonbg ANIM_DEF_PARTNER @@ -1709,24 +1709,24 @@ gBattleAnimMove_EarthPower:: playsewithpan SE_M_EARTHQUAKE, SOUND_PAN_TARGET delay 40 loopsewithpan 145, SOUND_PAN_TARGET 11, 3 - createvisualtask AnimTask_ShakeMon, 5, 5, ANIM_TARGET, 0, 3, 25, 1 - createsprite gDragonRageFirePlumeSpriteTemplate, 194, 3, 1, 5, 0 + createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 3, 25, 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 194, 1, 5, 0 delay 1 - createsprite gDragonRageFirePlumeSpriteTemplate, 194, 3, 1, -10, -15 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 194, 1, -10, -15 delay 1 - createsprite gDragonRageFirePlumeSpriteTemplate, 130, 3, 1, 0, 25 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 130, 1, 0, 25 delay 1 - createsprite gDragonRageFirePlumeSpriteTemplate, 194, 3, 1, 15, 5 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 194, 1, 15, 5 delay 1 - createsprite gDragonRageFirePlumeSpriteTemplate, 194, 3, 1, -25, 0 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 194, 1, -25, 0 delay 1 - createsprite gDragonRageFirePlumeSpriteTemplate, 130, 3, 1, 30, 30 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 130, 1, 30, 30 delay 1 - createsprite gDragonRageFirePlumeSpriteTemplate, 130, 3, 1, -27, 25 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 130, 1, -27, 25 delay 1 - createsprite gDragonRageFirePlumeSpriteTemplate, 194, 3, 1, 0, 8 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_TARGET, 194, 1, 0, 8 waitforvisualfinish - createsprite gSlideMonToOriginalPosSpriteTemplate, 194, 3, 0, 0, 4 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 194, 0, 0, 4 waitforvisualfinish end @@ -1735,12 +1735,12 @@ gBattleAnimMove_Switcheroo:: waitbgfadein loadspritegfx ANIM_TAG_ITEM_BAG loadspritegfx ANIM_TAG_SPEED_DUST - createsprite gTrickBagSpriteTemplate, 2, 2, -39, 80 - createsprite gTrickBagSpriteTemplate, 2, 2, -39, 208 + createsprite gTrickBagSpriteTemplate, ANIM_ATTACKER, 2, -39, 80 + createsprite gTrickBagSpriteTemplate, ANIM_ATTACKER, 2, -39, 208 delay 16 playsewithpan SE_M_SKETCH, 0 - createvisualtask AnimTask_StretchTargetUp, 3, 0 - createvisualtask AnimTask_StretchAttackerUp, 3, 0 + createvisualtask AnimTask_StretchTargetUp, 3 + createvisualtask AnimTask_StretchAttackerUp, 3 delay 30 playsewithpan SE_M_DOUBLE_TEAM, 0 delay 24 @@ -1787,17 +1787,17 @@ GigaImpactContinuity: delay 11 createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 26, 0, 0, 5 delay 6 - createsprite gBasicHitSplatSpriteTemplate, 4, 4, -10, 0, 1, 0 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 4, -10, 0, 1, 0 playsewithpan SE_M_MEGA_KICK2, SOUND_PAN_TARGET delay 1 - createsprite gSlideMonToOffsetSpriteTemplate 2, 5, 1, -16, 0, 0, 4 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_TARGET, 2, 1, -16, 0, 0, 4 waitforvisualfinish createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 4, 0, 12, 1 waitforvisualfinish delay 2 - createsprite gSlideMonToOriginalPosSpriteTemplate 2, 3, 0, 0, 5 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, ANIM_ATTACKER, 0, 5 delay 3 - createsprite gSlideMonToOriginalPosSpriteTemplate 2, 3, 1, 0, 6 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 2, ANIM_TARGET, 0, 6 waitforvisualfinish clearmonbg ANIM_DEF_PARTNER blendoff @@ -1813,7 +1813,7 @@ gBattleAnimMove_NastyPlot:: createvisualtask AnimTask_FadeScreenToWhite, 5 waitbgfadein delay 8 - createsprite gQuestionMarkSpriteTemplate, 20, 0 + createsprite gQuestionMarkSpriteTemplate, ANIM_ATTACKER, 20, 0 playsewithpan SE_M_METRONOME, SOUND_PAN_ATTACKER delay 54 loopsewithpan SE_M_METRONOME, SOUND_PAN_ATTACKER, 16, 3 @@ -1879,17 +1879,17 @@ gBattleAnimMove_Avalanche:: loadspritegfx ANIM_TAG_ROCKS loadspritegfx ANIM_TAG_ICE_CHUNK monbg ANIM_DEF_PARTNER - createsprite gShakeMonOrTerrainSpriteTemplate, 2, 4, 7, 1, 11, 1 - createsprite gAvalancheSpriteTemplate, 130, 4, -5, 1, -5, 1 + createsprite gShakeMonOrTerrainSpriteTemplate, ANIM_TARGET, 2, 7, 1, 11, 1 + createsprite gAvalancheSpriteTemplate, ANIM_TARGET, 130, 4, -5, 1, -5, 1 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET delay 2 - createsprite gAvalancheSpriteTemplate, 130, 4, 5, 0, 6, 1 + createsprite gAvalancheSpriteTemplate, ANIM_TARGET, 130, 5, 0, 6, 1 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET delay 2 - createsprite gAvalancheSpriteTemplate, 130, 4, 19, 1, 10, 1 + createsprite gAvalancheSpriteTemplate, ANIM_TARGET, 130, 19, 1, 10, 1 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET delay 2 - createsprite gAvalancheSpriteTemplate 130, 4, -17, 2, -20, 1 + createsprite gAvalancheSpriteTemplate ANIM_TARGET, 130, -17, 2, -20, 1 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 0, 5, 50, 1 createvisualtask AnimTask_ShakeMon, 2, ANIM_DEF_PARTNER, 0, 5, 50, 1 @@ -2183,8 +2183,8 @@ gBattleAnimMove_PsychoCut:: loadspritegfx ANIM_TAG_CROSS_IMPACT monbg ANIM_ATK_PARTNER createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_CROSS_IMPACT, 0, 9, 9, RGB_PURPLE - createvisualtask AnimTask_SwayMon, 5, 0, 6, 2048, 2, ANIM_ATTACKER - createsprite gPsychoCutSpiralSpriteTemplate, 2, 4, 0, 0, 0, 0 + createvisualtask AnimTask_SwayMon, ANIM_ATTACKER, 0, 6, 2048, 2, ANIM_ATTACKER + createsprite gPsychoCutSpiralSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 0, 0 createvisualtask AnimTask_BlendBattleAnimPal, 1, 1, 2, 0, 4, RGB_BLACK createvisualtask AnimTask_BlendBattleAnimPal, 1, 2, 2, 0, 10, RGB(20, 12, 23) delay 30 @@ -2210,28 +2210,28 @@ gBattleAnimMove_ZenHeadbutt:: loadspritegfx ANIM_TAG_WATER_IMPACT monbg ANIM_ATTACKER setalpha 12, 8 - createsprite gSimplePaletteBlendSpriteTemplate, 2, 5, 1, 2, 0, 4, 0 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, 1, 2, 0, 4, 0 waitforvisualfinish - createsprite gZenHeadbuttSpriteTemplate, 66, 1, 0 + createsprite gZenHeadbuttSpriteTemplate, ANIM_ATTACKER, 66, 0 delay 18 playsewithpan SE_M_MORNING_SUN, SOUND_PAN_ATTACKER waitforvisualfinish delay 2 playsewithpan SE_M_HEADBUTT, SOUND_PAN_ATTACKER loadspritegfx ANIM_TAG_IMPACT - createsprite gBowMonSpriteTemplate, 2, 1, 0 + createsprite gBowMonSpriteTemplate, ANIM_ATTACKER, 1, 0 playsewithpan SE_M_HEADBUTT, SOUND_PAN_ATTACKER waitforvisualfinish delay 2 - createsprite gBowMonSpriteTemplate, 2, 1, 1 + createsprite gBowMonSpriteTemplate, ANIM_ATTACKER, 1, 1 waitforvisualfinish createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_ATTACKER, 2, 0, 4, 1 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 5, 0, 6, 1 - createsprite gBowMonSpriteTemplate, 2, 1, 2 - createsprite gAquaTailHitSpriteTemplate, 131, 4, 0, 0, 1, 1 + createsprite gBowMonSpriteTemplate, ANIM_ATTACKER, 1, 2 + createsprite gAquaTailHitSpriteTemplate, ANIM_TARGER, 131, 0, 0, 1, 1 playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET waitforvisualfinish - createsprite gSimplePaletteBlendSpriteTemplate, 2, 5, 1, 4, 4, 0, 0 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, 1, 4, 4, 0, 0 clearmonbg ANIM_ATTACKER blendoff delay 1 @@ -2246,22 +2246,22 @@ gBattleAnimMove_MirrorShot:: createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 0, 10, RGB_WHITEALPHA createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_IMPACT, 0, 12, 12, RGB(21, 21, 21) waitforvisualfinish - createsprite gRandomPosHitSplatSpriteTemplate, 131, 2, 1, 2 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGER, 131, 1, 2 createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_VITAL_THROW2, SOUND_PAN_TARGET delay 3 - createsprite gRandomPosHitSplatSpriteTemplate, 131, 2, 1, 2 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGER, 131, 1, 2 createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_VITAL_THROW2, SOUND_PAN_TARGET delay 3 - createsprite gRandomPosHitSplatSpriteTemplate, 131, 2, 1, 2 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGER, 131, 1, 2 createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_VITAL_THROW2, SOUND_PAN_TARGET delay 3 - createsprite gRandomPosHitSplatSpriteTemplate, 131, 2, 1, 2 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGER, 131, 1, 2 createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_VITAL_THROW2, SOUND_PAN_TARGET delay 3 - createsprite gRandomPosHitSplatSpriteTemplate, 131, 2, 1, 2 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGER, 131, 1, 2 createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_VITAL_THROW2, SOUND_PAN_TARGET delay 3 - createsprite gRandomPosHitSplatSpriteTemplate, 131, 2, 1, 2 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGER, 131, 1, 2 createvisualtask SoundTask_PlaySE1WithPanning, 5, SE_M_VITAL_THROW2, SOUND_PAN_TARGET waitforvisualfinish createvisualtask AnimTask_BlendBattleAnimPalExclude, 5, 5, 2, 10, 0, RGB_WHITEALPHA @@ -2320,25 +2320,25 @@ gBattleAnimMove_RockClimb:: setalpha 12, 8 createvisualtask AnimTask_Rollout, 2, 0 waitforvisualfinish - createvisualtask AnimTask_ShakeTargetBasedOnMovePowerOrDmg, 2, 5, 0, 1, 30, 1, RGB(0, 16, 1) - createsprite gBasicHitSplatSpriteTemplate, 131, 4, -15, 8, 1, 1 + createvisualtask AnimTask_ShakeTargetBasedOnMovePowerOrDmg, 2, 0, 1, 30, 1, RGB(0, 16, 1) + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, -15, 8, 1, 1 playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET delay 1 playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET - createsprite gBasicHitSplatSpriteTemplate, 131, 4, -5, -12, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, -5, -12, 1, 1 delay 1 playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET - createsprite gBasicHitSplatSpriteTemplate, 131, 4, 0, -32, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, 0, -32, 1, 1 delay 1 playsewithpan SE_M_VITAL_THROW2, SOUND_PAN_TARGET - createsprite gBasicHitSplatSpriteTemplate, 131, 4, 5, -52, 1, 1 - createsprite gSlideMonToOffsetSpriteTemplate, 2, 5, 1, -25, 16, 1, 4 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, 5, -52, 1, 1 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_TARGET, 2, 1, -25, 16, 1, 4 delay 4 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 0, 3, 6, 1 delay 30 - createsprite gSlideMonToOriginalPosSpriteTemplate, 2, 3, 0, 0, 6 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 6 delay 4 - createsprite gSlideMonToOriginalPosSpriteTemplate, 2, 3, 1, 0, 6 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_TARGET, 2, 1, 0, 6 clearmonbg ANIM_DEF_PARTNER blendoff end @@ -2383,7 +2383,7 @@ gBattleAnimMove_DracoMeteor:: loadspritegfx ANIM_TAG_FAIRY_LOCK_CHAINS @Gray Colour loadspritegfx ANIM_TAG_WATER_GUN @Sparkles Trail loadspritegfx ANIM_TAG_FIRE_PLUME @Eruption - createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 0, 12, 0x2C41 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 0, 12, RGB(1, 2, 11) createvisualtask AnimTask_BlendParticle, 5, ANIM_TAG_WATER_GUN, 0, 10, 10, RGB_PURPLE @;Purple monbg ANIM_TARGET setalpha 12, 8 @@ -2395,72 +2395,72 @@ gBattleAnimMove_DracoMeteor:: call DracoMeteor2 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 - createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 0x28, 0x20 @; For Meteor 1 - createvisualtask AnimTask_HorizontalShake, 5, 3, 5, 2, 0x1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 40, 32 @; For Meteor 1 + createvisualtask AnimTask_HorizontalShake, 5, 5, 2, 1 delay 7 call DracoMeteor3 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 - createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 0xFFF8, 0x20 @; For Meteor 2 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, -8, 32 @; For Meteor 2 delay 7 call DracoMeteor4 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 - createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 0x15, 0x20 @; For Meteor 3 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 21, 32 @; For Meteor 3 delay 7 call DracoMeteor1 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 - createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 0xFFF8, 0x20 @; For Meteor 4 - createvisualtask AnimTask_HorizontalShake, 5, 3, 5, 2, 0x1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, -8, 32 @; For Meteor 4 + createvisualtask AnimTask_HorizontalShake, 5, 5, 2, 1 delay 7 call DracoMeteor2 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 - createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 0x28, 0x20 @; For Meteor 1 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 40, 32 @; For Meteor 1 delay 7 call DracoMeteor3 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 - createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 0x15, 0x20 @; For Meteor 3 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 21, 32 @; For Meteor 3 delay 15 playsewithpan SE_M_ROCK_THROW, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 7, 4, 2 - createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 0x15, 0x20 @; For Meteor 3 + createsprite gDragonRageFirePlumeSpriteTemplate, ANIM_ATTACKER, 2, ANIM_TARGET, 21, 32 @; For Meteor 3 createvisualtask AnimTask_HorizontalShake, 5, ANIM_TARGET, 2, 1 delay 7 - createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 12, 0, 0x2C41 + createvisualtask AnimTask_BlendBattleAnimPal, 10, F_PAL_BG, 1, 12, 0, RGB(1, 2, 11) waitforvisualfinish clearmonbg ANIM_TARGET blendoff end DracoMeteor1: - createsprite gDracoMeteorRocksSpriteTemplate 0x83, 5, 0xffd0, 0xffc0, 0x28, 0x20, 0x19 + createsprite gDracoMeteorRocksSpriteTemplate, ANIM_ATTACKER, 131, -48, -64, 40, 32, 25 delay 2 - createsprite gDracoMeteorTailSpriteTemplate 0x83, 5, 0xffd0, 0xffc0, 0x28, 0x20, 0x19 + createsprite gDracoMeteorTailSpriteTemplate, ANIM_ATTACKER, 131, -48, -64, 40, 32, 25 delay 2 - createsprite gDracoMeteorTailSpriteTemplate 0x83, 5, 0xffd0, 0xffc0, 0x28, 0x20, 0x19 + createsprite gDracoMeteorTailSpriteTemplate, ANIM_ATTACKER, 131, -48, -64, 40, 32, 25 return DracoMeteor2: - createsprite gDracoMeteorRocksSpriteTemplate 0x83, 5, 0xff90, 0xffc0, 0xFFF8, 0x20, 0x19 + createsprite gDracoMeteorRocksSpriteTemplate, ANIM_ATTACKER, 131, -112, -64, -8, 32, 25 delay 2 - createsprite gDracoMeteorTailSpriteTemplate 0x83, 5, 0xff90, 0xffc0, 0xFFF8, 0x20, 0x19 + createsprite gDracoMeteorTailSpriteTemplate, ANIM_ATTACKER, 131, -112, -64, -8, 32, 25 delay 2 - createsprite gDracoMeteorTailSpriteTemplate 0x83, 5, 0xff90, 0xffc0, 0xFFF8, 0x20, 0x19 + createsprite gDracoMeteorTailSpriteTemplate, ANIM_ATTACKER, 131, -112, -64, -8, 32, 25 return DracoMeteor3: - createsprite gDracoMeteorRocksSpriteTemplate 0x83, 5, 0xffb0, 0xffc0, 0x18, 0x20, 0x19 + createsprite gDracoMeteorRocksSpriteTemplate, ANIM_ATTACKER, 131, -80, -64, 24, 32, 25 delay 2 - createsprite gDracoMeteorTailSpriteTemplate 0x83, 5, 0xffb0, 0xffc0, 0x18, 0x20, 0x19 + createsprite gDracoMeteorTailSpriteTemplate, ANIM_ATTACKER, 131, -80, -64, 24, 32, 25 delay 2 - createsprite gDracoMeteorTailSpriteTemplate 0x83, 5, 0xffb0, 0xffc0, 0x18, 0x20, 0x19 + createsprite gDracoMeteorTailSpriteTemplate, ANIM_ATTACKER, 131, -80, -64, 24, 32, 25 return DracoMeteor4: - createsprite gDracoMeteorRocksSpriteTemplate 0x83, 5, 0xffb0, 0xffc0, 0xFFF8, 0x20, 0x19 + createsprite gDracoMeteorRocksSpriteTemplate, ANIM_ATTACKER, 131, -80, -64, -8, 32, 25 delay 2 - createsprite gDracoMeteorTailSpriteTemplate 0x83, 5, 0xffb0, 0xffc0, 0xFFF8, 0x20, 0x19 + createsprite gDracoMeteorTailSpriteTemplate, ANIM_ATTACKER, 131, -80, -64, -8, 32, 25 delay 2 - createsprite gDracoMeteorTailSpriteTemplate 0x83, 5, 0xffb0, 0xffc0, 0xFFF8, 0x20, 0x19 + createsprite gDracoMeteorTailSpriteTemplate, ANIM_ATTACKER, 131, -80, -64, -8, 32, 25 return gBattleAnimMove_Discharge:: @@ -2576,14 +2576,14 @@ gBattleAnimMove_LavaPlume:: createvisualtask AnimTask_ShakeMon2, 2, ANIM_DEF_PARTNER, 1, 0, 32, 1 createvisualtask AnimTask_ShakeMon2, 2, ANIM_ATK_PARTNER, 1, 0, 32, 1 waitforvisualfinish - createsprite gLavaPlumeSpriteTemplate, 130, 1, 0 - createsprite gLavaPlumeSpriteTemplate, 130, 1, 32 - createsprite gLavaPlumeSpriteTemplate, 130, 1, 64 - createsprite gLavaPlumeSpriteTemplate, 130, 1, 96 - createsprite gLavaPlumeSpriteTemplate, 130, 1, 128 - createsprite gLavaPlumeSpriteTemplate, 130, 1, 160 - createsprite gLavaPlumeSpriteTemplate, 130, 1, 192 - createsprite gLavaPlumeSpriteTemplate, 130, 1, 224 + createsprite gLavaPlumeSpriteTemplate, ANIM_ATTACKER, 130, 0 + createsprite gLavaPlumeSpriteTemplate, ANIM_ATTACKER, 130, 32 + createsprite gLavaPlumeSpriteTemplate, ANIM_ATTACKER, 130, 64 + createsprite gLavaPlumeSpriteTemplate, ANIM_ATTACKER, 130, 96 + createsprite gLavaPlumeSpriteTemplate, ANIM_ATTACKER, 130, 128 + createsprite gLavaPlumeSpriteTemplate, ANIM_ATTACKER, 130, 160 + createsprite gLavaPlumeSpriteTemplate, ANIM_ATTACKER, 130, 192 + createsprite gLavaPlumeSpriteTemplate, ANIM_ATTACKER, 130, 224 playsewithpan SE_M_SACRED_FIRE, SOUND_PAN_ATTACKER waitforvisualfinish end @@ -2726,36 +2726,36 @@ RockWrecker_1: createvisualtask AnimTask_StartSlidingBg, 5, -1024, 0, 0, -1 loadspritegfx ANIM_TAG_ROCKS loadspritegfx ANIM_TAG_IMPACT - createsprite gHorizontalLungeSpriteTemplate, 2, 2, 4, 6 + createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 6 delay 3 playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER - createsprite gRockBlastRockSpriteTemplate, 130, 6, 16, 0, 0, 0, 25, 257 + createsprite gRockBlastRockSpriteTemplate, ANIM_ATTACKER, 130, 16, 0, 0, 0, 25, 257 waitforvisualfinish - createsprite gBasicHitSplatSpriteTemplate, 131, 4, 0, 0, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, 0, 0, 1, 1 playsewithpan SE_M_ROCK_THROW SOUND_PAN_TARGET - createsprite gRockFragmentSpriteTemplate, 130, 6, 0, 0, 20, 24, 14, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 130, 0, 0, 20, 24, 14, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 5, 1 - createsprite gRockFragmentSpriteTemplate, 130, 6, 5, 0, -20, 24, 14, 1 - createsprite gRockFragmentSpriteTemplate, 130, 6, 0, 5, 20, -18, 14, 2 - createsprite gRockFragmentSpriteTemplate, 130, 6, -5, 0, -20, -18, 14, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 130, 5, 0, -20, 24, 14, 1 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 130, 0, 5, 20, -18, 14, 2 + createsprite gRockFragmentSpriteTemplate, ANIM_TARGET, 130, -5, 0, -20, -18, 14, 2 waitforvisualfinish call UnsetPsychicBg end RockWrecker_2: loadspritegfx ANIM_TAG_ROCKS loadspritegfx ANIM_TAG_IMPACT - createsprite gHorizontalLungeSpriteTemplate, 2, 2, 4, 6 + createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 6 delay 3 playsewithpan SE_M_SWAGGER, SOUND_PAN_ATTACKER - createsprite gRockBlastRockSpriteTemplate, 130, 6, 16, 0, 0, 0, 25, 257 + createsprite gRockBlastRockSpriteTemplate, ANIM_ATTACKER, 130, 16, 0, 0, 0, 25, 257 waitforvisualfinish - createsprite gBasicHitSplatSpriteTemplate, 131, 4, 0, 0, 1, 1 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, 0, 0, 1, 1 playsewithpan SE_M_ROCK_THROW SOUND_PAN_TARGET - createsprite gRockFragmentSpriteTemplate 130, 6, 0, 0, 20, 24, 14, 2 + createsprite gRockFragmentSpriteTemplate ANIM_TARGET, 130, 0, 0, 20, 24, 14, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 5, 1 - createsprite gRockFragmentSpriteTemplate 130, 6, 5, 0, -20, 24, 14, 1 - createsprite gRockFragmentSpriteTemplate 130, 6, 0, 5, 20, -18, 14, 2 - createsprite gRockFragmentSpriteTemplate 130, 6, -5, 0, -20, -18, 14, 2 + createsprite gRockFragmentSpriteTemplate ANIM_ATTACKER, 130, 5, 0, -20, 24, 14, 1 + createsprite gRockFragmentSpriteTemplate ANIM_ATTACKER, 130, 0, 5, 20, -18, 14, 2 + createsprite gRockFragmentSpriteTemplate ANIM_ATTACKER, 130, -5, 0, -20, -18, 14, 2 waitforvisualfinish call UnsetPsychicBg end @@ -2785,7 +2785,7 @@ gBattleAnimMove_GunkShot:: splitbgprio ANIM_TARGET setalpha 12, 8 call SetGunkShotBG - createvisualtask AnimTask_ShakeMon, 5, 5, ANIM_ATTACKER, 0, 2, 40, 1 + createvisualtask AnimTask_ShakeMon, 5, ANIM_ATTACKER, 0, 2, 40, 1 delay 6 panse SE_M_HYDRO_PUMP, SOUND_PAN_ATTACKER, SOUND_PAN_TARGET, 2, 0 createvisualtask AnimTask_StartSinAnimTimer, 5, 1, 100 @@ -2817,16 +2817,16 @@ gBattleAnimMove_GunkShot:: blendoff end GunkShotParticles: - createsprite gGunkShoParticlesSpriteTemplate, 3, 4, 10, 10, 0, 16 - createsprite gGunkShoParticlesSpriteTemplate, 3, 4, 10, 10, 0, -16 + createsprite gGunkShoParticlesSpriteTemplate, ANIM_ATTACKER, 3, 10, 10, 0, 16 + createsprite gGunkShoParticlesSpriteTemplate, ANIM_ATTACKER, 3, 10, 10, 0, -16 delay 1 - createsprite gGunkShoParticlesSpriteTemplate, 3, 4, 10, 10, 0, 16 - createsprite gGunkShoParticlesSpriteTemplate, 3, 4, 10, 10, 0, -16 + createsprite gGunkShoParticlesSpriteTemplate, ANIM_ATTACKER, 3, 10, 10, 0, 16 + createsprite gGunkShoParticlesSpriteTemplate, ANIM_ATTACKER, 3, 10, 10, 0, -16 delay 1 return GunkShotImpact: - createsprite gGunkShotImpactSpriteTemplate, 4, 4, 0, 15, 1, 1 - createsprite gGunkShotImpactSpriteTemplate, 4, 4, 0, -15, 1, 1 + createsprite gGunkShotImpactSpriteTemplate, ANIM_TARGET, 4, 0, 15, 1, 1 + createsprite gGunkShotImpactSpriteTemplate, ANIM_TARGET, 4, 0, -15, 1, 1 return SetGunkShotBG: fadetobg BG_GUNK_SHOT @@ -2860,16 +2860,16 @@ gBattleAnimMove_MagnetBomb:: loadspritegfx ANIM_TAG_SPARK_2 delay 0 playsewithpan 119, 192 - createsprite gSparkElectricitySpriteTemplate, 0, 7, 32, 24, 190, 12, 0, 1, 0 + createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 32, 24, 190, 12, 0, 1, 0 delay 0 - createsprite gSparkElectricitySpriteTemplate, 0, 7, 80, 24, 22, 12, 0, 1, 0 - createsprite gSparkElectricitySpriteTemplate, 0, 7, 156, 24, 121, 13, 0, 1, 1 + createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 80, 24, 22, 12, 0, 1, 0 + createsprite gSparkElectricitySpriteTemplate, ANIM_ATTACKER, 0, 156, 24, 121, 13, 0, 1, 1 delay 0 playsewithpan 119, 192 - createsprite gSparkElectricitySpriteTemplate 0, 7, 100, 24, 60, 10, 0, 1, 0 - createsprite gSparkElectricitySpriteTemplate 0, 7, 170, 24, 42, 11, 0, 1, 1 + createsprite gSparkElectricitySpriteTemplate ANIM_ATTACKER, 0, 100, 24, 60, 10, 0, 1, 0 + createsprite gSparkElectricitySpriteTemplate ANIM_ATTACKER, 0, 170, 24, 42, 11, 0, 1, 1 delay 0 - createsprite gSparkElectricitySpriteTemplate 0, 7, 238, 24, 165, 10, 0, 1, 1 + createsprite gSparkElectricitySpriteTemplate ANIM_ATTACKER, 0, 238, 24, 165, 10, 0, 1, 1 delay 0 loadspritegfx ANIM_TAG_RED_ORB playsewithpan 152, SOUND_PAN_ATTACKER @@ -2901,22 +2901,22 @@ gBattleAnimMove_MagnetBomb:: loadspritegfx ANIM_TAG_GRAY_SMOKE loadspritegfx ANIM_TAG_BLACK_BALL playsewithpan 177, 63 - createsprite gOctazookaSmokeSpriteTemplate, 130, 4, 8, 8, 1, 0 + createsprite gOctazookaSmokeSpriteTemplate, ANIM_TARGET, 130, 8, 8, 1, 0 delay 2 - createsprite gOctazookaSmokeSpriteTemplate, 130, 4, -8, -8, 1, 0 + createsprite gOctazookaSmokeSpriteTemplate, ANIM_TARGET, 130, -8, -8, 1, 0 delay 2 - createsprite gOctazookaSmokeSpriteTemplate, 130, 4, 8, -8, 1, 0 + createsprite gOctazookaSmokeSpriteTemplate, ANIM_TARGET, 130, 8, -8, 1, 0 delay 2 - createsprite gOctazookaSmokeSpriteTemplate, 130, 4, -8, 8, 1, 0 + createsprite gOctazookaSmokeSpriteTemplate, ANIM_TARGET, 130, -8, 8, 1, 0 waitforvisualfinish playsewithpan 177, 63 - createsprite gOctazookaSmokeSpriteTemplate, 130, 4, 8, 8, 1, 0 + createsprite gOctazookaSmokeSpriteTemplate, ANIM_TARGET, 130, 8, 8, 1, 0 delay 2 - createsprite gOctazookaSmokeSpriteTemplate, 130, 4, -8, -8, 1, 0 + createsprite gOctazookaSmokeSpriteTemplate, ANIM_TARGET, 130, -8, -8, 1, 0 delay 2 - createsprite gOctazookaSmokeSpriteTemplate, 130, 4, 8, -8, 1, 0 + createsprite gOctazookaSmokeSpriteTemplate, ANIM_TARGET, 130, 8, -8, 1, 0 delay 2 - createsprite gOctazookaSmokeSpriteTemplate, 130, 4, -8, 8, 1, 0 + createsprite gOctazookaSmokeSpriteTemplate, ANIM_TARGET, 130, -8, 8, 1, 0 waitforvisualfinish end @@ -2924,55 +2924,55 @@ gBattleAnimMove_StoneEdge:: loadspritegfx ANIM_TAG_STONE_EDGE loadspritegfx ANIM_TAG_IMPACT playsewithpan SE_M_ROCK_THROW SOUND_PAN_TARGET - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 28, 528, 30, 13, 50, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 28, 528, 30, 13, 50, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 32, 480, 20, 16, -46, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 32, 480, 20, 16, -46, 1 delay 2 loopsewithpan 131, SOUND_PAN_TARGET 24, 3 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 33, 576, 20, 8, 42, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 33, 576, 20, 8, 42, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 31, 400, 25, 11, -42, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 31, 400, 25, 11, -42, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 28, 512, 25, 16, 46, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 28, 512, 25, 16, 46, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 33, 464, 30, 15, 49, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 33, 464, 30, 15, 49, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 28, 528, 30, 13, 50, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 28, 528, 30, 13, 50, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 32, 480, 20, 16, -46, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 32, 480, 20, 16, -46, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 33, 576, 20, 8, 42, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 33, 576, 20, 8, 42, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 31, 400, 25, 11, -42, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 31, 400, 25, 11, -42, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 28, 512, 25, 16, 46, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 28, 512, 25, 16, 46, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 33, 464, 30, 15, 49, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 33, 464, 30, 15, 49, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 28, 528, 30, 13, 50, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 28, 528, 30, 13, 50, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 32, 480, 20, 16, -46, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 32, 480, 20, 16, -46, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 33, 576, 20, 8, 42, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 33, 576, 20, 8, 42, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 31, 400, 25, 11, -42, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 31, 400, 25, 11, -42, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 28, 512, 25, 16, 46, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 28, 512, 25, 16, 46, 1 delay 2 - createsprite gStoneEdgeSpriteTemplate, 130, 7, 0, 33, 464, 30, 15, 49, 1 + createsprite gStoneEdgeSpriteTemplate, ANIM_TARGET, 130, 0, 33, 464, 30, 15, 49, 1 delay 2 - createsprite gBasicHitSplatSpriteTemplate, 131, 4, -32, -16, 1, 3 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, -32, -16, 1, 3 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 3, 0, 12, 1 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_DEF_PARTNER, 3, 0, 12, 1 delay 4 - createsprite gRandomPosHitSplatSpriteTemplate, 131, 2, 1, 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 131, 1, 3 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET delay 4 - createsprite gRandomPosHitSplatSpriteTemplate, 131, 2, 1, 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 131, 1, 3 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET delay 4 - createsprite gBasicHitSplatSpriteTemplate, 131, 4, 32, 20, 1, 3 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, 32, 20, 1, 3 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET waitforvisualfinish clearmonbg ANIM_DEF_PARTNER @@ -2982,14 +2982,14 @@ gBattleAnimMove_StoneEdge:: gBattleAnimMove_Captivate:: loadspritegfx ANIM_TAG_MAGENTA_HEART loadspritegfx ANIM_TAG_SPARKLE_2 - createvisualtask AnimTask_RockMonBackAndForth, 5, ANIM_DEF_PARTNER, 0, 2, 0 - createsprite gMagentaHeartSpriteTemplate, 3, 2, 0, 20 + createvisualtask AnimTask_RockMonBackAndForth, 5, ANIM_ATTACKER, 2, 0 + createsprite gMagentaHeartSpriteTemplate, ANIM_ATTACKER, 3, 0, 20 playsewithpan SE_M_CHARM, SOUND_PAN_ATTACKER delay 15 - createsprite gMagentaHeartSpriteTemplate, 3, 2, -20, 20 + createsprite gMagentaHeartSpriteTemplate, ANIM_ATTACKER, 3, -20, 20 playsewithpan SE_M_CHARM, SOUND_PAN_ATTACKER delay 15 - createsprite gMagentaHeartSpriteTemplate, 3, 2, 20, 20 + createsprite gMagentaHeartSpriteTemplate, ANIM_ATTACKER, 3, 20, 20 playsewithpan 228, SOUND_PAN_ATTACKER call GrantingStarsEffect waitforvisualfinish @@ -3015,14 +3015,14 @@ gBattleAnimMove_StealthRock:: gBattleAnimMove_GrassKnot:: loadspritegfx ANIM_TAG_RAZOR_LEAF loadspritegfx ANIM_TAG_IMPACT - createsprite gSlideMonToOffsetSpriteTemplate, 2, 5, 0, 20, 0, 0, 4 - createsprite gGrassKnotSpriteTemplate, 130, 6, -18, 19, 40, 8, 160, 0 + createsprite gSlideMonToOffsetSpriteTemplate, ANIM_ATTACKER, 2, 0, 20, 0, 0, 4 + createsprite gGrassKnotSpriteTemplate, ANIM_TARGET, 130, -18, 19, 40, 8, 160, 0 delay 4 - createsprite gBasicHitSplatSpriteTemplate, 130, 4, -8, 8, 1, 2 - createvisualtask AnimTask_RotateMonSpriteToSide, 2, 4, 6, 384, ANIM_TARGET, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 130, -8, 8, 1, 2 + createvisualtask AnimTask_RotateMonSpriteToSide, 2, 6, 384, ANIM_TARGET, 2 playsewithpan SE_M_VITAL_THROW2 SOUND_PAN_TARGET waitforvisualfinish - createsprite gSlideMonToOriginalPosSpriteTemplate, 2, 3, 0, 1, 4 + createsprite gSlideMonToOriginalPosSpriteTemplate, ANIM_ATTACKER, 2, 0, 1, 4 end gBattleAnimMove_Chatter:: @@ -3288,10 +3288,10 @@ gBattleAnimMove_AquaJet:: loadspritegfx ANIM_TAG_ROUND_SHADOW loadspritegfx ANIM_TAG_SPLASH playsewithpan SE_M_HEADBUTT, SOUND_PAN_ATTACKER - createsprite gDiveBallSpriteTemplate, 2, 4, 0, 0, 13, 336 + createsprite gDiveBallSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, 13, 336 waitforvisualfinish playsewithpan SE_M_DIVE, SOUND_PAN_ATTACKER - createsprite gDiveWaterSplashSpriteTemplate, 3, 1, 0 + createsprite gDiveWaterSplashSpriteTemplate, ANIM_ATTACKER, 3, 0 call DiveSetUpWaterDroplets call DiveSetUpWaterDroplets call DiveSetUpWaterDroplets @@ -3302,7 +3302,7 @@ gBattleAnimMove_AquaJet:: monbg ANIM_DEF_PARTNER setalpha 12, 8 playsewithpan SE_M_EXPLOSION, SOUND_PAN_TARGET - createsprite gDiveWaterSplashSpriteTemplate, 131, 1, 1 + createsprite gDiveWaterSplashSpriteTemplate, ANIM_TARGET, 131, 1 call DiveAttackWaterDroplets call DiveAttackWaterDroplets call DiveAttackWaterDroplets @@ -3344,18 +3344,18 @@ gBattleAnimMove_AttackOrder:: createsprite gAttackOrderParticleSpriteTemplate, ANIM_TARGET, 5, 20, 255, 15, 32, 0 createsprite gAttackOrderParticleSpriteTemplate, ANIM_TARGET, 5, 110, 10, 8, 32, 20 waitforvisualfinish - createsprite gBasicHitSplatSpriteTemplate 131, 4, -32, -16, 1, 3 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, -32, -16, 1, 3 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 3, 0, 12, 1 createvisualtask AnimTask_ShakeMonInPlace, 2, ANIM_TARGET, 3, 0, 12, 1 delay 4 - createsprite gRandomPosHitSplatSpriteTemplate 131, 2, 1, 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 131, 1, 3 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET delay 4 - createsprite gRandomPosHitSplatSpriteTemplate 131, 2, 1, 3 + createsprite gRandomPosHitSplatSpriteTemplate, ANIM_TARGET, 131, 1, 3 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET delay 4 - createsprite gBasicHitSplatSpriteTemplate 131, 4, 32, 20, 1, 3 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 131, 32, 20, 1, 3 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET waitforvisualfinish clearmonbg ANIM_DEF_PARTNER @@ -3369,26 +3369,26 @@ gBattleAnimMove_DefendOrder:: monbg ANIM_DEF_PARTNER splitbgprio ANIM_TARGET playsewithpan SE_M_SWEET_SCENT, SOUND_PAN_TARGET - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 120, 70, 5, 70, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 120, 70, 5, 70, 30 delay 1 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 55, 6, 60, 25 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 55, 6, 60, 25 delay 1 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 60, 7, 60, 30 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 55, 10, 60, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 60, 7, 60, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 55, 10, 60, 30 delay 3 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 100, 50, 4, 50, 26 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 100, 50, 4, 50, 26 delay 1 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 105, 25, 8, 60, 20 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 105, 25, 8, 60, 20 delay 1 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 40, 10, 48, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 40, 10, 48, 30 delay 3 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 120, 30, 6, 45, 25 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 35, 10, 60, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 120, 30, 6, 45, 25 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 35, 10, 60, 30 delay 3 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 105, 20, 8, 40, 0 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 105, 20, 8, 40, 0 delay 3 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 20, 255, 15, 32, 0 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 110, 10, 8, 32, 20 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 20, 255, 15, 32, 0 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 110, 10, 8, 32, 20 waitforvisualfinish loadspritegfx ANIM_TAG_BLUE_STAR waitforvisualfinish @@ -3406,26 +3406,26 @@ gBattleAnimMove_HealOrder:: monbg ANIM_DEF_PARTNER splitbgprio ANIM_TARGET playsewithpan SE_M_SWEET_SCENT, SOUND_PAN_TARGET - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 120, 70, 5, 70, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 120, 70, 5, 70, 30 delay 1 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 55, 6, 60, 25 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 55, 6, 60, 25 delay 1 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 60, 7, 60, 30 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 55, 10, 60, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 60, 7, 60, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 55, 10, 60, 30 delay 3 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 100, 50, 4, 50, 26 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 100, 50, 4, 50, 26 delay 1 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 105, 25, 8, 60, 20 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 105, 25, 8, 60, 20 delay 1 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 40, 10, 48, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 40, 10, 48, 30 delay 3 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 120, 30, 6, 45, 25 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 115, 35, 10, 60, 30 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 120, 30, 6, 45, 25 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 115, 35, 10, 60, 30 delay 3 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 105, 20, 8, 40, 0 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 105, 20, 8, 40, 0 delay 3 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 20, 255, 15, 32, 0 - createsprite gAttackOrderParticleSpriteTemplate, 130, 5, 110, 10, 8, 32, 20 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 20, 255, 15, 32, 0 + createsprite gAttackOrderParticleSpriteTemplate, ANIM_ATTACKER, 130, 110, 10, 8, 32, 20 waitforvisualfinish loadspritegfx ANIM_TAG_BLUE_STAR waitforvisualfinish @@ -3462,16 +3462,16 @@ gBattleAnimMove_DoubleHit:: loadspritegfx ANIM_TAG_IMPACT monbg ANIM_TARGET setalpha 12, 8 - createsprite gHorizontalLungeSpriteTemplate, 2, 2, 4, 4 + createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 4 delay 6 - createsprite gBasicHitSplatSpriteTemplate, 2, 4, 0, 0, 1, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 0, 0, 1, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET delay 8 waitforvisualfinish - createsprite gHorizontalLungeSpriteTemplate, 2, 2, 4, 4 + createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 4 delay 6 - createsprite gBasicHitSplatSpriteTemplate, 2, 4, 0, 0, 1, 2 + createsprite gBasicHitSplatSpriteTemplate, ANIM_TARGET, 2, 0, 0, 1, 2 createvisualtask AnimTask_ShakeMon, 2, ANIM_TARGET, 3, 0, 6, 1 playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET delay 8 @@ -3560,33 +3560,33 @@ gBattleAnimMove_LunarDance:: loadspritegfx ANIM_TAG_GREEN_SPARKLE loadspritegfx ANIM_TAG_HOLLOW_ORB setalpha 0, 16 - createsprite gSimplePaletteBlendSpriteTemplate, 2, 5, 1, 1, 0, 16, 0 + createsprite gSimplePaletteBlendSpriteTemplate, ANIM_ATTACKER, 2, 1, 1, 0, 16, 0 waitforvisualfinish - createsprite gMoonSpriteTemplate, 2, 2, 120, 56 - createvisualtask AnimTask_AlphaFadeIn, 3, 5, 0, 16, 16, 0, 1 + createsprite gMoonSpriteTemplate, ANIM_ATTACKER, 2, 120, 56 + createvisualtask AnimTask_AlphaFadeIn, 3, 0, 16, 16, 0, 1 playsewithpan 211, 0 delay 30 - createsprite gMoonlightSparkleSpriteTemplate, 40, 2, -12, 0 + createsprite gMoonlightSparkleSpriteTemplate, ANIM_ATTACKER, 40, -12, 0 delay 30 - createsprite gMoonlightSparkleSpriteTemplate, 40, 2, -18, 0 + createsprite gMoonlightSparkleSpriteTemplate, ANIM_ATTACKER, 40, -18, 0 delay 30 - createsprite gMoonlightSparkleSpriteTemplate, 40, 2, 21, 0 + createsprite gMoonlightSparkleSpriteTemplate, ANIM_ATTACKER, 40, 21, 0 delay 30 - createsprite gMoonlightSparkleSpriteTemplate, 40, 2, 0, 0 + createsprite gMoonlightSparkleSpriteTemplate, ANIM_ATTACKER, 40, 0, 0 delay 30 - createsprite gMoonlightSparkleSpriteTemplate, 40, 2, 10, 0 + createsprite gMoonlightSparkleSpriteTemplate, ANIM_ATTACKER, 40, 10, 0 delay 20 createvisualtask AnimTask_MoonlightEndFade, 2, 0 createvisualtask AnimTask_DragonDanceWaver, 5, 0 playsewithpan 203, SOUND_PAN_ATTACKER delay 8 - createvisualtask AnimTask_BlendPalInAndOutByTag, 5, 5, ANIM_TAG_HOLLOW_ORB, RGB(0, 0, 19), 14, 0, 3 - createsprite gDragonDanceOrbSpriteTemplate, 2, 1, 0 - createsprite gDragonDanceOrbSpriteTemplate, 2, 1, 43 - createsprite gDragonDanceOrbSpriteTemplate, 2, 1, 85 - createsprite gDragonDanceOrbSpriteTemplate, 2, 1, 128 - createsprite gDragonDanceOrbSpriteTemplate, 2, 1, 170 - createsprite gDragonDanceOrbSpriteTemplate, 2, 1, 213 + createvisualtask AnimTask_BlendPalInAndOutByTag, 5, ANIM_TAG_HOLLOW_ORB, RGB(0, 0, 19), 14, 0, 3 + createsprite gDragonDanceOrbSpriteTemplate, ANIM_ATTACKER, 2, 0 + createsprite gDragonDanceOrbSpriteTemplate, ANIM_ATTACKER, 2, 43 + createsprite gDragonDanceOrbSpriteTemplate, ANIM_ATTACKER, 2, 85 + createsprite gDragonDanceOrbSpriteTemplate, ANIM_ATTACKER, 2, 128 + createsprite gDragonDanceOrbSpriteTemplate, ANIM_ATTACKER, 2, 170 + createsprite gDragonDanceOrbSpriteTemplate, ANIM_ATTACKER, 2, 213 delay 30 playsewithpan 203, SOUND_PAN_ATTACKER delay 30 @@ -3767,7 +3767,7 @@ gBattleAnimMove_OminousWind:: monbg ANIM_DEF_PARTNER @bankBG_over_partnerBG delay 0 - createvisualtask AnimTask_BlendBattleAnimPalExclude, 10, 5, 1, 0, 0, 0, 0 + createvisualtask AnimTask_BlendBattleAnimPalExclude, 10, 1, 0, 0, 0, 0 delay 0 createvisualtask AnimTask_GetAttackerSide, 2, 0 jumpargeq 7, 1, OminousWindFadeToBg diff --git a/src/battle_anim_dark.c b/src/battle_anim_dark.c index 2400c22aaf..fd9ffdf923 100644 --- a/src/battle_anim_dark.c +++ b/src/battle_anim_dark.c @@ -257,6 +257,10 @@ const struct SpriteTemplate gPunishmentImpactSpriteTemplate = .callback = AnimPunishment, }; +// arg 0: x pixel offset +// arg 1: y pixel offset +// arg 2: Something +// arg 3: Something static void AnimPunishment(struct Sprite *sprite) { StartSpriteAffineAnim(sprite, gBattleAnimArgs[3]); diff --git a/src/battle_anim_electric.c b/src/battle_anim_electric.c index 6deb4667bb..fb9861a3f3 100644 --- a/src/battle_anim_electric.c +++ b/src/battle_anim_electric.c @@ -646,6 +646,13 @@ static void AnimUnusedCirclingShock(struct Sprite *sprite) sprite->callback = TranslateSpriteInCircle; } +// arg 0: +// arg 1: +// arg 2: +// arg 3: duration +// arg 4: target +// arg 5: +// arg 6: void AnimSparkElectricity(struct Sprite *sprite) { u8 battler; diff --git a/src/battle_anim_mon_movement.c b/src/battle_anim_mon_movement.c index 240e43b713..0bacd96219 100644 --- a/src/battle_anim_mon_movement.c +++ b/src/battle_anim_mon_movement.c @@ -908,7 +908,7 @@ static void AnimTask_SlideOffScreen_Step(u8 taskId) // arg 1: wave amplitude // arg 2: wave period // arg 3: num sways -// arg 4: which mon (0 = attacker, 1`= target) +// arg 4: which mon (0 = attacker, 1 = target) void AnimTask_SwayMon(u8 taskId) { u8 spriteId; From 96122d9342ca4ef148147515101e6097cc701d1d Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sun, 12 Jan 2025 13:08:04 +0100 Subject: [PATCH 68/85] Adds Liquid Ooze and Aromatic Mist test (#6012) --- test/battle/ability/liquid_ooze.c | 27 ++++++++++++++++++ test/battle/move_effect/aromatic_mist.c | 38 +++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/test/battle/ability/liquid_ooze.c b/test/battle/ability/liquid_ooze.c index bb4da48f86..b1f94091f6 100644 --- a/test/battle/ability/liquid_ooze.c +++ b/test/battle/ability/liquid_ooze.c @@ -108,5 +108,32 @@ SINGLE_BATTLE_TEST("Liquid Ooze causes Strength Sap users to lose HP instead of } } +SINGLE_BATTLE_TEST("Liquid Ooze causes leech seedee to faint before seeder") +{ + KNOWN_FAILING; // Message fails + u16 ability; + PARAMETRIZE { ability = ABILITY_CLEAR_BODY; } + PARAMETRIZE { ability = ABILITY_LIQUID_OOZE; } + GIVEN { + PLAYER(SPECIES_BULBASAUR) { HP(1); } + OPPONENT(SPECIES_TENTACOOL) { HP(1); Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_LEECH_SEED); } + } SCENE { + MESSAGE("Bulbasaur used Leech Seed!"); + // Drain at end of turn + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_LEECH_SEED_DRAIN, opponent); + if (ability != ABILITY_LIQUID_OOZE) { + MESSAGE("The opposing Tentacool's health is sapped by Leech Seed!"); + MESSAGE("The opposing Tentacool fainted!"); + } else { + ABILITY_POPUP(opponent, ABILITY_LIQUID_OOZE); + MESSAGE("Bulbasaur sucked up the liquid ooze!"); + MESSAGE("The opposing Tentacool fainted!"); + MESSAGE("Bulbasaur fainted!"); + } + } +} + TO_DO_BATTLE_TEST("Liquid Ooze does not cause Dream Eater users to lose HP instead of heal (Gen 3-4"); TO_DO_BATTLE_TEST("Liquid Ooze causes Dream Eater users to lose HP instead of heal (Gen 5+"); diff --git a/test/battle/move_effect/aromatic_mist.c b/test/battle/move_effect/aromatic_mist.c index 516ed14f16..130305cd99 100644 --- a/test/battle/move_effect/aromatic_mist.c +++ b/test/battle/move_effect/aromatic_mist.c @@ -1,5 +1,39 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Aromatic Mist raises Sp. Defense of a target ally by 1 stage"); -TO_DO_BATTLE_TEST("Aromatic Mist fails in Single Battles"); +DOUBLE_BATTLE_TEST("Aromatic Mist raises Sp. Defense of a target ally by 1 stage") +{ + GIVEN { + PLAYER(SPECIES_WEEZING_GALAR); + PLAYER(SPECIES_SYLVEON); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(playerLeft, MOVE_AROMATIC_MIST); } + } SCENE { + MESSAGE("Weezing used Aromatic Mist!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + } THEN { + EXPECT_EQ(playerLeft->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(playerRight->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE + 1); + EXPECT_EQ(opponentLeft->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponentRight->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE); + } +} + +SINGLE_BATTLE_TEST("Aromatic Mist fails in Single Battles") +{ + GIVEN { + PLAYER(SPECIES_WEEZING_GALAR); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_AROMATIC_MIST); } + } SCENE { + MESSAGE("Weezing used Aromatic Mist!"); + MESSAGE("But it failed!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, player); + } THEN { + EXPECT_EQ(player->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE); + EXPECT_EQ(opponent->statStages[STAT_SPDEF], DEFAULT_STAT_STAGE); + } +} From 536f386bed5b030a514d619500862180fa6292eb Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Sun, 12 Jan 2025 18:01:47 -0500 Subject: [PATCH 69/85] Explicitly specify dependencies for teachable learnset helper (#6015) --- Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index 5f806e45ec..a1b6068156 100644 --- a/Makefile +++ b/Makefile @@ -426,8 +426,8 @@ $(OBJ_DIR)/sym_common.ld: sym_common.txt $(C_OBJS) $(wildcard common_syms/*.txt) $(OBJ_DIR)/sym_ewram.ld: sym_ewram.txt $(RAMSCRGEN) ewram_data $< ENGLISH > $@ -# NOTE: Depending on event_scripts.o is hacky, but we want to depend on everything event_scripts.s depends on without having to alter scaninc -$(DATA_SRC_SUBDIR)/pokemon/teachable_learnsets.h: $(DATA_ASM_BUILDDIR)/event_scripts.o +TEACHABLE_DEPS := $(shell find data/ -type f -name '*.inc') $(INCLUDE_DIRS)/constants/tms_hms.h $(C_SUBDIR)/pokemon.c +$(DATA_SRC_SUBDIR)/pokemon/teachable_learnsets.h: $(TEACHABLE_DEPS) python3 $(TOOLS_DIR)/learnset_helpers/teachable.py # Linker script From f1eebc978d05697c6bae087dfb135e35b9c26c27 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Mon, 13 Jan 2025 10:09:55 +0100 Subject: [PATCH 70/85] Fixes defrosting if frozon mon is not damaged by opponent (#6016) Co-authored-by: Bassoonian --- src/battle_script_commands.c | 1 + test/battle/status1/freeze.c | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index ffb03a1d73..32f2b1138b 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -5846,6 +5846,7 @@ static void Cmd_moveend(void) break; case MOVEEND_DEFROST: // defrosting check if (gBattleMons[gBattlerTarget].status1 & STATUS1_FREEZE + && TARGET_TURN_DAMAGED && IsBattlerAlive(gBattlerTarget) && gBattlerAttacker != gBattlerTarget && (moveType == TYPE_FIRE || CanBurnHitThaw(gCurrentMove)) diff --git a/test/battle/status1/freeze.c b/test/battle/status1/freeze.c index f218430909..d19e1776be 100644 --- a/test/battle/status1/freeze.c +++ b/test/battle/status1/freeze.c @@ -43,3 +43,21 @@ SINGLE_BATTLE_TEST("Freeze is thawed by user's Flame Wheel") MESSAGE("Wobbuffet used Flame Wheel!"); } } + +SINGLE_BATTLE_TEST("Freeze isn't thawed if opponent is asleep during thawing attack") +{ + PASSES_RANDOMLY(80, 100, RNG_FROZEN); + GIVEN { + ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE); + PLAYER(SPECIES_WOBBUFFET) { Status1(STATUS1_FREEZE); } + OPPONENT(SPECIES_WOBBUFFET) { Status1(STATUS1_SLEEP); }; + } WHEN { + TURN { MOVE(opponent, MOVE_EMBER); MOVE(player, MOVE_CELEBRATE); } + } SCENE { + NONE_OF { + MESSAGE("The opposing Wobbuffet used Ember!"); + MESSAGE("Wobbuffet thawed out!"); + STATUS_ICON(player, none: TRUE); + } + } +} From 52201b15611e11239dd35fdc66f66e1d5de6100a Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Mon, 13 Jan 2025 06:16:43 -0300 Subject: [PATCH 71/85] Improved Hidden Power test (#6014) --- test/battle/move_effect/hidden_power.c | 141 +++++++++++++------------ 1 file changed, 72 insertions(+), 69 deletions(-) diff --git a/test/battle/move_effect/hidden_power.c b/test/battle/move_effect/hidden_power.c index 8ec63c21a7..d1d175013a 100644 --- a/test/battle/move_effect/hidden_power.c +++ b/test/battle/move_effect/hidden_power.c @@ -4,77 +4,77 @@ // IV combinations sourced from https://www.smogon.com/forums/threads/hidden-power-iv-combinations.78083/ SINGLE_BATTLE_TEST("Hidden Power's type is determined by IVs") { - u32 type, j, foeType, foeSpecies; + u32 type, j, foeType, foeSpecies, foeItem; u32 hp, atk, def, spAtk, spDef, speed; bool32 hidden; PARAMETRIZE { type = TYPE_NONE; hidden = FALSE; } PARAMETRIZE { type = TYPE_NORMAL; hidden = FALSE; } - PARAMETRIZE { type = TYPE_FIGHTING; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; hp = 30; atk = 2; def = 31; spAtk = 30; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_FIGHTING; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; hp = 31; atk = 15; def = 30; spAtk = 30; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_FIGHTING; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; hp = 30; atk = 22; def = 31; spAtk = 30; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_FIGHTING; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; hp = 31; atk = 31; def = 30; spAtk = 30; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_FLYING; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_REGISTEEL; hp = 31; atk = 2; def = 31; spAtk = 30; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_FLYING; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_REGISTEEL; hp = 31; atk = 15; def = 31; spAtk = 30; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_FLYING; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_REGISTEEL; hp = 31; atk = 22; def = 31; spAtk = 30; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_FLYING; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_REGISTEEL; hp = 31; atk = 31; def = 31; spAtk = 30; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_POISON; hidden = TRUE; foeType = TYPE_POISON; foeSpecies = SPECIES_ARBOK; hp = 30; atk = 2; def = 31; spAtk = 30; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_POISON; hidden = TRUE; foeType = TYPE_POISON; foeSpecies = SPECIES_ARBOK; hp = 31; atk = 15; def = 30; spAtk = 30; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_POISON; hidden = TRUE; foeType = TYPE_POISON; foeSpecies = SPECIES_ARBOK; hp = 30; atk = 22; def = 31; spAtk = 30; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_POISON; hidden = TRUE; foeType = TYPE_POISON; foeSpecies = SPECIES_ARBOK; hp = 31; atk = 31; def = 30; spAtk = 30; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_GROUND; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; hp = 31; atk = 2; def = 31; spAtk = 30; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_GROUND; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; hp = 31; atk = 15; def = 31; spAtk = 30; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_GROUND; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; hp = 31; atk = 22; def = 31; spAtk = 30; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_GROUND; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; hp = 31; atk = 31; def = 31; spAtk = 30; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_ROCK; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 2; def = 30; spAtk = 31; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_ROCK; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 15; def = 30; spAtk = 31; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_ROCK; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 22; def = 30; spAtk = 31; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_ROCK; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 31; def = 30; spAtk = 31; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_BUG; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 2; def = 31; spAtk = 31; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_BUG; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 15; def = 31; spAtk = 31; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_BUG; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 22; def = 31; spAtk = 31; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_BUG; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 31; def = 31; spAtk = 31; spDef = 30; speed = 30; } - PARAMETRIZE { type = TYPE_GHOST; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; hp = 31; atk = 2; def = 31; spAtk = 31; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_GHOST; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; hp = 31; atk = 15; def = 30; spAtk = 31; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_GHOST; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; hp = 31; atk = 22; def = 31; spAtk = 31; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_GHOST; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; hp = 31; atk = 31; def = 30; spAtk = 31; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_STEEL; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 2; def = 30; spAtk = 30; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_STEEL; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 15; def = 31; spAtk = 31; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_STEEL; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 22; def = 30; spAtk = 30; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_STEEL; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 31; def = 31; spAtk = 31; spDef = 30; speed = 31; } - PARAMETRIZE { type = TYPE_FIRE; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_BLASTOISE; hp = 31; atk = 2; def = 31; spAtk = 30; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_FIRE; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_BLASTOISE; hp = 31; atk = 15; def = 30; spAtk = 30; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_FIRE; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_BLASTOISE; hp = 31; atk = 22; def = 31; spAtk = 30; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_FIRE; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_BLASTOISE; hp = 31; atk = 31; def = 30; spAtk = 30; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_WATER; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_BLASTOISE; hp = 31; atk = 2; def = 30; spAtk = 30; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_WATER; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_BLASTOISE; hp = 31; atk = 15; def = 31; spAtk = 30; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_WATER; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_BLASTOISE; hp = 31; atk = 22; def = 30; spAtk = 30; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_WATER; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_BLASTOISE; hp = 31; atk = 31; def = 31; spAtk = 30; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_GRASS; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 2; def = 31; spAtk = 30; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_GRASS; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 15; def = 31; spAtk = 30; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_GRASS; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 22; def = 31; spAtk = 30; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_GRASS; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 31; def = 31; spAtk = 30; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_ELECTRIC; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; hp = 31; atk = 2; def = 30; spAtk = 31; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_ELECTRIC; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; hp = 30; atk = 15; def = 30; spAtk = 31; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_ELECTRIC; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; hp = 31; atk = 22; def = 30; spAtk = 31; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_ELECTRIC; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; hp = 30; atk = 31; def = 30; spAtk = 31; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_PSYCHIC; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 2; def = 31; spAtk = 31; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_PSYCHIC; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 15; def = 31; spAtk = 31; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_PSYCHIC; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 31; atk = 22; def = 31; spAtk = 31; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_PSYCHIC; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 31; def = 31; spAtk = 31; spDef = 31; speed = 30; } - PARAMETRIZE { type = TYPE_ICE; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 2; def = 30; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_ICE; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 15; def = 30; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_ICE; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 22; def = 30; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_ICE; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 31; def = 30; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_FIGHTING; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; foeItem = ITEM_CHOPLE_BERRY; hp = 30; atk = 2; def = 31; spAtk = 30; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_FIGHTING; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; foeItem = ITEM_CHOPLE_BERRY; hp = 31; atk = 15; def = 30; spAtk = 30; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_FIGHTING; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; foeItem = ITEM_CHOPLE_BERRY; hp = 30; atk = 22; def = 31; spAtk = 30; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_FIGHTING; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; foeItem = ITEM_CHOPLE_BERRY; hp = 31; atk = 31; def = 30; spAtk = 30; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_FLYING; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_COBA_BERRY; hp = 31; atk = 2; def = 31; spAtk = 30; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_FLYING; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_COBA_BERRY; hp = 31; atk = 15; def = 31; spAtk = 30; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_FLYING; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_COBA_BERRY; hp = 31; atk = 22; def = 31; spAtk = 30; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_FLYING; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_COBA_BERRY; hp = 31; atk = 31; def = 31; spAtk = 30; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_POISON; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_KEBIA_BERRY; hp = 30; atk = 2; def = 31; spAtk = 30; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_POISON; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_KEBIA_BERRY; hp = 31; atk = 15; def = 30; spAtk = 30; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_POISON; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_KEBIA_BERRY; hp = 30; atk = 22; def = 31; spAtk = 30; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_POISON; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_KEBIA_BERRY; hp = 31; atk = 31; def = 30; spAtk = 30; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_GROUND; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; foeItem = ITEM_SHUCA_BERRY; hp = 31; atk = 2; def = 31; spAtk = 30; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_GROUND; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; foeItem = ITEM_SHUCA_BERRY; hp = 31; atk = 15; def = 31; spAtk = 30; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_GROUND; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; foeItem = ITEM_SHUCA_BERRY; hp = 31; atk = 22; def = 31; spAtk = 30; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_GROUND; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; foeItem = ITEM_SHUCA_BERRY; hp = 31; atk = 31; def = 31; spAtk = 30; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_ROCK; hidden = TRUE; foeType = TYPE_FIRE; foeSpecies = SPECIES_VULPIX; foeItem = ITEM_CHARTI_BERRY; hp = 31; atk = 2; def = 30; spAtk = 31; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_ROCK; hidden = TRUE; foeType = TYPE_FIRE; foeSpecies = SPECIES_VULPIX; foeItem = ITEM_CHARTI_BERRY; hp = 31; atk = 15; def = 30; spAtk = 31; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_ROCK; hidden = TRUE; foeType = TYPE_FIRE; foeSpecies = SPECIES_VULPIX; foeItem = ITEM_CHARTI_BERRY; hp = 31; atk = 22; def = 30; spAtk = 31; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_ROCK; hidden = TRUE; foeType = TYPE_FIRE; foeSpecies = SPECIES_VULPIX; foeItem = ITEM_CHARTI_BERRY; hp = 31; atk = 31; def = 30; spAtk = 31; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_BUG; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; foeItem = ITEM_TANGA_BERRY; hp = 31; atk = 2; def = 31; spAtk = 31; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_BUG; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; foeItem = ITEM_TANGA_BERRY; hp = 31; atk = 15; def = 31; spAtk = 31; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_BUG; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; foeItem = ITEM_TANGA_BERRY; hp = 31; atk = 22; def = 31; spAtk = 31; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_BUG; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; foeItem = ITEM_TANGA_BERRY; hp = 31; atk = 31; def = 31; spAtk = 31; spDef = 30; speed = 30; } + PARAMETRIZE { type = TYPE_GHOST; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; foeItem = ITEM_KASIB_BERRY; hp = 31; atk = 2; def = 31; spAtk = 31; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_GHOST; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; foeItem = ITEM_KASIB_BERRY; hp = 31; atk = 15; def = 30; spAtk = 31; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_GHOST; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; foeItem = ITEM_KASIB_BERRY; hp = 31; atk = 22; def = 31; spAtk = 31; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_GHOST; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; foeItem = ITEM_KASIB_BERRY; hp = 31; atk = 31; def = 30; spAtk = 31; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_STEEL; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_BABIRI_BERRY; hp = 31; atk = 2; def = 30; spAtk = 30; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_STEEL; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_BABIRI_BERRY; hp = 31; atk = 15; def = 31; spAtk = 31; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_STEEL; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_BABIRI_BERRY; hp = 31; atk = 22; def = 30; spAtk = 30; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_STEEL; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_BABIRI_BERRY; hp = 31; atk = 31; def = 31; spAtk = 31; spDef = 30; speed = 31; } + PARAMETRIZE { type = TYPE_FIRE; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_OCCA_BERRY; hp = 31; atk = 2; def = 31; spAtk = 30; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_FIRE; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_OCCA_BERRY; hp = 31; atk = 15; def = 30; spAtk = 30; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_FIRE; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_OCCA_BERRY; hp = 31; atk = 22; def = 31; spAtk = 30; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_FIRE; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_OCCA_BERRY; hp = 31; atk = 31; def = 30; spAtk = 30; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_WATER; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_PASSHO_BERRY; hp = 31; atk = 2; def = 30; spAtk = 30; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_WATER; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_PASSHO_BERRY; hp = 31; atk = 15; def = 31; spAtk = 30; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_WATER; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_PASSHO_BERRY; hp = 31; atk = 22; def = 30; spAtk = 30; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_WATER; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_PASSHO_BERRY; hp = 31; atk = 31; def = 31; spAtk = 30; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_GRASS; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_RINDO_BERRY; hp = 30; atk = 2; def = 31; spAtk = 30; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_GRASS; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_RINDO_BERRY; hp = 30; atk = 15; def = 31; spAtk = 30; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_GRASS; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_RINDO_BERRY; hp = 30; atk = 22; def = 31; spAtk = 30; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_GRASS; hidden = TRUE; foeType = TYPE_ROCK; foeSpecies = SPECIES_NOSEPASS; foeItem = ITEM_RINDO_BERRY; hp = 30; atk = 31; def = 31; spAtk = 30; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_ELECTRIC; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_SQUIRTLE; foeItem = ITEM_WACAN_BERRY; hp = 31; atk = 2; def = 30; spAtk = 31; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_ELECTRIC; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_SQUIRTLE; foeItem = ITEM_WACAN_BERRY; hp = 30; atk = 15; def = 30; spAtk = 31; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_ELECTRIC; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_SQUIRTLE; foeItem = ITEM_WACAN_BERRY; hp = 31; atk = 22; def = 30; spAtk = 31; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_ELECTRIC; hidden = TRUE; foeType = TYPE_WATER; foeSpecies = SPECIES_SQUIRTLE; foeItem = ITEM_WACAN_BERRY; hp = 30; atk = 31; def = 30; spAtk = 31; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_PSYCHIC; hidden = TRUE; foeType = TYPE_POISON; foeSpecies = SPECIES_KOFFING; foeItem = ITEM_PAYAPA_BERRY; hp = 31; atk = 2; def = 31; spAtk = 31; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_PSYCHIC; hidden = TRUE; foeType = TYPE_POISON; foeSpecies = SPECIES_KOFFING; foeItem = ITEM_PAYAPA_BERRY; hp = 30; atk = 15; def = 31; spAtk = 31; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_PSYCHIC; hidden = TRUE; foeType = TYPE_POISON; foeSpecies = SPECIES_KOFFING; foeItem = ITEM_PAYAPA_BERRY; hp = 31; atk = 22; def = 31; spAtk = 31; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_PSYCHIC; hidden = TRUE; foeType = TYPE_POISON; foeSpecies = SPECIES_KOFFING; foeItem = ITEM_PAYAPA_BERRY; hp = 30; atk = 31; def = 31; spAtk = 31; spDef = 31; speed = 30; } + PARAMETRIZE { type = TYPE_ICE; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_YACHE_BERRY; hp = 30; atk = 2; def = 30; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_ICE; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_YACHE_BERRY; hp = 30; atk = 15; def = 30; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_ICE; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_YACHE_BERRY; hp = 30; atk = 22; def = 30; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_ICE; hidden = TRUE; foeType = TYPE_GRASS; foeSpecies = SPECIES_TANGELA; foeItem = ITEM_YACHE_BERRY; hp = 30; atk = 31; def = 30; spAtk = 31; spDef = 31; speed = 31; } PARAMETRIZE { type = TYPE_MYSTERY; hidden = FALSE; } - PARAMETRIZE { type = TYPE_DRAGON; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 2; def = 31; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_DRAGON; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 15; def = 31; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_DRAGON; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 22; def = 31; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_DRAGON; hidden = TRUE; foeType = TYPE_STEEL; foeSpecies = SPECIES_KLINK; hp = 30; atk = 31; def = 31; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_DARK; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; hp = 31; atk = 3; def = 31; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_DARK; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; hp = 31; atk = 15; def = 31; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_DARK; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; hp = 31; atk = 23; def = 31; spAtk = 31; spDef = 31; speed = 31; } - PARAMETRIZE { type = TYPE_DARK; hidden = TRUE; foeType = TYPE_DARK; foeSpecies = SPECIES_UMBREON; hp = 31; atk = 31; def = 31; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_DRAGON; hidden = TRUE; foeType = TYPE_DRAGON; foeSpecies = SPECIES_DRATINI; foeItem = ITEM_HABAN_BERRY; hp = 30; atk = 2; def = 31; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_DRAGON; hidden = TRUE; foeType = TYPE_DRAGON; foeSpecies = SPECIES_DRATINI; foeItem = ITEM_HABAN_BERRY; hp = 30; atk = 15; def = 31; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_DRAGON; hidden = TRUE; foeType = TYPE_DRAGON; foeSpecies = SPECIES_DRATINI; foeItem = ITEM_HABAN_BERRY; hp = 30; atk = 22; def = 31; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_DRAGON; hidden = TRUE; foeType = TYPE_DRAGON; foeSpecies = SPECIES_DRATINI; foeItem = ITEM_HABAN_BERRY; hp = 30; atk = 31; def = 31; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_DARK; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; foeItem = ITEM_COLBUR_BERRY; hp = 31; atk = 3; def = 31; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_DARK; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; foeItem = ITEM_COLBUR_BERRY; hp = 31; atk = 15; def = 31; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_DARK; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; foeItem = ITEM_COLBUR_BERRY; hp = 31; atk = 23; def = 31; spAtk = 31; spDef = 31; speed = 31; } + PARAMETRIZE { type = TYPE_DARK; hidden = TRUE; foeType = TYPE_PSYCHIC; foeSpecies = SPECIES_WOBBUFFET; foeItem = ITEM_COLBUR_BERRY; hp = 31; atk = 31; def = 31; spAtk = 31; spDef = 31; speed = 31; } // Any type after Dark shouldn't be part of Hidden Power officially. for (j = TYPE_DARK + 1; j < NUMBER_OF_MON_TYPES; j++) { @@ -83,22 +83,25 @@ SINGLE_BATTLE_TEST("Hidden Power's type is determined by IVs") GIVEN { if (hidden) { - ASSUME(gTypeEffectivenessTable[type][foeType] == UQ_4_12(0.5)); // Foe's Type resists + ASSUME(gTypeEffectivenessTable[type][foeType] == UQ_4_12(2.0)); // Foe's Type resists ASSUME(gSpeciesInfo[foeSpecies].types[0] == gSpeciesInfo[foeSpecies].types[1]); // Foe's pure type - ASSUME(gSpeciesInfo[foeSpecies].types[0] == foeType); // Foe is the resisted type + ASSUME(gSpeciesInfo[foeSpecies].types[0] == foeType); // Foe is the super-effective type + ASSUME(ItemId_GetHoldEffect(foeItem) == HOLD_EFFECT_RESIST_BERRY); // Item is resist berry + ASSUME(ItemId_GetHoldEffectParam(foeItem) == type); // Resist berry of type PLAYER(SPECIES_DUNSPARCE) { HPIV(hp); AttackIV(atk); DefenseIV(def); SpAttackIV(spAtk); SpDefenseIV(spDef); SpeedIV(speed); } } else { PLAYER(SPECIES_DUNSPARCE); } - OPPONENT(foeSpecies); + OPPONENT(foeSpecies) { Item(foeItem); } } WHEN { TURN { MOVE(player, MOVE_HIDDEN_POWER); } } SCENE { // Only test valid Hidden Power types if (hidden) { + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, opponent); // Check that the item is triggered ANIMATION(ANIM_TYPE_MOVE, MOVE_HIDDEN_POWER, player); HP_BAR(opponent); - MESSAGE("It's not very effective…"); + MESSAGE("It's super effective!"); } } } From c02b7ba828f8140b03c48e7b30b605cbf9866559 Mon Sep 17 00:00:00 2001 From: psf <77138753+pkmnsnfrn@users.noreply.github.com> Date: Mon, 13 Jan 2025 11:52:49 -0800 Subject: [PATCH 72/85] Codify new expansion release schedule (#5916) Co-authored-by: Bassoonian Co-authored-by: Eduardo Quezada --- .github/pull_request_template.md | 3 +- docs/SUMMARY.md | 3 +- docs/team_procedures/schedule.md | 51 +++++++++++++++++++++++++++++ docs/{ => team_procedures}/scope.md | 0 4 files changed, 55 insertions(+), 2 deletions(-) create mode 100644 docs/team_procedures/schedule.md rename docs/{ => team_procedures}/scope.md (100%) diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md index f083a2a23f..9a04e86f2b 100644 --- a/.github/pull_request_template.md +++ b/.github/pull_request_template.md @@ -1,11 +1,12 @@ - + ## Description + ## Images diff --git a/docs/SUMMARY.md b/docs/SUMMARY.md index fe13ea72ee..fb10d5b265 100644 --- a/docs/SUMMARY.md +++ b/docs/SUMMARY.md @@ -69,4 +69,5 @@ - [Version 0.9.0](changelogs/0.9.x/0.9.0.md) - [Team Procedures]() - [How to make an Expansion version](team_procedures/expansion_versions.md) - - [Scope Guidelines](scope.md) + - [Release Schedule and Process](team_procedures/schedule.md) + - [Scope Guidelines](team_procedures/scope.md) diff --git a/docs/team_procedures/schedule.md b/docs/team_procedures/schedule.md new file mode 100644 index 0000000000..c23d8a5105 --- /dev/null +++ b/docs/team_procedures/schedule.md @@ -0,0 +1,51 @@ +# Release Schedule and Process + +## Version Lifecycle + +### Minor Release (90 days to next Minor Release) +`upcoming` and `master` are synchronized. Minor Release should occur once every three months. Maintainers can vote to do extra Minor Releases for special cases, but this should be considered highly irregular. + +### Patch Release (60 / 30 days to the next Minor Release) +Releases that focus primarily on bugfixes or improvements to the test system. Patch Releases should occur AT LEAST once a month, but can be more frequent than that. + +### Big Feature Freeze (30 days to the next Minor Release) +PRs with the Github label [`type: big feature`](https://github.com/rh-hideout/pokeemerald-expansion/issues?q=sort%3Aupdated-desc+is%3Aopen+label%3A%22type%3A+big+feature%22) will NOT be merged until after the next Minor Release. + +### Merge Freeze (14 days to the next Minor Release) +PRs that DO NOT have the Github labels [`bugfix`](https://github.com/rh-hideout/pokeemerald-expansion/issues?q=sort%3Aupdated-desc+label%3Abugfix) or [`type: cleanup`](https://github.com/rh-hideout/pokeemerald-expansion/issues?q=sort%3Aupdated-desc+label%3A%22type%3A+cleanup%22+) will NOT be merged until after the next Minor Release. + + +### Sample Schedule +| Major | Minor | Patch | Type | Goal Date | +| ----- | ----- | ----- | ------------------ | ----------- | +| 2 | 1 | 0 | Minor | Dec 1 2025 | +| 2 | 1 | 1 | Patch | Dec 31 2025 | +| 2 | 1 | 2 | Patch | Jan 30 2026 | +| 2 | 1 | 2 | Big Feature Freeze | Jan 30 2026 | +| 2 | 1 | 2 | Merge Freeze | Feb 15 2026 | +| 2 | 1 | 3 | Patch | Mar 1 2026 | +| 2 | 2 | 0 | Minor | Mar 1 2026 | + +--- + +## What is a "Big Feature"? +* If the original owner of the PR thinks a feature should be labeled a Big Feature, it is, no questions asked +* If a reviewer thinks a PR is a Big Feature, then it is +* If the two disagree, it can be discussed in a PR thread, and can ultimately be resolved with a Maintainer vote. + +### How To Identify a Big Feature +* **Big diffs**: It's easy for something to go unnoticed in review when it's a tiny part of a massive diff. +* **High-impact**: High-impact changes are harder to review because they often have consequences that aren't obvious to the reviewer. We catch these consequences from users who use upcoming reporting them. +* **Subjective**: Subjective changes are more likely to have differences of opinions between senate members. +* **Pervasive**: The PR touches several different parts of the codebase or is involved in several different parts of the codebase, even if those elements are small. + +--- + +## Release Blocking and Milestones +When an issue or PR is assigned to a [milestone on Github](https://github.com/rh-hideout/pokeemerald-expansion/milestones) by a Maintainer, that means it is "Blocking". If another Maintainer agrees with this, then that version cannot be released until that issue is resolved or PR is merged. + +This designation should be reserved for instances where an existing feature on `upcoming` or `master` is broken and causing problems for users or players. + +Blocking issues or PRs can be deferred to future releases but should be discussed with the Maintainers that assigned the designation in the first place. + +If a version's milestone does not have any issues or PRs assigned to it, that version should be [released](https://github.com/rh-hideout/pokeemerald-expansion/blob/master/docs/team_procedures/expansion_versions.md) as close to the goal date as possible. diff --git a/docs/scope.md b/docs/team_procedures/scope.md similarity index 100% rename from docs/scope.md rename to docs/team_procedures/scope.md From 7af6c4c09e8884927ef51522c24b28a8999fe021 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Mon, 13 Jan 2025 20:03:18 -0500 Subject: [PATCH 73/85] Workflow for Scope Discussion (#6022) --- docs/team_procedures/scope.md | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/docs/team_procedures/scope.md b/docs/team_procedures/scope.md index fe6333090f..e3c736c1cc 100644 --- a/docs/team_procedures/scope.md +++ b/docs/team_procedures/scope.md @@ -48,10 +48,22 @@ A pull request meets the scope criteria if: ## Discussion Required Categories -Pull Requests that fall into this category should be brought up to maintainers, who will discuss and vote as to whether or not the feature is considered in scope. Considerations for acceptance may include invasiveness of implementation, popularity, ease of maintenance, etc. +Pull Requests that fall into this category are not in scope by default and should be brought up to maintainers, who will discuss and vote as to whether or not the feature is considered in scope. Considerations for acceptance may include invasiveness of implementation, popularity, ease of maintenance, etc. 1. **Developer Ease of Use**: Lowers barrier of entry for developers to use existing behavior 2. **Fangame Features**: Adds a popular feature from other fangames 3. **Popular Non-SS Features**: Exceptions can be made for uniquely popular or requested features (Drowsy, PLA Legend Plate, etc.) 4. **External Program**: External programs like poryscript, porymoves, etc. +## Workflow for Proposed Feature Scope Discussion +For the contributor: +- Make a thread for the feature on Discord +- Describe how the feature fits into this scope document, and why you feel it should be considered +- Optionally include either a draft PR or describe in some detail the proposed implementation. Non-mandatory, but implementation invasiveness, maintenance cost, etc. are major considerations, so use your judgement. The senate may ask for this information during discussion. + +For the senate: +- Make a senate thread for the discussion +- Make and pin a two-week voting poll +- Discuss, conclude, and cast votes before the two-week deadline +- Inform contributor as to the results and reasons in their thread +- Amend this scope document if necessary From 5effd5a8b5a3adce3bff63696218340729ac1352 Mon Sep 17 00:00:00 2001 From: AZero13 Date: Tue, 14 Jan 2025 14:00:48 -0500 Subject: [PATCH 74/85] Remove redundant calls to GetMonData in pokemon.c (#5545) Co-authored-by: Rose <83477269+AreaZR@users.noreply.github.com> --- src/pokemon.c | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/pokemon.c b/src/pokemon.c index 7e38b2e291..eaffcabd39 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -4020,12 +4020,8 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov if (dataUnsigned != CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), temp2)) { dataUnsigned += itemEffect[itemEffectParam]; - moveId = GetMonData(mon, MON_DATA_MOVE1 + temp2, NULL); // Redundant if (dataUnsigned > CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), temp2)) - { - moveId = GetMonData(mon, MON_DATA_MOVE1 + temp2, NULL); // Redundant dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), temp2); - } SetMonData(mon, MON_DATA_PP1 + temp2, &dataUnsigned); retVal = FALSE; } @@ -4041,12 +4037,8 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov if (dataUnsigned != CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex)) { dataUnsigned += itemEffect[itemEffectParam++]; - moveId = GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL); // Redundant if (dataUnsigned > CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex)) - { - moveId = GetMonData(mon, MON_DATA_MOVE1 + moveIndex, NULL); // Redundant dataUnsigned = CalculatePPWithBonus(moveId, GetMonData(mon, MON_DATA_PP_BONUSES, NULL), moveIndex); - } SetMonData(mon, MON_DATA_PP1 + moveIndex, &dataUnsigned); retVal = FALSE; } From 1c3ce75a60268f0b9870dfdde2e0c78d96374494 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 14 Jan 2025 20:01:10 +0100 Subject: [PATCH 75/85] Wrong undefs (#6024) --- src/battle_script_commands.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 32f2b1138b..bbc58f430d 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1913,8 +1913,8 @@ s32 CalcCritChanceStageArgs(u32 battlerAtk, u32 battlerDef, u32 move, bool32 rec return critChance; } -#undef CRIT_BLOCKED -#undef ALWAYS_CRITS +#undef CRITICAL_HIT_BLOCKED +#undef CRITICAL_HIT_ALWAYS s32 CalcCritChanceStage(u32 battlerAtk, u32 battlerDef, u32 move, bool32 recordAbility) { From e8dd8da5f74a2d3b40f48d2f6470ab3be8517ee4 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Tue, 14 Jan 2025 14:13:48 -0500 Subject: [PATCH 76/85] Add AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE (#6025) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- docs/tutorials/ai_flags.md | 3 +++ include/constants/battle_ai.h | 3 ++- src/battle_ai_main.c | 3 ++- test/battle/ai/ai_flag_risky.c | 3 ++- 4 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/tutorials/ai_flags.md b/docs/tutorials/ai_flags.md index 48f8e969eb..0d685f3e0a 100644 --- a/docs/tutorials/ai_flags.md +++ b/docs/tutorials/ai_flags.md @@ -168,3 +168,6 @@ AI will always switch out after a KO in exactly party order as defined in the tr ## `AI_FLAG_WEIGH_ABILITY_PREDICTION` AI will predict the player's ability based to its aiRating. Without this flag the AI randomly assumes an ability with an even distribution between all possible abilities until one is confirmed. With this flag, it instead guesses proportionally to each ability's aiRating, making it far more likely to guess an ability like Water Absorb than Damp if both are options. + +## `AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE` +AI will add score to its highest damaging move, regardless of accuracy or secondary effects. Replaces deprecated `AI_FLAG_PREFER_STRONGEST_MOVE`. diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index d15d8e0c0f..acfe020f49 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -50,8 +50,9 @@ #define AI_FLAG_SEQUENCE_SWITCHING (1 << 19) // AI switches in mons in exactly party order, and never switches mid-battle. #define AI_FLAG_DOUBLE_ACE_POKEMON (1 << 20) // AI has *two* Ace Pokémon. The last two Pokémons in the party won't be used unless they're the last ones remaining. Goes well in battles where the trainer ID equals to twins, couples, etc. #define AI_FLAG_WEIGH_ABILITY_PREDICTION (1 << 21) // AI will predict player's ability based on aiRating +#define AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE (1 << 22) // AI adds score to highest damage move regardless of accuracy or secondary effect -#define AI_FLAG_COUNT 22 +#define AI_FLAG_COUNT 23 // The following options are enough to have a basic/smart trainer. Any other addtion could make the trainer worse/better depending on the flag #define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY) diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 0fefd71fbd..67e06badd6 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -4701,7 +4701,8 @@ static s32 AI_CheckViability(u32 battlerAtk, u32 battlerDef, u32 move, s32 score ADJUST_AND_RETURN_SCORE(NO_DAMAGE_OR_FAILS); // No point in checking the move further so return early else { - if ((AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_RISKY) && GetBestDmgMoveFromBattler(battlerAtk, battlerDef) == move) + if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & (AI_FLAG_RISKY | AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE) + && GetBestDmgMoveFromBattler(battlerAtk, battlerDef) == move) ADJUST_SCORE(BEST_DAMAGE_MOVE); else ADJUST_SCORE(AI_CompareDamagingMoves(battlerAtk, battlerDef, AI_THINKING_STRUCT->movesetIndex)); diff --git a/test/battle/ai/ai_flag_risky.c b/test/battle/ai/ai_flag_risky.c index bbc9a640a6..b725b0f444 100644 --- a/test/battle/ai/ai_flag_risky.c +++ b/test/battle/ai/ai_flag_risky.c @@ -74,12 +74,13 @@ AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: Mid-battle switches prioritize offensive o } } -AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY: AI prefers high damage moves at the expense of accuracy regardless of KO thresholds") +AI_SINGLE_BATTLE_TEST("AI_FLAG_RISKY | AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE: AI prefers high damage moves at the expense of accuracy regardless of KO thresholds") { u32 aiRiskyFlag = 0; PARAMETRIZE { aiRiskyFlag = 0; } PARAMETRIZE { aiRiskyFlag = AI_FLAG_RISKY; } + PARAMETRIZE { aiRiskyFlag = AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE; } GIVEN { AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_CHECK_VIABILITY | AI_FLAG_TRY_TO_FAINT | aiRiskyFlag); From 7eb96ec615653c9939e63f843b76bdfe9538ad88 Mon Sep 17 00:00:00 2001 From: AZero13 Date: Tue, 14 Jan 2025 14:42:55 -0500 Subject: [PATCH 77/85] Use SET8 and SET32 consistently (#5544) Co-authored-by: Rose <83477269+AreaZR@users.noreply.github.com> --- src/pokemon.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/src/pokemon.c b/src/pokemon.c index eaffcabd39..efb4d91abb 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -3074,20 +3074,14 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) SET8(substruct3->metLocation); break; case MON_DATA_MET_LEVEL: - { - u8 metLevel = *data; - substruct3->metLevel = metLevel; + SET8(substruct3->metLevel); break; - } case MON_DATA_MET_GAME: SET8(substruct3->metGame); break; case MON_DATA_POKEBALL: - { - u8 pokeball = *data; - substruct0->pokeball = pokeball; + SET8(substruct0->pokeball); break; - } case MON_DATA_OT_GENDER: SET8(substruct3->otGender); break; @@ -3175,7 +3169,8 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) break; case MON_DATA_IVS: { - u32 ivs = data[0] | (data[1] << 8) | (data[2] << 16) | (data[3] << 24); + u32 ivs; + SET32(ivs); substruct3->hpIV = ivs & MAX_IV_MASK; substruct3->attackIV = (ivs >> 5) & MAX_IV_MASK; substruct3->defenseIV = (ivs >> 10) & MAX_IV_MASK; @@ -3212,12 +3207,8 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg) SET8(substruct3->gigantamaxFactor); break; case MON_DATA_TERA_TYPE: - { - u32 teraType; - SET8(teraType); - substruct0->teraType = teraType; + SET8(substruct0->teraType); break; - } case MON_DATA_EVOLUTION_TRACKER: { union EvolutionTracker evoTracker; From c46f8541f9237f154c894d4cd68762729c1da154 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 14 Jan 2025 21:18:00 +0100 Subject: [PATCH 78/85] =?UTF-8?q?Fixes=20self=20effect=20moves=20not=20pro?= =?UTF-8?q?cing=20for=20spread=20moves=20when=20battler=203=20w=E2=80=A6?= =?UTF-8?q?=20(#6020)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/battle_script_commands.c | 8 ++-- .../move_effects_combined/make_it_rain.c | 43 +++++++++++++++++++ 2 files changed, 46 insertions(+), 5 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index b602cdedf3..3846c55d7f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -3566,7 +3566,7 @@ void SetMoveEffect(bool32 primary, bool32 certain) // For a move that hits multiple targets (i.e. Make it Rain) // we only want to print the message on the final hit - if (!(IsSpreadMove(moveTarget) && GetNextTarget(moveTarget, TRUE) != MAX_BATTLERS_COUNT)) + if (!(NumAffectedSpreadMoveTargets() > 1 && GetNextTarget(moveTarget, TRUE) != MAX_BATTLERS_COUNT)) { BattleScriptPush(gBattlescriptCurrInstr + 1); gBattlescriptCurrInstr = BattleScript_MoveEffectPayDay; @@ -4325,12 +4325,10 @@ void SetMoveEffect(bool32 primary, bool32 certain) static bool32 CanApplyAdditionalEffect(const struct AdditionalEffect *additionalEffect) { - u32 moveTarget = GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove); - // Self-targeting move effects only apply after the last mon has been hit if (additionalEffect->self - && IsSpreadMove(moveTarget) - && GetNextTarget(moveTarget, TRUE) != MAX_BATTLERS_COUNT) + && NumAffectedSpreadMoveTargets() > 1 + && GetNextTarget(GetBattlerMoveTargetType(gBattlerAttacker, gCurrentMove), TRUE) != MAX_BATTLERS_COUNT) return FALSE; // Certain move effects only apply if the target raised stats this turn (e.g. Burning Jealousy) diff --git a/test/battle/move_effects_combined/make_it_rain.c b/test/battle/move_effects_combined/make_it_rain.c index e9c8b153ce..e0e00015a4 100644 --- a/test/battle/move_effects_combined/make_it_rain.c +++ b/test/battle/move_effects_combined/make_it_rain.c @@ -58,3 +58,46 @@ DOUBLE_BATTLE_TEST("Make It Rain lowers special attack by one stage if it hits b MESSAGE("Wobbuffet's Sp. Atk fell!"); } } + +DOUBLE_BATTLE_TEST("Make It Rain lowers special attack by one stage if it hits both targets") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_MAKE_IT_RAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAKE_IT_RAIN, playerLeft); + HP_BAR(opponentLeft); + NONE_OF { + MESSAGE("Coins were scattered everywhere!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Wobbuffet's Sp. Atk fell!"); + } + HP_BAR(opponentRight); + MESSAGE("Coins were scattered everywhere!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Wobbuffet's Sp. Atk fell!"); + } +} +DOUBLE_BATTLE_TEST("Make It Rain lowers special attack by one stage if second target Protects") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, MOVE_PROTECT); MOVE(playerLeft, MOVE_MAKE_IT_RAIN); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PROTECT, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_MAKE_IT_RAIN, playerLeft); + HP_BAR(opponentLeft); + NOT HP_BAR(opponentRight); + MESSAGE("Coins were scattered everywhere!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerLeft); + MESSAGE("Wobbuffet's Sp. Atk fell!"); + } +} From 7c6c9120eabaa9d1c2064cdf378fcac678988e89 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Wed, 15 Jan 2025 14:07:12 +0100 Subject: [PATCH 79/85] Ewram and unused function cleanup sweep (#6019) Co-authored-by: Hedara --- include/battle_controllers.h | 4 - include/contest.h | 1 - include/field_weather.h | 2 - include/global.fieldmap.h | 2 +- include/player_pc.h | 1 - include/scanline_effect.h | 2 - include/trainer_card.h | 1 - src/battle_anim.c | 2 +- src/battle_controller_link_opponent.c | 4 - src/battle_controller_link_partner.c | 4 - src/battle_controller_opponent.c | 4 - src/battle_controller_player.c | 4 - src/battle_controller_player_partner.c | 4 - src/battle_controller_recorded_opponent.c | 4 - src/battle_controller_recorded_player.c | 4 - src/battle_controller_safari.c | 4 - src/battle_controller_wally.c | 4 - src/battle_controllers.c | 59 --------- src/bike.c | 2 - src/credits.c | 6 - src/decoration.c | 1 - src/field_camera.c | 8 +- src/field_weather_effect.c | 7 -- src/fieldmap.c | 1 - src/intro.c | 1 - src/mystery_event_menu.c | 5 - src/pokemon_storage_system.c | 147 +--------------------- src/scanline_effect.c | 4 - 28 files changed, 10 insertions(+), 282 deletions(-) diff --git a/include/battle_controllers.h b/include/battle_controllers.h index 6bd17f90b9..0e5f11e82e 100644 --- a/include/battle_controllers.h +++ b/include/battle_controllers.h @@ -168,10 +168,6 @@ enum CONTROLLER_CHOSENMONRETURNVALUE, CONTROLLER_ONERETURNVALUE, CONTROLLER_ONERETURNVALUE_DUPLICATE, - CONTROLLER_CLEARUNKVAR, - CONTROLLER_SETUNKVAR, - CONTROLLER_CLEARUNKFLAG, - CONTROLLER_TOGGLEUNKFLAG, CONTROLLER_HITANIMATION, CONTROLLER_CANTSWITCH, CONTROLLER_PLAYSE, diff --git a/include/contest.h b/include/contest.h index 8a3b6a3c65..acd12a4ebc 100644 --- a/include/contest.h +++ b/include/contest.h @@ -109,7 +109,6 @@ struct ContestPokemon bool8 gameCleared; u8 isShiny:1; u8 unused1:7; - u8 unused2[9]; u32 personality; u32 otId; }; diff --git a/include/field_weather.h b/include/field_weather.h index ba45d161b7..cff2eb5bc3 100644 --- a/include/field_weather.h +++ b/include/field_weather.h @@ -33,7 +33,6 @@ struct Weather } s1; struct { - u8 filler0[0xA0]; struct Sprite *fogHSprites[NUM_FOG_HORIZONTAL_SPRITES]; struct Sprite *ashSprites[NUM_ASH_SPRITES]; struct Sprite *fogDSprites[NUM_FOG_DIAGONAL_SPRITES]; @@ -129,7 +128,6 @@ struct Weather s16 droughtLastBrightnessStage; s16 droughtTimer; s16 droughtState; - u8 droughtUnused[9]; u8 loadDroughtPalsIndex; u8 loadDroughtPalsOffset; }; diff --git a/include/global.fieldmap.h b/include/global.fieldmap.h index 8ca0422cc8..8540d7b185 100644 --- a/include/global.fieldmap.h +++ b/include/global.fieldmap.h @@ -324,7 +324,7 @@ struct PlayerAvatar /*0x00*/ u8 flags; /*0x01*/ u8 transitionFlags; // used to be named bike, but its definitely not that. seems to be some transition flags /*0x02*/ u8 runningState:7; // this is a static running state. 00 is not moving, 01 is turn direction, 02 is moving. - u8 creeping:1; + u8 creeping:1; /*0x03*/ u8 tileTransitionState; // this is a transition running state: 00 is not moving, 01 is transition between tiles, 02 means you are on the frame in which you have centered on a tile but are about to keep moving, even if changing directions. 2 is also used for a ledge hop, since you are transitioning. /*0x04*/ u8 spriteId; /*0x05*/ u8 objectEventId; diff --git a/include/player_pc.h b/include/player_pc.h index 2521eac131..305c661766 100644 --- a/include/player_pc.h +++ b/include/player_pc.h @@ -9,7 +9,6 @@ struct PlayerPCItemPageStruct u16 itemsAbove; u8 pageItems; u8 count; - u8 filler[3]; u8 scrollIndicatorTaskId; }; diff --git a/include/scanline_effect.h b/include/scanline_effect.h index 80d9df764d..0b395d4f60 100644 --- a/include/scanline_effect.h +++ b/include/scanline_effect.h @@ -30,8 +30,6 @@ struct ScanlineEffect void (*setFirstScanlineReg)(void); u8 srcBuffer; u8 state; - u8 unused16; - u8 unused17; u8 waveTaskId; }; diff --git a/include/trainer_card.h b/include/trainer_card.h index 7c37a84a6c..9e5e53df66 100644 --- a/include/trainer_card.h +++ b/include/trainer_card.h @@ -50,7 +50,6 @@ struct TrainerCard u32 frontier; } linkPoints; // This field is used differently by FRLG vs Emerald /*0x40*/ u32 unionRoomNum; - /*0x44*/ u8 filler[8]; /*0x4C*/ bool8 shouldDrawStickers; // FRLG only /*0x4D*/ u8 unused; /*0x4E*/ u8 monIconTint; // FRLG only diff --git a/src/battle_anim.c b/src/battle_anim.c index 3e079647d2..640e0044ea 100644 --- a/src/battle_anim.c +++ b/src/battle_anim.c @@ -112,7 +112,7 @@ EWRAM_DATA static u16 sSoundAnimFramesToWait = 0; EWRAM_DATA static u8 sMonAnimTaskIdArray[2] = {0}; EWRAM_DATA u8 gAnimMoveTurn = 0; EWRAM_DATA static u8 sAnimBackgroundFadeState = 0; -EWRAM_DATA u16 gAnimMoveIndex = 0; // Set but unused. +EWRAM_DATA u16 gAnimMoveIndex = 0; EWRAM_DATA u8 gBattleAnimAttacker = 0; EWRAM_DATA u8 gBattleAnimTarget = 0; EWRAM_DATA u16 gAnimBattlerSpecies[MAX_BATTLERS_COUNT] = {0}; diff --git a/src/battle_controller_link_opponent.c b/src/battle_controller_link_opponent.c index 7aeefa54b6..c437a687bd 100644 --- a/src/battle_controller_link_opponent.c +++ b/src/battle_controller_link_opponent.c @@ -87,10 +87,6 @@ static void (*const sLinkOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 batt [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, diff --git a/src/battle_controller_link_partner.c b/src/battle_controller_link_partner.c index 283b492a91..795b885f95 100644 --- a/src/battle_controller_link_partner.c +++ b/src/battle_controller_link_partner.c @@ -86,10 +86,6 @@ static void (*const sLinkPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battl [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, diff --git a/src/battle_controller_opponent.c b/src/battle_controller_opponent.c index 898a59c2ee..822b04e04f 100644 --- a/src/battle_controller_opponent.c +++ b/src/battle_controller_opponent.c @@ -101,10 +101,6 @@ static void (*const sOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index bdf13d3101..eacf2d3fb7 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -138,10 +138,6 @@ static void (*const sPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = [CONTROLLER_CHOSENMONRETURNVALUE] = PlayerHandleChosenMonReturnValue, [CONTROLLER_ONERETURNVALUE] = PlayerHandleOneReturnValue, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = PlayerHandleOneReturnValue_Duplicate, - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, diff --git a/src/battle_controller_player_partner.c b/src/battle_controller_player_partner.c index 8bb2bd9993..1fcc4fbef7 100644 --- a/src/battle_controller_player_partner.c +++ b/src/battle_controller_player_partner.c @@ -90,10 +90,6 @@ static void (*const sPlayerPartnerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 bat [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, diff --git a/src/battle_controller_recorded_opponent.c b/src/battle_controller_recorded_opponent.c index afd56a9faf..7cffc5fd5b 100644 --- a/src/battle_controller_recorded_opponent.c +++ b/src/battle_controller_recorded_opponent.c @@ -93,10 +93,6 @@ static void (*const sRecordedOpponentBufferCommands[CONTROLLER_CMDS_COUNT])(u32 [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, diff --git a/src/battle_controller_recorded_player.c b/src/battle_controller_recorded_player.c index 2bb64f3066..568051bd8c 100644 --- a/src/battle_controller_recorded_player.c +++ b/src/battle_controller_recorded_player.c @@ -90,10 +90,6 @@ static void (*const sRecordedPlayerBufferCommands[CONTROLLER_CMDS_COUNT])(u32 ba [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, - [CONTROLLER_CLEARUNKVAR] = BtlController_HandleClearUnkVar, - [CONTROLLER_SETUNKVAR] = BtlController_HandleSetUnkVar, - [CONTROLLER_CLEARUNKFLAG] = BtlController_HandleClearUnkFlag, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_HandleToggleUnkFlag, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, diff --git a/src/battle_controller_safari.c b/src/battle_controller_safari.c index abb2aba946..2d85ddaaec 100644 --- a/src/battle_controller_safari.c +++ b/src/battle_controller_safari.c @@ -82,10 +82,6 @@ static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, - [CONTROLLER_CLEARUNKVAR] = BtlController_Empty, - [CONTROLLER_SETUNKVAR] = BtlController_Empty, - [CONTROLLER_CLEARUNKFLAG] = BtlController_Empty, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_Empty, [CONTROLLER_HITANIMATION] = BtlController_Empty, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = BtlController_HandlePlaySE, diff --git a/src/battle_controller_wally.c b/src/battle_controller_wally.c index 66d3932694..bba1ffd1da 100644 --- a/src/battle_controller_wally.c +++ b/src/battle_controller_wally.c @@ -94,10 +94,6 @@ static void (*const sWallyBufferCommands[CONTROLLER_CMDS_COUNT])(u32 battler) = [CONTROLLER_CHOSENMONRETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE] = BtlController_Empty, [CONTROLLER_ONERETURNVALUE_DUPLICATE] = BtlController_Empty, - [CONTROLLER_CLEARUNKVAR] = BtlController_Empty, - [CONTROLLER_SETUNKVAR] = BtlController_Empty, - [CONTROLLER_CLEARUNKFLAG] = BtlController_Empty, - [CONTROLLER_TOGGLEUNKFLAG] = BtlController_Empty, [CONTROLLER_HITANIMATION] = BtlController_HandleHitAnimation, [CONTROLLER_CANTSWITCH] = BtlController_Empty, [CONTROLLER_PLAYSE] = WallyHandlePlaySE, diff --git a/src/battle_controllers.c b/src/battle_controllers.c index f9106eb764..d60cd34312 100644 --- a/src/battle_controllers.c +++ b/src/battle_controllers.c @@ -28,7 +28,6 @@ static EWRAM_DATA u8 sLinkSendTaskId = 0; static EWRAM_DATA u8 sLinkReceiveTaskId = 0; -EWRAM_DATA struct UnusedControllerStruct gUnusedControllerStruct = {}; // Debug? Unused code that writes to it, never read COMMON_DATA void (*gBattlerControllerFuncs[MAX_BATTLERS_COUNT])(u32 battler) = {0}; COMMON_DATA u8 gBattleControllerData[MAX_BATTLERS_COUNT] = {0}; // Used by the battle controllers to store misc sprite/task IDs for each battler @@ -1371,40 +1370,6 @@ void BtlController_EmitOneReturnValue_Duplicate(u32 battler, u32 bufferId, u16 r PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); } -static void UNUSED BtlController_EmitClearUnkVar(u32 battler, u32 bufferId) -{ - gBattleResources->transferBuffer[0] = CONTROLLER_CLEARUNKVAR; - gBattleResources->transferBuffer[1] = CONTROLLER_CLEARUNKVAR; - gBattleResources->transferBuffer[2] = CONTROLLER_CLEARUNKVAR; - gBattleResources->transferBuffer[3] = CONTROLLER_CLEARUNKVAR; - PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); -} - -static void UNUSED BtlController_EmitSetUnkVar(u32 battler, u32 bufferId, u8 b) -{ - gBattleResources->transferBuffer[0] = CONTROLLER_SETUNKVAR; - gBattleResources->transferBuffer[1] = b; - PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 2); -} - -static void UNUSED BtlController_EmitClearUnkFlag(u32 battler, u32 bufferId) -{ - gBattleResources->transferBuffer[0] = CONTROLLER_CLEARUNKFLAG; - gBattleResources->transferBuffer[1] = CONTROLLER_CLEARUNKFLAG; - gBattleResources->transferBuffer[2] = CONTROLLER_CLEARUNKFLAG; - gBattleResources->transferBuffer[3] = CONTROLLER_CLEARUNKFLAG; - PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); -} - -static void UNUSED BtlController_EmitToggleUnkFlag(u32 battler, u32 bufferId) -{ - gBattleResources->transferBuffer[0] = CONTROLLER_TOGGLEUNKFLAG; - gBattleResources->transferBuffer[1] = CONTROLLER_TOGGLEUNKFLAG; - gBattleResources->transferBuffer[2] = CONTROLLER_TOGGLEUNKFLAG; - gBattleResources->transferBuffer[3] = CONTROLLER_TOGGLEUNKFLAG; - PrepareBufferDataTransfer(battler, bufferId, gBattleResources->transferBuffer, 4); -} - void BtlController_EmitHitAnimation(u32 battler, u32 bufferId) { gBattleResources->transferBuffer[0] = CONTROLLER_HITANIMATION; @@ -2761,30 +2726,6 @@ void BtlController_HandleStatusAnimation(u32 battler) } } -void BtlController_HandleClearUnkVar(u32 battler) -{ - gUnusedControllerStruct.unk = 0; - BattleControllerComplete(battler); -} - -void BtlController_HandleSetUnkVar(u32 battler) -{ - gUnusedControllerStruct.unk = gBattleResources->bufferA[battler][1]; - BattleControllerComplete(battler); -} - -void BtlController_HandleClearUnkFlag(u32 battler) -{ - gUnusedControllerStruct.flag = 0; - BattleControllerComplete(battler); -} - -void BtlController_HandleToggleUnkFlag(u32 battler) -{ - gUnusedControllerStruct.flag ^= 1; - BattleControllerComplete(battler); -} - void BtlController_HandleHitAnimation(u32 battler) { if (gSprites[gBattlerSpriteIds[battler]].invisible == TRUE) diff --git a/src/bike.c b/src/bike.c index 5bbf647ce9..afc3099ab7 100644 --- a/src/bike.c +++ b/src/bike.c @@ -996,8 +996,6 @@ bool8 IsPlayerNotUsingAcroBikeOnBumpySlope(void) void GetOnOffBike(u8 transitionFlags) { - gUnusedBikeCameraAheadPanback = FALSE; - if (gPlayerAvatar.flags & (PLAYER_AVATAR_FLAG_MACH_BIKE | PLAYER_AVATAR_FLAG_ACRO_BIKE)) { SetPlayerAvatarTransitionFlags(PLAYER_AVATAR_FLAG_ON_FOOT); diff --git a/src/credits.c b/src/credits.c index 5d5a80cf78..9269460e92 100644 --- a/src/credits.c +++ b/src/credits.c @@ -81,10 +81,8 @@ struct CreditsEntry const u8 *text; }; -static EWRAM_DATA s16 UNUSED sUnkVar = 0; // Never read, only set to 0 static EWRAM_DATA u16 sSavedTaskId = 0; EWRAM_DATA bool8 gHasHallOfFameRecords = 0; -static EWRAM_DATA bool8 sUsedSpeedUp = 0; // Never read static EWRAM_DATA struct CreditsData *sCreditsData = {0}; static const u16 sCredits_Pal[] = INCBIN_U16("graphics/credits/credits.gbapal"); @@ -355,7 +353,6 @@ static void CB2_Credits(void) VBlankCB_Credits(); RunTasks(); AnimateSprites(); - sUsedSpeedUp = TRUE; } BuildOamBuffer(); UpdatePaletteFade(); @@ -448,7 +445,6 @@ void CB2_StartCreditsSequence(void) SetVBlankCallback(VBlankCB_Credits); m4aSongNumStart(MUS_CREDITS); SetMainCallback2(CB2_Credits); - sUsedSpeedUp = FALSE; sCreditsData = AllocZeroed(sizeof(struct CreditsData)); DeterminePokemonToShow(); @@ -480,7 +476,6 @@ static void Task_CreditsMain(u8 taskId) return; } - sUnkVar = 0; mode = gTasks[taskId].tNextMode; if (gTasks[taskId].tNextMode == MODE_BIKE_SCENE) @@ -740,7 +735,6 @@ static void Task_UpdatePage(u8 taskId) gTasks[taskId].tState = 1; gTasks[taskId].tDelay = 72; gTasks[gTasks[taskId].tMainTaskId].tPrintedPage = FALSE; - sUnkVar = 0; } return; case 1: diff --git a/src/decoration.c b/src/decoration.c index d450ad7dfb..2b8973c815 100644 --- a/src/decoration.c +++ b/src/decoration.c @@ -113,7 +113,6 @@ EWRAM_DATA static u16 sDecorationsCursorPos = 0; EWRAM_DATA static u16 sDecorationsScrollOffset = 0; EWRAM_DATA u8 gCurDecorationIndex = 0; EWRAM_DATA static u8 sCurDecorationCategory = DECORCAT_DESK; -EWRAM_DATA static u32 UNUSED sFiller[2] = {}; EWRAM_DATA static struct DecorationPCContext sDecorationContext = {}; EWRAM_DATA static u8 sDecorMenuWindowIds[WINDOW_COUNT] = {}; EWRAM_DATA static struct DecorationItemsMenu *sDecorationItemsMenu = NULL; diff --git a/src/field_camera.c b/src/field_camera.c index e76ba3d855..89f73ccbec 100644 --- a/src/field_camera.c +++ b/src/field_camera.c @@ -12,7 +12,7 @@ #include "sprite.h" #include "text.h" -EWRAM_DATA bool8 gUnusedBikeCameraAheadPanback = FALSE; +//EWRAM_DATA bool8 gUnusedBikeCameraAheadPanback = FALSE; // Old EWRAM variable that was never set to anything other than false struct FieldCameraOffset { @@ -464,6 +464,11 @@ void UpdateCameraPanning(void) static void CameraPanningCB_PanAhead(void) { + InstallCameraPanAheadCallback(); + // Old code kept for archival purposes + // The else condition could never run since gUnusedBikeCameraAheadPanback was never set to TRUE + // So the behavior should not change + /* u8 var; if (gUnusedBikeCameraAheadPanback == FALSE) @@ -504,4 +509,5 @@ static void CameraPanningCB_PanAhead(void) sVerticalCameraPan -= 2; } } + */ } diff --git a/src/field_weather_effect.c b/src/field_weather_effect.c index cf31e862c3..234c9c56d3 100644 --- a/src/field_weather_effect.c +++ b/src/field_weather_effect.c @@ -15,7 +15,6 @@ #include "gpu_regs.h" EWRAM_DATA static u8 sCurrentAbnormalWeather = 0; -EWRAM_DATA static u16 sUnusedWeatherRelated = 0; const u16 gCloudsWeatherPalette[] = INCBIN_U16("graphics/weather/cloud.gbapal"); const u16 gSandstormWeatherPalette[] = INCBIN_U16("graphics/weather/sandstorm.gbapal"); @@ -2407,12 +2406,6 @@ static void UpdateBubbleSprite(struct Sprite *sprite) //------------------------------------------------------------------------------ -static void UNUSED UnusedSetCurrentAbnormalWeather(u32 weather, u32 unknown) -{ - sCurrentAbnormalWeather = weather; - sUnusedWeatherRelated = unknown; -} - #define tState data[0] #define tWeatherA data[1] #define tWeatherB data[2] diff --git a/src/fieldmap.c b/src/fieldmap.c index 34a654861a..84e3c564fc 100644 --- a/src/fieldmap.c +++ b/src/fieldmap.c @@ -30,7 +30,6 @@ EWRAM_DATA u16 ALIGNED(4) sBackupMapData[MAX_MAP_DATA_SIZE] = {0}; EWRAM_DATA struct MapHeader gMapHeader = {0}; EWRAM_DATA struct Camera gCamera = {0}; EWRAM_DATA static struct ConnectionFlags sMapConnectionFlags = {0}; -EWRAM_DATA static u32 UNUSED sFiller = 0; // without this, the next file won't align properly COMMON_DATA struct BackupMapLayout gBackupMapLayout = {0}; diff --git a/src/intro.c b/src/intro.c index 5409833733..93417bc4a1 100644 --- a/src/intro.c +++ b/src/intro.c @@ -176,7 +176,6 @@ enum { #define TIMER_START_LEGENDARIES 43 static EWRAM_DATA u16 sIntroCharacterGender = 0; -static EWRAM_DATA u16 UNUSED sUnusedVar = 0; static EWRAM_DATA u16 sFlygonYOffset = 0; COMMON_DATA u32 gIntroFrameCounter = 0; diff --git a/src/mystery_event_menu.c b/src/mystery_event_menu.c index 79cab2b050..67ec7855ad 100644 --- a/src/mystery_event_menu.c +++ b/src/mystery_event_menu.c @@ -28,8 +28,6 @@ enum { static void CB2_MysteryEventMenu(void); static void PrintMysteryMenuText(u8 windowId, const u8 *text, u8 x, u8 y, s32 speed); -static EWRAM_DATA u8 sUnused = 0; // set but unused - static const struct BgTemplate sBgTemplates[] = { { @@ -270,10 +268,7 @@ static void CB2_MysteryEventMenu(void) break; case 13: if (!IsTextPrinterActive(WIN_MSG)) - { gMain.state++; - sUnused = 0; - } break; case 14: if (JOY_NEW(A_BUTTON)) diff --git a/src/pokemon_storage_system.c b/src/pokemon_storage_system.c index 4498832743..81dff0f435 100644 --- a/src/pokemon_storage_system.c +++ b/src/pokemon_storage_system.c @@ -371,35 +371,15 @@ struct StorageMenu int textId; }; -struct UnkUtilData -{ - const u8 *src; - u8 *dest; - u16 size; - u16 unk; - u16 height; - void (*func)(struct UnkUtilData *data); -}; - -struct UnkUtil -{ - struct UnkUtilData *data; - u8 numActive; - u8 max; -}; - struct ChooseBoxMenu { struct Sprite *menuSprite; struct Sprite *menuSideSprites[4]; - u32 unused1[3]; struct Sprite *arrowSprites[2]; - u8 unused2[0x214]; bool32 loadedPalette; u16 tileTag; u16 paletteTag; u8 curBox; - u8 unused3; u8 subpriority; }; @@ -420,12 +400,8 @@ struct PokemonStorageSystemData u8 screenChangeType; bool8 isReopening; u8 taskId; - struct UnkUtil unkUtil; - struct UnkUtilData unkUtilData[8]; u16 partyMenuTilemapBuffer[0x108]; - u16 partyMenuUnused1; // Never read u16 partyMenuY; - u8 partyMenuUnused2; // Unused u8 partyMenuMoveTimer; u8 showPartyMenuState; bool8 closeBoxFlashing; @@ -436,18 +412,8 @@ struct PokemonStorageSystemData s16 scrollSpeed; u16 scrollTimer; u8 wallpaperOffset; - u8 scrollUnused1; // Never read - u8 scrollToBoxIdUnused; // Never read - u16 scrollUnused2; // Never read - s16 scrollDirectionUnused; // Never read. - u16 scrollUnused3; // Never read - u16 scrollUnused4; // Never read - u16 scrollUnused5; // Never read - u16 scrollUnused6; // Never read - u8 filler1[22]; - u8 boxTitleTiles[1024]; + u8 ALIGNED(2) boxTitleTiles[1024]; u8 boxTitleCycleId; - u8 wallpaperLoadState; // Written to, but never read. u8 wallpaperLoadBoxId; s8 wallpaperLoadDir; u16 boxTitlePal[16]; @@ -457,8 +423,6 @@ struct PokemonStorageSystemData struct Sprite *nextBoxTitleSprites[2]; struct Sprite *arrowSprites[2]; u32 wallpaperPalBits; - u8 filler2[80]; // Unused - u16 unkUnused1; // Never read. s16 wallpaperSetId; s16 wallpaperId; u16 wallpaperTilemap[360]; @@ -486,12 +450,10 @@ struct PokemonStorageSystemData u8 iconScrollCurColumn; s8 iconScrollDirection; // Unnecessary duplicate of scrollDirection u8 iconScrollState; - u8 iconScrollToBoxId; // Unused duplicate of scrollToBoxId struct WindowTemplate menuWindow; struct StorageMenu menuItems[7]; u8 menuItemsCount; u8 menuWidth; - u8 menuUnusedField; // Never read. u16 menuWindowId; struct Sprite *cursorSprite; struct Sprite *cursorShadowSprite; @@ -559,7 +521,6 @@ struct PokemonStorageSystemData struct ItemIcon itemIcons[MAX_ITEM_ICONS]; u16 movingItemId; u16 itemInfoWindowOffset; - u8 unkUnused2; // Unused u16 displayMonPalOffset; u16 *displayMonTilePtr; struct Sprite *displayMonSprite; @@ -882,12 +843,6 @@ static void TilemapUtil_Update(u8); static void TilemapUtil_DrawPrev(u8); static void TilemapUtil_Draw(u8); -// Unknown utility -static void UnkUtil_Init(struct UnkUtil *, struct UnkUtilData *, u32); -static void UnkUtil_Run(void); -static void UnkUtil_CpuRun(struct UnkUtilData *); -static void UnkUtil_DmaRun(struct UnkUtilData *); - // Form changing void SetMonFormPSS(struct BoxPokemon *boxMon); void UpdateSpeciesSpritePSS(struct BoxPokemon *boxmon); @@ -2002,7 +1957,6 @@ static void VBlankCB_PokeStorage(void) { LoadOam(); ProcessSpriteCopyRequests(); - UnkUtil_Run(); TransferPlttBuffer(); if (sStorage != NULL) { @@ -2079,7 +2033,6 @@ static void ResetForPokeStorage(void) FreeAllSpritePalettes(); ClearDma3Requests(); gReservedSpriteTileCount = 0x280; - UnkUtil_Init(&sStorage->unkUtil, sStorage->unkUtilData, ARRAY_COUNT(sStorage->unkUtilData)); gKeyRepeatStartDelay = 20; ClearScheduledBgCopiesToVram(); TilemapUtil_Init(TILEMAPID_COUNT); @@ -4116,7 +4069,6 @@ static void InitSupplementalTilemaps(void) static void SetUpShowPartyMenu(void) { - sStorage->partyMenuUnused1 = 20; sStorage->partyMenuY = 2; sStorage->partyMenuMoveTimer = 0; CreatePartyMonsSprites(FALSE); @@ -4127,7 +4079,6 @@ static bool8 ShowPartyMenu(void) if (sStorage->partyMenuMoveTimer == 20) return FALSE; - sStorage->partyMenuUnused1--; sStorage->partyMenuY++; TilemapUtil_Move(TILEMAPID_PARTY_MENU, 3, 1); TilemapUtil_Update(TILEMAPID_PARTY_MENU); @@ -4146,7 +4097,6 @@ static bool8 ShowPartyMenu(void) static void SetUpHidePartyMenu(void) { - sStorage->partyMenuUnused1 = 0; sStorage->partyMenuY = 22; sStorage->partyMenuMoveTimer = 0; if (sStorage->boxOption == OPTION_MOVE_ITEMS) @@ -4157,7 +4107,6 @@ static bool8 HidePartyMenu(void) { if (sStorage->partyMenuMoveTimer != 20) { - sStorage->partyMenuUnused1++; sStorage->partyMenuY--; TilemapUtil_Move(TILEMAPID_PARTY_MENU, 3, -1); TilemapUtil_Update(TILEMAPID_PARTY_MENU); @@ -4465,7 +4414,6 @@ static void InitMonIconFields(void) sStorage->boxMonsSprites[i] = NULL; sStorage->movingMonSprite = NULL; - sStorage->unkUnused1 = 0; } static u8 GetMonIconPriorityByCursorPos(void) @@ -4686,7 +4634,6 @@ static u8 CreateBoxMonIconsInColumn(u8 column, u16 distance, s16 speed) static void InitBoxMonIconScroll(u8 boxId, s8 direction) { sStorage->iconScrollState = 0; - sStorage->iconScrollToBoxId = boxId; sStorage->iconScrollDirection = direction; sStorage->iconScrollDistance = 32; sStorage->iconScrollSpeed = -(6 * direction); @@ -5318,16 +5265,8 @@ static void SetUpScrollToBox(u8 boxId) s8 direction = DetermineBoxScrollDirection(boxId); sStorage->scrollSpeed = (direction > 0) ? 6 : -6; - sStorage->scrollUnused1 = (direction > 0) ? 1 : 2; sStorage->scrollTimer = 32; - sStorage->scrollToBoxIdUnused = boxId; - sStorage->scrollUnused2 = (direction <= 0) ? 5 : 0; - sStorage->scrollDirectionUnused = direction; - sStorage->scrollUnused3 = (direction > 0) ? 264 : 56; - sStorage->scrollUnused4 = (direction <= 0) ? 5 : 0; - sStorage->scrollUnused5 = 0; - sStorage->scrollUnused6 = 2; sStorage->scrollToBoxId = boxId; sStorage->scrollDirection = direction; sStorage->scrollState = 0; @@ -5437,7 +5376,6 @@ static void LoadWallpaperGfx(u8 boxId, s8 direction) void *iconGfx; u32 tilesSize, iconSize; - sStorage->wallpaperLoadState = 0; sStorage->wallpaperLoadBoxId = boxId; sStorage->wallpaperLoadDir = direction; if (sStorage->wallpaperLoadDir != 0) @@ -8133,7 +8071,6 @@ static void AddMenu(void) PrintMenuTable(sStorage->menuWindowId, sStorage->menuItemsCount, (void *)sStorage->menuItems); InitMenuInUpperLeftCornerNormal(sStorage->menuWindowId, sStorage->menuItemsCount, 0); ScheduleBgCopyTilemapToVram(0); - sStorage->menuUnusedField = 0; } // Called after AddMenu to determine whether or not the handler callback should @@ -10103,88 +10040,6 @@ static void TilemapUtil_Draw(u8 id) // so UnkUtil_Run performs no actions. //------------------------------------------------------------------------------ - -EWRAM_DATA static struct UnkUtil *sUnkUtil = NULL; - -static void UnkUtil_Init(struct UnkUtil *util, struct UnkUtilData *data, u32 max) -{ - sUnkUtil = util; - util->data = data; - util->max = max; - util->numActive = 0; -} - -static void UnkUtil_Run(void) -{ - u16 i; - if (sUnkUtil->numActive) - { - for (i = 0; i < sUnkUtil->numActive; i++) - { - struct UnkUtilData *data = &sUnkUtil->data[i]; - data->func(data); - } - sUnkUtil->numActive = 0; - } -} - -static bool8 UNUSED UnkUtil_CpuAdd(u8 *dest, u16 dLeft, u16 dTop, const u8 *src, u16 sLeft, u16 sTop, u16 width, u16 height, u16 unkArg) -{ - struct UnkUtilData *data; - - if (sUnkUtil->numActive >= sUnkUtil->max) - return FALSE; - - data = &sUnkUtil->data[sUnkUtil->numActive++]; - data->size = width * 2; - data->dest = dest + 2 * (dTop * 32 + dLeft); - data->src = src + 2 * (sTop * unkArg + sLeft); - data->height = height; - data->unk = unkArg; - data->func = UnkUtil_CpuRun; - return TRUE; -} - -// Functionally unused -static void UnkUtil_CpuRun(struct UnkUtilData *data) -{ - u16 i; - - for (i = 0; i < data->height; i++) - { - CpuCopy16(data->src, data->dest, data->size); - data->dest += 64; - data->src += data->unk * 2; - } -} - -static bool8 UNUSED UnkUtil_DmaAdd(void *dest, u16 dLeft, u16 dTop, u16 width, u16 height) -{ - struct UnkUtilData *data; - - if (sUnkUtil->numActive >= sUnkUtil->max) - return FALSE; - - data = &sUnkUtil->data[sUnkUtil->numActive++]; - data->size = width * 2; - data->dest = dest + (dTop * 32 + dLeft) * 2; - data->height = height; - data->func = UnkUtil_DmaRun; - return TRUE; -} - -// Functionally unused -static void UnkUtil_DmaRun(struct UnkUtilData *data) -{ - u16 i; - - for (i = 0; i < data->height; i++) - { - Dma3FillLarge16_(0, data->dest, data->size); - data->dest += 64; - } -} - void UpdateSpeciesSpritePSS(struct BoxPokemon *boxMon) { u16 species = GetBoxMonData(boxMon, MON_DATA_SPECIES); diff --git a/src/scanline_effect.c b/src/scanline_effect.c index 684c89546a..ce9bf190ab 100644 --- a/src/scanline_effect.c +++ b/src/scanline_effect.c @@ -38,8 +38,6 @@ void ScanlineEffect_Clear(void) gScanlineEffect.dmaControl = 0; gScanlineEffect.srcBuffer = 0; gScanlineEffect.state = 0; - gScanlineEffect.unused16 = 0; - gScanlineEffect.unused17 = 0; gScanlineEffect.waveTaskId = TASK_NONE; } @@ -65,8 +63,6 @@ void ScanlineEffect_SetParams(struct ScanlineEffectParams params) gScanlineEffect.dmaControl = params.dmaControl; gScanlineEffect.dmaDest = params.dmaDest; gScanlineEffect.state = params.initState; - gScanlineEffect.unused16 = params.unused9; - gScanlineEffect.unused17 = params.unused9; } void ScanlineEffect_InitHBlankDmaTransfer(void) From ed0c9a46712cc589f3bca439e00d3e8fd1a9c66c Mon Sep 17 00:00:00 2001 From: Martin Griffin Date: Wed, 15 Jan 2025 13:22:26 +0000 Subject: [PATCH 80/85] Restore lock/lockall/locktrainer/release/releaseall in triggers (#5976) --- include/script.h | 8 ++++---- src/scrcmd.c | 15 --------------- 2 files changed, 4 insertions(+), 19 deletions(-) diff --git a/include/script.h b/include/script.h index 68e0c9e20e..1546d15dd4 100644 --- a/include/script.h +++ b/include/script.h @@ -1,8 +1,6 @@ #ifndef GUARD_SCRIPT_H #define GUARD_SCRIPT_H -#include - struct ScriptContext; typedef bool8 (*ScrCmdFunc)(struct ScriptContext *); @@ -107,9 +105,11 @@ enum // effects SCREFF_TRAINERBATTLE = 1 << 2, // 'trainerbattle' command. }; +#define SCREFF_ANY (SCREFF_SAVE | SCREFF_HARDWARE | SCREFF_TRAINERBATTLE) + enum // effects versions { - SCREFF_V1 = ~7, + SCREFF_V1 = 0xFFFFFFF8, }; extern struct ScriptEffectContext *gScriptEffectContext; @@ -140,7 +140,7 @@ static inline bool32 Script_IsAnalyzingEffects(void) _Static_assert((effects) & 0x80000000, "Script_RequestEffects requires an effects version"); \ if ((effects) != SCREFF_V1) \ if (Script_IsAnalyzingEffects()) \ - Script_RequestEffects_Internal(effects); \ + Script_RequestEffects_Internal((effects) & SCREFF_ANY); \ }) /* Optimize 'Script_RequestWriteVar' to a no-op if it would have no diff --git a/src/scrcmd.c b/src/scrcmd.c index 54585aa503..cf65ad270d 100644 --- a/src/scrcmd.c +++ b/src/scrcmd.c @@ -1527,9 +1527,6 @@ bool8 ScrCmd_turnvobject(struct ScriptContext *ctx) // The player is frozen after waiting for their current movement to finish. bool8 ScrCmd_lockall(struct ScriptContext *ctx) { - // As a special case, skip this during analysis. - if (Script_IsAnalyzingEffects()) - return FALSE; Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); if (IsOverworldLinkActive()) @@ -1548,9 +1545,6 @@ bool8 ScrCmd_lockall(struct ScriptContext *ctx) // The player and selected object are frozen after waiting for their current movement to finish. bool8 ScrCmd_lock(struct ScriptContext *ctx) { - // As a special case, skip this during analysis. - if (Script_IsAnalyzingEffects()) - return FALSE; Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); if (IsOverworldLinkActive()) @@ -1581,9 +1575,6 @@ bool8 ScrCmd_lock(struct ScriptContext *ctx) bool8 ScrCmd_releaseall(struct ScriptContext *ctx) { - // As a special case, skip this during analysis. - if (Script_IsAnalyzingEffects()) - return FALSE; Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); u8 playerObjectId; @@ -1603,9 +1594,6 @@ bool8 ScrCmd_releaseall(struct ScriptContext *ctx) bool8 ScrCmd_release(struct ScriptContext *ctx) { - // As a special case, skip this during analysis. - if (Script_IsAnalyzingEffects()) - return FALSE; Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); u8 playerObjectId; @@ -2858,9 +2846,6 @@ bool8 ScrCmd_selectapproachingtrainer(struct ScriptContext *ctx) bool8 ScrCmd_lockfortrainer(struct ScriptContext *ctx) { - // As a special case, skip this during analysis. - if (Script_IsAnalyzingEffects()) - return FALSE; Script_RequestEffects(SCREFF_V1 | SCREFF_HARDWARE); if (IsOverworldLinkActive()) From fd26d3a4068ecd5206c4f86d2323acd319565cbc Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Wed, 15 Jan 2025 09:20:31 -0500 Subject: [PATCH 81/85] Fix Redirection Abilities Not Drawing in Ally Moves (#6026) Co-authored-by: ghoulslash --- include/config/battle.h | 1 + src/battle_util.c | 59 +++++++++++++++++++---------- test/battle/ability/lightning_rod.c | 26 +++++++++++++ test/battle/move_effect/pledge.c | 2 +- 4 files changed, 66 insertions(+), 22 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index cdb0caacfe..8853d04324 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -142,6 +142,7 @@ #define B_SYMBIOSIS_GEMS GEN_LATEST // In Gen7+, Symbiosis passes an item after a gem-boosted attack. Previously, items are passed before the gem-boosted attack hits, making the item effect apply. #define B_ABSORBING_ABILITY_STRING GEN_LATEST // In Gen5+, the abilities that absorb moves of a certain type use a generic string for stat increases and decreases. #define B_REDIRECT_ABILITY_IMMUNITY GEN_LATEST // In Gen5+, Pokémon with Lightning Rod/Storm Drain become immune to Electric/Water-type moves and increase their Sp. Attack by 1 stage on top of the redirecting effect. +#define B_REDIRECT_ABILITY_ALLIES GEN_LATEST // In Gen4+, Lightning Rod/Storm Drain redirect ally's moves as well. #define B_LEAF_GUARD_PREVENTS_REST GEN_LATEST // In Gen5+, Leaf Guard prevents the use of Rest in harsh sunlight. #define B_SNOW_WARNING GEN_LATEST // In Gen9+, Snow Warning will summon snow instead of hail. #define B_TRANSISTOR_BOOST GEN_LATEST // In Gen9+, Transistor will only boost Electric-type moves by 1.3x as opposed to 1.5x. diff --git a/src/battle_util.c b/src/battle_util.c index 2c53b2282d..6d56a40e53 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -126,7 +126,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) // Functions void HandleAction_UseMove(void) { - u32 battler, i, side, moveType, var = 4; + u32 battler, i, side, moveType, ability, var = MAX_BATTLERS_COUNT; u16 moveTarget; gBattlerAttacker = gBattlerByTurnOrder[gCurrentTurnActionNumber]; @@ -217,6 +217,7 @@ void HandleAction_UseMove(void) // choose target side = BATTLE_OPPOSITE(GetBattlerSide(gBattlerAttacker)); + ability = GetBattlerAbility(gBattleStruct->moveTarget[gBattlerAttacker]); if (IsAffectedByFollowMe(gBattlerAttacker, side, gCurrentMove) && moveTarget == MOVE_TARGET_SELECTED && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gSideTimers[side].followmeTarget)) @@ -226,16 +227,18 @@ void HandleAction_UseMove(void) else if (IsDoubleBattle() && gSideTimers[side].followmeTimer == 0 && (!IS_MOVE_STATUS(gCurrentMove) || (moveTarget != MOVE_TARGET_USER && moveTarget != MOVE_TARGET_ALL_BATTLERS)) - && ((GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) - || (GetBattlerAbility(*(gBattleStruct->moveTarget + gBattlerAttacker)) != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) + && ((ability != ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) + || (ability != ABILITY_STORM_DRAIN && moveType == TYPE_WATER))) { - side = GetBattlerSide(gBattlerAttacker); + // Find first battler that redirects the move (in turn order) for (battler = 0; battler < gBattlersCount; battler++) { - if (side != GetBattlerSide(battler) - && *(gBattleStruct->moveTarget + gBattlerAttacker) != battler - && ((GetBattlerAbility(battler) == ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) - || (GetBattlerAbility(battler) == ABILITY_STORM_DRAIN && moveType == TYPE_WATER)) + ability = GetBattlerAbility(battler); + if ((B_REDIRECT_ABILITY_ALLIES >= GEN_4 || !IsAlly(gBattlerAttacker, battler)) + && battler != gBattlerAttacker + && gBattleStruct->moveTarget[gBattlerAttacker] != battler + && ((ability == ABILITY_LIGHTNING_ROD && moveType == TYPE_ELECTRIC) + || (ability == ABILITY_STORM_DRAIN && moveType == TYPE_WATER)) && GetBattlerTurnOrderNum(battler) < var && gMovesInfo[gCurrentMove].effect != EFFECT_SNIPE_SHOT && gMovesInfo[gCurrentMove].effect != EFFECT_PLEDGE @@ -245,7 +248,7 @@ void HandleAction_UseMove(void) var = GetBattlerTurnOrderNum(battler); } } - if (var == 4) + if (var == MAX_BATTLERS_COUNT) { if (moveTarget & MOVE_TARGET_RANDOM) { @@ -8446,22 +8449,36 @@ u32 GetMoveTarget(u16 move, u8 setTarget) } else { + u32 battlerAbilityOnField = 0; + targetBattler = SetRandomTarget(gBattlerAttacker); - if (moveType == TYPE_ELECTRIC - && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_LIGHTNING_ROD) - && GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD) + if (moveType == TYPE_ELECTRIC && GetBattlerAbility(targetBattler) != ABILITY_LIGHTNING_ROD) { - targetBattler ^= BIT_FLANK; - RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); - gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + if (B_REDIRECT_ABILITY_ALLIES >= GEN_4) + battlerAbilityOnField = IsAbilityOnField(ABILITY_LIGHTNING_ROD); + else + battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_LIGHTNING_ROD); + + if (battlerAbilityOnField > 0) + { + targetBattler = battlerAbilityOnField - 1; + RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); + gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + } } - else if (moveType == TYPE_WATER - && IsAbilityOnOpposingSide(gBattlerAttacker, ABILITY_STORM_DRAIN) - && GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN) + else if (moveType == TYPE_WATER && GetBattlerAbility(targetBattler) != ABILITY_STORM_DRAIN) { - targetBattler ^= BIT_FLANK; - RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); - gSpecialStatuses[targetBattler].stormDrainRedirected = TRUE; + if (B_REDIRECT_ABILITY_ALLIES >= GEN_4) + battlerAbilityOnField = IsAbilityOnField(ABILITY_STORM_DRAIN); + else + battlerAbilityOnField = IsAbilityOnOpposingSide(targetBattler, ABILITY_STORM_DRAIN); + + if (battlerAbilityOnField > 0) + { + targetBattler = battlerAbilityOnField - 1; + RecordAbilityBattle(targetBattler, gBattleMons[targetBattler].ability); + gSpecialStatuses[targetBattler].lightningRodRedirected = TRUE; + } } } break; diff --git a/test/battle/ability/lightning_rod.c b/test/battle/ability/lightning_rod.c index c719ee145d..38903f373b 100644 --- a/test/battle/ability/lightning_rod.c +++ b/test/battle/ability/lightning_rod.c @@ -71,3 +71,29 @@ DOUBLE_BATTLE_TEST("Lightning Rod forces single-target Electric-type moves to ta ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, opponentRight); } } + +DOUBLE_BATTLE_TEST("Lightning Rod redirects an ally's attack") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_THUNDERBOLT].type == TYPE_ELECTRIC); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_RAICHU) { Ability(ABILITY_LIGHTNING_ROD); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponentRight, MOVE_THUNDERBOLT, target: playerLeft); } + } SCENE { + MESSAGE("The opposing Wobbuffet used Thunderbolt!"); + if (B_REDIRECT_ABILITY_ALLIES >= GEN_5) + { + NOT HP_BAR(playerLeft); + ABILITY_POPUP(opponentLeft, ABILITY_LIGHTNING_ROD); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("The opposing Raichu's Sp. Atk rose!"); + } + else + { + HP_BAR(playerLeft); + } + } +} diff --git a/test/battle/move_effect/pledge.c b/test/battle/move_effect/pledge.c index 726adc8152..4441fdccb9 100644 --- a/test/battle/move_effect/pledge.c +++ b/test/battle/move_effect/pledge.c @@ -886,7 +886,7 @@ DOUBLE_BATTLE_TEST("Pledge move combo doesn't trigger on opponent's Pledge move { GIVEN { ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY); - PLAYER(SPECIES_MAROWAK) { Ability(ABILITY_LIGHTNING_ROD); } + PLAYER(SPECIES_ELECTIVIRE) { Ability(ABILITY_MOTOR_DRIVE); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); From 75d5edad08fba9c2ae478c78ced865cbf4e90fa4 Mon Sep 17 00:00:00 2001 From: cawtds <38510667+cawtds@users.noreply.github.com> Date: Wed, 15 Jan 2025 21:30:25 +0100 Subject: [PATCH 82/85] Fix UB when accessing move result flags (#6030) Co-authored-by: Alex <93446519+AlexOn1ine@users.noreply.github.com> --- include/battle_util.h | 1 + src/battle_ai_switch_items.c | 7 +++++-- src/battle_util.c | 19 +++++++++---------- 3 files changed, 15 insertions(+), 12 deletions(-) diff --git a/include/battle_util.h b/include/battle_util.h index 7df18d98de..4fde2ea341 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -248,6 +248,7 @@ uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); uq4_12_t GetTypeModifier(u32 atkType, u32 defType); uq4_12_t GetOverworldTypeEffectiveness(struct Pokemon *mon, u8 moveType); +void UpdateMoveResultFlags(uq4_12_t modifier, u16 *resultFlags); s32 GetStealthHazardDamage(enum TypeSideHazard hazardType, u32 battler); s32 GetStealthHazardDamageByTypesAndHP(enum TypeSideHazard hazardType, u8 type1, u8 type2, u32 maxHp); bool32 CanMegaEvolve(u32 battler); diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 7522c7ec05..24c8d34699 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -727,6 +727,8 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc for (i = firstId; i < lastId; i++) { u16 species, monAbility; + uq4_12_t typeMultiplier; + u16 moveFlags = 0; if (!IsValidForBattle(&party[i])) continue; @@ -743,8 +745,9 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG); monAbility = GetMonAbility(&party[i]); - CalcPartyMonTypeEffectivenessMultiplier(gLastLandedMoves[battler], species, monAbility); - if (gBattleStruct->moveResultFlags[BATTLE_OPPOSITE(battler)] & flags) + typeMultiplier = CalcPartyMonTypeEffectivenessMultiplier(gLastLandedMoves[battler], species, monAbility); + UpdateMoveResultFlags(typeMultiplier, &moveFlags); + if (moveFlags & flags) { battlerIn1 = gLastHitBy[battler]; diff --git a/src/battle_util.c b/src/battle_util.c index 0c71240d53..a6bf58b532 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -10654,27 +10654,27 @@ static inline void TryNoticeIllusionInTypeEffectiveness(u32 move, u32 moveType, RecordAbilityBattle(battlerDef, ABILITY_ILLUSION); } -static void UpdateMoveResultFlags(uq4_12_t modifier, u32 battler) +void UpdateMoveResultFlags(uq4_12_t modifier, u16 *resultFlags) { if (modifier == UQ_4_12(0.0)) { - gBattleStruct->moveResultFlags[battler] |= MOVE_RESULT_DOESNT_AFFECT_FOE; - gBattleStruct->moveResultFlags[battler] &= ~(MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE); + *resultFlags |= MOVE_RESULT_DOESNT_AFFECT_FOE; + *resultFlags &= ~(MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE); gBattleStruct->blunderPolicy = FALSE; // Don't activate if missed } else if (modifier == UQ_4_12(1.0)) { - gBattleStruct->moveResultFlags[battler] &= ~(MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE); + *resultFlags &= ~(MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE); } else if (modifier > UQ_4_12(1.0)) { - gBattleStruct->moveResultFlags[battler] |= MOVE_RESULT_SUPER_EFFECTIVE; - gBattleStruct->moveResultFlags[battler] &= ~(MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE); + *resultFlags |= MOVE_RESULT_SUPER_EFFECTIVE; + *resultFlags &= ~(MOVE_RESULT_NOT_VERY_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE); } else //if (modifier < UQ_4_12(1.0)) { - gBattleStruct->moveResultFlags[battler] |= MOVE_RESULT_NOT_VERY_EFFECTIVE; - gBattleStruct->moveResultFlags[battler] &= ~(MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE); + *resultFlags |= MOVE_RESULT_NOT_VERY_EFFECTIVE; + *resultFlags &= ~(MOVE_RESULT_SUPER_EFFECTIVE | MOVE_RESULT_DOESNT_AFFECT_FOE); } } @@ -10760,7 +10760,7 @@ uq4_12_t CalcTypeEffectivenessMultiplier(u32 move, u32 moveType, u32 battlerAtk, } if (recordAbilities) - UpdateMoveResultFlags(modifier, battlerDef); + UpdateMoveResultFlags(modifier, &gBattleStruct->moveResultFlags[battlerDef]); return modifier; } @@ -10781,7 +10781,6 @@ uq4_12_t CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 a modifier = UQ_4_12(0.0); } - UpdateMoveResultFlags(modifier, speciesDef); return modifier; } From 465d30fbd05677f5bb38291fbc32f17ae8596123 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Thu, 16 Jan 2025 15:43:16 -0500 Subject: [PATCH 83/85] Add AI_FLAG_PREDICT_SWITCH (#6028) --- include/battle.h | 5 +- include/battle_ai_util.h | 1 + include/constants/battle_ai.h | 3 +- include/random.h | 1 + src/battle_ai_main.c | 163 ++++++++++++++++++++++-- src/battle_ai_switch_items.c | 57 +++++---- src/battle_ai_util.c | 38 +++--- src/battle_main.c | 30 ++++- test/battle/ai/ai_flag_predict_switch.c | 139 ++++++++++++++++++++ 9 files changed, 379 insertions(+), 58 deletions(-) create mode 100644 test/battle/ai/ai_flag_predict_switch.c diff --git a/include/battle.h b/include/battle.h index d6b5abb7f9..a61eff5306 100644 --- a/include/battle.h +++ b/include/battle.h @@ -357,9 +357,12 @@ struct AiLogicData u8 weatherHasEffect:1; // The same as WEATHER_HAS_EFFECT. Stored here, so it's called only once. u8 ejectButtonSwitch:1; // Tracks whether current switch out was from Eject Button u8 ejectPackSwitch:1; // Tracks whether current switch out was from Eject Pack - u8 padding:5; + u8 predictingSwitch:1; // Determines whether AI will use predictions this turn or not + u8 aiSwitchPredictionInProgress:1; // Tracks whether the AI is in the middle of running prediction calculations + u8 padding:3; u8 shouldSwitch; // Stores result of ShouldSwitch, which decides whether a mon should be switched out u8 aiCalcInProgress:1; + u8 battlerDoingPrediction; // Stores which battler is currently running its prediction calcs }; struct AI_ThinkingStruct diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 4a47b63503..f561182fca 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -215,5 +215,6 @@ bool32 AI_ShouldSetUpHazards(u32 battlerAtk, u32 battlerDef, struct AiLogicData void IncreaseTidyUpScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); bool32 AI_ShouldSpicyExtract(u32 battlerAtk, u32 battlerAtkPartner, u32 move, struct AiLogicData *aiData); void IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score); +bool32 IsBattlerPredictedToSwitch(u32 battler); #endif //GUARD_BATTLE_AI_UTIL_H diff --git a/include/constants/battle_ai.h b/include/constants/battle_ai.h index acfe020f49..0e52c10128 100644 --- a/include/constants/battle_ai.h +++ b/include/constants/battle_ai.h @@ -51,8 +51,9 @@ #define AI_FLAG_DOUBLE_ACE_POKEMON (1 << 20) // AI has *two* Ace Pokémon. The last two Pokémons in the party won't be used unless they're the last ones remaining. Goes well in battles where the trainer ID equals to twins, couples, etc. #define AI_FLAG_WEIGH_ABILITY_PREDICTION (1 << 21) // AI will predict player's ability based on aiRating #define AI_FLAG_PREFER_HIGHEST_DAMAGE_MOVE (1 << 22) // AI adds score to highest damage move regardless of accuracy or secondary effect +#define AI_FLAG_PREDICT_SWITCH (1 << 23) // AI will predict the player's switches and switchins based on how it would handle the situation. Recommend using AI_FLAG_OMNISCIENT -#define AI_FLAG_COUNT 23 +#define AI_FLAG_COUNT 24 // The following options are enough to have a basic/smart trainer. Any other addtion could make the trainer worse/better depending on the flag #define AI_FLAG_BASIC_TRAINER (AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY) diff --git a/include/random.h b/include/random.h index 886094733a..1a735097d3 100644 --- a/include/random.h +++ b/include/random.h @@ -175,6 +175,7 @@ enum RandomTag RNG_SHELL_SIDE_ARM, RNG_RANDOM_TARGET, RNG_AI_PREDICT_ABILITY, + RNG_AI_PREDICT_SWITCH, RNG_HEALER, RNG_DEXNAV_ENCOUNTER_LEVEL, }; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 67e06badd6..8482716f5b 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -57,7 +57,7 @@ static s32 AI_FirstBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 AI_DynamicFunc(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); - +static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score); static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) = { @@ -84,7 +84,7 @@ static s32 (*const sBattleAiFuncTable[])(u32, u32, u32, s32) = [20] = NULL, // Unused [21] = NULL, // Unused [22] = NULL, // Unused - [23] = NULL, // Unused + [23] = AI_PredictSwitch, // AI_FLAG_PREDICT_SWITCH [24] = NULL, // Unused [25] = NULL, // Unused [26] = NULL, // Unused @@ -1328,6 +1328,14 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) // AI_CBM_HighRiskForDamage if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2) ADJUST_SCORE(-10); + if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) + || IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) + || gBattleMons[battlerDef].status2 & (STATUS2_INFATUATION | STATUS2_CONFUSION))) + ADJUST_SCORE(-10); + if (HasMoveEffect(battlerAtk, EFFECT_SUBSTITUTE) && !(gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE)) + ADJUST_SCORE(-10); + if (HasMoveEffect(battlerAtk, EFFECT_SLEEP) && ! (gBattleMons[battlerDef].status1 & STATUS1_SLEEP)) + ADJUST_SCORE(-10); break; case EFFECT_COUNTER: case EFFECT_MIRROR_COAT: @@ -3852,13 +3860,6 @@ static u32 AI_CalcMoveEffectScore(u32 battlerAtk, u32 battlerDef, u32 move) //if (CountUsablePartyMons(battlerDef) != 0) //ADJUST_SCORE(8); break; - case EFFECT_PURSUIT: - // TODO - // if (IsPredictedToSwitch(battlerDef, battlerAtk)) - // ADJUST_SCORE(GOOD_EFFECT); - // else if (IsPredictedToUsePursuitableMove(battlerDef, battlerAtk) && !MoveWouldHitFirst(move, battlerAtk, battlerDef)) //Pursuit against fast U-Turn - // ADJUST_SCORE(GOOD_EFFECT); - // break; case EFFECT_DEFOG: if ((gSideStatuses[GetBattlerSide(battlerAtk)] & SIDE_STATUS_HAZARDS_ANY && CountUsablePartyMons(battlerAtk) != 0) || (gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SCREEN_ANY | SIDE_STATUS_SAFEGUARD | SIDE_STATUS_MIST))) @@ -5268,6 +5269,150 @@ static s32 AI_PowerfulStatus(u32 battlerAtk, u32 battlerDef, u32 move, s32 score return score; } +static s32 AI_PredictSwitch(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) +{ + u32 i; + u32 unmodifiedScore = score; + u32 ability = gBattleMons[battlerAtk].ability; + u32 opposingHazardFlags = gSideStatuses[GetBattlerSide(battlerDef)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_TOXIC_SPIKES); + u32 aiHazardFlags = gSideStatuses[GetBattlerSide(battlerAtk)] & (SIDE_STATUS_HAZARDS_ANY); + u32 moveEffect = gMovesInfo[move].effect; + struct AiLogicData *aiData = AI_DATA; + u32 effectiveness = aiData->effectiveness[battlerAtk][battlerDef][AI_THINKING_STRUCT->movesetIndex]; + + // Switch benefit + switch (moveEffect) + { + case EFFECT_PURSUIT: + ADJUST_SCORE(GOOD_EFFECT); + // else if (IsPredictedToUsePursuitableMove(battlerDef, battlerAtk) && !MoveWouldHitFirst(move, battlerAtk, battlerDef)) //Pursuit against fast U-Turn + // ADJUST_SCORE(GOOD_EFFECT); + break; + + case EFFECT_FOCUS_PUNCH: + ADJUST_SCORE(DECENT_EFFECT); + if (AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_CHECK_BAD_MOVE) + { + if (aiData->abilities[battlerDef] == ABILITY_WONDER_GUARD && effectiveness < AI_EFFECTIVENESS_x2) + ADJUST_SCORE(10); + if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) + || IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) + || gBattleMons[battlerDef].status2 & (STATUS2_INFATUATION | STATUS2_CONFUSION))) + ADJUST_SCORE(10); + } + break; + + // Free setup (U-Turn etc. handled in Check Viability by ShouldPivot) + case EFFECT_BOLT_BEAK: + case EFFECT_LIGHT_SCREEN: + case EFFECT_REFLECT: + case EFFECT_MAGNET_RISE: + case EFFECT_TRICK_ROOM: + case EFFECT_STEALTH_ROCK: + case EFFECT_SPIKES: + case EFFECT_TOXIC_SPIKES: + ADJUST_SCORE(BEST_EFFECT); + break; + case EFFECT_FUTURE_SIGHT: + case EFFECT_TELEKINESIS: + case EFFECT_GRAVITY: + case EFFECT_RAIN_DANCE: + case EFFECT_SANDSTORM: + case EFFECT_SNOWSCAPE: + case EFFECT_HAIL: + case EFFECT_SUNNY_DAY: + case EFFECT_AQUA_RING: + case EFFECT_ELECTRIC_TERRAIN: + case EFFECT_PSYCHIC_TERRAIN: + case EFFECT_GRASSY_TERRAIN: + case EFFECT_MISTY_TERRAIN: + ADJUST_SCORE(GOOD_EFFECT); + break; + case EFFECT_HIT_SWITCH_TARGET: + if (opposingHazardFlags != 0) + ADJUST_SCORE(BEST_EFFECT); + else + ADJUST_SCORE(GOOD_EFFECT); + break; + case EFFECT_ROAR: + if (opposingHazardFlags != 0) + ADJUST_SCORE(GOOD_EFFECT); + break; + case EFFECT_DEFOG: + if (aiHazardFlags != 0) + ADJUST_SCORE(GOOD_EFFECT); + break; + case EFFECT_WISH: + case EFFECT_HEAL_BELL: + if (ShouldUseWishAromatherapy(battlerAtk, battlerDef, move)) + ADJUST_SCORE(DECENT_EFFECT); + break; + case EFFECT_RESTORE_HP: + if (AI_DATA->hpPercents[battlerAtk] < 60) + ADJUST_SCORE(GOOD_EFFECT); + break; + + // Fails if opponent switches + case EFFECT_PROTECT: + case EFFECT_COUNTER: + case EFFECT_MIRROR_COAT: + case EFFECT_SHELL_TRAP: + case EFFECT_METAL_BURST: + case EFFECT_SUCKER_PUNCH: + case EFFECT_UPPER_HAND: + case EFFECT_ENCORE: + case EFFECT_FOLLOW_ME: + case EFFECT_ME_FIRST: + case EFFECT_DISABLE: + case EFFECT_ELECTRIFY: + case EFFECT_ENDURE: + case EFFECT_HAZE: + case EFFECT_TOPSY_TURVY: + case EFFECT_ION_DELUGE: + case EFFECT_MAGIC_COAT: + case EFFECT_SNATCH: + ADJUST_SCORE(-BEST_EFFECT); + break; + + // Get stuck in bad matchup + case EFFECT_IMPRISON: + case EFFECT_EMBARGO: + case EFFECT_TAUNT: + case EFFECT_INGRAIN: + case EFFECT_NO_RETREAT: + case EFFECT_MEAN_LOOK: + ADJUST_SCORE(-GOOD_EFFECT); + break; + } + + // Additional effects + for (i = 0; i < gMovesInfo[move].numAdditionalEffects; i++) + { + switch (gMovesInfo[move].additionalEffects[i].moveEffect) + { + case MOVE_EFFECT_WRAP: + ADJUST_SCORE(-GOOD_EFFECT); + break; + case MOVE_EFFECT_RAPID_SPIN: + if (aiHazardFlags != 0) + ADJUST_SCORE(BEST_EFFECT); + break; + case MOVE_EFFECT_FEINT: + ADJUST_SCORE(-BEST_EFFECT); + break; + } + } + + // Take advantage of ability damage bonus + if ((ability == ABILITY_STAKEOUT || ability == ABILITY_ANALYTIC) && IsBattleMoveStatus(move)) + ADJUST_SCORE(-WEAK_EFFECT); + + // This must be last or the player can gauge whether the AI is predicting based on how long it thinks + if (!IsBattlerPredictedToSwitch(battlerDef)) + return unmodifiedScore; + return score; +} + static void AI_Flee(void) { AI_THINKING_STRUCT->aiAction |= (AI_ACTION_DONE | AI_ACTION_FLEE | AI_ACTION_DO_NOT_ATTACK); diff --git a/src/battle_ai_switch_items.c b/src/battle_ai_switch_items.c index 24c8d34699..93148d8b83 100644 --- a/src/battle_ai_switch_items.c +++ b/src/battle_ai_switch_items.c @@ -37,13 +37,20 @@ static void InitializeSwitchinCandidate(struct Pokemon *mon) AI_DATA->switchinCandidate.hypotheticalStatus = FALSE; } +u32 GetThinkingBattler(u32 battler) +{ + if (AI_DATA->aiSwitchPredictionInProgress) + return AI_DATA->battlerDoingPrediction; + return battler; +} + static bool32 IsAceMon(u32 battler, u32 monPartyId) { - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_ACE_POKEMON + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_ACE_POKEMON && !gBattleStruct->battlerState[battler].forcedSwitch && monPartyId == CalculateEnemyPartyCountInSide(battler)-1) return TRUE; - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_DOUBLE_ACE_POKEMON + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_DOUBLE_ACE_POKEMON && !gBattleStruct->battlerState[battler].forcedSwitch && (monPartyId == CalculateEnemyPartyCount()-1 || monPartyId == CalculateEnemyPartyCount()-2)) return TRUE; @@ -88,7 +95,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) u16 typeEffectiveness = UQ_4_12(1.0), aiMoveEffect; //baseline typing damage // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) + if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic @@ -156,7 +163,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) for (i = 0; i < MAX_MON_MOVES; i++) { playerMove = gBattleMons[opposingBattler].moves[i]; - if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove)) + if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && gMovesInfo[playerMove].effect != EFFECT_FOCUS_PUNCH) { damageTaken = AI_CalcDamage(playerMove, opposingBattler, battler, &effectiveness, FALSE, weather, DMG_ROLL_HIGHEST).expected; if (damageTaken > maxDamageTaken) @@ -190,7 +197,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) && gBattleMons[battler].hp >= gBattleMons[battler].maxHP / 4))) { // 50% chance to stay in regardless - if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50)) + if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50) || AI_DATA->aiSwitchPredictionInProgress) return FALSE; // Switch mon out @@ -210,7 +217,7 @@ static bool32 ShouldSwitchIfHasBadOdds(u32 battler) return FALSE; // 50% chance to stay in regardless - if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50)) + if (RandomPercentage(RNG_AI_SWITCH_HASBADODDS, 50) || AI_DATA->aiSwitchPredictionInProgress) return FALSE; // Switch mon out @@ -338,9 +345,9 @@ static bool32 FindMonThatAbsorbsOpponentsMove(u32 battler) bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove)); s32 i, j; - if (!(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) + if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; - if (HasSuperEffectiveMoveAgainstOpponents(battler, TRUE) && RandomPercentage(RNG_AI_SWITCH_ABSORBING, 66)) + if (HasSuperEffectiveMoveAgainstOpponents(battler, TRUE) && (RandomPercentage(RNG_AI_SWITCH_ABSORBING, 66) || AI_DATA->aiSwitchPredictionInProgress)) return FALSE; if (IsDoubleBattle()) @@ -438,7 +445,7 @@ static bool32 ShouldSwitchIfOpponentChargingOrInvulnerable(u32 battler) u32 incomingMove = AI_DATA->lastUsedMove[opposingBattler]; bool32 isOpposingBattlerChargingOrInvulnerable = (IsSemiInvulnerable(opposingBattler, incomingMove) || IsTwoTurnNotSemiInvulnerableMove(opposingBattler, incomingMove)); - if (IsDoubleBattle() || !(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) + if (IsDoubleBattle() || !(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; if (isOpposingBattlerChargingOrInvulnerable && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE) @@ -457,7 +464,7 @@ static bool32 ShouldSwitchIfTrapperInParty(u32 battler) s32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler))); // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) + if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Check if current mon has an ability that traps opponent @@ -500,7 +507,7 @@ static bool32 ShouldSwitchIfBadlyStatused(u32 battler) && monAbility != ABILITY_SOUNDPROOF) switchMon = TRUE; - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) { //Yawn if (gStatuses3[battler] & STATUS3_YAWN @@ -695,7 +702,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc u16 move; // Similar functionality handled more thoroughly by ShouldSwitchIfHasBadOdds - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) return FALSE; if (gLastLandedMoves[battler] == MOVE_NONE) @@ -757,7 +764,7 @@ static bool32 FindMonWithFlagsAndSuperEffective(u32 battler, u16 flags, u32 perc if (move == 0) continue; - if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= AI_EFFECTIVENESS_x2 && RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance)) + if (AI_GetMoveEffectiveness(move, battler, battlerIn1) >= AI_EFFECTIVENESS_x2 && (RandomPercentage(RNG_AI_SWITCH_SE_DEFENSIVE, percentChance) || AI_DATA->aiSwitchPredictionInProgress)) return SetSwitchinAndSwitch(battler, i); } } @@ -839,7 +846,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler) u32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler))); // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) + if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; // If not Encore'd don't switch @@ -855,7 +862,7 @@ static bool32 ShouldSwitchIfEncored(u32 battler) return FALSE; // Switch out 50% of the time otherwise - else if (RandomPercentage(RNG_AI_SWITCH_ENCORE, 50) && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE) + else if ((RandomPercentage(RNG_AI_SWITCH_ENCORE, 50) || AI_DATA->aiSwitchPredictionInProgress) && AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE) return SetSwitchinAndSwitch(battler, PARTY_SIZE); return FALSE; @@ -881,7 +888,7 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler) s8 spAttackingStage = gBattleMons[battler].statStages[STAT_SPATK]; // Only use this if AI_FLAG_SMART_SWITCHING is set for the trainer - if (!(AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING)) + if (!(AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING)) return FALSE; // Physical attacker @@ -893,7 +900,7 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler) // 50% chance if attack at -2 and have a good candidate mon else if (attackingStage == DEFAULT_STAT_STAGE - 2) { - if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, 50)) + if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, 50) || AI_DATA->aiSwitchPredictionInProgress)) return SetSwitchinAndSwitch(battler, PARTY_SIZE); } // If at -3 or worse, switch out regardless @@ -910,7 +917,7 @@ static bool32 ShouldSwitchIfAttackingStatsLowered(u32 battler) // 50% chance if attack at -2 and have a good candidate mon else if (spAttackingStage == DEFAULT_STAT_STAGE - 2) { - if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, 50)) + if (AI_DATA->mostSuitableMonId[battler] != PARTY_SIZE && (RandomPercentage(RNG_AI_SWITCH_STATS_LOWERED, 50) || AI_DATA->aiSwitchPredictionInProgress)) return SetSwitchinAndSwitch(battler, PARTY_SIZE); } // If at -3 or worse, switch out regardless @@ -939,7 +946,7 @@ bool32 ShouldSwitch(u32 battler) return FALSE; // Sequence Switching AI never switches mid-battle - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING) + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SEQUENCE_SWITCHING) return FALSE; availableToSwitch = 0; @@ -993,7 +1000,7 @@ bool32 ShouldSwitch(u32 battler) return TRUE; // These Functions can prompt switch to party member returned by GetMostSuitableMonToSwitchInto - if ((AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) && (CanMonSurviveHazardSwitchin(battler) == FALSE)) + if ((AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) && (CanMonSurviveHazardSwitchin(battler) == FALSE)) return FALSE; if (ShouldSwitchIfTrapperInParty(battler)) return TRUE; @@ -1019,7 +1026,7 @@ bool32 ShouldSwitch(u32 battler) // Removing switch capabilites under specific conditions // These Functions prevent the "FindMonWithFlagsAndSuperEffective" from getting out of hand. // We don't use FindMonWithFlagsAndSuperEffective with AI_FLAG_SMART_SWITCHING, so we can bail early. - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_SWITCHING) + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_SWITCHING) return FALSE; if (HasSuperEffectiveMoveAgainstOpponents(battler, FALSE)) return FALSE; @@ -1695,7 +1702,7 @@ static s32 GetMaxDamagePlayerCouldDealToSwitchin(u32 battler, u32 opposingBattle for (i = 0; i < MAX_MON_MOVES; i++) { playerMove = gBattleMons[opposingBattler].moves[i]; - if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove)) + if (playerMove != MOVE_NONE && !IsBattleMoveStatus(playerMove) && gMovesInfo[playerMove].effect != EFFECT_FOCUS_PUNCH) { damageTaken = AI_CalcPartyMonDamage(playerMove, opposingBattler, battler, battleMon, FALSE, DMG_ROLL_HIGHEST); if (damageTaken > maxDamageTaken) @@ -1826,7 +1833,7 @@ static u32 GetBestMonIntegrated(struct Pokemon *party, int firstId, int lastId, if (aiMove != MOVE_NONE && !IsBattleMoveStatus(aiMove)) { - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_CONSERVATIVE) + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_CONSERVATIVE) damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_LOWEST); else damageDealt = AI_CalcPartyMonDamage(aiMove, battler, opposingBattler, AI_DATA->switchinCandidate.battleMon, TRUE, DMG_ROLL_DEFAULT); @@ -2004,14 +2011,14 @@ u32 GetMostSuitableMonToSwitchInto(u32 battler, bool32 switchAfterMonKOd) GetAIPartyIndexes(battler, &firstId, &lastId); party = GetBattlerParty(battler); - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SEQUENCE_SWITCHING) + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SEQUENCE_SWITCHING) { bestMonId = GetNextMonInParty(party, firstId, lastId, battlerIn1, battlerIn2); return bestMonId; } // Only use better mon selection if AI_FLAG_SMART_MON_CHOICES is set for the trainer. - if (AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic + if (AI_THINKING_STRUCT->aiFlags[GetThinkingBattler(battler)] & AI_FLAG_SMART_MON_CHOICES && !IsDoubleBattle()) // Double Battles aren't included in AI_FLAG_SMART_MON_CHOICE. Defaults to regular switch in logic { bestMonId = GetBestMonIntegrated(party, firstId, lastId, battler, opposingBattler, battlerIn1, battlerIn2, switchAfterMonKOd); return bestMonId; diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index c9a3ae07b2..6f6b5c7188 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -102,6 +102,18 @@ bool32 IsAiBattlerPredictingAbility(u32 battlerId) return BattlerHasAi(battlerId); } +bool32 IsBattlerPredictedToSwitch(u32 battler) +{ + // Check for prediction flag on AI, whether they're using those predictions this turn, and whether the AI thinks the player should switch + if (AI_THINKING_STRUCT->aiFlags[AI_DATA->battlerDoingPrediction] & AI_FLAG_PREDICT_SWITCH + || AI_THINKING_STRUCT->aiFlags[AI_DATA->battlerDoingPrediction] & AI_FLAG_PREDICT_SWITCH) + { + if (AI_DATA->predictingSwitch && AI_DATA->shouldSwitch & (1u << battler)) + return TRUE; + } + return FALSE; +} + void ClearBattlerMoveHistory(u32 battlerId) { memset(BATTLE_HISTORY->usedMoves[battlerId], 0, sizeof(BATTLE_HISTORY->usedMoves[battlerId])); @@ -477,16 +489,6 @@ bool32 IsDamageMoveUnusable(u32 battlerAtk, u32 battlerDef, u32 move, u32 moveTy if (!gDisableStructs[battlerAtk].isFirstTurn) return TRUE; break; - case EFFECT_FOCUS_PUNCH: - if (HasDamagingMove(battlerDef) && !((gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE) - || IsBattlerIncapacitated(battlerDef, aiData->abilities[battlerDef]) - || gBattleMons[battlerDef].status2 & (STATUS2_INFATUATION | STATUS2_CONFUSION))) - // TODO: || IsPredictedToSwitch(battlerDef, battlerAtk) - return TRUE; - // If AI could Sub and doesn't have a Sub, don't Punch yet - if (HasMoveEffect(battlerAtk, EFFECT_SUBSTITUTE) && !(gBattleMons[battlerAtk].status2 & STATUS2_SUBSTITUTE)) - return TRUE; - break; } return FALSE; @@ -2779,9 +2781,8 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov if (CountUsablePartyMons(battlerAtk) == 0) return CAN_TRY_PIVOT; // can't switch, but attack might still be useful - //TODO - predict opponent switching - /*if (IsPredictedToSwitch(battlerDef, battlerAtk) && !hasStatBoost) - return SHOULD_PIVOT; // Try pivoting so you can switch to a better matchup to counter your new opponent*/ + if (IsBattlerPredictedToSwitch(battlerDef)) + return SHOULD_PIVOT; // Try pivoting so you can switch to a better matchup to counter your new opponent if (AI_IsFaster(battlerAtk, battlerDef, move)) // Attacker goes first { @@ -3793,6 +3794,10 @@ static u32 IncreaseStatUpScoreInternal(u32 battlerAtk, u32 battlerDef, u32 statI if (AI_DATA->abilities[battlerDef] == ABILITY_OPPORTUNIST) return NO_INCREASE; + // If predicting switch, stat increases are great momentum + if (IsBattlerPredictedToSwitch(battlerDef)) + tempScore += WEAK_EFFECT; + switch (statId) { case STAT_CHANGE_ATK: @@ -3951,7 +3956,7 @@ void IncreaseParalyzeScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) void IncreaseSleepScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 *score) { - if (((AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0)) + if (((AI_THINKING_STRUCT->aiFlags[battlerAtk] & AI_FLAG_TRY_TO_FAINT) && CanAIFaintTarget(battlerAtk, battlerDef, 0) && gMovesInfo[GetBestDmgMoveFromBattler(battlerAtk, battlerDef)].effect != EFFECT_FOCUS_PUNCH) || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_SLP || AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_CURE_STATUS) return; @@ -4193,9 +4198,8 @@ void IncreaseSubstituteMoveScore(u32 battlerAtk, u32 battlerDef, u32 move, s32 * else if (gBattleMons[battlerDef].status1 & (STATUS1_BURN | STATUS1_PSN_ANY | STATUS1_FROSTBITE)) ADJUST_SCORE_PTR(DECENT_EFFECT); - // TODO: - // if (IsPredictedToSwitch(battlerDef, battlerAtk) - // ADJUST_SCORE_PTR(DECENT_EFFECT); + if (IsBattlerPredictedToSwitch(battlerDef)) + ADJUST_SCORE(DECENT_EFFECT); if (HasMoveEffect(battlerDef, EFFECT_SLEEP) || HasMoveEffect(battlerDef, EFFECT_TOXIC) diff --git a/src/battle_main.c b/src/battle_main.c index 5dba22a160..5c1b999ab9 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4201,6 +4201,30 @@ enum STATE_SELECTION_SCRIPT_MAY_RUN }; +void SetupAISwitchingData(u32 battler, bool32 isAiRisky) +{ + s32 opposingBattler = GetBattlerAtPosition(BATTLE_OPPOSITE(GetBattlerPosition(battler))); + + // AI's data + AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, isAiRisky); + if (ShouldSwitch(battler)) + AI_DATA->shouldSwitch |= (1u << battler); + + // AI's predicting data + if ((AI_THINKING_STRUCT->aiFlags[battler] & AI_FLAG_PREDICT_SWITCH)) + { + AI_DATA->aiSwitchPredictionInProgress = TRUE; + AI_DATA->battlerDoingPrediction = battler; + AI_DATA->mostSuitableMonId[opposingBattler] = GetMostSuitableMonToSwitchInto(opposingBattler, isAiRisky); + if (ShouldSwitch(opposingBattler)) + AI_DATA->shouldSwitch |= (1u << opposingBattler); + AI_DATA->aiSwitchPredictionInProgress = FALSE; + + // Determine whether AI will use predictions this turn + AI_DATA->predictingSwitch = RandomPercentage(RNG_AI_PREDICT_SWITCH, 50); + } +} + static void HandleTurnActionSelectionState(void) { s32 i, battler; @@ -4225,11 +4249,7 @@ static void HandleTurnActionSelectionState(void) // Setup battler data sBattler_AI = battler; BattleAI_SetupAIData(0xF, sBattler_AI); - - // Setup switching data - AI_DATA->mostSuitableMonId[battler] = GetMostSuitableMonToSwitchInto(battler, isAiRisky); - if (ShouldSwitch(battler)) - AI_DATA->shouldSwitch |= (1u << battler); + SetupAISwitchingData(battler, isAiRisky); // Do scoring gBattleStruct->aiMoveOrAction[battler] = BattleAI_ChooseMoveOrAction(); diff --git a/test/battle/ai/ai_flag_predict_switch.c b/test/battle/ai/ai_flag_predict_switch.c new file mode 100644 index 0000000000..afed790a41 --- /dev/null +++ b/test/battle/ai/ai_flag_predict_switch.c @@ -0,0 +1,139 @@ +#include "global.h" +#include "test/battle.h" +#include "battle_ai_util.h" + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI will predict use Pursuit on predicted switches") +{ + PASSES_RANDOMLY(5, 10, RNG_AI_PREDICT_SWITCH); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PREDICT_SWITCH); + PLAYER(SPECIES_BRONZONG) { Moves(MOVE_PSYCHIC); } + PLAYER(SPECIES_CONKELDURR) { Moves(MOVE_HAMMER_ARM); } + OPPONENT(SPECIES_TYRANITAR) { Moves(MOVE_PURSUIT, MOVE_CRUNCH); } + } WHEN { + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, MOVE_PURSUIT); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in Pursuit scenario") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); + PLAYER(SPECIES_TYRANITAR) { Moves(MOVE_PURSUIT, MOVE_CRUNCH); } + OPPONENT(SPECIES_BRONZONG) { Moves(MOVE_PSYCHIC); } + OPPONENT(SPECIES_CONKELDURR) { Moves(MOVE_HAMMER_ARM); } + } WHEN { + TURN { MOVE(player, MOVE_PURSUIT); EXPECT_SWITCH(opponent, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI will predict switches with Wonder Guard") +{ + PASSES_RANDOMLY(5, 10, RNG_AI_PREDICT_SWITCH); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PREDICT_SWITCH); + PLAYER(SPECIES_BRONZONG) { Moves(MOVE_PSYCHIC); } + PLAYER(SPECIES_SWELLOW) { Moves(MOVE_PECK); } + OPPONENT(SPECIES_SHEDINJA) { Moves(MOVE_PURSUIT, MOVE_CRUNCH); } + } WHEN { + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, MOVE_PURSUIT); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in Wonder Guard scenario") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); + PLAYER(SPECIES_SHEDINJA) { Moves(MOVE_PURSUIT, MOVE_CRUNCH); } + OPPONENT(SPECIES_BRONZONG) { Moves(MOVE_PSYCHIC); } + OPPONENT(SPECIES_SWELLOW) { Moves(MOVE_PECK); } + } WHEN { + TURN { MOVE(player, MOVE_PURSUIT); EXPECT_SWITCH(opponent, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI will use hit escape moves on predicted switches") +{ + PASSES_RANDOMLY(5, 10, RNG_AI_PREDICT_SWITCH); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PREDICT_SWITCH); + PLAYER(SPECIES_BRONZONG) { Moves(MOVE_PSYCHIC); } + PLAYER(SPECIES_CONKELDURR) { Moves(MOVE_HAMMER_ARM); } + OPPONENT(SPECIES_TYRANITAR) { Moves(MOVE_U_TURN, MOVE_CRUNCH); } + OPPONENT(SPECIES_TYRANITAR) { Moves(MOVE_U_TURN, MOVE_CRUNCH); } + } WHEN { + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, MOVE_U_TURN); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in hit escape scenario") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); + PLAYER(SPECIES_TYRANITAR) { Moves(MOVE_U_TURN, MOVE_CRUNCH); } + PLAYER(SPECIES_TYRANITAR) { Moves(MOVE_U_TURN, MOVE_CRUNCH); } + OPPONENT(SPECIES_BRONZONG) { Moves(MOVE_PSYCHIC); } + OPPONENT(SPECIES_CONKELDURR) { Moves(MOVE_HAMMER_ARM); } + } WHEN { + TURN { EXPECT_SWITCH(opponent, 1); MOVE(player, MOVE_U_TURN); SEND_OUT(player, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: Considers ShouldSwitch and GetMostSuitableMonToSwitchInto from player's perspective") +{ + // Switching in trapper is an advanced feature of ShouldSwitch that requires GetMostSuitableMonToSwitchInto to also return a specific mon; this passing means the AI can use both in prediction + PASSES_RANDOMLY(5, 10, RNG_AI_PREDICT_SWITCH); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PREDICT_SWITCH); + PLAYER(SPECIES_CACNEA) { Moves(MOVE_ABSORB); } + PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_ARENA_TRAP); Moves(MOVE_ACROBATICS); } + OPPONENT(SPECIES_BRELOOM) { Ability(ABILITY_EFFECT_SPORE); Moves(MOVE_PURSUIT, MOVE_BITE); } + OPPONENT(SPECIES_BRELOOM); + } WHEN { + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, MOVE_PURSUIT); } + TURN { MOVE(player, MOVE_ACROBATICS); EXPECT_MOVE(opponent, MOVE_BITE); EXPECT_SEND_OUT(opponent, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in trapper-from-player's-perspective case") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); + PLAYER(SPECIES_BRELOOM) { Speed(5); Ability(ABILITY_EFFECT_SPORE); Moves(MOVE_PURSUIT, MOVE_BITE); } + PLAYER(SPECIES_BRELOOM) { Speed(5); } + OPPONENT(SPECIES_CACNEA) { Speed(6); Moves(MOVE_ABSORB); } + OPPONENT(SPECIES_DUGTRIO) { Speed(6); Ability(ABILITY_ARENA_TRAP); Moves(MOVE_ACROBATICS); } + } WHEN { + TURN { MOVE(player, MOVE_PURSUIT); EXPECT_SWITCH(opponent, 1); } + TURN { EXPECT_MOVE(opponent, MOVE_ACROBATICS); MOVE(player, MOVE_BITE); SEND_OUT(player, 1); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI can use Focus Punch on predicted switches") +{ + PASSES_RANDOMLY(5, 10, RNG_AI_PREDICT_SWITCH); + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES | AI_FLAG_PREDICT_SWITCH); + PLAYER(SPECIES_BRONZONG) { Moves(MOVE_PSYCHIC); } + PLAYER(SPECIES_CONKELDURR) { Moves(MOVE_HAMMER_ARM); } + OPPONENT(SPECIES_TYRANITAR) { Moves(MOVE_FOCUS_PUNCH, MOVE_BRICK_BREAK); } + } WHEN { + TURN { SWITCH(player, 1); EXPECT_MOVE(opponent, MOVE_FOCUS_PUNCH); } + } +} + +AI_SINGLE_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in Focus Punch scenario") +{ + GIVEN { + AI_FLAGS(AI_FLAG_CHECK_BAD_MOVE | AI_FLAG_TRY_TO_FAINT | AI_FLAG_CHECK_VIABILITY | AI_FLAG_OMNISCIENT | AI_FLAG_SMART_SWITCHING | AI_FLAG_SMART_MON_CHOICES); + PLAYER(SPECIES_TYRANITAR) { Moves(MOVE_FOCUS_PUNCH, MOVE_BRICK_BREAK); } + OPPONENT(SPECIES_BRONZONG) { Moves(MOVE_PSYCHIC); } + OPPONENT(SPECIES_CONKELDURR) { Moves(MOVE_HAMMER_ARM); } + } WHEN { + TURN { EXPECT_SWITCH(opponent, 1); MOVE(player, MOVE_FOCUS_PUNCH); } + } +} + +// This will be for a follow-up PR +TO_DO_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI will score against predicted incoming mon when switch predicted") +TO_DO_BATTLE_TEST("AI_FLAG_PREDICT_SWITCH: AI would switch out in predicted-incoming-mon scenario"); From 21d2e40f0aa0aa5bf56b4f78099d8184a7453b14 Mon Sep 17 00:00:00 2001 From: Mercy <98864243+MercedesCL@users.noreply.github.com> Date: Fri, 17 Jan 2025 00:23:12 -0500 Subject: [PATCH 84/85] Fix Match Call Behavior (#5931) (#6033) --- src/battle_setup.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/battle_setup.c b/src/battle_setup.c index 0c13fcdd09..37204c1d8d 100644 --- a/src/battle_setup.c +++ b/src/battle_setup.c @@ -1742,8 +1742,8 @@ static bool32 UpdateRandomTrainerRematches(const struct RematchTrainer *table, u for (i = 0; i <= REMATCH_SPECIAL_TRAINER_START; i++) { - if (DoesCurrentMapMatchRematchTrainerMap(i,table,mapGroup,mapNum) && !IsRematchForbidden(i)) - continue; + if (!DoesCurrentMapMatchRematchTrainerMap(i,table,mapGroup,mapNum) || IsRematchForbidden(i)) + continue; // Only check permitted trainers within the current map. if (gSaveBlock1Ptr->trainerRematches[i] != 0) { From 3b19f6972be3a577e2f67716371a6ed7e63e4548 Mon Sep 17 00:00:00 2001 From: moostoet <70690976+moostoet@users.noreply.github.com> Date: Fri, 17 Jan 2025 18:39:52 +0100 Subject: [PATCH 85/85] Rename Furfrou Species tags to match Pokemon Showdown exports (#6041) --- .../{dandy_trim => dandy}/anim_front.png | Bin .../furfrou/{dandy_trim => dandy}/back.png | Bin .../furfrou/{dandy_trim => dandy}/icon.png | Bin .../furfrou/{dandy_trim => dandy}/normal.pal | 0 .../{dandy_trim => dandy}/overworld.png | Bin .../overworld_normal.pal | 0 .../{dandy_trim => dandy}/overworld_shiny.pal | 0 .../furfrou/{dandy_trim => dandy}/shiny.pal | 0 .../anim_front.png | Bin .../{debutante_trim => debutante}/back.png | Bin .../{debutante_trim => debutante}/icon.png | Bin .../{debutante_trim => debutante}/normal.pal | 0 .../overworld.png | Bin .../overworld_normal.pal | 0 .../overworld_shiny.pal | 0 .../{debutante_trim => debutante}/shiny.pal | 0 .../{diamond_trim => diamond}/anim_front.png | Bin .../{diamond_trim => diamond}/back.png | Bin .../{diamond_trim => diamond}/icon.png | Bin .../{diamond_trim => diamond}/normal.pal | 0 .../{diamond_trim => diamond}/overworld.png | Bin .../overworld_normal.pal | 0 .../overworld_shiny.pal | 0 .../{diamond_trim => diamond}/shiny.pal | 0 .../{heart_trim => heart}/anim_front.png | Bin .../furfrou/{heart_trim => heart}/back.png | Bin .../furfrou/{heart_trim => heart}/icon.png | Bin .../furfrou/{heart_trim => heart}/normal.pal | 0 .../{heart_trim => heart}/overworld.png | Bin .../overworld_normal.pal | 0 .../{heart_trim => heart}/overworld_shiny.pal | 0 .../furfrou/{heart_trim => heart}/shiny.pal | 0 .../{kabuki_trim => kabuki}/anim_front.png | Bin .../furfrou/{kabuki_trim => kabuki}/back.png | Bin .../furfrou/{kabuki_trim => kabuki}/icon.png | Bin .../{kabuki_trim => kabuki}/normal.pal | 0 .../{kabuki_trim => kabuki}/overworld.png | Bin .../overworld_normal.pal | 0 .../overworld_shiny.pal | 0 .../furfrou/{kabuki_trim => kabuki}/shiny.pal | 0 .../anim_front.png | Bin .../{la_reine_trim => la_reine}/back.png | Bin .../{la_reine_trim => la_reine}/icon.png | Bin .../{la_reine_trim => la_reine}/normal.pal | 0 .../{la_reine_trim => la_reine}/overworld.png | Bin .../overworld_normal.pal | 0 .../overworld_shiny.pal | 0 .../{la_reine_trim => la_reine}/shiny.pal | 0 .../{matron_trim => matron}/anim_front.png | Bin .../furfrou/{matron_trim => matron}/back.png | Bin .../furfrou/{matron_trim => matron}/icon.png | Bin .../{matron_trim => matron}/normal.pal | 0 .../{matron_trim => matron}/overworld.png | Bin .../overworld_normal.pal | 0 .../overworld_shiny.pal | 0 .../furfrou/{matron_trim => matron}/shiny.pal | 0 .../{pharaoh_trim => pharaoh}/anim_front.png | Bin .../{pharaoh_trim => pharaoh}/back.png | Bin .../{pharaoh_trim => pharaoh}/icon.png | Bin .../{pharaoh_trim => pharaoh}/normal.pal | 0 .../{pharaoh_trim => pharaoh}/overworld.png | Bin .../overworld_normal.pal | 0 .../overworld_shiny.pal | 0 .../{pharaoh_trim => pharaoh}/shiny.pal | 0 .../{star_trim => star}/anim_front.png | Bin .../furfrou/{star_trim => star}/back.png | Bin .../furfrou/{star_trim => star}/icon.png | Bin .../furfrou/{star_trim => star}/normal.pal | 0 .../furfrou/{star_trim => star}/overworld.png | Bin .../{star_trim => star}/overworld_normal.pal | 0 .../{star_trim => star}/overworld_shiny.pal | 0 .../furfrou/{star_trim => star}/shiny.pal | 0 include/constants/species.h | 18 +-- spritesheet_rules.mk | 18 +-- src/data/graphics/pokemon.h | 144 +++++++++--------- .../object_event_pic_tables_followers.h | 36 ++--- src/data/pokemon/form_species_tables.h | 18 +-- src/data/pokemon/pokedex_orders.h | 36 ++--- .../pokemon/species_info/gen_6_families.h | 20 +-- 79 files changed, 145 insertions(+), 145 deletions(-) rename graphics/pokemon/furfrou/{dandy_trim => dandy}/anim_front.png (100%) rename graphics/pokemon/furfrou/{dandy_trim => dandy}/back.png (100%) rename graphics/pokemon/furfrou/{dandy_trim => dandy}/icon.png (100%) rename graphics/pokemon/furfrou/{dandy_trim => dandy}/normal.pal (100%) rename graphics/pokemon/furfrou/{dandy_trim => dandy}/overworld.png (100%) rename graphics/pokemon/furfrou/{dandy_trim => dandy}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{dandy_trim => dandy}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{dandy_trim => dandy}/shiny.pal (100%) rename graphics/pokemon/furfrou/{debutante_trim => debutante}/anim_front.png (100%) rename graphics/pokemon/furfrou/{debutante_trim => debutante}/back.png (100%) rename graphics/pokemon/furfrou/{debutante_trim => debutante}/icon.png (100%) rename graphics/pokemon/furfrou/{debutante_trim => debutante}/normal.pal (100%) rename graphics/pokemon/furfrou/{debutante_trim => debutante}/overworld.png (100%) rename graphics/pokemon/furfrou/{debutante_trim => debutante}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{debutante_trim => debutante}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{debutante_trim => debutante}/shiny.pal (100%) rename graphics/pokemon/furfrou/{diamond_trim => diamond}/anim_front.png (100%) rename graphics/pokemon/furfrou/{diamond_trim => diamond}/back.png (100%) rename graphics/pokemon/furfrou/{diamond_trim => diamond}/icon.png (100%) rename graphics/pokemon/furfrou/{diamond_trim => diamond}/normal.pal (100%) rename graphics/pokemon/furfrou/{diamond_trim => diamond}/overworld.png (100%) rename graphics/pokemon/furfrou/{diamond_trim => diamond}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{diamond_trim => diamond}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{diamond_trim => diamond}/shiny.pal (100%) rename graphics/pokemon/furfrou/{heart_trim => heart}/anim_front.png (100%) rename graphics/pokemon/furfrou/{heart_trim => heart}/back.png (100%) rename graphics/pokemon/furfrou/{heart_trim => heart}/icon.png (100%) rename graphics/pokemon/furfrou/{heart_trim => heart}/normal.pal (100%) rename graphics/pokemon/furfrou/{heart_trim => heart}/overworld.png (100%) rename graphics/pokemon/furfrou/{heart_trim => heart}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{heart_trim => heart}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{heart_trim => heart}/shiny.pal (100%) rename graphics/pokemon/furfrou/{kabuki_trim => kabuki}/anim_front.png (100%) rename graphics/pokemon/furfrou/{kabuki_trim => kabuki}/back.png (100%) rename graphics/pokemon/furfrou/{kabuki_trim => kabuki}/icon.png (100%) rename graphics/pokemon/furfrou/{kabuki_trim => kabuki}/normal.pal (100%) rename graphics/pokemon/furfrou/{kabuki_trim => kabuki}/overworld.png (100%) rename graphics/pokemon/furfrou/{kabuki_trim => kabuki}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{kabuki_trim => kabuki}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{kabuki_trim => kabuki}/shiny.pal (100%) rename graphics/pokemon/furfrou/{la_reine_trim => la_reine}/anim_front.png (100%) rename graphics/pokemon/furfrou/{la_reine_trim => la_reine}/back.png (100%) rename graphics/pokemon/furfrou/{la_reine_trim => la_reine}/icon.png (100%) rename graphics/pokemon/furfrou/{la_reine_trim => la_reine}/normal.pal (100%) rename graphics/pokemon/furfrou/{la_reine_trim => la_reine}/overworld.png (100%) rename graphics/pokemon/furfrou/{la_reine_trim => la_reine}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{la_reine_trim => la_reine}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{la_reine_trim => la_reine}/shiny.pal (100%) rename graphics/pokemon/furfrou/{matron_trim => matron}/anim_front.png (100%) rename graphics/pokemon/furfrou/{matron_trim => matron}/back.png (100%) rename graphics/pokemon/furfrou/{matron_trim => matron}/icon.png (100%) rename graphics/pokemon/furfrou/{matron_trim => matron}/normal.pal (100%) rename graphics/pokemon/furfrou/{matron_trim => matron}/overworld.png (100%) rename graphics/pokemon/furfrou/{matron_trim => matron}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{matron_trim => matron}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{matron_trim => matron}/shiny.pal (100%) rename graphics/pokemon/furfrou/{pharaoh_trim => pharaoh}/anim_front.png (100%) rename graphics/pokemon/furfrou/{pharaoh_trim => pharaoh}/back.png (100%) rename graphics/pokemon/furfrou/{pharaoh_trim => pharaoh}/icon.png (100%) rename graphics/pokemon/furfrou/{pharaoh_trim => pharaoh}/normal.pal (100%) rename graphics/pokemon/furfrou/{pharaoh_trim => pharaoh}/overworld.png (100%) rename graphics/pokemon/furfrou/{pharaoh_trim => pharaoh}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{pharaoh_trim => pharaoh}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{pharaoh_trim => pharaoh}/shiny.pal (100%) rename graphics/pokemon/furfrou/{star_trim => star}/anim_front.png (100%) rename graphics/pokemon/furfrou/{star_trim => star}/back.png (100%) rename graphics/pokemon/furfrou/{star_trim => star}/icon.png (100%) rename graphics/pokemon/furfrou/{star_trim => star}/normal.pal (100%) rename graphics/pokemon/furfrou/{star_trim => star}/overworld.png (100%) rename graphics/pokemon/furfrou/{star_trim => star}/overworld_normal.pal (100%) rename graphics/pokemon/furfrou/{star_trim => star}/overworld_shiny.pal (100%) rename graphics/pokemon/furfrou/{star_trim => star}/shiny.pal (100%) diff --git a/graphics/pokemon/furfrou/dandy_trim/anim_front.png b/graphics/pokemon/furfrou/dandy/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/dandy_trim/anim_front.png rename to graphics/pokemon/furfrou/dandy/anim_front.png diff --git a/graphics/pokemon/furfrou/dandy_trim/back.png b/graphics/pokemon/furfrou/dandy/back.png similarity index 100% rename from graphics/pokemon/furfrou/dandy_trim/back.png rename to graphics/pokemon/furfrou/dandy/back.png diff --git a/graphics/pokemon/furfrou/dandy_trim/icon.png b/graphics/pokemon/furfrou/dandy/icon.png similarity index 100% rename from graphics/pokemon/furfrou/dandy_trim/icon.png rename to graphics/pokemon/furfrou/dandy/icon.png diff --git a/graphics/pokemon/furfrou/dandy_trim/normal.pal b/graphics/pokemon/furfrou/dandy/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/dandy_trim/normal.pal rename to graphics/pokemon/furfrou/dandy/normal.pal diff --git a/graphics/pokemon/furfrou/dandy_trim/overworld.png b/graphics/pokemon/furfrou/dandy/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/dandy_trim/overworld.png rename to graphics/pokemon/furfrou/dandy/overworld.png diff --git a/graphics/pokemon/furfrou/dandy_trim/overworld_normal.pal b/graphics/pokemon/furfrou/dandy/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/dandy_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/dandy/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/dandy_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/dandy/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/dandy_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/dandy/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/dandy_trim/shiny.pal b/graphics/pokemon/furfrou/dandy/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/dandy_trim/shiny.pal rename to graphics/pokemon/furfrou/dandy/shiny.pal diff --git a/graphics/pokemon/furfrou/debutante_trim/anim_front.png b/graphics/pokemon/furfrou/debutante/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/debutante_trim/anim_front.png rename to graphics/pokemon/furfrou/debutante/anim_front.png diff --git a/graphics/pokemon/furfrou/debutante_trim/back.png b/graphics/pokemon/furfrou/debutante/back.png similarity index 100% rename from graphics/pokemon/furfrou/debutante_trim/back.png rename to graphics/pokemon/furfrou/debutante/back.png diff --git a/graphics/pokemon/furfrou/debutante_trim/icon.png b/graphics/pokemon/furfrou/debutante/icon.png similarity index 100% rename from graphics/pokemon/furfrou/debutante_trim/icon.png rename to graphics/pokemon/furfrou/debutante/icon.png diff --git a/graphics/pokemon/furfrou/debutante_trim/normal.pal b/graphics/pokemon/furfrou/debutante/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/debutante_trim/normal.pal rename to graphics/pokemon/furfrou/debutante/normal.pal diff --git a/graphics/pokemon/furfrou/debutante_trim/overworld.png b/graphics/pokemon/furfrou/debutante/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/debutante_trim/overworld.png rename to graphics/pokemon/furfrou/debutante/overworld.png diff --git a/graphics/pokemon/furfrou/debutante_trim/overworld_normal.pal b/graphics/pokemon/furfrou/debutante/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/debutante_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/debutante/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/debutante_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/debutante/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/debutante_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/debutante/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/debutante_trim/shiny.pal b/graphics/pokemon/furfrou/debutante/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/debutante_trim/shiny.pal rename to graphics/pokemon/furfrou/debutante/shiny.pal diff --git a/graphics/pokemon/furfrou/diamond_trim/anim_front.png b/graphics/pokemon/furfrou/diamond/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/diamond_trim/anim_front.png rename to graphics/pokemon/furfrou/diamond/anim_front.png diff --git a/graphics/pokemon/furfrou/diamond_trim/back.png b/graphics/pokemon/furfrou/diamond/back.png similarity index 100% rename from graphics/pokemon/furfrou/diamond_trim/back.png rename to graphics/pokemon/furfrou/diamond/back.png diff --git a/graphics/pokemon/furfrou/diamond_trim/icon.png b/graphics/pokemon/furfrou/diamond/icon.png similarity index 100% rename from graphics/pokemon/furfrou/diamond_trim/icon.png rename to graphics/pokemon/furfrou/diamond/icon.png diff --git a/graphics/pokemon/furfrou/diamond_trim/normal.pal b/graphics/pokemon/furfrou/diamond/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/diamond_trim/normal.pal rename to graphics/pokemon/furfrou/diamond/normal.pal diff --git a/graphics/pokemon/furfrou/diamond_trim/overworld.png b/graphics/pokemon/furfrou/diamond/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/diamond_trim/overworld.png rename to graphics/pokemon/furfrou/diamond/overworld.png diff --git a/graphics/pokemon/furfrou/diamond_trim/overworld_normal.pal b/graphics/pokemon/furfrou/diamond/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/diamond_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/diamond/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/diamond_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/diamond/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/diamond_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/diamond/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/diamond_trim/shiny.pal b/graphics/pokemon/furfrou/diamond/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/diamond_trim/shiny.pal rename to graphics/pokemon/furfrou/diamond/shiny.pal diff --git a/graphics/pokemon/furfrou/heart_trim/anim_front.png b/graphics/pokemon/furfrou/heart/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/heart_trim/anim_front.png rename to graphics/pokemon/furfrou/heart/anim_front.png diff --git a/graphics/pokemon/furfrou/heart_trim/back.png b/graphics/pokemon/furfrou/heart/back.png similarity index 100% rename from graphics/pokemon/furfrou/heart_trim/back.png rename to graphics/pokemon/furfrou/heart/back.png diff --git a/graphics/pokemon/furfrou/heart_trim/icon.png b/graphics/pokemon/furfrou/heart/icon.png similarity index 100% rename from graphics/pokemon/furfrou/heart_trim/icon.png rename to graphics/pokemon/furfrou/heart/icon.png diff --git a/graphics/pokemon/furfrou/heart_trim/normal.pal b/graphics/pokemon/furfrou/heart/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/heart_trim/normal.pal rename to graphics/pokemon/furfrou/heart/normal.pal diff --git a/graphics/pokemon/furfrou/heart_trim/overworld.png b/graphics/pokemon/furfrou/heart/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/heart_trim/overworld.png rename to graphics/pokemon/furfrou/heart/overworld.png diff --git a/graphics/pokemon/furfrou/heart_trim/overworld_normal.pal b/graphics/pokemon/furfrou/heart/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/heart_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/heart/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/heart_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/heart/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/heart_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/heart/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/heart_trim/shiny.pal b/graphics/pokemon/furfrou/heart/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/heart_trim/shiny.pal rename to graphics/pokemon/furfrou/heart/shiny.pal diff --git a/graphics/pokemon/furfrou/kabuki_trim/anim_front.png b/graphics/pokemon/furfrou/kabuki/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/kabuki_trim/anim_front.png rename to graphics/pokemon/furfrou/kabuki/anim_front.png diff --git a/graphics/pokemon/furfrou/kabuki_trim/back.png b/graphics/pokemon/furfrou/kabuki/back.png similarity index 100% rename from graphics/pokemon/furfrou/kabuki_trim/back.png rename to graphics/pokemon/furfrou/kabuki/back.png diff --git a/graphics/pokemon/furfrou/kabuki_trim/icon.png b/graphics/pokemon/furfrou/kabuki/icon.png similarity index 100% rename from graphics/pokemon/furfrou/kabuki_trim/icon.png rename to graphics/pokemon/furfrou/kabuki/icon.png diff --git a/graphics/pokemon/furfrou/kabuki_trim/normal.pal b/graphics/pokemon/furfrou/kabuki/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/kabuki_trim/normal.pal rename to graphics/pokemon/furfrou/kabuki/normal.pal diff --git a/graphics/pokemon/furfrou/kabuki_trim/overworld.png b/graphics/pokemon/furfrou/kabuki/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/kabuki_trim/overworld.png rename to graphics/pokemon/furfrou/kabuki/overworld.png diff --git a/graphics/pokemon/furfrou/kabuki_trim/overworld_normal.pal b/graphics/pokemon/furfrou/kabuki/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/kabuki_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/kabuki/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/kabuki_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/kabuki/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/kabuki_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/kabuki/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/kabuki_trim/shiny.pal b/graphics/pokemon/furfrou/kabuki/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/kabuki_trim/shiny.pal rename to graphics/pokemon/furfrou/kabuki/shiny.pal diff --git a/graphics/pokemon/furfrou/la_reine_trim/anim_front.png b/graphics/pokemon/furfrou/la_reine/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/la_reine_trim/anim_front.png rename to graphics/pokemon/furfrou/la_reine/anim_front.png diff --git a/graphics/pokemon/furfrou/la_reine_trim/back.png b/graphics/pokemon/furfrou/la_reine/back.png similarity index 100% rename from graphics/pokemon/furfrou/la_reine_trim/back.png rename to graphics/pokemon/furfrou/la_reine/back.png diff --git a/graphics/pokemon/furfrou/la_reine_trim/icon.png b/graphics/pokemon/furfrou/la_reine/icon.png similarity index 100% rename from graphics/pokemon/furfrou/la_reine_trim/icon.png rename to graphics/pokemon/furfrou/la_reine/icon.png diff --git a/graphics/pokemon/furfrou/la_reine_trim/normal.pal b/graphics/pokemon/furfrou/la_reine/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/la_reine_trim/normal.pal rename to graphics/pokemon/furfrou/la_reine/normal.pal diff --git a/graphics/pokemon/furfrou/la_reine_trim/overworld.png b/graphics/pokemon/furfrou/la_reine/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/la_reine_trim/overworld.png rename to graphics/pokemon/furfrou/la_reine/overworld.png diff --git a/graphics/pokemon/furfrou/la_reine_trim/overworld_normal.pal b/graphics/pokemon/furfrou/la_reine/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/la_reine_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/la_reine/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/la_reine_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/la_reine/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/la_reine_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/la_reine/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/la_reine_trim/shiny.pal b/graphics/pokemon/furfrou/la_reine/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/la_reine_trim/shiny.pal rename to graphics/pokemon/furfrou/la_reine/shiny.pal diff --git a/graphics/pokemon/furfrou/matron_trim/anim_front.png b/graphics/pokemon/furfrou/matron/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/matron_trim/anim_front.png rename to graphics/pokemon/furfrou/matron/anim_front.png diff --git a/graphics/pokemon/furfrou/matron_trim/back.png b/graphics/pokemon/furfrou/matron/back.png similarity index 100% rename from graphics/pokemon/furfrou/matron_trim/back.png rename to graphics/pokemon/furfrou/matron/back.png diff --git a/graphics/pokemon/furfrou/matron_trim/icon.png b/graphics/pokemon/furfrou/matron/icon.png similarity index 100% rename from graphics/pokemon/furfrou/matron_trim/icon.png rename to graphics/pokemon/furfrou/matron/icon.png diff --git a/graphics/pokemon/furfrou/matron_trim/normal.pal b/graphics/pokemon/furfrou/matron/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/matron_trim/normal.pal rename to graphics/pokemon/furfrou/matron/normal.pal diff --git a/graphics/pokemon/furfrou/matron_trim/overworld.png b/graphics/pokemon/furfrou/matron/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/matron_trim/overworld.png rename to graphics/pokemon/furfrou/matron/overworld.png diff --git a/graphics/pokemon/furfrou/matron_trim/overworld_normal.pal b/graphics/pokemon/furfrou/matron/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/matron_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/matron/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/matron_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/matron/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/matron_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/matron/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/matron_trim/shiny.pal b/graphics/pokemon/furfrou/matron/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/matron_trim/shiny.pal rename to graphics/pokemon/furfrou/matron/shiny.pal diff --git a/graphics/pokemon/furfrou/pharaoh_trim/anim_front.png b/graphics/pokemon/furfrou/pharaoh/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/pharaoh_trim/anim_front.png rename to graphics/pokemon/furfrou/pharaoh/anim_front.png diff --git a/graphics/pokemon/furfrou/pharaoh_trim/back.png b/graphics/pokemon/furfrou/pharaoh/back.png similarity index 100% rename from graphics/pokemon/furfrou/pharaoh_trim/back.png rename to graphics/pokemon/furfrou/pharaoh/back.png diff --git a/graphics/pokemon/furfrou/pharaoh_trim/icon.png b/graphics/pokemon/furfrou/pharaoh/icon.png similarity index 100% rename from graphics/pokemon/furfrou/pharaoh_trim/icon.png rename to graphics/pokemon/furfrou/pharaoh/icon.png diff --git a/graphics/pokemon/furfrou/pharaoh_trim/normal.pal b/graphics/pokemon/furfrou/pharaoh/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/pharaoh_trim/normal.pal rename to graphics/pokemon/furfrou/pharaoh/normal.pal diff --git a/graphics/pokemon/furfrou/pharaoh_trim/overworld.png b/graphics/pokemon/furfrou/pharaoh/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/pharaoh_trim/overworld.png rename to graphics/pokemon/furfrou/pharaoh/overworld.png diff --git a/graphics/pokemon/furfrou/pharaoh_trim/overworld_normal.pal b/graphics/pokemon/furfrou/pharaoh/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/pharaoh_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/pharaoh/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/pharaoh_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/pharaoh/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/pharaoh_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/pharaoh/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/pharaoh_trim/shiny.pal b/graphics/pokemon/furfrou/pharaoh/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/pharaoh_trim/shiny.pal rename to graphics/pokemon/furfrou/pharaoh/shiny.pal diff --git a/graphics/pokemon/furfrou/star_trim/anim_front.png b/graphics/pokemon/furfrou/star/anim_front.png similarity index 100% rename from graphics/pokemon/furfrou/star_trim/anim_front.png rename to graphics/pokemon/furfrou/star/anim_front.png diff --git a/graphics/pokemon/furfrou/star_trim/back.png b/graphics/pokemon/furfrou/star/back.png similarity index 100% rename from graphics/pokemon/furfrou/star_trim/back.png rename to graphics/pokemon/furfrou/star/back.png diff --git a/graphics/pokemon/furfrou/star_trim/icon.png b/graphics/pokemon/furfrou/star/icon.png similarity index 100% rename from graphics/pokemon/furfrou/star_trim/icon.png rename to graphics/pokemon/furfrou/star/icon.png diff --git a/graphics/pokemon/furfrou/star_trim/normal.pal b/graphics/pokemon/furfrou/star/normal.pal similarity index 100% rename from graphics/pokemon/furfrou/star_trim/normal.pal rename to graphics/pokemon/furfrou/star/normal.pal diff --git a/graphics/pokemon/furfrou/star_trim/overworld.png b/graphics/pokemon/furfrou/star/overworld.png similarity index 100% rename from graphics/pokemon/furfrou/star_trim/overworld.png rename to graphics/pokemon/furfrou/star/overworld.png diff --git a/graphics/pokemon/furfrou/star_trim/overworld_normal.pal b/graphics/pokemon/furfrou/star/overworld_normal.pal similarity index 100% rename from graphics/pokemon/furfrou/star_trim/overworld_normal.pal rename to graphics/pokemon/furfrou/star/overworld_normal.pal diff --git a/graphics/pokemon/furfrou/star_trim/overworld_shiny.pal b/graphics/pokemon/furfrou/star/overworld_shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/star_trim/overworld_shiny.pal rename to graphics/pokemon/furfrou/star/overworld_shiny.pal diff --git a/graphics/pokemon/furfrou/star_trim/shiny.pal b/graphics/pokemon/furfrou/star/shiny.pal similarity index 100% rename from graphics/pokemon/furfrou/star_trim/shiny.pal rename to graphics/pokemon/furfrou/star/shiny.pal diff --git a/include/constants/species.h b/include/constants/species.h index b94a15a396..3656d7664e 100644 --- a/include/constants/species.h +++ b/include/constants/species.h @@ -1214,15 +1214,15 @@ #define SPECIES_FLORGES_ORANGE 1143 #define SPECIES_FLORGES_BLUE 1144 #define SPECIES_FLORGES_WHITE 1145 -#define SPECIES_FURFROU_HEART_TRIM 1146 -#define SPECIES_FURFROU_STAR_TRIM 1147 -#define SPECIES_FURFROU_DIAMOND_TRIM 1148 -#define SPECIES_FURFROU_DEBUTANTE_TRIM 1149 -#define SPECIES_FURFROU_MATRON_TRIM 1150 -#define SPECIES_FURFROU_DANDY_TRIM 1151 -#define SPECIES_FURFROU_LA_REINE_TRIM 1152 -#define SPECIES_FURFROU_KABUKI_TRIM 1153 -#define SPECIES_FURFROU_PHARAOH_TRIM 1154 +#define SPECIES_FURFROU_HEART 1146 +#define SPECIES_FURFROU_STAR 1147 +#define SPECIES_FURFROU_DIAMOND 1148 +#define SPECIES_FURFROU_DEBUTANTE 1149 +#define SPECIES_FURFROU_MATRON 1150 +#define SPECIES_FURFROU_DANDY 1151 +#define SPECIES_FURFROU_LA_REINE 1152 +#define SPECIES_FURFROU_KABUKI 1153 +#define SPECIES_FURFROU_PHARAOH 1154 #define SPECIES_MEOWSTIC_F 1155 #define SPECIES_AEGISLASH_BLADE 1156 #define SPECIES_PUMPKABOO_SMALL 1157 diff --git a/spritesheet_rules.mk b/spritesheet_rules.mk index 88725dda66..b1cc2ac025 100644 --- a/spritesheet_rules.mk +++ b/spritesheet_rules.mk @@ -4212,31 +4212,31 @@ $(POKEMONGFXDIR)/florges/orange/overworld.4bpp: %.4bpp: %.png $(POKEMONGFXDIR)/florges/white/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/heart_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/heart/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/star_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/star/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/diamond_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/diamond/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/debutante_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/debutante/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/matron_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/matron/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/dandy_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/dandy/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/la_reine_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/la_reine/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/kabuki_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/kabuki/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 -$(POKEMONGFXDIR)/furfrou/pharaoh_trim/overworld.4bpp: %.4bpp: %.png +$(POKEMONGFXDIR)/furfrou/pharaoh/overworld.4bpp: %.4bpp: %.png $(GFX) $< $@ -mwidth 4 -mheight 4 $(POKEMONGFXDIR)/hoopa/unbound/overworld.4bpp: %.4bpp: %.png diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h index 726a0414f4..141e2f16f8 100644 --- a/src/data/graphics/pokemon.h +++ b/src/data/graphics/pokemon.h @@ -19787,92 +19787,92 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ const u8 gMonFootprint_Furfrou[] = INCBIN_U8("graphics/pokemon/furfrou/footprint.1bpp"); #endif //P_FOOTPRINTS - const u32 gMonFrontPic_FurfrouHeartTrim[] = INCBIN_U32("graphics/pokemon/furfrou/heart_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouHeartTrim[] = INCBIN_U32("graphics/pokemon/furfrou/heart_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouHeartTrim[] = INCBIN_U32("graphics/pokemon/furfrou/heart_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouHeartTrim[] = INCBIN_U32("graphics/pokemon/furfrou/heart_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouHeartTrim[] = INCBIN_U8("graphics/pokemon/furfrou/heart_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouHeart[] = INCBIN_U32("graphics/pokemon/furfrou/heart/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouHeart[] = INCBIN_U32("graphics/pokemon/furfrou/heart/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouHeart[] = INCBIN_U32("graphics/pokemon/furfrou/heart/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouHeart[] = INCBIN_U32("graphics/pokemon/furfrou/heart/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouHeart[] = INCBIN_U8("graphics/pokemon/furfrou/heart/icon.4bpp"); - const u32 gMonFrontPic_FurfrouStarTrim[] = INCBIN_U32("graphics/pokemon/furfrou/star_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouStarTrim[] = INCBIN_U32("graphics/pokemon/furfrou/star_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouStarTrim[] = INCBIN_U32("graphics/pokemon/furfrou/star_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouStarTrim[] = INCBIN_U32("graphics/pokemon/furfrou/star_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouStarTrim[] = INCBIN_U8("graphics/pokemon/furfrou/star_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouStar[] = INCBIN_U32("graphics/pokemon/furfrou/star/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouStar[] = INCBIN_U32("graphics/pokemon/furfrou/star/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouStar[] = INCBIN_U32("graphics/pokemon/furfrou/star/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouStar[] = INCBIN_U32("graphics/pokemon/furfrou/star/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouStar[] = INCBIN_U8("graphics/pokemon/furfrou/star/icon.4bpp"); - const u32 gMonFrontPic_FurfrouDiamondTrim[] = INCBIN_U32("graphics/pokemon/furfrou/diamond_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouDiamondTrim[] = INCBIN_U32("graphics/pokemon/furfrou/diamond_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouDiamondTrim[] = INCBIN_U32("graphics/pokemon/furfrou/diamond_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouDiamondTrim[] = INCBIN_U32("graphics/pokemon/furfrou/diamond_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouDiamondTrim[] = INCBIN_U8("graphics/pokemon/furfrou/diamond_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouDiamond[] = INCBIN_U32("graphics/pokemon/furfrou/diamond/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouDiamond[] = INCBIN_U32("graphics/pokemon/furfrou/diamond/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouDiamond[] = INCBIN_U32("graphics/pokemon/furfrou/diamond/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouDiamond[] = INCBIN_U32("graphics/pokemon/furfrou/diamond/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouDiamond[] = INCBIN_U8("graphics/pokemon/furfrou/diamond/icon.4bpp"); - const u32 gMonFrontPic_FurfrouDebutanteTrim[] = INCBIN_U32("graphics/pokemon/furfrou/debutante_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouDebutanteTrim[] = INCBIN_U32("graphics/pokemon/furfrou/debutante_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouDebutanteTrim[] = INCBIN_U32("graphics/pokemon/furfrou/debutante_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouDebutanteTrim[] = INCBIN_U32("graphics/pokemon/furfrou/debutante_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouDebutanteTrim[] = INCBIN_U8("graphics/pokemon/furfrou/debutante_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouDebutante[] = INCBIN_U32("graphics/pokemon/furfrou/debutante/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouDebutante[] = INCBIN_U32("graphics/pokemon/furfrou/debutante/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouDebutante[] = INCBIN_U32("graphics/pokemon/furfrou/debutante/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouDebutante[] = INCBIN_U32("graphics/pokemon/furfrou/debutante/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouDebutante[] = INCBIN_U8("graphics/pokemon/furfrou/debutante/icon.4bpp"); - const u32 gMonFrontPic_FurfrouMatronTrim[] = INCBIN_U32("graphics/pokemon/furfrou/matron_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouMatronTrim[] = INCBIN_U32("graphics/pokemon/furfrou/matron_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouMatronTrim[] = INCBIN_U32("graphics/pokemon/furfrou/matron_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouMatronTrim[] = INCBIN_U32("graphics/pokemon/furfrou/matron_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouMatronTrim[] = INCBIN_U8("graphics/pokemon/furfrou/matron_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouMatron[] = INCBIN_U32("graphics/pokemon/furfrou/matron/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouMatron[] = INCBIN_U32("graphics/pokemon/furfrou/matron/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouMatron[] = INCBIN_U32("graphics/pokemon/furfrou/matron/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouMatron[] = INCBIN_U32("graphics/pokemon/furfrou/matron/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouMatron[] = INCBIN_U8("graphics/pokemon/furfrou/matron/icon.4bpp"); - const u32 gMonFrontPic_FurfrouDandyTrim[] = INCBIN_U32("graphics/pokemon/furfrou/dandy_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouDandyTrim[] = INCBIN_U32("graphics/pokemon/furfrou/dandy_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouDandyTrim[] = INCBIN_U32("graphics/pokemon/furfrou/dandy_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouDandyTrim[] = INCBIN_U32("graphics/pokemon/furfrou/dandy_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouDandyTrim[] = INCBIN_U8("graphics/pokemon/furfrou/dandy_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouDandy[] = INCBIN_U32("graphics/pokemon/furfrou/dandy/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouDandy[] = INCBIN_U32("graphics/pokemon/furfrou/dandy/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouDandy[] = INCBIN_U32("graphics/pokemon/furfrou/dandy/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouDandy[] = INCBIN_U32("graphics/pokemon/furfrou/dandy/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouDandy[] = INCBIN_U8("graphics/pokemon/furfrou/dandy/icon.4bpp"); - const u32 gMonFrontPic_FurfrouLaReineTrim[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouLaReineTrim[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouLaReineTrim[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouLaReineTrim[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouLaReineTrim[] = INCBIN_U8("graphics/pokemon/furfrou/la_reine_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouLaReine[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouLaReine[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouLaReine[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouLaReine[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouLaReine[] = INCBIN_U8("graphics/pokemon/furfrou/la_reine/icon.4bpp"); - const u32 gMonFrontPic_FurfrouKabukiTrim[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouKabukiTrim[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouKabukiTrim[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouKabukiTrim[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouKabukiTrim[] = INCBIN_U8("graphics/pokemon/furfrou/kabuki_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouKabuki[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouKabuki[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouKabuki[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouKabuki[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouKabuki[] = INCBIN_U8("graphics/pokemon/furfrou/kabuki/icon.4bpp"); - const u32 gMonFrontPic_FurfrouPharaohTrim[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh_trim/anim_front.4bpp.lz"); - const u32 gMonPalette_FurfrouPharaohTrim[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh_trim/normal.gbapal.lz"); - const u32 gMonBackPic_FurfrouPharaohTrim[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh_trim/back.4bpp.lz"); - const u32 gMonShinyPalette_FurfrouPharaohTrim[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh_trim/shiny.gbapal.lz"); - const u8 gMonIcon_FurfrouPharaohTrim[] = INCBIN_U8("graphics/pokemon/furfrou/pharaoh_trim/icon.4bpp"); + const u32 gMonFrontPic_FurfrouPharaoh[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh/anim_front.4bpp.lz"); + const u32 gMonPalette_FurfrouPharaoh[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh/normal.gbapal.lz"); + const u32 gMonBackPic_FurfrouPharaoh[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh/back.4bpp.lz"); + const u32 gMonShinyPalette_FurfrouPharaoh[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh/shiny.gbapal.lz"); + const u8 gMonIcon_FurfrouPharaoh[] = INCBIN_U8("graphics/pokemon/furfrou/pharaoh/icon.4bpp"); #if OW_POKEMON_OBJECT_EVENTS const u32 gObjectEventPic_FurfrouNatural[] = INCBIN_COMP("graphics/pokemon/furfrou/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouHeartTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/heart_trim/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouStarTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/star_trim/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouDiamondTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/diamond_trim/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouDebutanteTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/debutante_trim/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouMatronTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/matron_trim/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouDandyTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/dandy_trim/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouLaReineTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/la_reine_trim/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouKabukiTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/kabuki_trim/overworld.4bpp"); - const u32 gObjectEventPic_FurfrouPharaohTrim[] = INCBIN_COMP("graphics/pokemon/furfrou/pharaoh_trim/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouHeart[] = INCBIN_COMP("graphics/pokemon/furfrou/heart/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouStar[] = INCBIN_COMP("graphics/pokemon/furfrou/star/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouDiamond[] = INCBIN_COMP("graphics/pokemon/furfrou/diamond/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouDebutante[] = INCBIN_COMP("graphics/pokemon/furfrou/debutante/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouMatron[] = INCBIN_COMP("graphics/pokemon/furfrou/matron/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouDandy[] = INCBIN_COMP("graphics/pokemon/furfrou/dandy/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouLaReine[] = INCBIN_COMP("graphics/pokemon/furfrou/la_reine/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouKabuki[] = INCBIN_COMP("graphics/pokemon/furfrou/kabuki/overworld.4bpp"); + const u32 gObjectEventPic_FurfrouPharaoh[] = INCBIN_COMP("graphics/pokemon/furfrou/pharaoh/overworld.4bpp"); #if OW_PKMN_OBJECTS_SHARE_PALETTES == FALSE const u32 gOverworldPalette_FurfrouNatural[] = INCBIN_U32("graphics/pokemon/furfrou/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouHeartTrim[] = INCBIN_U32("graphics/pokemon/furfrou/heart_trim/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouStarTrim[] = INCBIN_U32("graphics/pokemon/furfrou/star_trim/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouDiamondTrim[] = INCBIN_U32("graphics/pokemon/furfrou/diamond_trim/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouDebutanteTrim[] = INCBIN_U32("graphics/pokemon/furfrou/debutante_trim/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouMatronTrim[] = INCBIN_U32("graphics/pokemon/furfrou/matron_trim/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouDandyTrim[] = INCBIN_U32("graphics/pokemon/furfrou/dandy_trim/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouLaReineTrim[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine_trim/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouKabukiTrim[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki_trim/overworld_normal.gbapal.lz"); - const u32 gOverworldPalette_FurfrouPharaohTrim[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh_trim/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouHeart[] = INCBIN_U32("graphics/pokemon/furfrou/heart/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouStar[] = INCBIN_U32("graphics/pokemon/furfrou/star/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouDiamond[] = INCBIN_U32("graphics/pokemon/furfrou/diamond/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouDebutante[] = INCBIN_U32("graphics/pokemon/furfrou/debutante/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouMatron[] = INCBIN_U32("graphics/pokemon/furfrou/matron/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouDandy[] = INCBIN_U32("graphics/pokemon/furfrou/dandy/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouLaReine[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouKabuki[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki/overworld_normal.gbapal.lz"); + const u32 gOverworldPalette_FurfrouPharaoh[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh/overworld_normal.gbapal.lz"); const u32 gShinyOverworldPalette_FurfrouNatural[] = INCBIN_U32("graphics/pokemon/furfrou/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouHeartTrim[] = INCBIN_U32("graphics/pokemon/furfrou/heart_trim/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouStarTrim[] = INCBIN_U32("graphics/pokemon/furfrou/star_trim/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouDiamondTrim[] = INCBIN_U32("graphics/pokemon/furfrou/diamond_trim/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouDebutanteTrim[] = INCBIN_U32("graphics/pokemon/furfrou/debutante_trim/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouMatronTrim[] = INCBIN_U32("graphics/pokemon/furfrou/matron_trim/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouDandyTrim[] = INCBIN_U32("graphics/pokemon/furfrou/dandy_trim/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouLaReineTrim[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine_trim/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouKabukiTrim[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki_trim/overworld_shiny.gbapal.lz"); - const u32 gShinyOverworldPalette_FurfrouPharaohTrim[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh_trim/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouHeart[] = INCBIN_U32("graphics/pokemon/furfrou/heart/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouStar[] = INCBIN_U32("graphics/pokemon/furfrou/star/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouDiamond[] = INCBIN_U32("graphics/pokemon/furfrou/diamond/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouDebutante[] = INCBIN_U32("graphics/pokemon/furfrou/debutante/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouMatron[] = INCBIN_U32("graphics/pokemon/furfrou/matron/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouDandy[] = INCBIN_U32("graphics/pokemon/furfrou/dandy/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouLaReine[] = INCBIN_U32("graphics/pokemon/furfrou/la_reine/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouKabuki[] = INCBIN_U32("graphics/pokemon/furfrou/kabuki/overworld_shiny.gbapal.lz"); + const u32 gShinyOverworldPalette_FurfrouPharaoh[] = INCBIN_U32("graphics/pokemon/furfrou/pharaoh/overworld_shiny.gbapal.lz"); #endif //OW_PKMN_OBJECTS_SHARE_PALETTES #endif //OW_POKEMON_OBJECT_EVENTS #endif //P_FAMILY_FURFROU diff --git a/src/data/object_events/object_event_pic_tables_followers.h b/src/data/object_events/object_event_pic_tables_followers.h index 07193cedc7..54b8cc317d 100644 --- a/src/data/object_events/object_event_pic_tables_followers.h +++ b/src/data/object_events/object_event_pic_tables_followers.h @@ -4679,32 +4679,32 @@ static const struct SpriteFrameImage sPicTable_Pangoro[] = { static const struct SpriteFrameImage sPicTable_FurfrouNatural[] = { overworld_ascending_frames(gObjectEventPic_FurfrouNatural, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouHeartTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouHeartTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouHeart[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouHeart, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouStarTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouStarTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouStar[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouStar, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouDiamondTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouDiamondTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouDiamond[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouDiamond, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouDebutanteTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouDebutanteTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouDebutante[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouDebutante, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouMatronTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouMatronTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouMatron[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouMatron, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouDandyTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouDandyTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouDandy[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouDandy, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouLaReineTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouLaReineTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouLaReine[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouLaReine, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouKabukiTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouKabukiTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouKabuki[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouKabuki, 4, 4), }; -static const struct SpriteFrameImage sPicTable_FurfrouPharaohTrim[] = { - overworld_ascending_frames(gObjectEventPic_FurfrouPharaohTrim, 4, 4), +static const struct SpriteFrameImage sPicTable_FurfrouPharaoh[] = { + overworld_ascending_frames(gObjectEventPic_FurfrouPharaoh, 4, 4), }; #endif //P_FAMILY_FURFROU diff --git a/src/data/pokemon/form_species_tables.h b/src/data/pokemon/form_species_tables.h index f2c4560216..f30c1cca77 100644 --- a/src/data/pokemon/form_species_tables.h +++ b/src/data/pokemon/form_species_tables.h @@ -1459,15 +1459,15 @@ static const u16 sFlorgesFormSpeciesIdTable[] = { #if P_FAMILY_FURFROU static const u16 sFurfrouFormSpeciesIdTable[] = { SPECIES_FURFROU_NATURAL, - SPECIES_FURFROU_HEART_TRIM, - SPECIES_FURFROU_STAR_TRIM, - SPECIES_FURFROU_DIAMOND_TRIM, - SPECIES_FURFROU_DEBUTANTE_TRIM, - SPECIES_FURFROU_MATRON_TRIM, - SPECIES_FURFROU_DANDY_TRIM, - SPECIES_FURFROU_LA_REINE_TRIM, - SPECIES_FURFROU_KABUKI_TRIM, - SPECIES_FURFROU_PHARAOH_TRIM, + SPECIES_FURFROU_HEART, + SPECIES_FURFROU_STAR, + SPECIES_FURFROU_DIAMOND, + SPECIES_FURFROU_DEBUTANTE, + SPECIES_FURFROU_MATRON, + SPECIES_FURFROU_DANDY, + SPECIES_FURFROU_LA_REINE, + SPECIES_FURFROU_KABUKI, + SPECIES_FURFROU_PHARAOH, FORM_SPECIES_END, }; #endif //P_FAMILY_FURFROU diff --git a/src/data/pokemon/pokedex_orders.h b/src/data/pokemon/pokedex_orders.h index 1b0b32c63c..b2f5f3cc02 100644 --- a/src/data/pokemon/pokedex_orders.h +++ b/src/data/pokemon/pokedex_orders.h @@ -1894,15 +1894,15 @@ const u16 gPokedexOrder_Weight[] = NATIONAL_DEX_SIMISEAR, NATIONAL_DEX_MARACTUS, NATIONAL_DEX_FURFROU,//_NATURAL, - //NATIONAL_DEX_FURFROU_HEART_TRIM, - //NATIONAL_DEX_FURFROU_STAR_TRIM, - //NATIONAL_DEX_FURFROU_DIAMOND_TRIM, - //NATIONAL_DEX_FURFROU_DEBUTANTE_TRIM, - //NATIONAL_DEX_FURFROU_MATRON_TRIM, - //NATIONAL_DEX_FURFROU_DANDY_TRIM, - //NATIONAL_DEX_FURFROU_LA_REINE_TRIM, - //NATIONAL_DEX_FURFROU_KABUKI_TRIM, - //NATIONAL_DEX_FURFROU_PHARAOH_TRIM, + //NATIONAL_DEX_FURFROU_HEART, + //NATIONAL_DEX_FURFROU_STAR, + //NATIONAL_DEX_FURFROU_DIAMOND, + //NATIONAL_DEX_FURFROU_DEBUTANTE, + //NATIONAL_DEX_FURFROU_MATRON, + //NATIONAL_DEX_FURFROU_DANDY, + //NATIONAL_DEX_FURFROU_LA_REINE, + //NATIONAL_DEX_FURFROU_KABUKI, + //NATIONAL_DEX_FURFROU_PHARAOH, NATIONAL_DEX_PERRSERKER, NATIONAL_DEX_INDEEDEE,//_MALE, //NATIONAL_DEX_INDEEDEE_FEMALE, @@ -3711,15 +3711,15 @@ const u16 gPokedexOrder_Height[] = NATIONAL_DEX_TALONFLAME, NATIONAL_DEX_VIVILLON, NATIONAL_DEX_FURFROU,//_NATURAL, - //NATIONAL_DEX_FURFROU_HEART_TRIM, - //NATIONAL_DEX_FURFROU_STAR_TRIM, - //NATIONAL_DEX_FURFROU_DIAMOND_TRIM, - //NATIONAL_DEX_FURFROU_DEBUTANTE_TRIM, - //NATIONAL_DEX_FURFROU_MATRON_TRIM, - //NATIONAL_DEX_FURFROU_DANDY_TRIM, - //NATIONAL_DEX_FURFROU_LA_REINE_TRIM, - //NATIONAL_DEX_FURFROU_KABUKI_TRIM, - //NATIONAL_DEX_FURFROU_PHARAOH_TRIM, + //NATIONAL_DEX_FURFROU_HEART, + //NATIONAL_DEX_FURFROU_STAR, + //NATIONAL_DEX_FURFROU_DIAMOND, + //NATIONAL_DEX_FURFROU_DEBUTANTE, + //NATIONAL_DEX_FURFROU_MATRON, + //NATIONAL_DEX_FURFROU_DANDY, + //NATIONAL_DEX_FURFROU_LA_REINE, + //NATIONAL_DEX_FURFROU_KABUKI, + //NATIONAL_DEX_FURFROU_PHARAOH, //NATIONAL_DEX_ZYGARDE_10, //NATIONAL_DEX_ZYGARDE_10_POWER_CONSTRUCT, NATIONAL_DEX_SALAZZLE, diff --git a/src/data/pokemon/species_info/gen_6_families.h b/src/data/pokemon/species_info/gen_6_families.h index 147fadbaf8..08e175c9d3 100644 --- a/src/data/pokemon/species_info/gen_6_families.h +++ b/src/data/pokemon/species_info/gen_6_families.h @@ -2192,16 +2192,16 @@ const struct SpeciesInfo gSpeciesInfoGen6[] = .formChangeTable = sFurfrouFormChangeTable, \ } - [SPECIES_FURFROU_NATURAL] = FURFROU_MISC_INFO(Natural, FALSE, 48, 3, 56, 0, 0), - [SPECIES_FURFROU_HEART_TRIM] = FURFROU_MISC_INFO(HeartTrim, FALSE, 56, 2, 56, 1, 0), - [SPECIES_FURFROU_STAR_TRIM] = FURFROU_MISC_INFO(StarTrim, FALSE, 56, 2, 64, 1, 0), - [SPECIES_FURFROU_DIAMOND_TRIM] = FURFROU_MISC_INFO(DiamondTrim, FALSE, 48, 2, 56, 1, 0), - [SPECIES_FURFROU_DEBUTANTE_TRIM] = FURFROU_MISC_INFO(DebutanteTrim, TRUE, 48, 2, 56, 1, 2), - [SPECIES_FURFROU_MATRON_TRIM] = FURFROU_MISC_INFO(MatronTrim, FALSE, 48, 2, 56, 1, 2), - [SPECIES_FURFROU_DANDY_TRIM] = FURFROU_MISC_INFO(DandyTrim, FALSE, 48, 2, 56, 1, 1), - [SPECIES_FURFROU_LA_REINE_TRIM] = FURFROU_MISC_INFO(LaReineTrim, FALSE, 48, 2, 56, 1, 0), - [SPECIES_FURFROU_KABUKI_TRIM] = FURFROU_MISC_INFO(KabukiTrim, FALSE, 56, 2, 56, 1, 0), - [SPECIES_FURFROU_PHARAOH_TRIM] = FURFROU_MISC_INFO(PharaohTrim, FALSE, 48, 2, 56, 1, 0), + [SPECIES_FURFROU_NATURAL] = FURFROU_MISC_INFO(Natural, FALSE, 48, 3, 56, 0, 0), + [SPECIES_FURFROU_HEART] = FURFROU_MISC_INFO(Heart, FALSE, 56, 2, 56, 1, 0), + [SPECIES_FURFROU_STAR] = FURFROU_MISC_INFO(Star, FALSE, 56, 2, 64, 1, 0), + [SPECIES_FURFROU_DIAMOND] = FURFROU_MISC_INFO(Diamond, FALSE, 48, 2, 56, 1, 0), + [SPECIES_FURFROU_DEBUTANTE] = FURFROU_MISC_INFO(Debutante, TRUE, 48, 2, 56, 1, 2), + [SPECIES_FURFROU_MATRON] = FURFROU_MISC_INFO(Matron, FALSE, 48, 2, 56, 1, 2), + [SPECIES_FURFROU_DANDY] = FURFROU_MISC_INFO(Dandy, FALSE, 48, 2, 56, 1, 1), + [SPECIES_FURFROU_LA_REINE] = FURFROU_MISC_INFO(LaReine, FALSE, 48, 2, 56, 1, 0), + [SPECIES_FURFROU_KABUKI] = FURFROU_MISC_INFO(Kabuki, FALSE, 56, 2, 56, 1, 0), + [SPECIES_FURFROU_PHARAOH] = FURFROU_MISC_INFO(Pharaoh, FALSE, 48, 2, 56, 1, 0), #endif //P_FAMILY_FURFROU #if P_FAMILY_ESPURR