From 77442987888fffbdbdf9c7ff5f760cd9bdef0ff0 Mon Sep 17 00:00:00 2001 From: Philipp AUER Date: Thu, 5 Dec 2024 06:35:56 -0500 Subject: [PATCH 01/26] Fix fixed point damage calculation off-by-1s (#5775) Co-authored-by: sbird --- include/fpmath.h | 3 +- include/gba/defines.h | 2 + src/battle_dynamax.c | 6 +- src/battle_util.c | 145 ++++++------------------------- test/battle/ability/transistor.c | 22 ++--- test/battle/damage_formula.c | 131 ++++++++++++++++++++++++++++ 6 files changed, 172 insertions(+), 137 deletions(-) diff --git a/include/fpmath.h b/include/fpmath.h index 6e3edd64e0..69265652e6 100644 --- a/include/fpmath.h +++ b/include/fpmath.h @@ -12,7 +12,8 @@ typedef u32 uq4_12_t; // Converts a number to Q4.12 fixed-point format #define Q_4_12(n) ((q4_12_t)((n) * 4096)) -#define UQ_4_12(n) ((uq4_12_t)((n) * 4096)) +#define UQ_4_12(n) ((uq4_12_t)((n) * 4096 + 0.5)) +#define UQ_4_12_FLOORED(n) ((uq4_12_t)((n) * 4096)) // Converts a number to Q24.8 fixed-point format #define Q_24_8(n) ((s32)((n) << 8)) diff --git a/include/gba/defines.h b/include/gba/defines.h index c54dac8c13..0bf7110810 100644 --- a/include/gba/defines.h +++ b/include/gba/defines.h @@ -13,6 +13,8 @@ #define COMMON_DATA __attribute__((section("common_data"))) #define UNUSED __attribute__((unused)) +#define ARM_FUNC __attribute__((target("arm"))) + #if MODERN #define NOINLINE __attribute__((noinline)) #else diff --git a/src/battle_dynamax.c b/src/battle_dynamax.c index 1523bcbd6e..98ee89af9b 100644 --- a/src/battle_dynamax.c +++ b/src/battle_dynamax.c @@ -151,7 +151,7 @@ u16 GetNonDynamaxHP(u32 battler) return gBattleMons[battler].hp; else { - u16 mult = UQ_4_12(1.0/1.5); // placeholder + u16 mult = UQ_4_12_FLOORED(1.0/1.5); // placeholder u16 hp = UQ_4_12_TO_INT((gBattleMons[battler].hp * mult) + UQ_4_12_ROUND); return hp; } @@ -164,7 +164,7 @@ u16 GetNonDynamaxMaxHP(u32 battler) return gBattleMons[battler].maxHP; else { - u16 mult = UQ_4_12(1.0/1.5); // placeholder + u16 mult = UQ_4_12_FLOORED(1.0/1.5); // placeholder u16 maxHP = UQ_4_12_TO_INT((gBattleMons[battler].maxHP * mult) + UQ_4_12_ROUND); return maxHP; } @@ -202,7 +202,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 + u16 mult = UQ_4_12_FLOORED(1.0/1.5); // placeholder 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); diff --git a/src/battle_util.c b/src/battle_util.c index 4b764776e2..c00598eb14 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -62,6 +62,8 @@ static u32 GetFlingPowerFromItemId(u32 itemId); static void SetRandomMultiHitCounter(); static u32 GetBattlerItemHoldEffectParam(u32 battler, u32 item); static bool32 CanBeInfinitelyConfused(u32 battler); +ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent); +ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent); extern const u8 *const gBattlescriptsForRunningByItem[]; extern const u8 *const gBattlescriptsForUsingItem[]; @@ -757,113 +759,18 @@ static const u8 sHoldEffectToType[][2] = {HOLD_EFFECT_FAIRY_POWER, TYPE_FAIRY}, }; -// percent in UQ_4_12 format -static const uq4_12_t sPercentToModifier[] = -{ - UQ_4_12(0.00), // 0 - UQ_4_12(0.01), // 1 - UQ_4_12(0.02), // 2 - UQ_4_12(0.03), // 3 - UQ_4_12(0.04), // 4 - UQ_4_12(0.05), // 5 - UQ_4_12(0.06), // 6 - UQ_4_12(0.07), // 7 - UQ_4_12(0.08), // 8 - UQ_4_12(0.09), // 9 - UQ_4_12(0.10), // 10 - UQ_4_12(0.11), // 11 - UQ_4_12(0.12), // 12 - UQ_4_12(0.13), // 13 - UQ_4_12(0.14), // 14 - UQ_4_12(0.15), // 15 - UQ_4_12(0.16), // 16 - UQ_4_12(0.17), // 17 - UQ_4_12(0.18), // 18 - UQ_4_12(0.19), // 19 - UQ_4_12(0.20), // 20 - UQ_4_12(0.21), // 21 - UQ_4_12(0.22), // 22 - UQ_4_12(0.23), // 23 - UQ_4_12(0.24), // 24 - UQ_4_12(0.25), // 25 - UQ_4_12(0.26), // 26 - UQ_4_12(0.27), // 27 - UQ_4_12(0.28), // 28 - UQ_4_12(0.29), // 29 - UQ_4_12(0.30), // 30 - UQ_4_12(0.31), // 31 - UQ_4_12(0.32), // 32 - UQ_4_12(0.33), // 33 - UQ_4_12(0.34), // 34 - UQ_4_12(0.35), // 35 - UQ_4_12(0.36), // 36 - UQ_4_12(0.37), // 37 - UQ_4_12(0.38), // 38 - UQ_4_12(0.39), // 39 - UQ_4_12(0.40), // 40 - UQ_4_12(0.41), // 41 - UQ_4_12(0.42), // 42 - UQ_4_12(0.43), // 43 - UQ_4_12(0.44), // 44 - UQ_4_12(0.45), // 45 - UQ_4_12(0.46), // 46 - UQ_4_12(0.47), // 47 - UQ_4_12(0.48), // 48 - UQ_4_12(0.49), // 49 - UQ_4_12(0.50), // 50 - UQ_4_12(0.51), // 51 - UQ_4_12(0.52), // 52 - UQ_4_12(0.53), // 53 - UQ_4_12(0.54), // 54 - UQ_4_12(0.55), // 55 - UQ_4_12(0.56), // 56 - UQ_4_12(0.57), // 57 - UQ_4_12(0.58), // 58 - UQ_4_12(0.59), // 59 - UQ_4_12(0.60), // 60 - UQ_4_12(0.61), // 61 - UQ_4_12(0.62), // 62 - UQ_4_12(0.63), // 63 - UQ_4_12(0.64), // 64 - UQ_4_12(0.65), // 65 - UQ_4_12(0.66), // 66 - UQ_4_12(0.67), // 67 - UQ_4_12(0.68), // 68 - UQ_4_12(0.69), // 69 - UQ_4_12(0.70), // 70 - UQ_4_12(0.71), // 71 - UQ_4_12(0.72), // 72 - UQ_4_12(0.73), // 73 - UQ_4_12(0.74), // 74 - UQ_4_12(0.75), // 75 - UQ_4_12(0.76), // 76 - UQ_4_12(0.77), // 77 - UQ_4_12(0.78), // 78 - UQ_4_12(0.79), // 79 - UQ_4_12(0.80), // 80 - UQ_4_12(0.81), // 81 - UQ_4_12(0.82), // 82 - UQ_4_12(0.83), // 83 - UQ_4_12(0.84), // 84 - UQ_4_12(0.85), // 85 - UQ_4_12(0.86), // 86 - UQ_4_12(0.87), // 87 - UQ_4_12(0.88), // 88 - UQ_4_12(0.89), // 89 - UQ_4_12(0.90), // 90 - UQ_4_12(0.91), // 91 - UQ_4_12(0.92), // 92 - UQ_4_12(0.93), // 93 - UQ_4_12(0.94), // 94 - UQ_4_12(0.95), // 95 - UQ_4_12(0.96), // 96 - UQ_4_12(0.97), // 97 - UQ_4_12(0.98), // 98 - UQ_4_12(0.99), // 99 - UQ_4_12(1.00), // 100 -}; - // code + +ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12(u32 percent) +{ + return (4096 * percent + 50) / 100; +} + +ARM_FUNC NOINLINE static uq4_12_t PercentToUQ4_12_Floored(u32 percent) +{ + return (4096 * percent) / 100; +} + u8 GetBattlerForBattleScript(u8 caseId) { u8 ret = 0; @@ -4136,7 +4043,7 @@ static inline u8 GetBattlerSideFaintCounter(u32 battler) // Supreme Overlord adds a x0.1 damage boost for each fainted ally. static inline uq4_12_t GetSupremeOverlordModifier(u32 battler) { - return UQ_4_12(1.0) + (UQ_4_12(0.1) * gBattleStruct->supremeOverlordCounter[battler]); + return UQ_4_12(1.0) + (PercentToUQ4_12(gBattleStruct->supremeOverlordCounter[battler] * 10)); } static inline bool32 HadMoreThanHalfHpNowDoesnt(u32 battler) @@ -9302,7 +9209,7 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * if (gProtectStructs[battlerAtk].helpingHand) modifier = uq4_12_multiply(modifier, UQ_4_12(1.5)); if (gSpecialStatuses[battlerAtk].gemBoost) - modifier = uq4_12_multiply(modifier, UQ_4_12(1.0) + sPercentToModifier[gSpecialStatuses[battlerAtk].gemParam]); + modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12(gSpecialStatuses[battlerAtk].gemParam))); if (gStatuses3[battlerAtk] & STATUS3_CHARGED_UP && moveType == TYPE_ELECTRIC) modifier = uq4_12_multiply(modifier, UQ_4_12(2.0)); if (gStatuses3[battlerAtk] & STATUS3_ME_FIRST) @@ -9491,18 +9398,18 @@ static inline u32 CalcMoveBasePowerAfterModifiers(struct DamageCalculationData * if (holdEffectParamAtk > 100) holdEffectParamAtk = 100; - holdEffectModifier = UQ_4_12(1.0) + sPercentToModifier[holdEffectParamAtk]; + holdEffectModifier = uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12(holdEffectParamAtk)); // attacker's hold effect switch (holdEffectAtk) { case HOLD_EFFECT_MUSCLE_BAND: if (IS_MOVE_PHYSICAL(move)) - modifier = uq4_12_multiply(modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12_Floored(holdEffectParamAtk))); break; case HOLD_EFFECT_WISE_GLASSES: if (IS_MOVE_SPECIAL(move)) - modifier = uq4_12_multiply(modifier, holdEffectModifier); + modifier = uq4_12_multiply(modifier, uq4_12_add(UQ_4_12(1.0), PercentToUQ4_12_Floored(holdEffectParamAtk))); break; case HOLD_EFFECT_LUSTROUS_ORB: if (GET_BASE_SPECIES_ID(gBattleMons[battlerAtk].species) == SPECIES_PALKIA && (moveType == TYPE_WATER || moveType == TYPE_DRAGON)) @@ -9768,11 +9675,11 @@ static inline u32 CalcAttackStat(struct DamageCalculationData *damageCalcData, u break; case ABILITY_ORICHALCUM_PULSE: if ((weather & B_WEATHER_SUN) && WEATHER_HAS_EFFECT && IS_MOVE_PHYSICAL(move)) - modifier = uq4_12_multiply(modifier, UQ_4_12(1.33)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3333)); break; case ABILITY_HADRON_ENGINE: if (gFieldStatuses & STATUS_FIELD_ELECTRIC_TERRAIN && IS_MOVE_SPECIAL(move)) - modifier = uq4_12_multiply(modifier, UQ_4_12(1.33)); + modifier = uq4_12_multiply(modifier, UQ_4_12(1.3333)); break; } @@ -10234,19 +10141,23 @@ static inline uq4_12_t GetDefenderPartnerAbilitiesModifier(u32 battlerPartnerDef static inline uq4_12_t GetAttackerItemsModifier(u32 battlerAtk, uq4_12_t typeEffectivenessModifier, u32 holdEffectAtk) { - u32 percentBoost; + u32 metronomeTurns; + uq4_12_t metronomeBoostBase; switch (holdEffectAtk) { case HOLD_EFFECT_METRONOME: - percentBoost = min((gBattleStruct->sameMoveTurns[battlerAtk] * GetBattlerHoldEffectParam(battlerAtk)), 100); - return uq4_12_add(sPercentToModifier[percentBoost], UQ_4_12(1.0)); + metronomeBoostBase = PercentToUQ4_12(GetBattlerHoldEffectParam(battlerAtk)); + metronomeTurns = min(gBattleStruct->sameMoveTurns[battlerAtk], 5); + // according to bulbapedia this is the "correct" way to calculate the metronome boost + // due to the limited domain of damage numbers it will never really matter whether this is off by one + return uq4_12_add(UQ_4_12(1.0), metronomeBoostBase * metronomeTurns); break; case HOLD_EFFECT_EXPERT_BELT: if (typeEffectivenessModifier >= UQ_4_12(2.0)) return UQ_4_12(1.2); break; case HOLD_EFFECT_LIFE_ORB: - return UQ_4_12(1.3); + return UQ_4_12_FLOORED(1.3); break; } return UQ_4_12(1.0); diff --git a/test/battle/ability/transistor.c b/test/battle/ability/transistor.c index f02743ab8c..8dd1a1bdb3 100644 --- a/test/battle/ability/transistor.c +++ b/test/battle/ability/transistor.c @@ -4,7 +4,7 @@ #include "global.h" #include "test/battle.h" -SINGLE_BATTLE_TEST("Transistor increases Electric-type move damage", s16 damage) +SINGLE_BATTLE_TEST("Transistor increases Electric-type attack / special attack", s16 damage) { u32 move; u16 ability; @@ -30,20 +30,13 @@ SINGLE_BATTLE_TEST("Transistor increases Electric-type move damage", s16 damage) HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { EXPECT_EQ(results[0].damage, results[1].damage); // Tackle should be unaffected - if (B_TRANSISTOR_BOOST >= GEN_9) - { - EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.3), results[3].damage); // Wild Charge should be affected - EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.3), results[5].damage); // Thunder Shock should be affected - } - else - { - EXPECT_MUL_EQ(results[2].damage, Q_4_12(1.5), results[3].damage); // Wild Charge should be affected - EXPECT_MUL_EQ(results[4].damage, Q_4_12(1.5), results[5].damage); // Thunder Shock should be affected - } + + EXPECT_LT(results[2].damage, results[3].damage); // cannot test exact factor because ATK / SPATK introduces inaccuracies + EXPECT_LT(results[4].damage, results[5].damage); } } -SINGLE_BATTLE_TEST("Transistor boosts Electric type moves by 1.5 in Gen8 and 1.3 in Gen9+", s16 damage) +SINGLE_BATTLE_TEST("Transistor is blocked by neutralizing gas", s16 damage) { u16 ability; PARAMETRIZE { ability = ABILITY_NEUTRALIZING_GAS; } @@ -58,9 +51,6 @@ SINGLE_BATTLE_TEST("Transistor boosts Electric type moves by 1.5 in Gen8 and 1.3 } SCENE { HP_BAR(opponent, captureDamage: &results[i].damage); } FINALLY { - if (B_TRANSISTOR_BOOST >= GEN_9) - EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.3), results[1].damage); - else - EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + EXPECT_LT(results[0].damage, results[1].damage); // cannot test exact factor because ATK / SPATK introduces inaccuracies } } diff --git a/test/battle/damage_formula.c b/test/battle/damage_formula.c index 473f631b11..049bbf4051 100644 --- a/test/battle/damage_formula.c +++ b/test/battle/damage_formula.c @@ -150,3 +150,134 @@ DOUBLE_BATTLE_TEST("A spread move will do correct damage to the second mon if th EXPECT_EQ(damage[4], damage[5]); } } + +SINGLE_BATTLE_TEST("Punching Glove vs Muscle Band Damage calculation") +{ + s16 dmgPlayer, dmgOpponent; + s16 expectedDamagePlayer, expectedDamageOpponent; + PARAMETRIZE { expectedDamagePlayer = 204, expectedDamageOpponent = 201; } + PARAMETRIZE { expectedDamagePlayer = 201, expectedDamageOpponent = 198; } + PARAMETRIZE { expectedDamagePlayer = 199, expectedDamageOpponent = 196; } + PARAMETRIZE { expectedDamagePlayer = 196, expectedDamageOpponent = 193; } + PARAMETRIZE { expectedDamagePlayer = 195, expectedDamageOpponent = 192; } + PARAMETRIZE { expectedDamagePlayer = 193, expectedDamageOpponent = 190; } + PARAMETRIZE { expectedDamagePlayer = 190, expectedDamageOpponent = 187; } + PARAMETRIZE { expectedDamagePlayer = 189, expectedDamageOpponent = 186; } + PARAMETRIZE { expectedDamagePlayer = 187, expectedDamageOpponent = 184; } + PARAMETRIZE { expectedDamagePlayer = 184, expectedDamageOpponent = 181; } + PARAMETRIZE { expectedDamagePlayer = 183, expectedDamageOpponent = 180; } + PARAMETRIZE { expectedDamagePlayer = 181, expectedDamageOpponent = 178; } + PARAMETRIZE { expectedDamagePlayer = 178, expectedDamageOpponent = 175; } + PARAMETRIZE { expectedDamagePlayer = 177, expectedDamageOpponent = 174; } + PARAMETRIZE { expectedDamagePlayer = 174, expectedDamageOpponent = 172; } + PARAMETRIZE { expectedDamagePlayer = 172, expectedDamageOpponent = 169; } + GIVEN { + PLAYER(SPECIES_MAKUHITA) { Item(ITEM_PUNCHING_GLOVE); } + OPPONENT(SPECIES_MAKUHITA) { Item(ITEM_MUSCLE_BAND); } + } WHEN { + TURN { + MOVE(player, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i)); + MOVE(opponent, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i)); + } + } + SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, player); + HP_BAR(opponent, captureDamage: &dmgPlayer); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, opponent); + HP_BAR(player, captureDamage: &dmgOpponent); + } + THEN { + EXPECT_EQ(expectedDamagePlayer, dmgPlayer); + EXPECT_EQ(expectedDamageOpponent, dmgOpponent); + } +} + +SINGLE_BATTLE_TEST("Gem boosted Damage calculation") +{ + s16 dmg; + s16 expectedDamage; + PARAMETRIZE { expectedDamage = 240; } + PARAMETRIZE { expectedDamage = 237; } + PARAMETRIZE { expectedDamage = 234; } + PARAMETRIZE { expectedDamage = 232; } + PARAMETRIZE { expectedDamage = 229; } + PARAMETRIZE { expectedDamage = 228; } + PARAMETRIZE { expectedDamage = 225; } + PARAMETRIZE { expectedDamage = 222; } + PARAMETRIZE { expectedDamage = 220; } + PARAMETRIZE { expectedDamage = 217; } + PARAMETRIZE { expectedDamage = 216; } + PARAMETRIZE { expectedDamage = 213; } + PARAMETRIZE { expectedDamage = 210; } + PARAMETRIZE { expectedDamage = 208; } + PARAMETRIZE { expectedDamage = 205; } + PARAMETRIZE { expectedDamage = 204; } + GIVEN { + PLAYER(SPECIES_MAKUHITA) { Item(ITEM_FIGHTING_GEM); } + OPPONENT(SPECIES_MAKUHITA); + } WHEN { + TURN { + MOVE(player, MOVE_DRAIN_PUNCH, WITH_RNG(RNG_DAMAGE_MODIFIER, i)); + } + } + SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DRAIN_PUNCH, player); + HP_BAR(opponent, captureDamage: &dmg); + } + THEN { + EXPECT_EQ(expectedDamage, dmg); + } +} + +#define NUM_DAMAGE_SPREADS (DMG_ROLL_PERCENT_HI - DMG_ROLL_PERCENT_LO) + 1 + +static const s16 sThunderShockTransistorSpread[] = { 54, 55, 56, 57, 57, 58, 59, 60, 60, 60, 61, 62, 63, 63, 64, 65 }; +static const s16 sThunderShockRegularSpread[] = { 42, 42, 43, 43, 44, 45, 45, 45, 46, 46, 47, 48, 48, 48, 49, 50 }; +static const s16 sWildChargeTransistorSpread[] = { 123, 124, 126, 127, 129, 130, 132, 133, 135, 136, 138, 139, 141, 142, 144, 145 }; +static const s16 sWildChargeRegularSpread[] = { 94, 96, 96, 98, 99, 100, 101, 102, 103, 105, 105, 107, 108, 109, 110, 111 }; + +DOUBLE_BATTLE_TEST("Transistor Damage calculation", s16 damage) +{ + s16 expectedDamageTransistorSpec = 0, expectedDamageRegularPhys = 0, expectedDamageRegularSpec = 0, expectedDamageTransistorPhys = 0; + s16 damagePlayerLeft, damagePlayerRight, damageOpponentLeft, damageOpponentRight; + for (u32 spread = 0; spread < 16; ++spread) { + PARAMETRIZE { expectedDamageTransistorSpec = sThunderShockTransistorSpread[spread], + expectedDamageRegularSpec = sThunderShockRegularSpread[spread], + expectedDamageTransistorPhys = sWildChargeTransistorSpread[spread], + expectedDamageRegularPhys = sWildChargeRegularSpread[spread]; + } + } + GIVEN { + ASSUME(gMovesInfo[MOVE_WILD_CHARGE].type == TYPE_ELECTRIC); + ASSUME(gMovesInfo[MOVE_THUNDER_SHOCK].type == TYPE_ELECTRIC); + ASSUME(gMovesInfo[MOVE_WILD_CHARGE].category == DAMAGE_CATEGORY_PHYSICAL); + ASSUME(gMovesInfo[MOVE_THUNDER_SHOCK].category == DAMAGE_CATEGORY_SPECIAL); + ASSUME(NUM_DAMAGE_SPREADS == 16); + + PLAYER(SPECIES_REGIELEKI) { Ability(ABILITY_KLUTZ); } + PLAYER(SPECIES_REGIELEKI) { Ability(ABILITY_TRANSISTOR); } + OPPONENT(SPECIES_REGIELEKI) { Ability(ABILITY_KLUTZ); } + OPPONENT(SPECIES_REGIELEKI) { Ability(ABILITY_TRANSISTOR); } + } WHEN { + TURN { + MOVE(playerLeft, MOVE_THUNDER_SHOCK, target: opponentLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i)); + MOVE(playerRight, MOVE_THUNDER_SHOCK, target: opponentRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i)); + MOVE(opponentLeft, MOVE_WILD_CHARGE, target: playerLeft, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i)); + MOVE(opponentRight, MOVE_WILD_CHARGE, target: playerRight, WITH_RNG(RNG_DAMAGE_MODIFIER, 15 - i)); + } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, playerLeft); + HP_BAR(opponentLeft, captureDamage: &damageOpponentLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_THUNDER_SHOCK, playerRight); + HP_BAR(opponentRight, captureDamage: &damageOpponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WILD_CHARGE, opponentLeft); + HP_BAR(playerLeft, captureDamage: &damagePlayerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_WILD_CHARGE, opponentRight); + HP_BAR(playerRight, captureDamage: &damagePlayerRight); + } THEN { + EXPECT_EQ(damageOpponentLeft, expectedDamageRegularSpec); + EXPECT_EQ(damageOpponentRight, expectedDamageTransistorSpec); + EXPECT_EQ(damagePlayerLeft, expectedDamageRegularPhys); + EXPECT_EQ(damagePlayerRight, expectedDamageTransistorPhys); + } +} From 47768431a2973884cff5a0efb7c01a469bb543b9 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Thu, 5 Dec 2024 09:56:41 -0300 Subject: [PATCH 02/26] Fix test TIMEOUT messaging in summary (#5772) --- test/test_runner.c | 1 + 1 file changed, 1 insertion(+) diff --git a/test/test_runner.c b/test/test_runner.c index f7c4cf780e..1ff37fe8bc 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -490,6 +490,7 @@ static void Intr_Timer2(void) if (gTestRunnerState.state == STATE_RUN_TEST) gTestRunnerState.state = STATE_REPORT_RESULT; gTestRunnerState.result = TEST_RESULT_TIMEOUT; + Test_MgbaPrintf(":L%s:%d - TIMEOUT", gTestRunnerState.test->filename, SourceLine(0)); ReinitCallbacks(); IRQ_LR = ((uintptr_t)JumpToAgbMainLoop & ~1) + 4; } From da2a1e2abac1fc0dadd5c585ce35b42afbcf4fe7 Mon Sep 17 00:00:00 2001 From: Pawkkie <61265402+Pawkkie@users.noreply.github.com> Date: Thu, 5 Dec 2024 16:29:20 -0500 Subject: [PATCH 03/26] Destiny Bond fails on repeated use in Gen 7+ (#5652) --- asm/macros/battle_script.inc | 3 +- data/battle_scripts_1.s | 2 +- include/battle_util.h | 1 + include/config/battle.h | 1 + src/battle_ai_main.c | 2 + src/battle_script_commands.c | 20 ++++++--- src/battle_util.c | 9 ++++ test/battle/move_effect/destiny_bond.c | 62 ++++++++++++++++++++++++++ 8 files changed, 91 insertions(+), 9 deletions(-) diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index c9c95515f0..118aebab8f 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -928,8 +928,9 @@ .4byte \failInstr .endm - .macro setdestinybond + .macro trysetdestinybond failInstr:req .byte 0xaa + .4byte \failInstr .endm .macro trysetdestinybondtohappen diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 2c9bd46f52..c7d9a35bb7 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -4063,7 +4063,7 @@ BattleScript_EffectDestinyBond:: attackcanceler attackstring ppreduce - setdestinybond + trysetdestinybond BattleScript_ButItFailed attackanimation waitanimation printstring STRINGID_PKMNTRYINGTOTAKEFOE diff --git a/include/battle_util.h b/include/battle_util.h index 2b0192aa71..20a228eef6 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -331,5 +331,6 @@ void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty); bool32 IsSleepClauseActiveForSide(u32 battlerSide); bool32 IsSleepClauseEnabled(); void ClearDamageCalcResults(void); +u32 DoesDestinyBondFail(u32 battler); #endif // GUARD_BATTLE_UTIL_H diff --git a/include/config/battle.h b/include/config/battle.h index 861e3e3fad..781df413a0 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -125,6 +125,7 @@ #define B_POWDER_RAIN GEN_LATEST // In Gen7+, Powder doesn't damage the user of a Fire type move in heavy rain. #define B_AFTER_YOU_TURN_ORDER GEN_LATEST // In Gen8+, After You doesn't fail if the turn order wouldn't change after use. #define B_QUASH_TURN_ORDER GEN_LATEST // In Gen8+, Quash-affected battlers move according to speed order. Before Gen8, Quash-affected battlers move in the order they were affected by Quash. +#define B_DESTINY_BOND_FAIL GEN_LATEST // In Gen7+, Destiny Bond fails if used repeatedly. // Ability settings #define B_ABILITY_WEATHER GEN_LATEST // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index a7e462ff97..d988142beb 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1875,6 +1875,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_DESTINY_BOND: + if (DoesDestinyBondFail(battlerAtk)) + ADJUST_SCORE(-10); if (gBattleMons[battlerDef].status2 & STATUS2_DESTINY_BOND) ADJUST_SCORE(-10); else if (GetActiveGimmick(battlerDef) == GIMMICK_DYNAMAX) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 469f9f7eb2..791ea1f68f 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -508,7 +508,7 @@ static void Cmd_settypetorandomresistance(void); static void Cmd_setalwayshitflag(void); static void Cmd_copymovepermanently(void); static void Cmd_trychoosesleeptalkmove(void); -static void Cmd_setdestinybond(void); +static void Cmd_trysetdestinybond(void); static void Cmd_trysetdestinybondtohappen(void); static void Cmd_settailwind(void); static void Cmd_tryspiteppreduce(void); @@ -767,7 +767,7 @@ void (* const gBattleScriptingCommandsTable[])(void) = Cmd_setalwayshitflag, //0xA7 Cmd_copymovepermanently, //0xA8 Cmd_trychoosesleeptalkmove, //0xA9 - Cmd_setdestinybond, //0xAA + Cmd_trysetdestinybond, //0xAA Cmd_trysetdestinybondtohappen, //0xAB Cmd_settailwind, //0xAC Cmd_tryspiteppreduce, //0xAD @@ -13446,12 +13446,18 @@ static void Cmd_trychoosesleeptalkmove(void) } } -static void Cmd_setdestinybond(void) +static void Cmd_trysetdestinybond(void) { - CMD_ARGS(); - - gBattleMons[gBattlerAttacker].status2 |= STATUS2_DESTINY_BOND; - gBattlescriptCurrInstr = cmd->nextInstr; + CMD_ARGS(const u8 *failInstr); + if (DoesDestinyBondFail(gBattlerAttacker)) + { + gBattlescriptCurrInstr = cmd->failInstr; + } + else + { + gBattleMons[gBattlerAttacker].status2 |= STATUS2_DESTINY_BOND; + gBattlescriptCurrInstr = cmd->nextInstr; + } } static void TrySetDestinyBondToHappen(void) diff --git a/src/battle_util.c b/src/battle_util.c index c00598eb14..aa2f36882c 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -12010,3 +12010,12 @@ void ClearDamageCalcResults(void) gBattleStruct->printedStrongWindsWeakenedAttack = FALSE; gBattleStruct->numSpreadTargets = 0; } + +bool32 DoesDestinyBondFail(u32 battler) +{ + if (B_DESTINY_BOND_FAIL >= GEN_7 + && gMovesInfo[gLastResultingMoves[battler]].effect == EFFECT_DESTINY_BOND + && !(gBattleStruct->lastMoveFailed & (1u << battler))) + return TRUE; + return FALSE; +} diff --git a/test/battle/move_effect/destiny_bond.c b/test/battle/move_effect/destiny_bond.c index ba49e0ec43..7291fe7fb3 100644 --- a/test/battle/move_effect/destiny_bond.c +++ b/test/battle/move_effect/destiny_bond.c @@ -1,6 +1,11 @@ #include "global.h" #include "test/battle.h" +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_DESTINY_BOND].effect == EFFECT_DESTINY_BOND); +} + SINGLE_BATTLE_TEST("Destiny Bond faints the opposing mon if it fainted from the attack") { GIVEN { @@ -15,3 +20,60 @@ SINGLE_BATTLE_TEST("Destiny Bond faints the opposing mon if it fainted from the MESSAGE("The opposing Wobbuffet fainted!"); } } + +SINGLE_BATTLE_TEST("Destiny Bond fails if used sequentially in Gen 7+") +{ + GIVEN { + ASSUME(B_DESTINY_BOND_FAIL >= GEN_7); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_DESTINY_BOND); } + TURN { MOVE(player, MOVE_DESTINY_BOND); SWITCH(opponent, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + MESSAGE("2 sent out Zigzagoon!"); + NOT { ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); } + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Destiny Bond does not fail if used repeatedly separated by other moves in Gen 7+") +{ + GIVEN { + ASSUME(B_DESTINY_BOND_FAIL >= GEN_7); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_DESTINY_BOND); } + TURN { MOVE(player, MOVE_GROWL); SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_DESTINY_BOND); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + MESSAGE("2 sent out Zigzagoon!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + NOT { MESSAGE("But it failed!"); } + } +} + +SINGLE_BATTLE_TEST("Destiny Bond does not fail if used after failing in Gen 7+") +{ + GIVEN { + ASSUME(B_DESTINY_BOND_FAIL >= GEN_7); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_ZIGZAGOON); + } WHEN { + TURN { MOVE(player, MOVE_DESTINY_BOND); } + TURN { MOVE(player, MOVE_DESTINY_BOND); SWITCH(opponent, 1); } + TURN { MOVE(player, MOVE_DESTINY_BOND); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + MESSAGE("2 sent out Zigzagoon!"); + NOT { ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); } + MESSAGE("But it failed!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_DESTINY_BOND, player); + } +} From 19578f6d2226af96550fbc90a46e7d35643a0aca Mon Sep 17 00:00:00 2001 From: iriv24 <40581123+iriv24@users.noreply.github.com> Date: Fri, 6 Dec 2024 04:04:37 -0500 Subject: [PATCH 04/26] Fix Off-by-One Error in Move Relearner (#5778) --- src/move_relearner.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/move_relearner.c b/src/move_relearner.c index a4cc778a45..1e66702695 100644 --- a/src/move_relearner.c +++ b/src/move_relearner.c @@ -165,18 +165,18 @@ enum { static EWRAM_DATA struct { u8 state; - u8 heartSpriteIds[16]; /*0x001*/ - u16 movesToLearn[MAX_RELEARNER_MOVES]; /*0x01A*/ - u8 partyMon; /*0x044*/ - u8 moveSlot; /*0x045*/ - struct ListMenuItem menuItems[MAX_RELEARNER_MOVES]; /*0x0E8*/ - u8 numMenuChoices; /*0x110*/ - u8 numToShowAtOnce; /*0x111*/ - u8 moveListMenuTask; /*0x112*/ - u8 moveListScrollArrowTask; /*0x113*/ - u8 moveDisplayArrowTask; /*0x114*/ - u16 scrollOffset; /*0x116*/ - u8 categoryIconSpriteId; /*0x117*/ + u8 heartSpriteIds[16]; /*0x001*/ + u16 movesToLearn[MAX_RELEARNER_MOVES]; /*0x01A*/ + u8 partyMon; /*0x044*/ + u8 moveSlot; /*0x045*/ + struct ListMenuItem menuItems[MAX_RELEARNER_MOVES + 1]; /*0x0E8*/ + u8 numMenuChoices; /*0x110*/ + u8 numToShowAtOnce; /*0x111*/ + u8 moveListMenuTask; /*0x112*/ + u8 moveListScrollArrowTask; /*0x113*/ + u8 moveDisplayArrowTask; /*0x114*/ + u16 scrollOffset; /*0x116*/ + u8 categoryIconSpriteId; /*0x117*/ } *sMoveRelearnerStruct = {0}; static EWRAM_DATA struct { From 775ea3b564af2ad5455e92af8fa7ab33bb7f563f Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Fri, 6 Dec 2024 18:14:46 +0000 Subject: [PATCH 05/26] Pursuit refactor (#5707) --- data/battle_scripts_1.s | 55 +- include/battle.h | 3 + include/battle_scripts.h | 2 + include/config/battle.h | 1 + include/constants/battle_script_commands.h | 1 + src/battle_main.c | 58 ++- src/battle_script_commands.c | 94 ++-- src/battle_util.c | 8 +- test/battle/move_effect/pursuit.c | 566 ++++++++++++++++++++- 9 files changed, 694 insertions(+), 94 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index c7d9a35bb7..d1d139b800 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -298,12 +298,20 @@ BattleScript_CheckPrimalWeather: jumpifhalfword CMP_COMMON_BITS, gBattleWeather, B_WEATHER_STRONG_WINDS, BattleScript_MysteriousAirCurrentBlowsOn return +BattleScript_MoveSwitchPursuit: + jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_MoveSwitchEnd + jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_MoveSwitchEnd + printstring STRINGID_PKMNWENTBACK + waitmessage B_WAIT_TIME_SHORT + jumpifnopursuitswitchdmg BattleScript_MoveSwitchOpenPartyScreen + end + BattleScript_MoveSwitch: jumpifbattletype BATTLE_TYPE_ARENA, BattleScript_MoveSwitchEnd jumpifcantswitch SWITCH_IGNORE_ESCAPE_PREVENTION | BS_ATTACKER, BattleScript_MoveSwitchEnd printstring STRINGID_PKMNWENTBACK waitmessage B_WAIT_TIME_SHORT -BattleScript_MoveSwitchOpenPartyScreen: +BattleScript_MoveSwitchOpenPartyScreen:: openpartyscreen BS_ATTACKER, BattleScript_MoveSwitchEnd switchoutabilities BS_ATTACKER waitstate @@ -1343,7 +1351,7 @@ BattleScript_EffectPartingShotTrySpAtk: waitmessage B_WAIT_TIME_LONG BattleScript_EffectPartingShotSwitch: moveendall - goto BattleScript_MoveSwitch + goto BattleScript_MoveSwitchPursuit BattleScript_EffectPowder:: attackcanceler @@ -2785,7 +2793,7 @@ BattleScript_EffectHitEscape:: jumpifbattleend BattleScript_HitEscapeEnd jumpifbyte CMP_NOT_EQUAL, gBattleOutcome, 0, BattleScript_HitEscapeEnd jumpifemergencyexited BS_TARGET, BattleScript_HitEscapeEnd - goto BattleScript_MoveSwitch + goto BattleScript_MoveSwitchPursuit BattleScript_HitEscapeEnd: end @@ -5767,19 +5775,10 @@ BattleScript_PrintFullBox:: BattleScript_ActionSwitch:: hpthresholds2 BS_ATTACKER printstring STRINGID_RETURNMON - jumpifbattletype BATTLE_TYPE_DOUBLE, BattleScript_PursuitSwitchDmgSetMultihit - setmultihit 1 - goto BattleScript_PursuitSwitchDmgLoop -BattleScript_PursuitSwitchDmgSetMultihit:: - setmultihit 2 -BattleScript_PursuitSwitchDmgLoop:: jumpifnopursuitswitchdmg BattleScript_DoSwitchOut - swapattackerwithtarget - trysetdestinybondtohappen - call BattleScript_PursuitDmgOnSwitchOut - swapattackerwithtarget + end2 + BattleScript_DoSwitchOut:: - decrementmultihit BattleScript_PursuitSwitchDmgLoop switchoutabilities BS_ATTACKER updatedynamax waitstate @@ -5801,34 +5800,6 @@ BattleScript_DoSwitchOut:: moveendcase MOVEEND_MIRROR_MOVE end2 -BattleScript_PursuitDmgOnSwitchOut:: - pause B_WAIT_TIME_SHORT - orword gHitMarker, HITMARKER_OBEYS - attackstring - ppreduce - critcalc - damagecalc - adjustdamage - attackanimation - waitanimation - effectivenesssound - hitanimation BS_TARGET - waitstate - healthbarupdate BS_TARGET - datahpupdate BS_TARGET - critmessage - waitmessage B_WAIT_TIME_LONG - resultmessage - waitmessage B_WAIT_TIME_LONG - tryfaintmon BS_TARGET - moveendfromto MOVEEND_ABILITIES, MOVEEND_ATTACKER_INVISIBLE @ MOVEEND_CHOICE_MOVE has to be included - jumpiffainted BS_TARGET, FALSE, BattleScript_PursuitDmgOnSwitchOutRet - setbyte sGIVEEXP_STATE, 0 - getexp BS_TARGET -BattleScript_PursuitDmgOnSwitchOutRet: - bicword gHitMarker, HITMARKER_OBEYS - return - BattleScript_Pausex20:: pause B_WAIT_TIME_SHORT return diff --git a/include/battle.h b/include/battle.h index fc2d73e62d..aa21a88a12 100644 --- a/include/battle.h +++ b/include/battle.h @@ -836,6 +836,9 @@ struct BattleStruct 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 pursuitSwitchByMove:1; + u8 pursuitStoredSwitch; // Stored id for the Pursuit target's switch s32 battlerExpReward; // Simultaneous hp reduction for spread moves diff --git a/include/battle_scripts.h b/include/battle_scripts.h index bf4b34509f..cac3ce990f 100644 --- a/include/battle_scripts.h +++ b/include/battle_scripts.h @@ -46,6 +46,8 @@ extern const u8 BattleScript_PrintFailedToRunString[]; extern const u8 BattleScript_PrintCantEscapeFromBattle[]; extern const u8 BattleScript_PrintFullBox[]; extern const u8 BattleScript_ActionSwitch[]; +extern const u8 BattleScript_DoSwitchOut[]; +extern const u8 BattleScript_MoveSwitchOpenPartyScreen[]; extern const u8 BattleScript_Pausex20[]; extern const u8 BattleScript_LevelUp[]; extern const u8 BattleScript_RainContinuesOrEnds[]; diff --git a/include/config/battle.h b/include/config/battle.h index 781df413a0..b15a32a664 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -126,6 +126,7 @@ #define B_AFTER_YOU_TURN_ORDER GEN_LATEST // In Gen8+, After You doesn't fail if the turn order wouldn't change after use. #define B_QUASH_TURN_ORDER GEN_LATEST // In Gen8+, Quash-affected battlers move according to speed order. Before Gen8, Quash-affected battlers move in the order they were affected by Quash. #define B_DESTINY_BOND_FAIL GEN_LATEST // In Gen7+, Destiny Bond fails if used repeatedly. +#define B_PURSUIT_TARGET GEN_LATEST // In Gen4+, Pursuit attacks a switching opponent even if they weren't targeting them. Before Gen4, Pursuit only attacks a switching opponent that it originally targeted. // Ability settings #define B_ABILITY_WEATHER GEN_LATEST // In Gen6+, ability-induced weather lasts 5 turns. Before, it lasted until the battle ended or until it was changed by a move or a different weather-affecting ability. diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 609090b12e..3b3faa5790 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -302,6 +302,7 @@ enum MoveEndEffects MOVEEND_SAME_MOVE_TURNS, MOVEEND_SET_EVOLUTION_TRACKER, MOVEEND_CLEAR_BITS, + MOVEEND_PURSUIT_NEXT_ACTION, MOVEEND_COUNT, }; diff --git a/src/battle_main.c b/src/battle_main.c index c7c72564f0..25f69d44b0 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -3114,6 +3114,9 @@ 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; gSelectedMonPartyId = PARTY_SIZE; // Revival Blessing gCategoryIconSpriteId = 0xFF; @@ -3355,6 +3358,9 @@ const u8* FaintClearSetData(u32 battler) gBattleStruct->lastTakenMoveFrom[battler][1] = 0; gBattleStruct->lastTakenMoveFrom[battler][2] = 0; gBattleStruct->lastTakenMoveFrom[battler][3] = 0; + gBattleStruct->pursuitTarget = 0; + gBattleStruct->pursuitSwitchByMove = FALSE; + gBattleStruct->pursuitStoredSwitch = 0; gBattleStruct->palaceFlags &= ~(1u << battler); gBattleStruct->boosterEnergyActivates &= ~(1u << battler); @@ -5164,6 +5170,9 @@ static void TurnValuesCleanUp(bool8 var0) 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 ClearDamageCalcResults(); } @@ -5180,11 +5189,26 @@ static void PopulateArrayWithBattlers(u8 *battlers) battlers[i] = i; } +static bool32 TryActivateGimmick(u32 battler) +{ + if ((gBattleStruct->gimmick.toActivate & (1u << battler)) && !(gProtectStructs[battler].noValidMoves)) + { + gBattlerAttacker = gBattleScripting.battler = battler; + gBattleStruct->gimmick.toActivate &= ~(1u << battler); + if (gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick != NULL) + { + gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick(battler); + return TRUE; + } + } + return FALSE; +} + static bool32 TryDoGimmicksBeforeMoves(void) { if (!(gHitMarker & HITMARKER_RUN) && gBattleStruct->gimmick.toActivate) { - u32 i, battler; + u32 i; u8 order[MAX_BATTLERS_COUNT]; PopulateArrayWithBattlers(order); @@ -5192,16 +5216,8 @@ static bool32 TryDoGimmicksBeforeMoves(void) for (i = 0; i < gBattlersCount; i++) { // Search through each battler and activate their gimmick if they have one prepared. - if ((gBattleStruct->gimmick.toActivate & (1u << order[i])) && !(gProtectStructs[order[i]].noValidMoves)) - { - battler = gBattlerAttacker = gBattleScripting.battler = order[i]; - gBattleStruct->gimmick.toActivate &= ~(1u << battler); - if (gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick != NULL) - { - gGimmicksInfo[gBattleStruct->gimmick.usableGimmick[battler]].ActivateGimmick(battler); - return TRUE; - } - } + if (TryActivateGimmick(order[i])) + return TRUE; } } @@ -5251,7 +5267,7 @@ static bool32 TryDoMoveEffectsBeforeMoves(void) static void TryChangeTurnOrder(void) { u32 i, j; - for (i = 0; i < gBattlersCount - 1; i++) + for (i = gCurrentTurnActionNumber; i < gBattlersCount - 1; i++) { for (j = i + 1; j < gBattlersCount; j++) { @@ -5369,11 +5385,19 @@ 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 (TryDoGimmicksBeforeMoves()) - return; - else if (TryDoMoveEffectsBeforeMoves()) - return; - gBattleStruct->effectsBeforeUsingMoveDone = TRUE; + if (!gBattleStruct->pursuitTarget) + { + if (TryDoGimmicksBeforeMoves()) + return; + else if (TryDoMoveEffectsBeforeMoves()) + return; + gBattleStruct->effectsBeforeUsingMoveDone = TRUE; + } + else + { + if (TryActivateGimmick(gBattlerByTurnOrder[gCurrentTurnActionNumber])) + return; + } } *(&gBattleStruct->savedTurnActionNumber) = gCurrentTurnActionNumber; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 791ea1f68f..6e95788859 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -329,6 +329,7 @@ static void BestowItem(u32 battlerAtk, u32 battlerDef); static bool8 IsFinalStrikeEffect(u32 moveEffect); static void TryUpdateRoundTurnOrder(void); static bool32 ChangeOrderTargetAfterAttacker(void); +static bool32 SetTargetToNextPursuiter(u32 battlerDef); void ApplyExperienceMultipliers(s32 *expAmount, u8 expGetterMonId, u8 faintedBattler); static void RemoveAllWeather(void); static void RemoveAllTerrains(void); @@ -1487,6 +1488,10 @@ static bool32 AccuracyCalcHelper(u32 move, u32 battler) { effect = TRUE; } + else if (gBattleStruct->pursuitTarget & (1u << battler)) + { + effect = TRUE; + } else if (GetActiveGimmick(gBattlerAttacker) == GIMMICK_Z_MOVE && !(gStatuses3[battler] & STATUS3_SEMI_INVULNERABLE)) { effect = TRUE; @@ -6947,6 +6952,32 @@ static void Cmd_moveend(void) } } + gBattleScripting.moveendState++; + break; + case MOVEEND_PURSUIT_NEXT_ACTION: + if (gBattleStruct->pursuitTarget & (1u << gBattlerTarget)) + { + u32 storedTarget = gBattlerTarget; + if (SetTargetToNextPursuiter(gBattlerTarget)) + { + ChangeOrderTargetAfterAttacker(); + *(gBattleStruct->moveTarget + gBattlerTarget) = storedTarget; + gBattlerTarget = storedTarget; + } + else if (IsBattlerAlive(gBattlerTarget)) + { + gBattlerAttacker = gBattlerTarget; + if (gBattleStruct->pursuitSwitchByMove) + gBattlescriptCurrInstr = BattleScript_MoveSwitchOpenPartyScreen; + else + gBattlescriptCurrInstr = BattleScript_DoSwitchOut; + *(gBattleStruct->monToSwitchIntoId + gBattlerTarget) = gBattleStruct->pursuitStoredSwitch; + gBattleStruct->pursuitTarget = 0; + gBattleStruct->pursuitSwitchByMove = FALSE; + gBattleStruct->pursuitStoredSwitch = 0; + effect = TRUE; + } + } gBattleScripting.moveendState++; break; case MOVEEND_COUNT: @@ -13967,45 +13998,44 @@ static void Cmd_magnitudedamagecalculation(void) gBattlescriptCurrInstr = cmd->nextInstr; } +static bool32 SetTargetToNextPursuiter(u32 battlerDef) +{ + u32 i; + for (i = gCurrentTurnActionNumber + 1; i < gBattlersCount; i++) + { + u32 battler = gBattlerByTurnOrder[i]; + if (gChosenActionByBattler[battler] == B_ACTION_USE_MOVE + && gMovesInfo[gChosenMoveByBattler[battler]].effect == EFFECT_PURSUIT + && IsBattlerAlive(battlerDef) + && IsBattlerAlive(battler) + && GetBattlerSide(battler) != GetBattlerSide(battlerDef) + && (B_PURSUIT_TARGET >= GEN_4 || *(gBattleStruct->moveTarget + battler) == battlerDef) + && !IsGimmickSelected(battler, GIMMICK_Z_MOVE) + && !IsGimmickSelected(battler, GIMMICK_DYNAMAX) + && GetActiveGimmick(battler) != GIMMICK_DYNAMAX) + { + gBattlerTarget = battler; + return TRUE; + } + } + return FALSE; +} + static void Cmd_jumpifnopursuitswitchdmg(void) { CMD_ARGS(const u8 *jumpInstr); - if (gMultiHitCounter == 1) - { - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT); - else - gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT); - } - else - { - if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) - gBattlerTarget = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT); - else - gBattlerTarget = GetBattlerAtPosition(B_POSITION_PLAYER_RIGHT); - } + u32 savedTarget = gBattlerTarget; - if (gChosenActionByBattler[gBattlerTarget] == B_ACTION_USE_MOVE - && gBattlerAttacker == *(gBattleStruct->moveTarget + gBattlerTarget) - && !(gBattleMons[gBattlerTarget].status1 & (STATUS1_SLEEP | STATUS1_FREEZE)) - && gBattleMons[gBattlerAttacker].hp - && !gDisableStructs[gBattlerTarget].truantCounter - && gMovesInfo[gChosenMoveByBattler[gBattlerTarget]].effect == EFFECT_PURSUIT) + if (SetTargetToNextPursuiter(gBattlerAttacker)) { - s32 i; - - for (i = 0; i < gBattlersCount; i++) - { - if (gBattlerByTurnOrder[i] == gBattlerTarget) - gActionsByTurnOrder[i] = B_ACTION_TRY_FINISH; - } - - gCurrentMove = gChosenMove = gChosenMoveByBattler[gBattlerTarget]; - gCurrMovePos = gChosenMovePos = *(gBattleStruct->chosenMovePositions + gBattlerTarget); + ChangeOrderTargetAfterAttacker(); + gBattleStruct->pursuitTarget = 1u << gBattlerAttacker; + gBattleStruct->pursuitSwitchByMove = gActionsByTurnOrder[gCurrentTurnActionNumber] == B_ACTION_USE_MOVE; + gBattleStruct->pursuitStoredSwitch = gBattleStruct->monToSwitchIntoId[gBattlerAttacker]; + *(gBattleStruct->moveTarget + gBattlerTarget) = gBattlerAttacker; + gBattlerTarget = savedTarget; gBattlescriptCurrInstr = cmd->nextInstr; - gBattleScripting.animTurn = 1; - gHitMarker &= ~HITMARKER_ATTACKSTRING_PRINTED; } else { diff --git a/src/battle_util.c b/src/battle_util.c index aa2f36882c..3848a31212 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -119,6 +119,9 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move) || ability == ABILITY_PROPELLER_TAIL || ability == ABILITY_STALWART) return FALSE; + if (gMovesInfo[move].effect == EFFECT_PURSUIT && gBattleStruct->pursuitTarget) + return FALSE; + if (gSideTimers[defSide].followmePowder && !IsAffectedByPowder(battlerAtk, ability, GetBattlerHoldEffect(battlerAtk, TRUE))) return FALSE; @@ -226,6 +229,7 @@ void HandleAction_UseMove(void) } else if (IsDoubleBattle() && gSideTimers[side].followmeTimer == 0 + && !(gBattleStruct->pursuitTarget & (1u << *(gBattleStruct->moveTarget + gBattlerAttacker))) && (gMovesInfo[gCurrentMove].power != 0 || (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))) @@ -705,7 +709,7 @@ void HandleAction_ActionFinished(void) gBattleScripting.multihitMoveEffect = 0; gBattleResources->battleScriptsStack->size = 0; - if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove) + if (B_RECALC_TURN_AFTER_ACTIONS >= GEN_8 && !afterYouActive && !gBattleStruct->pledgeMove && !gBattleStruct->pursuitTarget) { // 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 @@ -8961,7 +8965,7 @@ static inline u32 CalcMoveBasePower(struct DamageCalculationData *damageCalcData basePower *= 2; break; case EFFECT_PURSUIT: - if (gActionsByTurnOrder[GetBattlerTurnOrderNum(battlerDef)] == B_ACTION_SWITCH) + if (gBattleStruct->pursuitTarget & (1u << battlerDef)) basePower *= 2; break; case EFFECT_NATURAL_GIFT: diff --git a/test/battle/move_effect/pursuit.c b/test/battle/move_effect/pursuit.c index 3a1db03d06..5dfa3f8e33 100644 --- a/test/battle/move_effect/pursuit.c +++ b/test/battle/move_effect/pursuit.c @@ -6,10 +6,462 @@ ASSUMPTIONS ASSUME(gMovesInfo[MOVE_PURSUIT].effect == EFFECT_PURSUIT); } +SINGLE_BATTLE_TEST("Pursuit attacks a switching foe") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + HP_BAR(player); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +SINGLE_BATTLE_TEST("Pursuit attacks a foe using Volt Switch / U-Turn / Parting Shot to switch out") +{ + u32 move; + PARAMETRIZE { move = MOVE_VOLT_SWITCH; } + PARAMETRIZE { move = MOVE_U_TURN; } + PARAMETRIZE { move = MOVE_PARTING_SHOT; } + GIVEN { + ASSUME(gMovesInfo[MOVE_VOLT_SWITCH].effect == EFFECT_HIT_ESCAPE); + ASSUME(gMovesInfo[MOVE_U_TURN].effect == EFFECT_HIT_ESCAPE); + ASSUME(gMovesInfo[MOVE_PARTING_SHOT].effect == EFFECT_PARTING_SHOT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(player, move); MOVE(opponent, MOVE_PURSUIT); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, move, player); + MESSAGE("Wobbuffet went back to 1!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit doesn't attack a foe using Teleport / Baton Pass to switch out") +{ + u32 move; + PARAMETRIZE { move = MOVE_TELEPORT; } + PARAMETRIZE { move = MOVE_BATON_PASS; } + GIVEN { + ASSUME(gMovesInfo[MOVE_QUASH].effect == EFFECT_QUASH); + ASSUME(gMovesInfo[MOVE_TELEPORT].effect == EFFECT_TELEPORT); + ASSUME(gMovesInfo[MOVE_BATON_PASS].effect == EFFECT_BATON_PASS); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_NIDOKING); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { MOVE(playerRight, MOVE_QUASH, target: opponentLeft); MOVE(playerLeft, move); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_QUASH, playerRight); + ANIMATION(ANIM_TYPE_MOVE, move, playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + SEND_IN_MESSAGE("Zigzagoon"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + } +} + +SINGLE_BATTLE_TEST("Pursuit doesn't attack switching foe if user already acted that turn") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { MOVE(opponent, MOVE_PURSUIT); MOVE(player, MOVE_VOLT_SWITCH); SEND_OUT(player, 1); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, player); + MESSAGE("Wobbuffet went back to 1!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +SINGLE_BATTLE_TEST("Pursuit doubles in power if attacking while target switches out", s16 damage) +{ + u32 speed; + PARAMETRIZE { speed = 5; } + PARAMETRIZE { speed = 3; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(4); } + PLAYER(SPECIES_ZIGZAGOON) { Speed(2); } + OPPONENT(SPECIES_WYNAUT) { Speed(speed); } + } WHEN { + TURN { MOVE(opponent, MOVE_PURSUIT); MOVE(player, MOVE_VOLT_SWITCH); SEND_OUT(player, 1); } + } SCENE { + if (speed == 3) + ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + HP_BAR(player, captureDamage: &results[i].damage); + if (speed == 5) + ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, player); + SEND_IN_MESSAGE("Zigzagoon"); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(2.0), results[1].damage); + } +} + +SINGLE_BATTLE_TEST("Pursuit ignores accuracy checks when attacking a switching target") +{ + PASSES_RANDOMLY(100, 100, RNG_ACCURACY); + GIVEN { + ASSUME(gMovesInfo[MOVE_SAND_ATTACK].effect == EFFECT_ACCURACY_DOWN); + ASSUME(gMovesInfo[MOVE_HAIL].effect == EFFECT_HAIL); + PLAYER(SPECIES_GLACEON) { Ability(ABILITY_SNOW_CLOAK); } + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_SAND_ATTACK); MOVE(opponent, MOVE_HAIL); } + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SAND_ATTACK, player); + ANIMATION(ANIM_TYPE_MOVE, MOVE_HAIL, opponent); + SWITCH_OUT_MESSAGE("Glaceon"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit attacks switching foes even if not targetting them (Gen 4+)") +{ + GIVEN { + ASSUME(B_PURSUIT_TARGET >= GEN_4); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_GRIMER); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerRight); MOVE(opponentRight, MOVE_PURSUIT, target: playerRight); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + HP_BAR(playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + HP_BAR(playerLeft); + SEND_IN_MESSAGE("Grimer"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + } +} + +DOUBLE_BATTLE_TEST("Pursuit attacks a switching foe from fastest to slowest") +{ + u32 speedLeft, speedRight; + PARAMETRIZE { speedLeft = 5; speedRight = 3; } + PARAMETRIZE { speedLeft = 3; speedRight = 5; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(1); } + PLAYER(SPECIES_ZIGZAGOON) { Speed(4); } + PLAYER(SPECIES_GRIMER) { Speed(2); } + OPPONENT(SPECIES_WYNAUT) { Speed(speedLeft); } + OPPONENT(SPECIES_LINOONE) { Speed(speedRight); } + } WHEN { + TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + if (speedLeft > speedRight) { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + HP_BAR(playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + HP_BAR(playerLeft); + } else { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + HP_BAR(playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + HP_BAR(playerLeft); + } + SEND_IN_MESSAGE("Grimer"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerRight); + } +} + +DOUBLE_BATTLE_TEST("Pursuit attacks a switching foe but not switching allies") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_GRIMER); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + OPPONENT(SPECIES_ABRA); + } WHEN { + TURN { SWITCH(playerLeft, 2); SWITCH(opponentRight, 2); MOVE(playerRight, MOVE_PURSUIT, target: opponentRight); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + SEND_IN_MESSAGE("Grimer"); + MESSAGE("2 withdrew Linoone!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, playerRight); + MESSAGE("2 sent out Abra!"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit only attacks the first switching foe") +{ + // This test does not make sense for B_PURSUIT_TARGET < GEN_4 + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_GRIMER); + PLAYER(SPECIES_SUNKERN); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + HP_BAR(playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + HP_BAR(playerLeft); + SEND_IN_MESSAGE("Grimer"); + SWITCH_OUT_MESSAGE("Zigzagoon"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + HP_BAR(playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + HP_BAR(playerRight); + } + SEND_IN_MESSAGE("Sunkern"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit only attacks a switching foe if foe is alive") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_GRIMER); + PLAYER(SPECIES_SUNKERN); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + HP_BAR(playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + MESSAGE("Wobbuffet fainted!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + SEND_IN_MESSAGE("Grimer"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit attacks the second switching foe if the first faints from pursuit") +{ + // This test does not make sense for B_PURSUIT_TARGET < GEN_4 + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { HP(1); } + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_GRIMER); + PLAYER(SPECIES_SUNKERN); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { SWITCH(playerLeft, 2); SWITCH(playerRight, 3); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerRight); SEND_OUT(playerLeft, 2); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + HP_BAR(playerLeft); + MESSAGE("Wobbuffet fainted!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + SWITCH_OUT_MESSAGE("Zigzagoon"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + HP_BAR(playerRight); + SEND_IN_MESSAGE("Sunkern"); + SEND_IN_MESSAGE("Grimer"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit only attacks a switching foe if user is alive") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_GRIMER); + OPPONENT(SPECIES_WYNAUT) { HP(1); } + OPPONENT(SPECIES_LINOONE); + OPPONENT(SPECIES_SUNKERN); + } WHEN { + TURN { MOVE(playerLeft, MOVE_VOLT_SWITCH, target: opponentLeft); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); SEND_OUT(opponentLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, playerLeft); + MESSAGE("The opposing Wynaut fainted!"); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + SEND_IN_MESSAGE("Grimer"); + } +} + +SINGLE_BATTLE_TEST("Pursuit attacks a switching foe but fails if user is asleep") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT) { Status1(STATUS1_SLEEP_TURN(2)); } + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + MESSAGE("The opposing Wynaut is fast asleep."); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +SINGLE_BATTLE_TEST("Pursuit attacks a switching foe and takes Life Orb damage") +{ + GIVEN { + ASSUME(gItemsInfo[ITEM_LIFE_ORB].holdEffect == HOLD_EFFECT_LIFE_ORB); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT) { Item(ITEM_LIFE_ORB); } + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + HP_BAR(opponent); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit attacks a switching foe but isn't affected by Follow Me") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_FOLLOW_ME].effect == EFFECT_FOLLOW_ME); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_CLEFABLE); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { MOVE(playerRight, MOVE_FOLLOW_ME); MOVE(playerLeft, MOVE_VOLT_SWITCH, target: opponentLeft); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_FOLLOW_ME, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +SINGLE_BATTLE_TEST("Pursuit user mega evolves before attacking a switching foe and hits twice if user has Parental Bond") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); } + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT, gimmick: GIMMICK_MEGA); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + HP_BAR(player); + HP_BAR(player); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit user mega evolves before attacking a switching foe and others mega evolve after switch") +{ + GIVEN { + PLAYER(SPECIES_CHARIZARD) { Item(ITEM_CHARIZARDITE_X); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_KANGASKHAN) { Item(ITEM_KANGASKHANITE); } + } WHEN { + TURN { SWITCH(playerRight, 2); MOVE(opponentRight, MOVE_PURSUIT, gimmick: GIMMICK_MEGA, target: playerRight); MOVE(playerLeft, MOVE_CELEBRATE, gimmick: GIMMICK_MEGA); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, opponentRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + HP_BAR(playerRight); + HP_BAR(playerRight); + SEND_IN_MESSAGE("Zigzagoon"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_MEGA_EVOLUTION, playerLeft); + ANIMATION(ANIM_TYPE_MOVE, MOVE_CELEBRATE, playerLeft); + } +} + +SINGLE_BATTLE_TEST("Pursuit user terastalizes before attacking a switching foe and gets the damage boost from the tera type", s16 damage) +{ + u32 tera; + PARAMETRIZE { tera = GIMMICK_NONE; } + PARAMETRIZE { tera = GIMMICK_TERA; } + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_KANGASKHAN) { TeraType(TYPE_DARK); } + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT, gimmick: tera); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + if (tera == GIMMICK_TERA) + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_TERA_ACTIVATE, opponent); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + HP_BAR(player, captureDamage: &results[i].damage); + SEND_IN_MESSAGE("Zigzagoon"); + } FINALLY { + EXPECT_MUL_EQ(results[0].damage, Q_4_12(1.5), results[1].damage); + } +} + +DOUBLE_BATTLE_TEST("Pursuit affected by Electrify fails against immune target") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY); + PLAYER(SPECIES_DONPHAN); + PLAYER(SPECIES_HELIOLISK); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { MOVE(playerRight, MOVE_ELECTRIFY, target: opponentLeft); MOVE(playerLeft, MOVE_VOLT_SWITCH, target: opponentLeft); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + +DOUBLE_BATTLE_TEST("Pursuit affected by Electrify fails against target with Volt Absorb") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_ELECTRIFY].effect == EFFECT_ELECTRIFY); + PLAYER(SPECIES_LANTURN) { Ability(ABILITY_VOLT_ABSORB); } + PLAYER(SPECIES_HELIOLISK); + PLAYER(SPECIES_ZIGZAGOON); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_LINOONE); + } WHEN { + TURN { MOVE(playerRight, MOVE_ELECTRIFY, target: opponentLeft); MOVE(playerLeft, MOVE_VOLT_SWITCH, target: opponentLeft); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); SEND_OUT(playerLeft, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, playerRight); + ANIMATION(ANIM_TYPE_MOVE, MOVE_VOLT_SWITCH, playerLeft); + NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + ABILITY_POPUP(playerLeft, ABILITY_VOLT_ABSORB); + SEND_IN_MESSAGE("Zigzagoon"); + } +} + SINGLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and activated ability Tangling Hair") { GIVEN { - PLAYER(SPECIES_DUGTRIO) { Ability(ABILITY_TANGLING_HAIR); } + PLAYER(SPECIES_DUGTRIO_ALOLA) { Ability(ABILITY_TANGLING_HAIR); } PLAYER(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WYNAUT); OPPONENT(SPECIES_WOBBUFFET); @@ -25,6 +477,80 @@ SINGLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and ac } } +DOUBLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and activated ability Tangling Hair - Doubles") +{ + GIVEN { + PLAYER(SPECIES_DUGTRIO_ALOLA) { Ability(ABILITY_TANGLING_HAIR); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); } + } SCENE { + SWITCH_OUT_MESSAGE("Dugtrio"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + ABILITY_POPUP(playerLeft, ABILITY_TANGLING_HAIR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("The opposing Wynaut's Speed fell!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + ABILITY_POPUP(playerLeft, ABILITY_TANGLING_HAIR); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("The opposing Wobbuffet's Speed fell!"); + SEND_IN_MESSAGE("Wobbuffet"); + } +} + +SINGLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and activated ability Tangling Hair - Mirror Armor") +{ + GIVEN { + PLAYER(SPECIES_DUGTRIO_ALOLA) { Ability(ABILITY_TANGLING_HAIR); } + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_CORVIKNIGHT) { Ability(ABILITY_MIRROR_ARMOR); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(player, 1); MOVE(opponent, MOVE_PURSUIT); } + } SCENE { + SWITCH_OUT_MESSAGE("Dugtrio"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + ABILITY_POPUP(player, ABILITY_TANGLING_HAIR); + ABILITY_POPUP(opponent, ABILITY_MIRROR_ARMOR); + SEND_IN_MESSAGE("Wobbuffet"); + } +} + +DOUBLE_BATTLE_TEST("Pursuited mon correctly switches out after it got hit and activated ability Cotton Down") +{ + GIVEN { + PLAYER(SPECIES_ELDEGOSS) { Ability(ABILITY_COTTON_DOWN); } + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { SWITCH(playerLeft, 2); MOVE(opponentLeft, MOVE_PURSUIT, target: playerLeft); MOVE(opponentRight, MOVE_PURSUIT, target: playerLeft); } + } SCENE { + SWITCH_OUT_MESSAGE("Eldegoss"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentLeft); + ABILITY_POPUP(playerLeft, ABILITY_COTTON_DOWN); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("The opposing Wynaut's Speed fell!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Wobbuffet's Speed fell!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("The opposing Wobbuffet's Speed fell!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponentRight); + ABILITY_POPUP(playerLeft, ABILITY_COTTON_DOWN); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentLeft); + MESSAGE("The opposing Wynaut's Speed fell!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, playerRight); + MESSAGE("Wobbuffet's Speed fell!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponentRight); + MESSAGE("The opposing Wobbuffet's Speed fell!"); + SEND_IN_MESSAGE("Wobbuffet"); + } +} + // Checked so that Pursuit has only 1 PP and it forces the player to use Struggle. SINGLE_BATTLE_TEST("Pursuit becomes a locked move after being used on switch-out while holding a Choice Item") { @@ -46,4 +572,42 @@ SINGLE_BATTLE_TEST("Pursuit becomes a locked move after being used on switch-out } } +SINGLE_BATTLE_TEST("Pursuit attacks a switching foe and switchin is correctly stored") +{ + u32 switchin; + PARAMETRIZE { switchin = 1; } + PARAMETRIZE { switchin = 2; } + PARAMETRIZE { switchin = 3; } + PARAMETRIZE { switchin = 4; } + + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_ZIGZAGOON); + PLAYER(SPECIES_AIPOM); + PLAYER(SPECIES_ABRA); + PLAYER(SPECIES_VENIPEDE); + OPPONENT(SPECIES_WYNAUT); + } WHEN { + TURN { SWITCH(player, switchin); MOVE(opponent, MOVE_PURSUIT); } + } SCENE { + SWITCH_OUT_MESSAGE("Wobbuffet"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_PURSUIT, opponent); + switch (switchin) + { + case 1: + SEND_IN_MESSAGE("Zigzagoon"); + break; + case 2: + SEND_IN_MESSAGE("Aipom"); + break; + case 3: + SEND_IN_MESSAGE("Abra"); + break; + case 4: + SEND_IN_MESSAGE("Venipede"); + break; + } + } +} + TO_DO_BATTLE_TEST("Baton Pass doesn't cause Pursuit to increase its power or priority"); From 54d372162fb89907256782e8689d0cfc3c9cdabe Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sat, 7 Dec 2024 11:26:23 +0100 Subject: [PATCH 06/26] Added NBSP and up+down arrows to all fonts (#5767) Co-authored-by: Hedara --- charmap.txt | 2 ++ graphics/fonts/latin_narrow.png | Bin 3449 -> 4553 bytes graphics/fonts/latin_narrower.png | Bin 7346 -> 4764 bytes graphics/fonts/latin_short.png | Bin 3475 -> 4678 bytes graphics/fonts/latin_short_narrow.png | Bin 7508 -> 4993 bytes graphics/fonts/latin_short_narrower.png | Bin 4374 -> 4409 bytes graphics/fonts/latin_small.png | Bin 3665 -> 4587 bytes graphics/fonts/latin_small_narrow.png | Bin 3114 -> 4518 bytes graphics/fonts/latin_small_narrower.png | Bin 4397 -> 4433 bytes include/constants/characters.h | 1 + src/battle_message.c | 5 ++++- src/fonts.c | 16 ++++++++-------- test/test_runner_battle.c | 1 + 13 files changed, 16 insertions(+), 9 deletions(-) diff --git a/charmap.txt b/charmap.txt index 3a2081e304..e2acfdf16b 100644 --- a/charmap.txt +++ b/charmap.txt @@ -46,6 +46,8 @@ LV = 34 '=' = 35 ';' = 36 V_D_ARROW = 38 +NBSP = 39 +'~' = 39 '¿' = 51 '¡' = 52 PK = 53 diff --git a/graphics/fonts/latin_narrow.png b/graphics/fonts/latin_narrow.png index 08652d45f4896aac83a107b00b8086f2740b2964..434638ed17692ef98bf2c8cee733168c77144e99 100644 GIT binary patch literal 4553 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 XTA6~m{)Yek)Bu+ZOmQXp_~`!t#W_z& delta 3436 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 diff --git a/graphics/fonts/latin_narrower.png b/graphics/fonts/latin_narrower.png index 22847ef09953dda2644214d2619277f4090324b2..2b92e411c3ebec97196a6302e89ead3af7f9cf17 100644 GIT binary patch delta 4397 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 literal 7346 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 diff --git a/graphics/fonts/latin_short.png b/graphics/fonts/latin_short.png index 7eba3e748bfd2c0371cfd6a398c1901e5b5a65a7..98ad3c5cc3c9e2bc7864f6a541d7a0cce72f2cdf 100644 GIT binary patch literal 4678 zcmc&&`8Sl0|9zgvV1}_yqL4|Jk}bTEEMtizOCf8RD3X24Zct>2@uos{VJtP)p|VVr ztwj>X5@X9=#yXba)A^k9`Th&vbM86!zJ9zv-FsgNW+nz4Y$w?O0N^mZqIUxTz`qg# z;7otXR!^trFM<9y40M3kUxgO`9!Rrm7MJneN2;o-6bj|&=*W@kFA4xW3x;~y7Qs2I zx9-Olqmj~6M@RGT5`X?{D0a8T&eL^U)4o?%0D)gy3u5|lWvL!_C)!%5oy=7aL? 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 delta 3462 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 b{6Xc{7)jIeEgFv>F2F#~-xU8cP4|oB9 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 literal 7508 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 delta 4062 zcmZ9OX*`q*z{Q_=%w!o88X>7sb`g<13<+f!m7=U&MV2Y9Wn_DXB9$#ki)~7wxb`*M zpb#-5G4>_0?}lL(-h1Eo+j~BoFX!9&o!{?&YEGt}Op<qKb^ z00>53G%>ObPG8Q5tjsPr7%fw`uSbd9PFa#XbHTyk`BQza-tEEX9V#*mB!Ez}I_VBM z6Yr*J;DptM%M4Y>z8K#!S;>3xI}c#e{kN@O9EV9jOpa939OClieNo~_eBDNI%Q|tt zD7xV1qVD#*Vncox?aBMSfGBi>Gtute+9=4znE!hCL^P&h;V~TF?tMkpFln;vyib{W zvezq3C4fz|YWBXu!{-|mi@$E}^)f+3as-}ETAZ|UJ6PhnEdWWv@c9>V5BBBq~ zgrJM1^z=6zO-o+_QC4L1ge!D3i;RS&?vV4D3LfF#Qql)ovppQpzj|s|+on2No zv}Ir|C>ef*_&XCb2zOQ>+n~inBp(85ve>f*l7c6nGFP)f9urTFAGv8SX#QiF?pQoG z3Gdv}V*r4{4S*eliWvvD_k>AuzzMhMxR-10B%n)k_tTGhECKAGlwnniInvuHv?r+HyWK!y#>!n*FzOOvPb^iF- zT^41Dv)8Su$9QyvJ{8SwOBp=^N1Om-o)eD*|1(DnLFS{CN?@GZjnwOdo$HMVN@;h7 z{*pTxzQl~!U8)Z02;l_92p$}|h$U8h^<`_rk`q3s4)>uUmEuB*gQ%yN2==Qe_Kx;V zE^&sPI!<@#c;@3`kZ$K-mPXd~w>?H%WZ8vhMl~_u117I3+Ajh28bOu7os%D=$bUQb z0qnDOhl6)-T?HJM(w7)8GvtH@tX?u)A*=GL6Y0T>k{%d)N#N9lK;Dn?e}4v?QELc6 zW#U_9YYQm%9m2+{HR3&&fJtAq1&=En23v^ubc2gT$=jrL;6_hLs9+b6lJCcVfMDz# zPNeiJTy%0AG& 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 diff --git a/graphics/fonts/latin_small.png b/graphics/fonts/latin_small.png index 371cd5a9684dbb02da670b7f02e3b6d80f72cb33..41bb38cff8c3803e29a8ba0fda854f8182a94cbe 100644 GIT binary patch literal 4587 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 IUFXFA055H-fdBvi diff --git a/graphics/fonts/latin_small_narrow.png b/graphics/fonts/latin_small_narrow.png index 3a88def3adfe70baf0990c294288bec78bed18e1..ff07b857d7e91ea619ab5bfed1be35f517a3ce9f 100644 GIT binary patch literal 4518 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 delta 3099 zcmV+$4CM2sBdQpX7zqLc0000G^jc_)RQ)qudc_!4BC8JJTJqs-F(1W3f%<01i4 zCYK-$17Yi1uU=PmxsBW1DBF{%k{;#muKINSdaujv_YxtBrkhBJzLX0oN0B+c4$Xh@ zI+sH(W!<{2E?nqJtD!l*(8rLzE*A)rzI9z)7%9TaojU5zkt3BbDOFt#Im9ljE;PfW zv>a*ca>yZeS#^Q?3Rw$jkZj>GKn}6Xs|$8>QK9O{NPyiWoNPr&840jYZ06~Lec~j; zENq5G)P=p!$Xj{b3mwtrkVDQQBLjbn<~$m6A^D{BJu>=z9FC`<34?-l5M-(B0@8$` z?y+m7#9^3RiL1IRY^4}rTP@p4iNLA+BqXKE+=U<-1Ry`ul4h|WaSIww3vdh@!0L@c zt!U6{4edfBG4kEMED=*}=JY8V@XvroYzmYcd!0H0T*7f7>lL`j) zJ_<=UHiiLgT@UJm8VWsuZk&HfB{-2?I9zf7aRqtzh67-`z|(mAOo-E0!vJW(_r@MH z(g0~)ux-M2-PnWe6u^mW!AAz1Yq4#@yNdtR7JQ4@q2=fW8Er zzMvbNKO1~Cl4!w-EWCfZBXfBWyr3=saJ^2~uiuOS;L-kFKzR^Q7ZgCZ;NofsU_}G= z<;LP#ekA$QpT4C5d}{-+5;t7{ zHW{)dy))U8f6MO+Kj?RgvJ00{@^yfE;fOC8>V<+V^-&hS!6tv>EaO7*si0B)B!Ht^ zu3cmSB)+ve(*Gn~;CG6-TX5Uk%}jv8W6&rH*e(iqcMIVBPNvbP+XsoSdw>x4Ly`%3 z{6&}pFjXhOLjdYI0F^}oAcu?%c-b|Ta{+Mo4cYWf3EIum1pppNc`R}c;-suJDM;># z8~~rjOlknHME-x5Fh@lJ>RDI>puPea;_VbTlg zI~TCuql@g=iIxDszKIthc>}Qn&xHnX*VHsJ0I&K^bql!Z7rJYw4A6J(r2)`n<)~pb z`)y=7G3Z&~fjnaXUI!kA=GEX%XnYaSs`#@=x|ZEAK=~bn=GEY3WPB0M?a#toO8^Qj zB%ekM+Kqpcr-=IVpODsoJI9#;aIeD)C#<@YApj`VPyp@@2<{FDx8%b?5`c5n$mFOO zD@HFeD-X+BDbhM!@ApXy)BKuKn-wf*1=E0&m81{%n$FjwAplmMLk;+OpSq?Teo3KDFPy_pdeuIB-ot#t`(%x9IO*q*n!1=k=Y~4NN zY8LiV0BjR3Z}hsjA(z8FYqolN_C_w{%V@+(^l7xw9A#ij0N{tDT4lmKjd|s<|FUfd zR4%mZJ?{f>&~^ZTv;VRyZ3dv=T4bL800a@8Z-&Ny*_O4?I0ULD;SGMp0xU(Q3+x?O z4UK;dz1+Mk+2kSiVSl814 zyF&o{b2-lcB+LCW41kRUHW+Mql%IA)$9#XDTcDIFR+z}RUZ+{07g18}Q7*7sz-G$c z-rL)MH+};E7#_8`s#q6L(2c54@d^=rYq0^U1?|WfjlP}*Z25Q}5XUP-q|RKfrt7I) z8S6cC9CiS|G4ehjj#r4t@te!N()Gq#NM|YKd=g_CQdd$v#y>frUjT5F1<=3c+TnkJ z1_V)Z2Lio^Lh<)$cYnYddiZw@NZW1OUqgx8xY$7Qps?GfLV4epSM+3l3LO z08nG7FN}%WNJP{fwj0gRsQ2N%1AzXwbVUFF`)^40!L}Qx8g_(1gl^mW091q}#(n@c z;W8xqVA~DY1@*2WZ6TrJ$1tN^@D6_nl(PO9GfWh~UV*s)g<1d?dwyT&>O*FL9Vk3@ z3lOJZ-<9_RnOlG{u#LvJtx*6wo-x-L*p(VqJ{BO3WwP?jgUGfZj@ycE_d~kdh2&Fu za$Sw@1aQBeE|~$dTj`RT5K*)wADqXFLU|7(HFl%~Buy(H@HK(}5NIFWCmMgyd@dh* z0ST@JJ0t_XMhU=c3D_XOQweyg?~H4W=k$5N*Jx^y+>L8B0yMS_0C#L@2)AUw*XYYG z0ajK90S&7%kI8_qk?I1Rp4SP`lz^$K5dV_jM%r4otj`0!M)yLBX;J{$jnxeTJX%hd zR9_>+H0|$GWYu0zhdO8E3Znb~`4cVOu33W z(6)5@0s0O#m3OXGX=X+OY~8+xY3z`S_oNEX&1C>2bh}HH$65!YlHY$HWJpCeSZWYG zzym%LfKO$Z1rP9masYfP!z_4!2b2TgQyFH#13aJ{0H4Y*3m)JBwilmp#V=g)uqFBl_4X$r6^MOe81vT+=B!50vc!~p;Zzj+`(&!A#Je*A85 zL>y7YfXZ_NsL2-Hljmm;%b=sD?sW{{{-TbkvH{Ji0jN{5@(jj=W0!;pTLK_(0spKy z07Mm_usq+W>cQ54$*u%!3L5=*aJnXj0sjv37ab}HL3{(cgaCi4URQUa<^qI?Vc3x8 zC#(T`)Fq%j25osxO&Q*Q5r%o3KBCBw` zNaw#1`uc=Zc4C2+Db_lo3$eVRFb|;+(?S^(oPW7M`9zff${wIFqK2?cMTd?zYFg`H z=3r$4`uyczB@2HluPsys0g~HN%Vz&zT3pe0a{;X#Qf&YN-KCZ^K+57E^vVVxvIqdQ zqz+(9<`X)MQJ#C!(l-GB{aF5;0icp<-XeiicjWQbtPs0@p#aL}B3Y_70P1emGXcj4 z#R34ig6Mqm8ydVySI0o19^#nTqziqF0fp63`Y(^?Llb}Rq^{}XNvobuca`ohj8{J1 zWO01s(D36?fQLH1amM;@0k$3wugFVZ0dQwL_hvKznu)ad(B!B9UEqp%sNz@waOXfj z|FJw_15gQqCB8gM*P#o`vQ_nI9q&7<0eGZW0=?Eda@lsN`Q3Rc2+-GGQ=DH%KI=Mj z^qJ%S#NU6Up0{fzZkJntghDS{rtfURFk8@41$bJeCoiXoWx6}Yg3T6me__JR5_g+g z&`w4aq9xcHL6rf)z)fl6qCV?$fBLfqRF(&)iEZTcRxOV07(Z$PDHLkV1ie~tQ!CT diff --git a/graphics/fonts/latin_small_narrower.png b/graphics/fonts/latin_small_narrower.png index d03f1b8ad0e2dd74778b0054d91943ab79943dc0..576dac01e4fb45fe0255626f61cc5ae976468283 100644 GIT binary patch literal 4433 zcmeI0S5%Yfx5mFO1xNydBE2dOAcBC3bP^On0g(X}L`nn(kgk+uNFW~_Mw+7s86glx ztSCj0CV?PL9BCp_1QK9|A|*&mC`tZ!&h1(2f6m>xIPcB#?tSrIJZtagx7M5P=wKs; zmPZ2sAa>!rl@kDfdsi4B0^buit214D0!BF5oB_&u6zBH}QAhjB=W^Z)jEszihld3M zffp;{FaSubU9hseOe|RP=uars5bFM+U)=n~#xZq&4x(frl8_HR zFv&l==Ki7uD;M0*P2q2yZXMxhfOA5ST`~q1KerW0w+3e&;yC14zBV8|2P5vA$!3L% zg-ab@NfOc@1av7mVUNV;T=Z3j4(&$NmjQWMMjto`FbCJ{yjn3NoUy6j1oUg&LH?<} zzcmKz$Y+=(U>$(a#G(mAf=r&i$FB5>$%VEfxOUHxmXi~z#3oWK8AIHvykJZut0oz8 ztK%Kr+(zk{h|Be^@u{*fORwr9b*jk#3l4s#$Co?&z!npBJuj{bM7$n z#Ht8YhZQf<@2hvrH}&=nkcB&C^-~yZIOUQIqxG|J<~gD~@kHGr23`_cO9!Oi--^~` zoR}$WZbFHo=jbV^^e#1+s6qT_80=?I>s&z!T>D;&CJx#4C;wCv68(=2Wqcm4$vTnZ z0s4hMd&FNCPg1wq>h~g;SZYudF9|irs9siZzJ7PjOTsHp&m0cBdGn^=E2d*&=6%4^ zn8moNRR2U9%$%gW86{ghgGUi^2^XXRx~|`EAZY8ZNnO;m=h1q~(yT=(8F%>h(Ar`9 zkExyfos+pcu~#IGPRIozTsQP!vgdZy^|HF}63L)%>KUp)mGS(ds=NwR>oiPJk)};uzj5=B zIheq2&JH=2xy_dK62a)5En1l`Z>a+=?z%$N)zzfyr2{CRMPFI0ncycf%m{fN6wnxbZl>nsdP->7Br%DZX^lE&s3>1iKMtyEqddWNj z3_?vnkr(`feA^54*ayE99>v`VVz}|erSY+2V>6sOChF?jlBsD#z`?p?70Em;ByK_r z_hS~8#;HAn6$Oy|U#Mr5|3;oZemp*g_X`Y+{9O`%?;q8|qRv^;;iQ%mm3;U zDewkC1f%PUts$8U zM`^O20ij|QDu|b*tztC@%7BU?co2AUPk~CK2FEr7n^jMu;+P_O_i#J#Om!SAG6;y1 zjI056&6}j~zcRRYo%9nRoE`Nz2`o?tuDsy=F=mIPZS0V^Y}6kLZW;4I`vwrw=lGLM zsl#t;p(Vt;j-x-{%CBhOr9K(P2yPMuY8@vIyWC}NASlG^R&VTzx;5b4JY;u}1lm2Z zyyaUk4YwoS6a826$m%#cLq+@Z1p0tVE6);&13kb`pFS;zJfgmrpJM#HwArnX&j9bskA1NY;6Z)zt%GY=kp(2gO>}_iJUpNdp(L*f)VtYrOko32UQ2*Pp0~5J+fi+` z2rdk%{nD1_m6p2H7sC&erqStqDk9+HVxQBOa%qSni>m2KXzymK1HDT>$G;_|KmT6Q zKj!)9gN(b0DUKThV{AA&oRJTx&W;F@2+NgR-e!FFLY|Z}NcUD>Ee| zQvRE(&#YEzYGoGreqng_N?UmsVIYVbGnORA)IjJt??zeWHtuc0HH9RR%X)k56)7ZZ~Cg*duBr43!{g*y9uUudB(zs3S@X;o=dwqxV2qr z0T}uyNJAWjMM8}5b{c=9?l(yaiQ}}jeVVPrDmt?D7AJWKXFTkQl9>6EP#fX zL%oiv0Tis;PctQJ(Xr!^1QOO(MT!*)FaEEzxJNRcPzsE0$l-r*$P07yBePp4rj1Ty zg!qzw1<@I1TB7X%(^IU_J4&k;sc+B8X70C?k_@X~th@h*SJ=dw>!2bJ-NPdg!-eP_^?T=(E*r4ayH5_Ds zINO31ciVY%Md-yQyHxd=Esi2&d_df2zw>`|I=mh&qTxYW3NC%0RmL`~G3KPf%hd(G z(9W(S+-?8iwL1q5v~cz`YX$Rq6zjTgi#hm$2ZB3qEURoe)51xUI(WlQY_T=#I*cRm zvf~oa9l&=3S4$wnCP%<-6J8Zy2iH~}2n zBKd#&t7v?qV`g@HXJQ-PC;&N?*g+|2h;EE#SaGekP9qo^e}DXP`f5(zZqJyPk2d8s zP&rRx7H#HMQ~>&dMsGxyWHkl5s^bo>q??AQH>!GHhUV6P&0+6P&Y}oZ&;46_`6jV14Z(}TmJEiR*hO~HfHEu_#oASb3@N=>71pUryx2IZ#;A!#nTTz&v$LRJ`$x1?yggz_RU>rO8x=aLMDxylamJ>MlR!po6m>0|Xf; zB}+z?>(m%q7Jdj6GQ<(j0B^T*JA3pgg#+eZhfN5?+ihs+pen#$(wk#^x;`eREzlWH zc;~ygt^xHphl8zik>+9Ciu(e4P?3}Co$zQutU&$)=c#%i)-nyvI+rAGY7sep?cs9t z6slk9@Tu$y5&k~k5!ppDx~|RsMiHu37}*M3Sllb+5geHP!|ve< z8{!?q=tK6x@6;;8BvsvL{)qZqpiu=E@NyaT=>z2^XidG_TMFt$qA?O1J;yZw#k3Ci zp9|n;suNM2`%Ft+kLT3Vw>ISkm4wA=iXdu_^yt6MDGQGSe8RZN^@k_WL=U?%h=8 z5k5a9Z_Csiy?)rbo_M+&kf4Q91S`Rln_FZT=%?DFxMUc3JSj-{Qg!kXG(+b}X`eG} znD=F6N|o`q*^L80PwiIi_=Jf8Y~U#N$&ef-VADkntdWwGFy!3i z(cg;@0mj^W24;ZEv6*ch5IvZ;>IiM5U*55DXkR!P>s}~S*r3}VCh zw^WsWIyVcUPkucfr@0r_xzd#w#JM;8Do;pbceao%VNeh7hezd1Rl-$B(I7~sjG|fG z&N^e+eN>rh)7v1pNTzwgw_ykO)w#O9Di243eIAR}?(bmQkIx~aSL9)lypWflW5K}6 ziJ8sjD<$q1AUNNE+p8!}^A(jH(ehruk6FnO*q66tkv#h89(=l!%8&Y7L18UMg!bku zCMP%diNXJpIL?GK{}Vd>0N5Up4GsVQ`Tri||L4rf%@w+8JDxcBZF-UEe*+9&oh|*v z){(Llz!&OR%*%f*Lq-%YkYEj-hF7`ueL= zHA&{6ZLz#ByZL@i1Z#F3CP%Y~fw}S&hJp(ECGqt*lt^D)ZoR+>P7|+$<(vuE)l`kT zril~8yf5m~-L+FXz$nOy2~Fa_!c!bDK437?9qqN1cvJ@xD2+6+!0&u)D8D~5Slpkz4!(hKnM3Y^$3s)YrqnWQbW{^$ zLs;3|GylhNsTr6SZ?8{e_t}IEM^*IyVIA{oCy_KilX?%M3>C|49amx|*t}B&=A4q& zhKkL6g<9Uz+v2M?tQCAV5_~S&5nfQ&DAd|i*r~I@vQy7ARka+WpL)k%yJc^H-figY z@R+h*8BU{37p5RxQ&&^;JbOhdq@NBXeOb83W$5gSI<}kSHle;^$d7yU!6m;*BWW_R z!Qi<^<{q=Z1CD^&O7yGgD*)#6i`(ysMf4G0`^~_Z;@_wYc^y>>#mgc(_36H1KdB|T zg645=0;NGQ+3`2?n_^#* z|I-4}vA?s(zbm;ONqz*})*0(+KbEfxaM6qA#Z`l~8)F2m8PR_fV5h9J%<@I#7`(-U z<-v)(RAWsgG}HvS;0kuz)~*4oNLrgKJUjr!H5{mcGi>+rV2To`SEwKCV1Mi9#-Zmid56`jVb2wqs$dT%YvD6pIojqj-dhi$16RJKHBmhVLQL$#oj`q{m$Ip`QFP{IBQg%pMVN;Yu^IEJ8xp**GYLRNxcX#jcy*Burxw@ae zg&}{PBgvMBJQEjPpv)SJHdn&Z`*_;mj5vJe8X8KTS&weC0ecCFy!dJ1VL)jHL6(`y zVMWM9DC%<3#0|aydP%wAkL70E4Y0lYHlu1^0{PjdA1|i>cEuwMb>&(m|^0yF=1GY-x#I&HMX!Q%% zUAUF>-zMbm;aC{?N3FhY?`0>OAx3gghW#*tBIBgYX!$CUb&9M)HlXff_+sFd8-UXL z$k>C7pQj$s=_qNbna1?%jUNILyGYRM5yT_t>>s8w5*|va&al+KPHhFpqZK~p2YK)>!BAcqV3i!R?;zJ`7xaxok9?rdP^tr@TJCoztNbc@1s$CuZknOySs%oCYg<& zZ+#)G)e6ehyk*pI#ZEz-P0d9A1$Q{`E58f&Q!hePFcNeMxeB$$Wlz&BwzSiAIjG- zR3^7qxdlNbyBw|d;df&I|4b(%GcPfREGo*=N(aA}1Yr>Q{fI|gkgRiUi{}R(qA6a& zJ<-N@iFlP^CC;L~<7hw7Z3ZLU2+`NYW2}_aak$0)?{m@3yDWCMMJ<`gKLvhbu#j&e zFS^4iCwmlF^+xf|w} zaBb=H0apRN-(q?vaq#vfqs(YTxT-T<=!Z(wC7Hmhx_Bbssk0!-8Xf2!4M=`|{!`ts+-6JM^QP6NYw`ekkl7s&iy=Q^Xbl~G zvW3BF0)&??b)zjo69^6NG5B4QRtbQfAr<;yyCDKq-;qe!s*!1qPQL-&zh%;s2v{I`7x zMn%$wJY~a*;|C*TXyRqn$oejTq2uyU4zGZ(5*c1V6S#?(iKN(Hb>2v_(vipAFB zFG5rSx`RIQ0YTxcR5bk)$$_U9$CiZH8U=Nv9Z1juGP8DjF-><=^`PLWn1jIF7xSH! z)hMFWA^82@QNrRvM_3Tb6)|-c!@t8Med(NL%IY0*Wne_-C{G~CuMi~DVh1oE%n@|{2IF}N89 zaR${C`GavcvQ$1V8a(mB*)k9K$#i)b2-%-X0>h}=J0YH&o@DCq?fxp>l zUp)x;tVzUwgr4qh-AmhNxfW=C+CikRCDi28dV204VJw>d0H`Ui%!Xe5V4M3--+j&v z2=cUoYExhfBDp;N0@nh~pGskrl z*UUk1UHc5cTqh4WOtYe29xlMs?KS+4(NfcwcfIqDP}N^l>FeQEk>W&XT6)2 z7A6J>`bcUWz}{>;vNqYtz8bJnE2Py3fhAFzfLSyrg=P$^B7HUDAI0y1SeV~0hV0R? zb4UziR~Y0K9ma=l4D+5g9yoj$-)>d0>-aKaaU>@m?GD6`5eiUx8M_qK%@fon1kz3U z02jEXiO=yjQZMq~!cSM;EH2^%FFk(aBTFzj+tgy)Eif3<~cX)2VBUCmC1P7|?q? znVmwfVCJjrS*Qq0Me(MlduA+jaTyPI?Y$wfN*pOR+Xq9snJkAbEwi zxdIX}=QipUf&>1Cvk!to32^6U`1X-qW+c!pJlv!Rs(kD{*M)^wwI6d>~* zGlr&_6LYH>-(E6C(^{FU+Hi+!1lTeYeJq?Gp(AntRe5>-DUau6?yG#{J=G#v9nX+r zok~-&u#6r$caI%AhWetYQJ(*37SWfK-701}cQdRjDlmYH$SG3RW6}ci&2~ION_!N` z(cOyr@L!EfjiH23H@D(JhvwV8&gYkJdA@CV*wC_zPO_Von+;vpexOXvN zbS)oiax-OKaV2I^=C1C`hpUB;8V~sYc{8v_8UW{nJh=)bc2VbLBz4jlSxQuAT#Hy_ zU3-&j4N_a96|bHK>PJ+(RS_QdwH+YFy0M5h;PuqT*L?EbYMnp$SxDN?@YWRD&h!!$ z_!pYj$-Khhai|Uo9cYa~l>RU|swK&K9r+S0+(cV)|Ck(DHIqu0)inYSvPeIyFM!V# z0R`b{1B>M$9lV_0tQ!a^+^@Aa{>D{_*S`wjZ-a9!S7sES)leR4h;;@ z1LwrNxkb-1KF!BM;H%gx;C6lZ>VIoEa|FBpi8*cim+7`$j{X1g|Gkg@-y^5Hn_>UV zmU1rP{+8hIVc1b9ApN!TYyGhTda{AV)ZYt8?D3h62kUFKMaeE+$l^oMe}0|Pd+p3< zxwZV*^8S}=54dZlXY>;EvT%M*uuG|UpJ2p(z>E`hHCdX7JqErIX3ZOQ%%CFb@hHhI zYF@3VTpW+}N2*_Ac@yz-RYX|0mTPsJⅇt1ES35YB82ljNRtAOe95-zvH&hbaLAMB(Lk6WY_1`)> zk+o%S>*2Vb4H1%OxW+E69;13Oh5eGu4yyurw2OlKhYUK!pQAj5cgfY0+#Z*yZU zddB|zbr747yy$aSJ$o&OCU)NmVny=^OO=;V`AbHijKL;J*8 ziQ`;_CESGJY^)4JTgYFQ(F{jxl1vM;bo^iJCjcdX(W4rxL@@{kxs76G&{{CoNch&G zVDM1UZip|A(jT#Sd4_kD8Emw*CL4?5jqkbZqnq@PD!$l~n0|t7Fo^rqx&6-poIXXc KetE(-<-Y*@4^nRc diff --git a/include/constants/characters.h b/include/constants/characters.h index 3725cecce0..6ac3c5224c 100644 --- a/include/constants/characters.h +++ b/include/constants/characters.h @@ -54,6 +54,7 @@ #define CHAR_SEMICOLON 0x36 #define CHAR_BARD_WORD_DELIMIT 0x37 // Empty space to separate words in Bard's song #define CHAR_V_D_ARROW 0x38 +#define CHAR_NBSP 0x39 #define CHAR_INV_QUESTION_MARK 0x51 #define CHAR_INV_EXCL_MARK 0x52 #define CHAR_PK 0x53 diff --git a/src/battle_message.c b/src/battle_message.c index 51d41d947e..76b9fde5cc 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -3115,7 +3115,10 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst, u32 dstSize) { while (*toCpy != EOS) { - dst[dstID] = *toCpy; + if (*toCpy == CHAR_SPACE) + dst[dstID] = CHAR_NBSP; + else + dst[dstID] = *toCpy; dstID++; toCpy++; } diff --git a/src/fonts.c b/src/fonts.c index 2eb8ed062b..fba0dfb7a6 100644 --- a/src/fonts.c +++ b/src/fonts.c @@ -5,7 +5,7 @@ ALIGNED(4) const u8 gFontSmallNarrowLatinGlyphWidths[] = { 3, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 4, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 8, 5, 6, 3, - 3, 3, 3, 3, 8, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 8, 0, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 3, 8, 8, 8, 8, 8, 8, 8, 4, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 4, @@ -41,7 +41,7 @@ ALIGNED(4) const u8 gFontSmallLatinGlyphWidths[] = { 3, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 3, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5, 6, 5, 5, 5, 5, 5, 5, 8, 7, 8, 3, - 3, 3, 3, 3, 8, 8, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 8, 8, 7, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 5, 8, 8, 8, 8, 8, 8, 8, 4, 7, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 4, @@ -77,7 +77,7 @@ ALIGNED(4) const u8 gFontNarrowLatinGlyphWidths[] = { 3, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5, 8, 5, 5, 5, 5, 6, 5, 5, 3, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5, 8, 5, 5, 5, 5, 5, 6, 9, 6, 6, 3, - 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 8, 8, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 4, @@ -113,7 +113,7 @@ ALIGNED(4) const u8 gFontShortLatinGlyphWidths[] = { 3, 6, 6, 6, 6, 6, 6, 6, 6, 6, 3, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 6, 3, 6, 6, 6, 6, 6, 6, 3, 6, 6, 6, 6, 6, 8, 6, 6, 6, 6, 6, 6, 9, 8, 8, 3, - 3, 3, 3, 3, 10, 8, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 10, 8, 5, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 6, 6, 8, 8, 8, 8, 8, 8, 4, 6, 8, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 3, 3, 3, 3, 3, 3, 6, @@ -185,7 +185,7 @@ ALIGNED(4) const u8 gFontNarrowerLatinGlyphWidths[] = { 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 8, 4, 4, 4, 5, 5, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 5, 8, 6, 6, 3, - 3, 3, 3, 3, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 8, 8, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, @@ -221,7 +221,7 @@ ALIGNED(4) const u8 gFontSmallNarrowerLatinGlyphWidths[] = { 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 4, 7, 5, 6, 3, - 3, 3, 3, 3, 8, 0, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 8, 0, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 4, 3, 7, 7, 7, 8, 8, 8, 8, 4, 5, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, @@ -257,7 +257,7 @@ ALIGNED(4) const u8 gFontShortNarrowLatinGlyphWidths[] = { 3, 5, 5, 5, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5, 8, 5, 5, 5, 5, 6, 5, 5, 3, 5, 5, 5, 5, 5, 4, 3, 4, 4, 5, 5, 5, 8, 5, 5, 5, 5, 6, 6, 9, 6, 6, 3, - 3, 3, 3, 3, 10, 8, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 10, 8, 5, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 6, 6, 6, 8, 8, 8, 8, 8, 8, 4, 6, 8, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 5, 3, 3, 3, 3, 3, 3, 6, @@ -294,7 +294,7 @@ ALIGNED(4) const u8 gFontShortNarrowerLatinGlyphWidths[] = { 8, 4, 4, 4, 5, 5, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 5, 8, 6, 6, 3, 3, 3, 3, 3, 8, 8, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3, - 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3, 5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 5, 3, 7, 7, 7, 7, 0, 0, 3, diff --git a/test/test_runner_battle.c b/test/test_runner_battle.c index b073ac226a..c55ef489b3 100644 --- a/test/test_runner_battle.c +++ b/test/test_runner_battle.c @@ -1160,6 +1160,7 @@ static s32 TryMessage(s32 i, s32 n, const u8 *string) switch (string[j]) { case CHAR_SPACE: + case CHAR_NBSP: case CHAR_PROMPT_SCROLL: case CHAR_PROMPT_CLEAR: case CHAR_NEWLINE: From a45f18b9b7dcbbb9778bec843e7fe4d431af7aae Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 7 Dec 2024 13:37:37 +0100 Subject: [PATCH 07/26] Fixes Wormadam define for teachable learnset script (#5783) --- tools/learnset_helpers/porymoves_files/b2w2.json | 2 +- tools/learnset_helpers/porymoves_files/bdsp.json | 2 +- tools/learnset_helpers/porymoves_files/bw.json | 2 +- tools/learnset_helpers/porymoves_files/dp.json | 2 +- tools/learnset_helpers/porymoves_files/hgss.json | 2 +- tools/learnset_helpers/porymoves_files/la.json | 2 +- tools/learnset_helpers/porymoves_files/oras.json | 2 +- tools/learnset_helpers/porymoves_files/pt.json | 2 +- tools/learnset_helpers/porymoves_files/sm.json | 2 +- tools/learnset_helpers/porymoves_files/sv.json | 2 +- tools/learnset_helpers/porymoves_files/usum.json | 2 +- tools/learnset_helpers/porymoves_files/xy.json | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/tools/learnset_helpers/porymoves_files/b2w2.json b/tools/learnset_helpers/porymoves_files/b2w2.json index 976b125c6c..bd1762990e 100644 --- a/tools/learnset_helpers/porymoves_files/b2w2.json +++ b/tools/learnset_helpers/porymoves_files/b2w2.json @@ -50290,7 +50290,7 @@ "MOVE_SNORE" ] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 1, diff --git a/tools/learnset_helpers/porymoves_files/bdsp.json b/tools/learnset_helpers/porymoves_files/bdsp.json index 8e4ac589d3..af2e75a3ae 100644 --- a/tools/learnset_helpers/porymoves_files/bdsp.json +++ b/tools/learnset_helpers/porymoves_files/bdsp.json @@ -46223,7 +46223,7 @@ "EggMoves": [], "TutorMoves": [] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 0, diff --git a/tools/learnset_helpers/porymoves_files/bw.json b/tools/learnset_helpers/porymoves_files/bw.json index 7728235c5f..4a93b57602 100644 --- a/tools/learnset_helpers/porymoves_files/bw.json +++ b/tools/learnset_helpers/porymoves_files/bw.json @@ -45087,7 +45087,7 @@ "EggMoves": [], "TutorMoves": [] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 1, diff --git a/tools/learnset_helpers/porymoves_files/dp.json b/tools/learnset_helpers/porymoves_files/dp.json index 666a6dda58..fdae45c2a6 100644 --- a/tools/learnset_helpers/porymoves_files/dp.json +++ b/tools/learnset_helpers/porymoves_files/dp.json @@ -44067,7 +44067,7 @@ "EggMoves": [], "TutorMoves": [] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 1, diff --git a/tools/learnset_helpers/porymoves_files/hgss.json b/tools/learnset_helpers/porymoves_files/hgss.json index b0241c96f4..8aaf2714b3 100644 --- a/tools/learnset_helpers/porymoves_files/hgss.json +++ b/tools/learnset_helpers/porymoves_files/hgss.json @@ -49305,7 +49305,7 @@ "MOVE_STRING_SHOT" ] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 1, diff --git a/tools/learnset_helpers/porymoves_files/la.json b/tools/learnset_helpers/porymoves_files/la.json index 599596a902..4492a37c69 100644 --- a/tools/learnset_helpers/porymoves_files/la.json +++ b/tools/learnset_helpers/porymoves_files/la.json @@ -8433,7 +8433,7 @@ "EggMoves": [], "TutorMoves": [] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 1, diff --git a/tools/learnset_helpers/porymoves_files/oras.json b/tools/learnset_helpers/porymoves_files/oras.json index 11a737628e..da1a3bf21f 100644 --- a/tools/learnset_helpers/porymoves_files/oras.json +++ b/tools/learnset_helpers/porymoves_files/oras.json @@ -53725,7 +53725,7 @@ "MOVE_SNORE" ] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 1, diff --git a/tools/learnset_helpers/porymoves_files/pt.json b/tools/learnset_helpers/porymoves_files/pt.json index e969777fa6..bf2ace3c59 100644 --- a/tools/learnset_helpers/porymoves_files/pt.json +++ b/tools/learnset_helpers/porymoves_files/pt.json @@ -48085,7 +48085,7 @@ "MOVE_SNORE" ] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 1, diff --git a/tools/learnset_helpers/porymoves_files/sm.json b/tools/learnset_helpers/porymoves_files/sm.json index 65255a69fa..d79ab5c4e9 100644 --- a/tools/learnset_helpers/porymoves_files/sm.json +++ b/tools/learnset_helpers/porymoves_files/sm.json @@ -48246,7 +48246,7 @@ "EggMoves": [], "TutorMoves": [] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 0, diff --git a/tools/learnset_helpers/porymoves_files/sv.json b/tools/learnset_helpers/porymoves_files/sv.json index 04bc72f9e6..190b084611 100644 --- a/tools/learnset_helpers/porymoves_files/sv.json +++ b/tools/learnset_helpers/porymoves_files/sv.json @@ -36838,7 +36838,7 @@ "EggMoves": [], "TutorMoves": [] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [], "PreEvoMoves": [], "TMMoves": [], diff --git a/tools/learnset_helpers/porymoves_files/usum.json b/tools/learnset_helpers/porymoves_files/usum.json index ed4cfb69e0..2587a7de81 100644 --- a/tools/learnset_helpers/porymoves_files/usum.json +++ b/tools/learnset_helpers/porymoves_files/usum.json @@ -53477,7 +53477,7 @@ "MOVE_SNORE" ] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 0, diff --git a/tools/learnset_helpers/porymoves_files/xy.json b/tools/learnset_helpers/porymoves_files/xy.json index 8be594e6d7..1cb68d527b 100644 --- a/tools/learnset_helpers/porymoves_files/xy.json +++ b/tools/learnset_helpers/porymoves_files/xy.json @@ -47960,7 +47960,7 @@ "EggMoves": [], "TutorMoves": [] }, - "WORMADAM_PLANT_CLOAK": { + "WORMADAM_PLANT": { "LevelMoves": [ { "Level": 1, From a775098e83e4b5e9b171e085664a364591de13d1 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sat, 7 Dec 2024 07:38:34 -0500 Subject: [PATCH 08/26] Fix octolock + defiant (#5781) Co-authored-by: ghoulslash --- data/battle_scripts_1.s | 2 +- src/battle_util.c | 3 +-- test/battle/move_effect/octolock.c | 21 +++++++++++++++++++++ 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index b38dc4b7f8..6c2b9ecac1 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -864,7 +864,7 @@ BattleScript_EffectOctolock:: goto BattleScript_MoveEnd BattleScript_OctolockEndTurn:: - playstatchangeanimation BS_ATTACKER, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE + playstatchangeanimation BS_TARGET, BIT_DEF | BIT_SPDEF, STAT_CHANGE_NEGATIVE setstatchanger STAT_DEF, 1, TRUE statbuffchange STAT_CHANGE_ALLOW_PTR | STAT_CHANGE_NOT_PROTECT_AFFECTED, BattleScript_OctolockTryLowerSpDef printfromtable gStatDownStringIds diff --git a/src/battle_util.c b/src/battle_util.c index b376a20920..3aaa756e44 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2618,15 +2618,14 @@ u8 DoBattlerEndTurnEffects(void) gBattleStruct->turnEffectsTracker++; break; case ENDTURN_OCTOLOCK: - { if (gDisableStructs[battler].octolock) { + gBattlerAttacker = gDisableStructs[battler].battlerPreventingEscape; gBattlerTarget = battler; BattleScriptExecute(BattleScript_OctolockEndTurn); effect++; } gBattleStruct->turnEffectsTracker++; - } break; case ENDTURN_UPROAR: // uproar if (gBattleMons[battler].status2 & STATUS2_UPROAR) diff --git a/test/battle/move_effect/octolock.c b/test/battle/move_effect/octolock.c index 1a04de7331..e93f6f29cb 100644 --- a/test/battle/move_effect/octolock.c +++ b/test/battle/move_effect/octolock.c @@ -131,3 +131,24 @@ SINGLE_BATTLE_TEST("Octolock will not decrease Defense and Sp. Def further then } } } + +SINGLE_BATTLE_TEST("Octolock triggers Defiant for both stat reductions") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_BISHARP) { Ability(ABILITY_DEFIANT); } + } WHEN { + TURN { MOVE(player, MOVE_OCTOLOCK); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player); + MESSAGE("The opposing Bisharp can no longer escape because of Octolock!"); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Bisharp's Defense fell!"); + ABILITY_POPUP(opponent, ABILITY_DEFIANT); + MESSAGE("The opposing Bisharp's Attack sharply rose!"); + NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent); + MESSAGE("The opposing Bisharp's Sp. Def fell!"); + ABILITY_POPUP(opponent, ABILITY_DEFIANT); + MESSAGE("The opposing Bisharp's Attack sharply rose!"); + } +} From 6e24b6af3dd134c90fa2342d7378825697dd5d27 Mon Sep 17 00:00:00 2001 From: ghoulslash <41651341+ghoulslash@users.noreply.github.com> Date: Sat, 7 Dec 2024 08:48:01 -0500 Subject: [PATCH 09/26] Gravity fix + Sky Drop Test (#5780) Co-authored-by: ghoulslash --- data/battle_scripts_1.s | 4 +-- test/battle/move_effect/gravity.c | 47 +++++++++++++++++++++++++++++++ 2 files changed, 49 insertions(+), 2 deletions(-) create mode 100644 test/battle/move_effect/gravity.c diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6c2b9ecac1..5f7e898e1d 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -2741,9 +2741,9 @@ BattleScript_GravityLoopDrop: printstring STRINGID_GRAVITYGROUNDING waitmessage B_WAIT_TIME_LONG BattleScript_GravityLoopEnd: - moveendto MOVEEND_NEXT_TARGET + moveendcase MOVEEND_TARGET_VISIBLE jumpifnexttargetvalid BattleScript_GravityLoop - end + goto BattleScript_MoveEnd BattleScript_EffectRoost:: attackcanceler diff --git a/test/battle/move_effect/gravity.c b/test/battle/move_effect/gravity.c new file mode 100644 index 0000000000..4ccad08b58 --- /dev/null +++ b/test/battle/move_effect/gravity.c @@ -0,0 +1,47 @@ +#include "global.h" +#include "test/battle.h" + +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_GRAVITY].effect == EFFECT_GRAVITY); +} + +DOUBLE_BATTLE_TEST("Gravity cancels fly and sky drop if they are in the air") +{ + u8 visibility; + GIVEN { + PLAYER(SPECIES_WOBBUFFET) { Speed(100); } + PLAYER(SPECIES_WYNAUT) { Speed(90); } + OPPONENT(SPECIES_PIDGEY) { Speed(50); } + OPPONENT(SPECIES_ROOKIDEE) { Speed(45); } + } WHEN { + TURN { MOVE(opponentLeft, MOVE_SKY_DROP, target: playerRight); MOVE(opponentRight, MOVE_FLY, target: playerLeft); } + TURN { MOVE(playerLeft, MOVE_GRAVITY); SKIP_TURN(opponentRight); SKIP_TURN(opponentLeft); } + } SCENE { + // turn 1 + MESSAGE("The opposing Pidgey used Sky Drop!"); + MESSAGE("The opposing Pidgey took Wynaut into the sky!"); + ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, opponentLeft); + MESSAGE("The opposing Rookidee used Fly!"); + MESSAGE("The opposing Rookidee flew up high!"); + // turn 2 + MESSAGE("Wobbuffet used Gravity!"); + MESSAGE("Gravity intensified!"); + MESSAGE("The opposing Pidgey fell from the sky due to the gravity!"); + MESSAGE("The opposing Rookidee fell from the sky due to the gravity!"); + MESSAGE("The opposing Pidgey can't use Sky Drop because of gravity!"); + MESSAGE("The opposing Rookidee can't use Fly because of gravity!"); + } THEN { + // all battlers should be visible. assign to var first because expect_eq not working with bitfield address + visibility = gBattleSpritesDataPtr->battlerData[0].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[1].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[2].invisible; + EXPECT_EQ(visibility, 0); + visibility = gBattleSpritesDataPtr->battlerData[3].invisible; + EXPECT_EQ(visibility, 0); + // ensure moveend properly recorded + EXPECT_EQ(gLastMoves[0], MOVE_GRAVITY); + } +} From 3f3f4cfe1c3d6c156d7570c8a84c390ece1a715f Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Sat, 7 Dec 2024 15:52:13 +0100 Subject: [PATCH 10/26] New Volt Switch Animation (#5729) Co-authored-by: Hedara --- data/battle_anim_scripts.s | 62 ++++++++++++++++++-------------------- include/battle_anim.h | 1 + src/battle_anim_electric.c | 60 ++++++++++++++++++++++++++++++++++++ 3 files changed, 90 insertions(+), 33 deletions(-) diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 80d50710ba..e2b76524a8 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -5561,44 +5561,40 @@ GrassPledgeMiddleFountain: delay 4 return +@Credits to Skeli gBattleAnimMove_VoltSwitch:: - loadspritegfx ANIM_TAG_SPARK + loadspritegfx ANIM_TAG_SHADOW_BALL + loadspritegfx ANIM_TAG_IONS loadspritegfx ANIM_TAG_SPARK_2 - loadspritegfx ANIM_TAG_THIN_RING - monbg ANIM_ATTACKER - setalpha 12, 8 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, 0x3BDF, 8 - playsewithpan SE_M_CHARGE, SOUND_PAN_ATTACKER + playsewithpan SE_M_THUNDERBOLT, SOUND_PAN_ATTACKER + createsprite gVoltSwitchSpriteTemplate, ANIM_TARGET, 3, 0, 0, 0, 0, 32, 20 + delay 30 + createvisualtask AnimTask_ShakeMon2 2, ANIM_TARGET, 3, 0, 8, 1 + call VoltSwitchElectricFlashes + delay 2 + playsewithpan SE_M_THUNDERBOLT, SOUND_PAN_ATTACKER + createsprite gVoltSwitchSpriteTemplate ANIM_TARGET, 3, 0, 0, 0, 0, 32, -20 delay 4 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, 0x3BDF, 8 - delay 4 - createvisualtask AnimTask_ShakeMon, 5, ANIM_TARGET, 0, 3, 45, 1 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, 0x3BDF, 8 - delay 4 - createsprite gUproarRingSpriteTemplate, ANIM_ATTACKER, 3, 0, 0, 0, 0, 0x3BDF, 8 - delay 4 - call ElectricityEffect - playsewithpan SE_M_THUNDERBOLT2, SOUND_PAN_ATTACKER - createvisualtask AnimTask_CanBattlerSwitch, 1, ANIM_ATTACKER - jumpretfalse VoltSwitchContinue - createvisualtask AnimTask_IsTargetSameSide 1 - jumprettrue VoltSwitchAgainstPartner - createvisualtask AnimTask_SlideOffScreen, 5, ANIM_ATTACKER, -2 -VoltSwitchContinue: + call VoltSwitchElectricFlashes + delay 18 + createvisualtask AnimTask_ShakeMon2 2, ANIM_TARGET, 3, 0, 8, 1 + call VoltSwitchElectricFlashes + delay 6 + call VoltSwitchElectricFlashes waitforvisualfinish - clearmonbg ANIM_ATTACKER - blendoff - createvisualtask AnimTask_CanBattlerSwitch, 1, ANIM_ATTACKER - jumpretfalse VoltSwitchLast - invisible ANIM_ATTACKER -VoltSwitchLast: - delay 8 end -@ Attacking the same side requires a change of direction -@ why would you attack your partner though?! -VoltSwitchAgainstPartner: - createvisualtask AnimTask_SlideOffScreen, 5, ANIM_ATTACKER, 2 - goto VoltSwitchContinue + +VoltSwitchElectricFlashes: + playsewithpan SE_M_CHARGE, SOUND_PAN_TARGET + createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 5, 0, 5, 0 + createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -5, 10, 5, 1 + createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 15, 20, 5, 2 + createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -15, -10, 5, 0 + createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 25, 0, 5, 1 + createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -8, 8, 5, 2 + createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, 2, -8, 5, 0 + createsprite gElectricitySpriteTemplate, ANIM_TARGET, 2, -20, 15, 5, 1 + return gBattleAnimMove_StruggleBug:: loadspritegfx ANIM_TAG_MOVEMENT_WAVES diff --git a/include/battle_anim.h b/include/battle_anim.h index 96ba0c52ab..ef933a1c08 100644 --- a/include/battle_anim.h +++ b/include/battle_anim.h @@ -464,6 +464,7 @@ void AnimElectricPuff(struct Sprite *sprite); void AnimSparkElectricityFlashing(struct Sprite *sprite); void AnimGrowingShockWaveOrb(struct Sprite *sprite); void AnimElectricity(struct Sprite *); +void AnimTask_VoltSwitch(struct Sprite* sprite); extern const union AffineAnimCmd *const gAffineAnims_GrowingElectricOrb[]; extern const union AffineAnimCmd *const gAffineAnims_FlashingSpark[]; extern const union AnimCmd *const gAnims_ThunderboltOrb[]; diff --git a/src/battle_anim_electric.c b/src/battle_anim_electric.c index 64114227e1..929dc972f0 100644 --- a/src/battle_anim_electric.c +++ b/src/battle_anim_electric.c @@ -589,6 +589,17 @@ const struct SpriteTemplate gIonSpriteTemplate = .callback = AnimIon, }; +const struct SpriteTemplate gVoltSwitchSpriteTemplate = +{ + .tileTag = ANIM_TAG_SHADOW_BALL, + .paletteTag = ANIM_TAG_IONS, + .oam = &gOamData_AffineNormal_ObjNormal_32x32, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gAffineAnims_ShadowBall, + .callback = AnimTask_VoltSwitch, +}; + // functions static void AnimLightning(struct Sprite *sprite) { @@ -1523,3 +1534,52 @@ static void AnimIon_Step(struct Sprite *sprite) if (sprite->animEnded) DestroySprite(sprite); } + +//Volt Switch// + +//Launches the projectiles for Volt Switch +//arg 0: initial x pixel offset +//arg 1: initial y pixel offset +//arg 2: target x pixel offset +//arg 3: target y pixel offset +//arg 4: duration +//arg 5: wave amplitude +static void VoltSwitch_Step(struct Sprite* sprite) +{ + sprite->invisible = FALSE; + + if (TranslateAnimHorizontalArc(sprite)) + { + //Merge coords into one + sprite->x += sprite->x2; + sprite->y += sprite->y2; + sprite->x2 = 0; + sprite->y2 = 0; + + //Come straight back to the attacker + sprite->data[0] = 0x14; //Duration + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_X_2); + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimAttacker, BATTLER_COORD_Y_PIC_OFFSET); + + sprite->callback = StartAnimLinearTranslation; + StoreSpriteCallbackInData6(sprite, DestroyAnimSprite); + } +} + +void AnimTask_VoltSwitch(struct Sprite* sprite) +{ + InitSpritePosToAnimAttacker(sprite, 0); + + if (GetBattlerSide(gBattleAnimAttacker) == B_SIDE_OPPONENT) + gBattleAnimArgs[2] = -gBattleAnimArgs[2]; + else + sprite->y += 10; //Move slightly down + + sprite->data[0] = gBattleAnimArgs[4]; + sprite->data[2] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_X_2) + gBattleAnimArgs[2]; //Target X + sprite->data[4] = GetBattlerSpriteCoord(gBattleAnimTarget, BATTLER_COORD_Y_PIC_OFFSET) + gBattleAnimArgs[3]; //Target Y + sprite->data[5] = gBattleAnimArgs[5]; + InitAnimArcTranslation(sprite); + + sprite->callback = VoltSwitch_Step; +} From cb12bdc22086bafc34d90c3288d23662d0f514a6 Mon Sep 17 00:00:00 2001 From: iriv24 <40581123+iriv24@users.noreply.github.com> Date: Sat, 7 Dec 2024 16:11:45 -0500 Subject: [PATCH 11/26] Fix No Guard failing OHKO Moves into Semi-Invulnerable Pokemon (#5779) Co-authored-by: Bassoonian --- data/battle_scripts_1.s | 2 +- test/battle/move_effect/ohko.c | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 5f7e898e1d..1eb74cea31 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -3413,7 +3413,7 @@ BattleScript_EffectOHKO:: attackcanceler attackstring ppreduce - accuracycheck BattleScript_ButItFailed, NO_ACC_CALC_CHECK_LOCK_ON + accuracycheck BattleScript_ButItFailed, ACC_CURR_MOVE typecalc jumpifmovehadnoeffect BattleScript_HitFromAtkAnimation tryKO BattleScript_KOFail diff --git a/test/battle/move_effect/ohko.c b/test/battle/move_effect/ohko.c index 511d76a8ad..8a8015309b 100644 --- a/test/battle/move_effect/ohko.c +++ b/test/battle/move_effect/ohko.c @@ -20,6 +20,22 @@ SINGLE_BATTLE_TEST("Sheer Cold doesn't affect Ice-type Pokémon") MESSAGE("It doesn't affect the opposing Glalie…"); } } + +SINGLE_BATTLE_TEST("OHKO moves can hit semi-invulnerable mons when the user has No-Guard") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_SHEER_COLD].effect == EFFECT_OHKO); + PLAYER(SPECIES_WOBBUFFET) { Ability(ABILITY_NO_GUARD); } + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(opponent, MOVE_FLY); } + TURN { MOVE(player, MOVE_SHEER_COLD); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_SHEER_COLD, player); + HP_BAR(opponent, hp: 0); + } +} + TO_DO_BATTLE_TEST("Fissure faints the target, skipping regular damage calculations") TO_DO_BATTLE_TEST("Fissure always fails if the target has a higher level than the user") TO_DO_BATTLE_TEST("Fissure's accuracy increases by 1% for every level the user has over the target") From 6e6352569fd051ec1cedace97057b8929823af3f Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Sat, 7 Dec 2024 15:12:09 -0600 Subject: [PATCH 12/26] Narrower font tweaks and font fitting fixes (#5782) --- data/scripts/debug.inc | 29 ++++-- graphics/fonts/latin_narrower.png | Bin 4764 -> 4617 bytes graphics/fonts/latin_short_narrower.png | Bin 4409 -> 4399 bytes graphics/fonts/latin_small_narrower.png | Bin 4433 -> 4349 bytes src/debug.c | 130 +++++++++++++----------- src/fonts.c | 40 ++++---- src/item_menu.c | 4 +- test/text.c | 123 +++++----------------- 8 files changed, 137 insertions(+), 189 deletions(-) diff --git a/data/scripts/debug.inc b/data/scripts/debug.inc index 9da3f529fc..0be780609d 100644 --- a/data/scripts/debug.inc +++ b/data/scripts/debug.inc @@ -449,7 +449,7 @@ Debug_EventScript_EWRAMCounters_Text:: .string "Fishing Chain: {STR_VAR_2}.$" Debug_EventScript_FontTest_Text_1:: - .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font .string "Angel Adept Blind Bodice Clique\n" .string "Coast Dunce Docile Enact Eosin\l" .string "Furlong Focal Gnome Gondola Human\l" @@ -463,7 +463,7 @@ Debug_EventScript_FontTest_Text_1:: .string "Zloty Zodiac.$" Debug_EventScript_FontTest_Text_2:: - .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font .string "Angel angel adept for the nuance loads\n" .string "of the arena cocoa and quaalude. Blind\l" .string "blind bodice for the submit oboe of the\l" @@ -474,7 +474,7 @@ Debug_EventScript_FontTest_Text_2:: .string "loud statehood and huddle.$" Debug_EventScript_FontTest_Text_3:: - .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font .string "Enact enact eosin for the quench coed\n" .string "of the pique canoe and bleep. Furlong\l" .string "furlong focal for the genuflect\l" @@ -486,7 +486,7 @@ Debug_EventScript_FontTest_Text_3:: .string "bathhouse.$" Debug_EventScript_FontTest_Text_4:: - .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font .string "Inlet inlet iodine for the quince\n" .string "champion of the ennui scampi and shiite.\l" .string "Justin justin jocose for the djibouti\l" @@ -498,7 +498,7 @@ Debug_EventScript_FontTest_Text_4:: .string "shallot.$" Debug_EventScript_FontTest_Text_5:: - .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font .string "Milliner milliner modal for the alumna\n" .string "solomon of the album custom and summon.\l" .string "Number number nodule for the unmade\l" @@ -510,7 +510,7 @@ Debug_EventScript_FontTest_Text_5:: .string "bishop and supplies.$" Debug_EventScript_FontTest_Text_6:: - .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font .string "Quanta quanta qophs for the inquest\n" .string "sheqel of the cinq coq and suqqu. Rhone\l" .string "rhone roman for the burnt porous of the\l" @@ -521,7 +521,7 @@ Debug_EventScript_FontTest_Text_6:: .string "of the peasant ingot and ottoman.$" Debug_EventScript_FontTest_Text_7:: - .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font .string "Uncle uncle udder for the dunes cloud\n" .string "of the hindu thou and continuum. Vulcan\l" .string "vulcan vocal for the alluvial ovoid of\l" @@ -533,12 +533,24 @@ Debug_EventScript_FontTest_Text_7:: .string "exxon.$" Debug_EventScript_FontTest_Text_8:: - .string "{FONT_SHORT_NARROWER}" @ Edit this to test your font + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font .string "Yunnan yunnan young for the dynamo\n" .string "coyote of the obloquy employ and\l" .string "sayyid. Zloty zloty zodiac for the gizmo\l" .string "ozone of the franz laissez and buzzing.$" + +Debug_EventScript_FontTest_Text_9:: @ Special thanks to Nintendo for this nice pangram to test other glyphs + .string "{FONT_SMALL_NARROWER}" @ Edit this to test your font + .string "42 × 138 = 5796.\n" + .string "Mr Jock, TV quiz PhD: bags 20% fewer\l" + .string "lynx at a café; voilà, they're “worth”\l" + .string "♂1/♀1 = ¥1. That's 10 + 9 - 8 = 11\l" + .string "Nintendo GBA can connect to a Nintendo\l" + .string "GameCube console! He claimed-though I don't\l" + .string "believe him-to have done so in an eyes-shut\l" + .string "state…?$" + Debug_PrintFontTest:: msgbox Debug_EventScript_FontTest_Text_1, MSGBOX_DEFAULT msgbox Debug_EventScript_FontTest_Text_2, MSGBOX_DEFAULT @@ -548,6 +560,7 @@ Debug_PrintFontTest:: msgbox Debug_EventScript_FontTest_Text_6, MSGBOX_DEFAULT msgbox Debug_EventScript_FontTest_Text_7, MSGBOX_DEFAULT msgbox Debug_EventScript_FontTest_Text_8, MSGBOX_DEFAULT + msgbox Debug_EventScript_FontTest_Text_9, MSGBOX_DEFAULT releaseall end diff --git a/graphics/fonts/latin_narrower.png b/graphics/fonts/latin_narrower.png index 2b92e411c3ebec97196a6302e89ead3af7f9cf17..19a6a98fb664f1084cb901ff4cb3fd550b9234dd 100644 GIT binary patch delta 4197 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 delta 4345 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 diff --git a/graphics/fonts/latin_short_narrower.png b/graphics/fonts/latin_short_narrower.png index 830a90389f8f86eaf22db5fdda00960583fea13e..5c4f4c1d4d87a4dcbd5b58a6da7b03a920ad78bf 100644 GIT binary patch delta 3843 zcmV+e5B%`CBCjHlZ7QuvL_t(|ob8=~x~r%Tg(bZIJD;Q2U9v(+Q?zPb|J=FXq@uzS zkOX8;k(V%kXnXJc*&8?tdUi@sB?oQ9OCQazy@6>{QCo)W|Cj3ufXC5}=GQP@;C`p* z+1?X!YvA_vGwv}Yk;UCXGq`*;Q7-y@$t@*nfivG zgxFMm>_}84SVpp40i2M?*_(hJ+3AsI8Oc@x2sQyvfQ|iad;%W?SmFb(>ZhFb6;pC% z8@HZqO;AUN{rRW>;EvADYS;VNL4b6m0E>IRWfSkj%lz)r8%(K-oI_b|%mGV0( zof#uQv=5NQf0IxHNCNu^lbQoR0ZxkwbCw+e zM5Tw7qPm14qI!h`YJe|*XaUsRZz`RJ7ChKUtU;Ktu#E-x#$7kR1hB8f3Rd=o(N=wAE`*H-TU$Xzrij zL&@z0fAE?_T!6aMTKWLBXUWp5z5N=@YcE^d#|vNt0RdE#(fbvws|%iXw%-q^_5Zlv z!LR_Ja9OVb7xVIr21jmCO7ckFEi$T$=p zTy5hGgw6(LZ#cWR7vS4`JHMyXhXUMQfG;nSfA#h={5sy&T3hpN!Clw{LNVzr?su{p zaQh}e0q!n?`hcHl0=CoBpVu#THQP9Qlb8Pd9?6d#7@n^=^?7}-u#G?8Z+Y2vE=OdVdVv{Y%m24=GDGy*Ssie~7uYf45nE zJT8Fxc++Ii5x_41-p_8A*FS$}0oI+IUf&P|zykXPFoO4+Oi+NbQn)@I6ab^vo&cC( z)26*9WZQVR#$l6c?Jn2r1Z^K<3KSFocYJi7nAb!+0rC3YeupT4`CH~22oUS_oht4M zV7AvA90%avc8m&O+H`iFxZB2qe{UJD2EY>z_W`)6DLzrOTbrQvj+^U)pkDgj1;Fp? zu??9vWondj++5#O(Y|eVw*$MeZgB#;FTmkL-7#Mv%?jM00oxy z4+y*}u=xWDP~hUPD*@CGrxzf>Ztf^R`Dn4Wb%?FFt6G2@6F_@=zH`+*Za%X{0rYp9 z%Rohamnl$SfhJM@9>9PAi@?tWS)c9>m3>?K0>A_Kz}9_$z?aRX59kOWI!1-=ZnS`2 zd}4b6u+!5mXu>ajZ4=Pn3_{xokQcH8XU$2!xsxmi7=LpI0d%9qK4Ga5y(W#?DX>M8elr*`4Lrh2tSPA;Kdu9 z_=eqGeo%m{-=eF(ZtQv>r3HWs;@$v__=Fw@*mwro`@RM}Y?F!YeuDQJwGS5{y8Fq` z2@p7SAAcyo##QQS_Td>g+CDr3N8A1a1~c#&ogMBwC!_wpw*bTJWbM0;v6&!O0N0t> z*0wWIMgY%wh)tKros+HY+^-Qv0MDQH*6^6w;r`s;7oK=f0Gyq5s^}X6^aYI;(5b?B z+?&q7U=s*Fpy2w0VFAVi6#JeZ7QpK@z4ZZJ`hR$@ZSt4&apx@s0^o6Xem=TBz)Npz zXFY+HRvkxDM9c>?;fun75dycMx+uPF=Nq>S2Q-EUy7On`nj-0kBP!+znYG2Mad&qRKrdarqX6(t&!iY%!V(Li?Y?5f?jNAn?;8QO&XDovy^pCk zjwcvr4pwtVy{A$4HoAgibo#pyvC^Ml>@NV0f8_@Q9^o2ln`pNa42P&3|K4A76pJVL z`Ew&o`Zb9Db2J`c6gF+JA8%;H1G@19KYxAyKf`B#!y`c(mUhD2JKJW_RK^klqXL)} z9Ju1++v5uQ|0G6+Iuf56i&fFnfdWKVdHtLKdv{W&!w9hPP}NLCoDJN0Dei2c8r(TRaXLnu00p?b08SrZ=kvY!{r>UO;f(~}Sby)OKeqtL z?M8yg?FArrBmXgGN3XZ_{Xey@Ab^_A+}d7lSWg(YGK9xl>30(#Et_-wjn=ld8ww>g zf10zNQO|!rd`kdP8}R-AuQ_`?+e@Eof4foOrd=y&1X5dYiY~yCwmM&1C4H|3mi#_v z8izCGi9hC=eDnV}V_}I)6$J zq;I1DkK<-@v_^*T301dW1*ooP1;Fbq(|fg@)%BAnn99%c7aEos`{4QxaJLvKGKLvFK|q2VaAFAK9GO zT|ku$uR(oWz19{nB}q?!dIqy%wkzL>~U!e|O5~(r_0A z+|87&0KF%SHAV}tx=N>M0uBG#)PNKeK$HNFkj7tnzoNNDj5n%qYE>JCils-UIr>6zcf4Amf-teDu>oxfLEdcQZ6HyYW1v#9s zKfP7~^+fe+P`jTG@Ahdg4;MI(0C9g>72pvaxa>fPlhF-Ulkg21f5^_HB(#L^tZ`ha|Q=8-oA3^B)9)5l9Coo4_1u#{pmQ<%t(kNi{OZu-qoY6Hs z?DcGt-tkfzUBaFKDVZ9i??0Ee^TYqs6C{B8=n0_pZ(Of&Mo)nG0x2Ls<67$ea}9t# zL2Y2-JAZ z^+(Gm*B9)^2OLal z8{feQLGS#=Fuh?Ae@{KgsJ3qXmn2H?;V{Cg~rwY9*@ zwe)1Dx}{5nI6_1e2@4qf$Rrpn-QOjL$c22mhc606zH3C;S4 z<-c(1f2(I(0Vef`*V$w64ql({)c}Jj5PB~jUKa$;qVZNSxtQtGSbioQPr)bN=p)_; zQB{KCDc)PiYtlCT1oQ7vSIKx=7*WINY+MneC2;~M&Gen?rSeZl0H=n;abk+I;=NAQ zvrWXrtU!vzH@5eVrQ7FB*l9KW^^Wakcr?C283?%({{TQahIf7vu9^S<002ovPDHLk FV1ia9M`&97m+!2M3q zv%M$e*1*pT00lBlB4&SIfM}aFPZTp0v%fFEa3659CLnH&_;~>&)?^NT4SH`0?=53T zR*s#$k=dXf&0oeo#jy?HkrgO<{gGhwf~fG-1t52SBdBU0B)let zpa4gQ*k*;KR%vem!cD*ly6)Zt=E9FPfz)jR*@Uc|u|5V}2SaolLSS>N8fXG20Mvk} zH)g#d#WDAMqW}X*n0V~H9%C6GbC^Y@ce0<_}H>!roQ1j zAvTpCI}%k1mXT~%04F4J_9kFQc6#JlMzWOvf=$2^U}t|DpTHXdmiWM{`YC69#gv@c z#=U1-6V%aRe?BSzxTCYP+VwsT5FmY1fWoXna5*L=^Sk zM+Fdw()#0oo&D{lm(J>VHy(htc@0PV00>a{0-XId7=8=b`%{3P0ECQ@GgiWzfdVw! zWZ?YEK>>CUU>>YqR)CWEjsWQ10l7?0|BwL1{|pGQo^WLW%KwYK%(K-oI_b|%mGV0( zof#uQv=5NQf0IxHNCJBclbQoR0Z)_K1402ElN|&Ye|rnyH37XKy_8SesV>kwbCw+e zM5Tw7qPm14qI!id)Bs-q(E_Ns-&8scEr4n=_7fd=AgaclLI5KO2vGM+%^CoGMxDP_ ze(GLfe*sco01^FW77##0f3h$yfQSfSzA;G}T zgJA(c;j&%>F6ar6wVgUmV00vi;K`0^D5yZ-2qPIh_FB{(=YG?_>hp{xx`a0SM9LKi;!14+Y5jbNW_+@wlF_zc?8_ zr^m0$bD5db0;uWIi(?DiwExC)f9B5!03TBu0r2?MKfXrN1L@l+z{vt#?<0?|$=3qO zf1`Y8V-5Hf0Zf&L&+Av)^Z`H91Z=0LKd)cxYPNCqCNKT@J(3?gFg#y#>htGcKSj#yy70HzK1n@msuo1dTn7`65Uzzo|q>NFwS#=AAnHYw8y zb_Kvb#(Y>1765PPJTb3{cmmq%$KC??x6JntAlBn^+z0rWP%zH`+*Za%X{0rYp9%fLf@mnl$SfhJM@9>9PA zN&iKL3@eTOp|U&l?h619;0;^%0Rmq(mp-5)fan-ihMkh51@z(*`wM`bo^C-Ce(7tQ zfc_TRZtw4f>@Wb+PrthWf7t2a_6`|-X!HSUOAx&^d&4<%BT#+s^8f*Kqs2a9sS&*< zko9W^*P3r|mmL8PZUW6tFTbt%m zI%WM9o$zaa+)y&Z1#xeHMtnk#18jT%f9+#mgC4fY#CAWy zdyU#(7a+R($U@!xZ(b-{hTz`H)=SdWnH}!W{WS`(s{nR= zfhPdY&N^*og8+R&f1?68RTz)^i>%Jp1jK6s!3Pvve=sb-4gm^BfLQ*b`E}>#z1Ltg zy(hqi^#e&CcivLC$P3+1Z+fpO zOaXSbr%3v7@5{soaOCD?xPQKPys;X6(&;zM42{^0aTkNklh8?J(3C}e-mGrBI(aCatqmZUZVdR^wNL5Kw;Z_q2i1K zob=@OV1@X475{*(exm?)69AU`PcSU_eg+R00G3{UT>!`3JwO1xboGt`z&AaU!dqYO zFHwnw(EPc>okMoGe%}bNcZQ5V?|mG-b3DN~bFiA*tpPi`x6u_GqtoAwh?V{Xf8%%o za4bI<@CesX+eEvaU^qnO`1k&rqgXt_&z~D%(yu{WtsadB7==w6?8h4#@qlhT!Ovgc z|IhH*-|$G#hNZoUj$>`JXewg~fl&d>3J%;s;?v^_`u`+GhB^|T8jDrY(}4m+S9$%M z07rLHr^5)a^H9}HM4S!$o1t-MeQLlm>s>|-uHjkzJdU1I&*J( zxnVtF+{zFhZ>2v>fV6DR^*37E+iob7)ck4AdPY6}{qQLPL~X$L|6ghOf8zYL?WNDP z-6(L=t`#%_sVz7~7hp+Sov*EuzE=ZFexI`qOW~@|P1F40rM7K)k(c(PK+giA0C?P_ zcLbQTSA8K}GVmN8rzD;L0tLbXXDqO5SLaXZf%I(@;Bnk+j@HN!KB4+^;gXr^dR73u z-ZH&c+gV*dd4j3@%=71Ef5v?MK_2Bp8*9KL!?0hT$?%-CN^b;^$A6mzSf)2$3!Kyw zZa#oI2d2tD1ktwX1A0xMRQiW4YpZ)DfTW%Pl5*+9WUDRf|F)%Xbb6we5Ug8VR)UD= z<9fTewMy2Vo|4E4khK7|iA7&?IrtjX`^e_J?gFZ8cn#{~>b16reH+L(H{Zh|F}oI^i1`%su|HyEs|^)P>Sq*UHJ)}}cPPxq*u$UzEkRrMtMr%S z_5zTrv$e_|=8u1y9QUVZYTrSwEkJajv6la7ufv4v3gG(J+J0037z+1lj2cK4qjI0V zjOQ$%{Z|2AjuhAJf7NS&YC+`T&wZwRE)924z}-yQ3ebDPSYxyRtE+UHCeZM&O$|sv z0YnM#2xh!cA`tR0!nGODPZoLLyzXc$kU?NH)wIE+7>`$*%Ks{0Y7#h^>=fk^w+RFvbBS74r zRt0!O2QE7hB9rkAE0f?2Jd@xJ34d}hDM@WC$m`_4M_2%T`1)$863EKd^bH%6V``H; z;UfrL-@~uZ{RHM{s{p17)spJ;Ng4&Leo6n;hcmjShrOOn(mP&Cqf6KmASF|S^!?}3 zc7FJOdV&N{A3XuI{*CK3&gcm+UmyhpXk1I(f35-0hiCzeLU1oApy{$ufPen=F#k65 zbN-VI37}3#Jxhjb0c?U!3$p^~3OE;D>S43=}A{%(?XOjrOm!G**4GwZ%mnpcNLKhg(C0)ZN@x&BM9mB-%c=K5n-w-@lTJ9v9S z2qA==ncd?L$+?5?&_{3Bb$_tYna1q3?ho#zn;uS1_yY{RjPKI%E$m3x1^~KQg!7l7 zJR}CejC+X#Y3+?R#_9>jnmW6abk1L$x0eDmLu?r05EKvMDRSK-`v2vGe zBY2I;pyQr~1z3jiD#Lg^CBRagP7_+LH{k=LjIM%-+!p`qL0@Z!tjBV zCRNoKa332F00mG2muqdW0$89{mBSp@$(v0^B^T8T33dWYw7~fLb@{A2JasbEtfD>O z{Bn!x{^oKfykP|C9bYA=bI^z@D;50gw9r<<=jsy797e?)>**8v+)&7mFP~UmcjnZ z6y`V-0DS?kfH?VS&TpInz5tXMYXA-{!N11>Sz8OdTuV=es{5lau>2DXh-3ZQcYyO- z<<}Wntk>RMbLgrkGgStcW1=#oGKd1nl32}lPH5IYEdRo(uYaCx1(?($UT2TNJ9vG* zR|5>DKmA$8@MwI45EybN{sBb>g=bUT=~e&$002ovPDHLkV1mVsaPLYNU05R@qp0#P9ik}wkp$-}Pus@{iJ_kO(}?*8)MtJbbvYyWDkwRi2` zh&Cr>Ww0^;0LY#`b=)2R!1XBvNK34X^KtX{>jH+_pEL(vcc^mLjg3TW#}nzTVq;_D z{{DWkSWISzZU+E`?9<2193vn7aQhUWzjveJvN)FR!VK;EK=f2%78?xQS2I(yBy3JU z*#4yeJXrd`qTsF{-*!W0(40mr{Uc?5?KDscvh7FX37S!+ZiNmE!&cs7-cUAz0c8Q@ z?jmWqKH&T)WP53|gDihmN)WLEhisV($*RZSSCN6a$xox@6#!%^ZkIgu8Y4i1gHkAX ztEDWhsLe)Q7HvJ!vR>-J^7 zkRTn*_m%jgq@=`Or7F`bR-KjNGx@bu5Q-Ffh8OkblC%B!zzbxE@*~fbOoST9P*HHk(QT$Nx(tYhM+Ot`2_dC zVa({&SagPB7gg4ldYdYl;Rl5eNj`xbZy2AEa#BjLgJpg{vF00%Qfx~TRrW{`8NbR^ zL5C?Xo{Hw>X8sfOYq4Jkzy80{?PE8xvrQOu}JPAUL;3Y-NCuyXkwuzrTVGEyG8x&Qsvqx2E0Wl4%mI%G|9SM!mR zgnxT5i6pv#GP2k3F2H3x#_M>F6K`e*qCYBZ($#BNhp^{dTqg$bgZrdDXX2b{PXjN& z$3Qk&q7B>lr`EOGO$DI80Ph4Zgm|_3-fp^va;$nb#*t(|`lQrNak=)u*8=ESZmt`X zHOze^+m3uu{0PSW8wqiC9&D2Jey%jVGf>nUVDtuEUdv&522_|nm*U$$EI$~0LFrU% zJ}~@k*&J-UW;l;&7#z~(q78E92Jgub5F1jtnv91dAJhvmyK4oR7xoVhUucsinRDw1%+1zASe$3$Cs?jqWgxR2=>tHor+3cNL2D#dDw6` zE_1t>?{&TP`vG^HSrqDXb9QS$&nR*QGFI6wG=p!T)XUC(Eq=_#j4*8Pjm&$SDo;%7 zTp}e9+1O~=b3PK+JD?=LzWIJz)n14rg<25E{C;ffv^>g0WXHy~;)K7nN2Qu@r$;I^^mGT#2m<#xRD-{N>dw zYXCJO##&ohRh89L^~_C+BdkDsSdo1ZV)SR|S%2ZjrDxdykMb=*VjAmKa@H9@_)xVy ziTenD$p;NAq4_exaEOgAB+{!)nG4brM5!NBP?({naMnh_G;bUk)!6PRu-&~LtMj0g z@}ft`Q`4-JnmzF<@g z2(BOrq13FsWD0jma&!&}^jU!i`y@}nDdF*I;OhnK6q0}td4t{E-KNaXS?T{S8~>TG zeyIBEJ7@!#tL*KHI{*nn^zi=r`G7Xf>7Txm9$nyuopv@GgG)PGvR@>K?~byxB@lz)2P%D33GFHyr~7D~u7Y z1V!J_*-vc?yriOfB?`BaJhPycU%`|l0<6Y6rWfk=;-bgy*f1ALmD=TnHRZ=00U@1k zruJlQ?b6+h+dmy1l~py_wQFP|oG(jT$MZUHE{iCPVtUog1+MtxJWLd>SXKb)HlQbD zoLQTF2GAjOP04SjA^2JO9wyf=r9wq>x)E9mR64_pH$M&y#eS#`oXh+p(l|!K*O)-7}2EJjHHr(j3j&r6E=DXT5d z;|OSQ4^8xn6|qzX6Md3eI^MskbB(a;fnOuosrEESqhmPn)>*8JG(JpCSYuDoTan=J&$*e@1 zsOzAf?GP=NGu{wP#uOQ<8H;q2Rpg*h-6Pn0Z^T-MBh#}-UJ1URudyF!(rE50bduP6 zZ^<2u6h!YIv#2$ih_M^Hn%(X>=Os&#i|k>}u{`>Z$dF?7ETJ6z!y29@{l{)L@8&?p zXEaq6j+lHk2s$K0ynhC~#`BPDp(<hC5?JIsd9 z2Jjictw+6#aBWU+(RDgB7t$H&|eU;8kQ1Z@~vflum}#vkxxQH z{uc>A^b<#kqBeQ|*2{TI)$nVeba2iN_KR)c0ARIYhk<)~Y@If#I6B|drLLquF;V!;3YxxYO>RirJhq&erMW1Fi)blS`7j9lhEdz+P?pALt{Bg`M+P zubM3(yMdXK4Mc8%KbK;e83@orKm=L+xpfksEx$mM0?G9K+bMa-d%bg z_|x3wbfCx{hZs`bga4~R*OBG3!`Jzb`yZA~;#n|YigMU5MhQHK? z)^sTE0D~~QLC~b{&{FLeV8Y@R@JwL{C3DJ6Nk(`5z2GxzB+9ixy4##Q#-o)(lteR> z7Z`x3-a?;676+;NA1?Rkk>t;N=IfR!Buv(PGz~QO_bn5=Yzlt}@7jt1UUhSq;UD@c zbo3O`$WXxj)TRz{(rmi2l|`W2ZaYmuy3* zbs^CVy|#}tYN-mT9X!{Y5>RJh%U8i-@$BCS0t?b{v!~0vZYkb`T1zR~n9cw?z}{E1 zMC<77?+qP!nW2A&C*7rdWHw;?MPMnESbbSz3jfiJO9bW-)zH{i?Z=%^x(=|b84Fuj z@p;9B)B?t2>D0v+@9-z?vs&$~g9Y z@Gc8At2kC9N^&4e3~h4POIy~XZe-QX4n4vWED`3sCjCMbdtn$qwuj}?>f61Bg>8j`Z#YYqlI3TLiOTs#r_+ysUyQ`;sBa=81%RX6^Sx0q z_(qz^S$T&>+Br>Gj>=BP3@gMfv9G}t7ha=@T}`Uz@wf{}2C};o|@R literal 4433 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, 0); StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMap); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Util_Warp_SelectMap; } @@ -2033,7 +2033,7 @@ static void DebugAction_Util_Warp_SelectMap(u8 taskId) GetMapName(gStringVar2, Overworld_GetMapHeaderByGroupAndId(gTasks[taskId].tMapGroup, gTasks[taskId].tInput)->regionMapSectionId, 0); StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectMap); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -2045,7 +2045,7 @@ static void DebugAction_Util_Warp_SelectMap(u8 taskId) StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectWarp); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Util_Warp_SelectWarp; } else if (JOY_NEW(B_BUTTON)) @@ -2076,7 +2076,7 @@ static void DebugAction_Util_Warp_SelectWarp(u8 taskId) StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); StringExpandPlaceholders(gStringVar4, sDebugText_Util_WarpToMap_SelectWarp); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -2236,7 +2236,7 @@ static void DebugAction_Util_Weather(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, 2); StringCopyPadded(gStringVar1, sWeatherNames[0], CHAR_SPACE, 30); StringExpandPlaceholders(gStringVar4, sDebugText_Util_Weather_ID); - AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Util_Weather_SelectId; gTasks[taskId].tSubWindowId = windowId; @@ -2282,7 +2282,7 @@ static void DebugAction_Util_Weather_SelectId(u8 taskId) StringCopyPadded(gStringVar1, sDebugText_WeatherNotDefined, CHAR_SPACE, 30); StringExpandPlaceholders(gStringVar4, sDebugText_Util_Weather_ID); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -2445,7 +2445,7 @@ static void DebugAction_FlagsVars_Flags(u8 taskId) StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15); StringCopy(gStringVar3, gText_DigitIndicator[0]); StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Flag); - AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_FlagsVars_FlagsSelect; gTasks[taskId].tSubWindowId = windowId; @@ -2506,7 +2506,7 @@ static void DebugAction_FlagsVars_FlagsSelect(u8 taskId) StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15); StringCopy(gStringVar3, gText_DigitIndicator[gTasks[taskId].tDigit]); StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Flag); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } } @@ -2534,7 +2534,7 @@ static void DebugAction_FlagsVars_Vars(u8 taskId) StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringCopy(gStringVar2, gText_DigitIndicator[0]); StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Variable); - AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_FlagsVars_Select; gTasks[taskId].tSubWindowId = windowId; @@ -2586,7 +2586,7 @@ static void DebugAction_FlagsVars_Select(u8 taskId) //Combine str's to full window string StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_Variable); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -2606,7 +2606,7 @@ static void DebugAction_FlagsVars_Select(u8 taskId) StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_VariableValueSet); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].data[6] = gTasks[taskId].data[5]; //New value selector gTasks[taskId].func = DebugAction_FlagsVars_SetValue; @@ -2674,7 +2674,7 @@ static void DebugAction_FlagsVars_SetValue(u8 taskId) StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); StringExpandPlaceholders(gStringVar4, sDebugText_FlagsVars_VariableValueSet); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } } @@ -2960,10 +2960,11 @@ static void DebugAction_Give_Item(u8 taskId) // Display initial item StringCopy(gStringVar2, gText_DigitIndicator[0]); ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); - CopyItemName(1, gStringVar1); + u8* end = CopyItemName(1, gStringVar1); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_ItemID); - AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Item_SelectId; gTasks[taskId].tSubWindowId = windowId; @@ -3005,11 +3006,12 @@ static void DebugAction_Give_Item_SelectId(u8 taskId) } StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - CopyItemName(gTasks[taskId].tInput, gStringVar1); + u8* end = CopyItemName(gTasks[taskId].tInput, gStringVar1); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); StringExpandPlaceholders(gStringVar4, sDebugText_ItemID); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); FreeSpriteTilesByTag(ITEM_TAG); //Destroy item icon FreeSpritePaletteByTag(ITEM_TAG); //Destroy item icon @@ -3031,7 +3033,7 @@ static void DebugAction_Give_Item_SelectId(u8 taskId) ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEM_QUANTITY); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_ItemQuantity); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Item_SelectQuantity; } @@ -3082,7 +3084,7 @@ static void DebugAction_Give_Item_SelectQuantity(u8 taskId) ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEM_QUANTITY); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_ItemQuantity); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -3158,11 +3160,12 @@ static void DebugAction_Give_PokemonSimple(u8 taskId) // Display initial Pokémon StringCopy(gStringVar2, gText_DigitIndicator[0]); - ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, 3); - StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species)); + ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + u8 *end = StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species)); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID); - AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); //Set task data gTasks[taskId].func = DebugAction_Give_Pokemon_SelectId; @@ -3198,11 +3201,12 @@ static void DebugAction_Give_PokemonComplex(u8 taskId) // Display initial Pokémon StringCopy(gStringVar2, gText_DigitIndicator[0]); - ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, 4); - StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species)); + ConvertIntToDecimalStringN(gStringVar3, sDebugMonData->species, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); + u8 *end = StringCopy(gStringVar1, GetSpeciesName(sDebugMonData->species)); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(windowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID); - AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectId; gTasks[taskId].tSubWindowId = windowId; @@ -3247,11 +3251,12 @@ static void DebugAction_Give_Pokemon_SelectId(u8 taskId) } StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - StringCopy(gStringVar1, GetSpeciesName(gTasks[taskId].tInput)); //CopyItemName(gTasks[taskId].tInput, gStringVar1); + u8 *end = StringCopy(gStringVar1, GetSpeciesName(gTasks[taskId].tInput)); //CopyItemName(gTasks[taskId].tInput, gStringVar1); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); - ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 4); + ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonID); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); FreeAndDestroyMonIconSprite(&gSprites[gTasks[taskId].tSpriteId]); FreeMonIconPalettes(); @@ -3270,7 +3275,7 @@ static void DebugAction_Give_Pokemon_SelectId(u8 taskId) ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonLevel); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectLevel; } @@ -3317,7 +3322,7 @@ static void DebugAction_Give_Pokemon_SelectLevel(u8 taskId) ConvertIntToDecimalStringN(gStringVar1, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonLevel); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -3343,7 +3348,7 @@ static void DebugAction_Give_Pokemon_SelectLevel(u8 taskId) StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringCopyPadded(gStringVar2, sDebugText_False, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonShiny); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectShiny; } @@ -3371,7 +3376,7 @@ static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 0); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonShiny); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -3385,7 +3390,7 @@ static void DebugAction_Give_Pokemon_SelectShiny(u8 taskId) StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringCopy(gStringVar1, gNaturesInfo[0].name); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonNature); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectNature; } @@ -3421,7 +3426,7 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId) StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringCopy(gStringVar1, gNaturesInfo[gTasks[taskId].tInput].name); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonNature); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -3435,9 +3440,10 @@ static void DebugAction_Give_Pokemon_SelectNature(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); abilityId = GetAbilityBySpecies(sDebugMonData->species, 0); - StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name); + u8 *end = StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId)); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectAbility; } @@ -3480,9 +3486,10 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); - StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name); + u8 *end = StringCopy(gStringVar1, gAbilitiesInfo[abilityId].name); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId)); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonAbility); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -3495,7 +3502,7 @@ static void DebugAction_Give_Pokemon_SelectAbility(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 2); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_IV_HP); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectIVs; } @@ -3560,7 +3567,7 @@ static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId) StringExpandPlaceholders(gStringVar4, sDebugText_IV_SpDefense); break; } - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } //If A or B button @@ -3619,7 +3626,7 @@ static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId) StringExpandPlaceholders(gStringVar4, sDebugText_IV_SpDefense); break; } - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectIVs; } @@ -3633,7 +3640,7 @@ static void DebugAction_Give_Pokemon_SelectIVs(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_EV_HP); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs; } } @@ -3710,7 +3717,7 @@ static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId) StringExpandPlaceholders(gStringVar4, sDebugText_EV_SpDefense); break; } - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } //If A or B button @@ -3769,7 +3776,7 @@ static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId) StringExpandPlaceholders(gStringVar4, sDebugText_EV_SpDefense); break; } - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs; } @@ -3793,18 +3800,19 @@ static void DebugAction_Give_Pokemon_SelectEVs(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); StringCopyPadded(gStringVar3, gStringVar3, CHAR_SPACE, 15); StringExpandPlaceholders(gStringVar4, sDebugText_EV_HP); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_SelectEVs; } else { StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + u8 *end = StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_0); - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_Move; } @@ -3848,7 +3856,8 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId) } StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + u8 *end = StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); switch (gTasks[taskId].tIterator) @@ -3866,7 +3875,7 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId) StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_3); break; } - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -3900,7 +3909,8 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId) gTasks[taskId].tDigit = 0; StringCopy(gStringVar2, gText_DigitIndicator[gTasks[taskId].tDigit]); - StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + u8 *end = StringCopy(gStringVar1, GetMoveName(gTasks[taskId].tInput)); + WrapFontIdToFit(gStringVar1, end, DEBUG_MENU_FONT, WindowWidthPx(gTasks[taskId].tSubWindowId)); StringCopyPadded(gStringVar1, gStringVar1, CHAR_SPACE, 15); ConvertIntToDecimalStringN(gStringVar3, gTasks[taskId].tInput, STR_CONV_MODE_LEADING_ZEROS, 3); switch (gTasks[taskId].tIterator) @@ -3918,7 +3928,7 @@ static void DebugAction_Give_Pokemon_Move(u8 taskId) StringExpandPlaceholders(gStringVar4, sDebugText_PokemonMove_3); break; } - AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); gTasks[taskId].func = DebugAction_Give_Pokemon_Move; } @@ -4271,7 +4281,7 @@ static void DebugAction_Sound_SE(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, 1, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); StringCopyPadded(gStringVar1, sSENames[0], CHAR_SPACE, 35); StringExpandPlaceholders(gStringVar4, sDebugText_Sound_SFX_ID); - AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); StopMapMusic(); //Stop map music to better hear sounds @@ -4313,7 +4323,7 @@ static void DebugAction_Sound_SE_SelectId(u8 taskId) 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, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) @@ -4353,7 +4363,7 @@ static void DebugAction_Sound_MUS(u8 taskId) ConvertIntToDecimalStringN(gStringVar3, START_MUS, STR_CONV_MODE_LEADING_ZEROS, DEBUG_NUMBER_DIGITS_ITEMS); StringCopyPadded(gStringVar1, sBGMNames[0], CHAR_SPACE, 35); StringExpandPlaceholders(gStringVar4, sDebugText_Sound_Music_ID); - AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 1, 1, 0, NULL); + AddTextPrinterParameterized(windowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); StopMapMusic(); //Stop map music to better hear new music @@ -4395,7 +4405,7 @@ static void DebugAction_Sound_MUS_SelectId(u8 taskId) 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, 1, 1, 0, NULL); + AddTextPrinterParameterized(gTasks[taskId].tSubWindowId, DEBUG_MENU_FONT, gStringVar4, 0, 0, 0, NULL); } if (JOY_NEW(A_BUTTON)) diff --git a/src/fonts.c b/src/fonts.c index fba0dfb7a6..853f6fbde2 100644 --- a/src/fonts.c +++ b/src/fonts.c @@ -185,19 +185,19 @@ ALIGNED(4) const u8 gFontNarrowerLatinGlyphWidths[] = { 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 8, 4, 4, 4, 5, 5, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 5, 8, 6, 6, 3, - 3, 3, 3, 3, 8, 8, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 8, 8, 2, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3, + 5, 4, 2, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 5, 3, 7, 7, 7, 7, 0, 0, 3, 4, 5, 6, 7, 4, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 3, 5, 3, - 5, 5, 5, 3, 3, 5, 5, 6, 3, 6, 6, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, - 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, + 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 2, 4, 2, + 4, 4, 4, 2, 2, 4, 4, 6, 2, 5, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, - 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 8, 3, 3, 3, 3, + 2, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 8, 3, 3, 3, 3, 10, 10, 10, 10, 8, 8, 10, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, @@ -221,19 +221,19 @@ ALIGNED(4) const u8 gFontSmallNarrowerLatinGlyphWidths[] = { 3, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 5, 4, 4, 4, 5, 4, 4, 4, 3, 4, 4, 4, 4, 4, 3, 3, 4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 4, 7, 5, 6, 3, - 3, 3, 3, 3, 8, 0, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 8, 0, 2, 3, 7, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 5, 4, 3, 7, 7, 7, 8, 8, 8, 8, 4, 5, 4, 4, 3, 3, + 5, 4, 2, 7, 7, 7, 8, 8, 8, 8, 4, 7, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 5, 3, 8, 8, 8, 8, 0, 0, 3, 4, 5, 6, 7, 4, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 3, 4, 4, - 5, 5, 5, 3, 3, 5, 5, 5, 4, 5, 5, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 4, 5, 4, 4, 4, 4, 4, 4, 4, + 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 2, 4, 2, + 4, 4, 4, 2, 2, 4, 4, 8, 2, 8, 5, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 3, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 7, - 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 8, 3, 3, 3, 3, + 2, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 8, 3, 3, 3, 3, 8, 8, 8, 8, 8, 7, 8, 7, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, @@ -293,19 +293,19 @@ ALIGNED(4) const u8 gFontShortNarrowerLatinGlyphWidths[] = { 1, 4, 4, 4, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 8, 4, 4, 4, 5, 5, 4, 4, 3, 4, 4, 4, 4, 4, 4, 3, 4, 4, 4, 4, 4, 6, 4, 4, 4, 5, 4, 5, 8, 6, 6, 3, - 3, 3, 3, 3, 8, 8, 3, 5, 5, 3, 3, 3, 3, 3, 3, 3, + 3, 3, 3, 3, 10, 8, 5, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 3, 3, 3, 3, 3, 3, 3, - 5, 5, 4, 8, 8, 8, 7, 8, 8, 4, 4, 6, 4, 4, 3, 3, + 6, 6, 6, 8, 8, 8, 8, 8, 8, 4, 6, 8, 5, 5, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 4, 3, 3, 3, 3, 3, 3, 3, 5, 3, 7, 7, 7, 7, 0, 0, 3, 4, 5, 6, 7, 4, 6, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, - 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 5, 3, 5, 3, - 5, 5, 5, 3, 3, 5, 5, 6, 3, 6, 6, 4, 4, 4, 4, 4, - 4, 4, 4, 4, 4, 4, 4, 5, 5, 4, 4, 4, 4, 4, 4, 4, - 4, 5, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, + 7, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 6, 6, 5, 4, 5, + 6, 6, 6, 3, 3, 6, 6, 8, 3, 9, 6, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, + 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 4, 4, 2, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 8, - 4, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, + 5, 4, 4, 4, 4, 4, 4, 3, 3, 3, 3, 3, 3, 3, 3, 3, 10, 10, 10, 10, 8, 8, 10, 8, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 10, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, diff --git a/src/item_menu.c b/src/item_menu.c index d885f0a8ec..eae1c17eab 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -910,7 +910,7 @@ static void GetItemName(u8 *dest, u16 itemId) { case TMHM_POCKET: end = StringCopy(gStringVar2, GetMoveName(ItemIdToBattleMoveId(itemId))); - PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 73); + PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 61); if (itemId >= ITEM_HM01) { // Get HM number @@ -927,7 +927,7 @@ static void GetItemName(u8 *dest, u16 itemId) case BERRIES_POCKET: ConvertIntToDecimalStringN(gStringVar1, itemId - FIRST_BERRY_INDEX + 1, STR_CONV_MODE_LEADING_ZEROS, 2); end = CopyItemName(itemId, gStringVar2); - PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 73); + PrependFontIdToFit(gStringVar2, end, FONT_NARROW, 61); StringExpandPlaceholders(dest, gText_NumberItem_TMBerry); break; default: diff --git a/test/text.c b/test/text.c index 17d9ab0ee9..ed343d1039 100644 --- a/test/text.c +++ b/test/text.c @@ -44,7 +44,7 @@ TEST("Move names fit on Battle Screen") TEST("Move names fit on Contest Screen") { u32 i; - const u32 fontId = FONT_NARROWER, widthPx = 61; + const u32 fontId = FONT_NARROWER, widthPx = 59; u32 move = MOVE_NONE; for (i = 1; i < MOVES_COUNT; i++) { @@ -53,7 +53,9 @@ TEST("Move names fit on Contest Screen") // All moves explicitly listed here are too big to fit. switch (move) { + case MOVE_STOMPING_TANTRUM: case MOVE_NATURES_MADNESS: + case MOVE_DOUBLE_IRON_BASH: EXPECT_GT(GetStringWidth(fontId, gMovesInfo[move].name, 0), widthPx); break; default: @@ -65,14 +67,11 @@ TEST("Move names fit on Contest Screen") TEST("Move names fit on TMs & HMs Bag Screen") { u32 i; - const u32 fontId = FONT_NARROWER, widthPx = 63; + const u32 fontId = FONT_NARROWER, widthPx = 61; u32 move = MOVE_NONE; - for (i = 1; i < ITEMS_COUNT; i++) + for (i = 1; i < MOVES_COUNT; i++) { - if (gItemsInfo[i].pocket == POCKET_TM_HM) - { - PARAMETRIZE_LABEL("%S", gMovesInfo[gItemsInfo[i].secondaryId].name) { move = gItemsInfo[i].secondaryId; } - } + PARAMETRIZE_LABEL("%S", gMovesInfo[i].name) { move = i; } } EXPECT_LE(GetStringWidth(fontId, gMovesInfo[move].name, 0), widthPx); } @@ -105,7 +104,7 @@ TEST("Item names fit on Bag Screen (list)") { u32 i; const u32 fontId = FONT_NARROWER; - const u32 tmHmBerryWidthPx = 71, restWidthPx = 88; + const u32 tmHmBerryWidthPx = 61, restWidthPx = 88; u32 item = ITEM_NONE; for (i = 1; i < ITEMS_COUNT; i++) { @@ -122,7 +121,7 @@ TEST("Item plural names fit on Bag Screen (left box)") { u32 i; // -6 for the question mark in FONT_NORMAL. - const u32 fontId = FONT_NARROWER, widthPx = 102 - 6; + const u32 fontId = FONT_NARROWER, widthPx = 101 - 6; u32 item = ITEM_NONE; u8 pluralName[ITEM_NAME_PLURAL_LENGTH + 1]; for (i = 1; i < ITEMS_COUNT; i++) @@ -133,6 +132,18 @@ TEST("Item plural names fit on Bag Screen (left box)") EXPECT_LE(GetStringWidth(fontId, pluralName, 0), widthPx); } +TEST("Item names fit on PC Storage (list)") +{ + u32 i; + const u32 fontId = FONT_NARROWER, widthPx = 73; + u32 item = ITEM_NONE; + for (i = 1; i < ITEMS_COUNT; i++) + { + PARAMETRIZE_LABEL("%S", gItemsInfo[i].name) { item = i; } + } + EXPECT_LE(GetStringWidth(fontId, gItemsInfo[item].name, 0), widthPx); +} + TEST("Item plural names fit on PC storage (left box)") { u32 i; @@ -151,108 +162,22 @@ TEST("Item plural names fit on PC storage (left box)") TEST("Item names fit on Pokemon Storage System") { u32 i; - const u32 fontId = FONT_SMALL_NARROWER, widthPx = 50; + const u32 fontId = FONT_SMALL_NARROWER, widthPx = 66; u32 item = ITEM_NONE; for (i = 1; i < ITEMS_COUNT; i++) { if (gItemsInfo[i].importance) continue; PARAMETRIZE_LABEL("%S", gItemsInfo[i].name) { item = i; } } - // All items explicitly listed here are too big to fit. The ones - // with a hold effect are listed at the bottom in case you want to - // focus on making them fit (they are the most likely to appear on - // the storage system UI, along with anything that could be held - // in the wild). + // All items explicitly listed here are too big to fit. switch (item) { - case ITEM_ENERGY_POWDER: - case ITEM_PEWTER_CRUNCHIES: - case ITEM_RAGE_CANDY_BAR: - case ITEM_LUMIOSE_GALETTE: - case ITEM_HEALTH_FEATHER: - case ITEM_MUSCLE_FEATHER: - case ITEM_RESIST_FEATHER: - case ITEM_GENIUS_FEATHER: - case ITEM_CLEVER_FEATHER: - case ITEM_ABILITY_CAPSULE: - case ITEM_DYNAMAX_CANDY: - case ITEM_MAX_MUSHROOMS: - case ITEM_GOLD_BOTTLE_CAP: - case ITEM_PRETTY_FEATHER: - case ITEM_STRANGE_SOUVENIR: - case ITEM_FOSSILIZED_BIRD: - case ITEM_FOSSILIZED_FISH: - case ITEM_FOSSILIZED_DRAKE: - case ITEM_FOSSILIZED_DINO: - case ITEM_SURPRISE_MULCH: - case ITEM_YELLOW_APRICORN: - case ITEM_GREEN_APRICORN: - case ITEM_WHITE_APRICORN: - case ITEM_BLACK_APRICORN: - case ITEM_THUNDER_STONE: - case ITEM_GALARICA_WREATH: - case ITEM_STRAWBERRY_SWEET: - case ITEM_AUSPICIOUS_ARMOR: - case ITEM_BIG_BAMBOO_SHOOT: - case ITEM_GIMMIGHOUL_COIN: - case ITEM_LEADERS_CREST: - case ITEM_MALICIOUS_ARMOR: - case ITEM_TINY_BAMBOO_SHOOT: - case ITEM_BUG_TERA_SHARD: - case ITEM_DARK_TERA_SHARD: - case ITEM_DRAGON_TERA_SHARD: case ITEM_ELECTRIC_TERA_SHARD: - case ITEM_FAIRY_TERA_SHARD: case ITEM_FIGHTING_TERA_SHARD: - case ITEM_FIRE_TERA_SHARD: - case ITEM_FLYING_TERA_SHARD: - case ITEM_GHOST_TERA_SHARD: - case ITEM_GRASS_TERA_SHARD: - case ITEM_GROUND_TERA_SHARD: - case ITEM_ICE_TERA_SHARD: - case ITEM_NORMAL_TERA_SHARD: - case ITEM_POISON_TERA_SHARD: case ITEM_PSYCHIC_TERA_SHARD: - case ITEM_ROCK_TERA_SHARD: - case ITEM_STEEL_TERA_SHARD: - case ITEM_WATER_TERA_SHARD: - case ITEM_BLACK_AUGURITE: case ITEM_UNREMARKABLE_TEACUP: case ITEM_MASTERPIECE_TEACUP: - case ITEM_FRESH_START_MOCHI: - case ITEM_STELLAR_TERA_SHARD: - case ITEM_JUBILIFE_MUFFIN: - case ITEM_SUPERB_REMEDY: - case ITEM_AUX_POWERGUARD: - case ITEM_CHOICE_DUMPLING: case ITEM_TWICE_SPICED_RADISH: - // Items with hold effects: - case ITEM_ELECTRIC_MEMORY: - case ITEM_FIGHTING_MEMORY: - case ITEM_GROUND_MEMORY: - case ITEM_PSYCHIC_MEMORY: - case ITEM_DRAGON_MEMORY: - case ITEM_CHARIZARDITE_X: - case ITEM_CHARIZARDITE_Y: - case ITEM_ULTRANECROZIUM_Z: - case ITEM_DEEP_SEA_SCALE: - case ITEM_DEEP_SEA_TOOTH: - case ITEM_NEVER_MELT_ICE: - case ITEM_WEAKNESS_POLICY: - case ITEM_SAFETY_GOGGLES: - case ITEM_ADRENALINE_ORB: - case ITEM_TERRAIN_EXTENDER: - case ITEM_PROTECTIVE_PADS: - case ITEM_HEAVY_DUTY_BOOTS: - case ITEM_UTILITY_UMBRELLA: - case ITEM_MARANGA_BERRY: - case ITEM_PUNCHING_GLOVE: - case ITEM_BOOSTER_ENERGY: - case ITEM_ADAMANT_CRYSTAL: - case ITEM_LUSTROUS_GLOBE: - case ITEM_CORNERSTONE_MASK: - case ITEM_WELLSPRING_MASK: - case ITEM_HEARTHFLAME_MASK: EXPECT_GT(GetStringWidth(fontId, gItemsInfo[item].name, 0), widthPx); break; default: @@ -398,7 +323,7 @@ TEST("Species names fit on Pokemon Storage System") } } EXPECT_LE(GetStringWidth(FONT_NARROWER, gSpeciesInfo[species].speciesName, 0), 66); - EXPECT_LE(GetStringWidth(FONT_SHORT_NARROW, gSpeciesInfo[species].speciesName, 0), 60); + EXPECT_LE(GetStringWidth(FONT_SHORT_NARROWER, gSpeciesInfo[species].speciesName, 0), 60); } TEST("Species names fit on Contest Screen") @@ -434,7 +359,7 @@ TEST("Species names fit on Contest Screen - Rankings") TEST("Species names fit on Battle Dome Screen") { u32 i; - const u32 fontId = FONT_SHORT_NARROW, widthPx = 60; + const u32 fontId = FONT_SHORT_NARROWER, widthPx = 60; u32 species = SPECIES_NONE; for (i = 1; i < NUM_SPECIES; i++) { From fd397e9e1c2878111ce33484c1f76a000d9d0388 Mon Sep 17 00:00:00 2001 From: RavePossum <145081120+ravepossum@users.noreply.github.com> Date: Sun, 8 Dec 2024 05:07:19 -0500 Subject: [PATCH 13/26] Fix move category and category icon when PSS is off (#5786) --- src/battle_controller_player.c | 3 +-- src/battle_util.c | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/battle_controller_player.c b/src/battle_controller_player.c index 3396999487..00e73735e8 100644 --- a/src/battle_controller_player.c +++ b/src/battle_controller_player.c @@ -1759,7 +1759,6 @@ static void MoveSelectionDisplayMoveDescription(u32 battler) u16 move = moveInfo->moves[gMoveSelectionCursor[battler]]; u16 pwr = gMovesInfo[move].power; u16 acc = gMovesInfo[move].accuracy; - u8 cat = gMovesInfo[move].category; u8 pwr_num[3], acc_num[3]; u8 cat_desc[7] = _("CAT: "); @@ -1796,7 +1795,7 @@ static void MoveSelectionDisplayMoveDescription(u32 battler) if (gCategoryIconSpriteId == 0xFF) gCategoryIconSpriteId = CreateSprite(&gSpriteTemplate_CategoryIcons, 38, 64, 1); - StartSpriteAnim(&gSprites[gCategoryIconSpriteId], cat); + StartSpriteAnim(&gSprites[gCategoryIconSpriteId], GetBattleMoveCategory(move)); CopyWindowToVram(B_WIN_MOVE_DESCRIPTION, COPYWIN_FULL); } diff --git a/src/battle_util.c b/src/battle_util.c index 3aaa756e44..9cb4da700b 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -11212,7 +11212,7 @@ u8 GetBattleMoveCategory(u32 moveId) if (IS_MOVE_STATUS(moveId)) return DAMAGE_CATEGORY_STATUS; - return gTypesInfo[GetMoveType(gCurrentMove)].damageCategory; + return gTypesInfo[GetMoveType(moveId)].damageCategory; } static bool32 TryRemoveScreens(u32 battler) From 8088547334640b342a8fafd14a1c9c9b04555b69 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 8 Dec 2024 11:09:36 +0100 Subject: [PATCH 14/26] Palette cleanup (#5661) Co-authored-by: Hedara --- .../battle_anims/sprites/attack_order.png | Bin 1252 -> 545 bytes graphics/battle_anims/sprites/aura_sphere.png | Bin 1086 -> 302 bytes graphics/battle_anims/sprites/blue_flare.pal | 242 +----------------- .../battle_anims/sprites/dragon_pulse.png | Bin 930 -> 223 bytes graphics/battle_anims/sprites/embers.png | Bin 1334 -> 557 bytes graphics/battle_anims/sprites/fly.png | Bin 1172 -> 465 bytes .../battle_anims/sprites/horn_hit_new.png | Bin 1010 -> 286 bytes graphics/battle_anims/sprites/mean_look.png | Bin 1144 -> 344 bytes graphics/battle_anims/sprites/poison_jab.png | Bin 912 -> 205 bytes graphics/battle_anims/sprites/power_gem.png | Bin 905 -> 198 bytes graphics/battle_anims/sprites/psycho_cut.png | Bin 922 -> 215 bytes .../battle_anims/sprites/stealth_rock.png | Bin 926 -> 219 bytes graphics/battle_anims/sprites/stone_edge.png | Bin 1181 -> 474 bytes graphics/battle_anims/sprites/wood_hammer.png | Bin 1549 -> 842 bytes 14 files changed, 1 insertion(+), 241 deletions(-) diff --git a/graphics/battle_anims/sprites/attack_order.png b/graphics/battle_anims/sprites/attack_order.png index 18531b8304514c66d315a403a50cca37d8e82644..624708545e28f16adf325c0f0d4c577523c18db4 100644 GIT binary patch delta 62 zcmaFDxsYXoGCu=jage(c!@6@aFBupZ3?{0Y@U2O7{lmb(IN#I7F~p;DvpMrzMuGAe RP8py)gQu&X%Q~loCICO|5widQ delta 408 zcmZ3;@`Q7OG7~eyL?e@l32dW?4k5tz&E@AG1_s9Yo-U3d6>~P0%w-ga`aUI^0SG)@ L{an^LB{Ts5Sk;6g diff --git a/graphics/battle_anims/sprites/aura_sphere.png b/graphics/battle_anims/sprites/aura_sphere.png index 04c5030245573d73d59f3b99bae5317afb74c2b4..4ee16cd4881370980bf132e560c032c5278d2eeb 100644 GIT binary patch delta 213 zcmV;`04o2!2(AKL_t(Ijg6Dx4uv2HMp>{mG_(XCx7hiL8>cOQCSb$|%)*T?ggO4o@DFii6o5|ziWzNf416F^ zcouHnaZ}7t>k*D25EMd)Tn(*0rpX0ef$kvkW{7RE66AwGdqF-3^dd>5b?SA1@Kz{& zic*vHVSZSC*u`;=LfSBEM~0RQJ-ak*axb*)`^u~PAwD4IQgIpi4%3AH^jZ?(gxjt# P00000NkvXXu0mjfh5=mQ literal 1086 zcmeAS@N?(olHy`uVBq!ia0vp^3LwnE3?yBabR7dyjKx9jP7LeL$-D$|SkfJR9T^xl z_H+M9WMyDrW(e>JaRrM1`0?Y!j~_FB{K)w6!{Wye4j?-5gJZ@Ij*K517C$&RfG7i~ zY!r-!!0-zJk*s~jKwohdctjR6Fz_7)VaDV6D^h@h$30yfLoEDTCoyt08wjvCYi{}V zpZ$B;H=jP2%L}9SN-j!>dT3)Q*{{W;EC1z#P*YhwSR5D?JyCqipQ%$oVT*#g%{tEmXw$=&%S zd}Ge7Efc=q`&PJ>g|oQx&uqujKWv(LcASblC=^_hZT}@o=wbYfFK0oq=jrO_vd$@? F2>|#Hjtu|+ diff --git a/graphics/battle_anims/sprites/blue_flare.pal b/graphics/battle_anims/sprites/blue_flare.pal index 3b224c3459..87bb2254a3 100644 --- a/graphics/battle_anims/sprites/blue_flare.pal +++ b/graphics/battle_anims/sprites/blue_flare.pal @@ -1,6 +1,6 @@ JASC-PAL 0100 -256 +16 0 0 0 248 248 248 205 248 255 @@ -17,243 +17,3 @@ JASC-PAL 238 238 238 189 189 189 156 164 164 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 -0 0 0 diff --git a/graphics/battle_anims/sprites/dragon_pulse.png b/graphics/battle_anims/sprites/dragon_pulse.png index cc6e28bc328092c6fdc8cdd6d5f1ce5b6908745e..5a1f62321f0f6435d05afbe5d059b70995ab32d3 100644 GIT binary patch delta 61 zcmZ3)exGrIGCu=jage(c!@6@aFBupZ3?{0Y@Trs8|P)z4*}Q$iB}A*2#U literal 930 zcmeAS@N?(olHy`uVBq!ia0vp^3P3Et!3-oF?)7FfFfcO&_=LFrVE6$NaX65W@L|J- z4ILdFK<+3Q4S^970vhp>kwCA;db&7F_7mdKI;Vst0Py2Kxc~qF diff --git a/graphics/battle_anims/sprites/embers.png b/graphics/battle_anims/sprites/embers.png index 8bf2dd5aa6c2633c32e509bcb78a84641516ee53..c5799e7160bff96f4bcdc27178aec209d5983acc 100644 GIT binary patch delta 475 zcmV<10VMvm3atc?ED4T$`%#ks001zNH8g)hH(4D300F2;L_t(oh3#0;a>O7A%!4zC z`~Ux26peNQ*j{_nKFI6tkwn=A?z&D`0c`M6LIw(RltX^c%s~!GkaIw&I8ner$&`{X z-bvWJ!v&7NLJw+ll-OOyi4)(7T}6pH!)4}hmlftFGDTJzAP=KQ7}$fVTJ{t_|@2{8*#q? zddqPbz}=cnMpqvhy1Vh*)or%ksZK+g*KDil*8iibV?rMuR$;v&|34M1MG6B0;~7sE$B+p3w=)jrF&PRtf8P*fw)_A8{Ws<@GR~ao z5gH!zNciab%M)%e?$T}DrB^@Uh1K~u(E&1c`y=p^d=Dx)YFSdsXT(8_x%U-B% z5P7)l>#xuZx0lTge;!`CRG%?TW6S0eF7@ z`F^|UukHHacBVQ@ZGAQ$XKUX?scQ9$;lJ0ED<^)Qd27MU2~YpceAO_6G3wyzsA+%r zo0ykf{cU>Sz1)qb)BEe{e@Qh;x>U#286OO{H~cO@L}o+o(u28TV^%-YiK534a_Zacq-GK&6My| zmqBn%-4A^(#u(;sNk*kp`VzM?Z*Jso;wZQJ=(#5CU*PR;49@xLo}V^#9s?y}Pgg&e IbxsLQ0Go0NhX4Qo diff --git a/graphics/battle_anims/sprites/fly.png b/graphics/battle_anims/sprites/fly.png index dd1149de9937b3be65a8ba4f8951cbdc0c36bee3..ff648a6e2ebb87b4fbaf0f71d4c376bb0317870b 100644 GIT binary patch delta 62 zcmbQjd69X7GCu=jage(c!@6@aFBupZ3?{0Y@Lk;h;tT@=qraz%V@O2nW^-m=MgiUB R{SSfi44$rjF6*2UngCo=6F>j} literal 1172 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+yeRz|0Wf6XLpHLdTCEKN@a4$hdGL z;=%)i0~aJ3CI~oqyjbw!2g8pW0XHr%TKz56Auyamz|Pg~GXn#ozo(01 zNX4AD(+&zXEAY6OI{f%=pC`mp=q0q^^6cAkw^shXljHWba8K3O@TY#!??h%@GE!!C z;9sy_yJgN{htHZXz9=6k>6&xtgn#oANrz`26X!G@pK&sup^1IM=lN^)@|e_Z++5aG z!KAde>k)H;fI!~=N}&Z^c6WKU{NZ<4uXj{#fntL61r9BSpR*XRo;T%C(qvg8${@Sw z7ptSPO6viJILR0PDsqDu1?Jo{*tSi|;chcSQ)<3#R>K3e2Z|5Avz$^2d~osg0j~oE z)(5wG6t{Hh&QQLgYN2dkQ)N0!_0-Px#Fp(uRf9?c%NdN!z(@PG; zAP7Lw4hb6F|86Ttkx#XgH+W3%iM9z|*M2I^DI>PF1C{dVub^se4HFmxCa^sp@eANP13UsJ z7=%q=Ie-g51WpjhyJkcw`2ZDU26)}(`K8FKu~~P1DwGfJngtZY91MJ{mi zw_V?yZI<^$Xup+rd*|&CmhBo9GU25ya)R007oWL_t(oh3%Bf4uc>NMJ)`MrT_o8MMY!N zd0f*)H*;1ba1JD(%aSBX64Gz{BtMU6Hs7#qsuAfyg3+CXva;@wiSJdVlxiiI?Oy}C z&?%oSD6_qM2DC!={4;ySl2mle7$gZ7iz$Ni-`R2W55$%O<*RV z_}mX+BsQ4so$KIrHsR<@BG7{dW7`ehRw9q(BuSD#@CLn^A#mrtx-kF%002ovPDHLk FV1k*JcGCa= literal 1144 zcmeAS@N?(olHy`uVBq!ia0vp^4j|0I3?%1nZ+ru!7>k44ofy`glX(f`u%tWsIx;Y9 z?C1WI$jZRL%n;xc;`)Q(2N*DXxWI5>2g8C13<(JW8X6iv^`l@k1crSGBguM`2ddawf`m;2}F z>G+K%Eq6Zs6-~0Q`^XiPSz)*3neg+8-?=Q0N>nz+^mTqd@mHuw>(SjKRol3;>aI=r zR9l>|=Ifrj7mE2eH&h&T3E~Z#ry=3B=%H=Afw+}=)Zqja PVPNod^>bP0l+XkK9GMXN literal 912 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4m>B|mLR=Xd7%T)VG9)qe85Ol?aTfj;#1ba4!+m@~KETj+oRhtpC1kN?!y zE%UvdbC|D&XYq-RAy?nzpKUJrzvj5cMxi^`x6M?Z<;a}!bB>4m)%gd!*IZ)eXpnno e7h_eQe4X`&5aVva3F1Pafb(?qb6Mw<&;$SwDLtJ4 diff --git a/graphics/battle_anims/sprites/power_gem.png b/graphics/battle_anims/sprites/power_gem.png index 8d9ad469e39e0d64c9e2e409c4a5179bc6d4ffda..439610c71bbdfdaf6b14e2f810d455f0de3b5d8f 100644 GIT binary patch delta 61 zcmeBVKgKvgnV*5NILO_JVcj{ImkbOH1`}0H_*6;_wgTBMo-U3d5>qFeGdl@vHIiNg P6k_mn^>bP0l+XkK`xOva literal 905 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4m>B|mLR^0^`~ZqLI2=ew_^@Ha zhK`O7Aa@juhQJ630gZUcNT63;JY5_^D&|Z*=gq{Rz~UNM^=<#Nn(nljcas?cc^r}t z==iVKyR~Ol#bd8Gvk%;6VcqtZRrtjd$&*JaRhI5uWppcLo7Y#ih3gsJcQ5Ky1O=U^ LtDnm{r-UW|29Gti diff --git a/graphics/battle_anims/sprites/psycho_cut.png b/graphics/battle_anims/sprites/psycho_cut.png index 3eb1de7d2aea2fe98f3edaa17a1965bf7c15904c..f40d21f7064146b4b6f0a1820b6a13f58f15be5b 100644 GIT binary patch delta 61 zcmbQmew}fGGCu=jage(c!@6@aFBupZ3?{0Y@bM?9gTe~DWM4f82%9x literal 926 zcmeAS@N?(olHy`uVBq!ia0vp^0wB!63?wyl`GXl4m>B|mLR>8_C@h%Z(NJKJ5TW2< zAz`2)z`?-*R5J=jLtrF?z%wK9#Xx^Xdb&7&?fY$ioz%d*QeI&9LQllN1XN z3MXg(FMNLaqH^8c^!GQMHfvT3Hz;goy2-=UqEqO_(oyWR)}BM5<;nMB6Qy4@Y-+ip k|1L<+OlRjWqxxSb8P2sb9>2FyRTdPOp00i_>zopr07~aO>;M1& diff --git a/graphics/battle_anims/sprites/stone_edge.png b/graphics/battle_anims/sprites/stone_edge.png index 44f678d8db953314d1507da7cf97123a6356c869..80377da7ee9a910caecfd588ee64b65693cab1b0 100644 GIT binary patch delta 62 zcmbQsd5d|1GCu=jage(c!@6@aFBupZ3?{0Y@SQi_ewu-SF~ZZuF(jgOvpI7Zqd;^? R@^_#-gQu&X%Q~loCICj)5{Uo+ literal 1181 zcmeAS@N?(olHy`uVBq!ia0vp^3P8MogBeIhiOiE@U|?nl@Ck9XxS()iL&Aay9t{Ns z6&V%<2^t9z3JC!k0Uin-77`W)5(XLq3KAR=5)vF796-IJU^E1VQwUsp-*TFPfic3< z#WAE}&f6I$`;I8^xLD`(8J_!WX?TrMLvf^uS-9f3p;)JSsH6; z?X>5N!pEK&#n}-j0%wIUU^AUQf6kxdJqPvl9gXLF?`>z|?JJbr;M}^%tH)!)j-Uw& zM;F+gm=M$w&T6m!@!(Ps(;1RIhFzr_5*&F}HKrN1b(lINO7q=6SMc-X$@I(CJ8f=0 zyfgQEZ#<`z$RVSIb}rAU0uuth|C=-+V6tQFguvicTeMc#oo@{C$`TNiSgihfL04;5 z0Ix~+z3i=Q8aam_-hQcPZ}~Il*%$lSmf6cb@B4V>!i3*(Y;OV@LwDw@Y^iRYc;N=n zMHy#&!&+_rC;3?ax_aTVbdTXpt0jpGB}16cCY`&shLP)b!H=?Kr~UovBAq^bd>SwR zW_`EBL%px6PkPqzZ>p=wa8#?ImI?XnV*5NILO_JVcj{ImkbOH1`}0H_&U_qzGGluI^pT!7!uLC*_`}!PC{xWt~$(697T75;gz; delta 801 zcmX@b*2^pYfAv)|1zR=&J(!YU?#ov%3`fgIuK>gTe~DWM4fpI{+@ From af83503265b2eb6e87068bf57b3457b03b87da34 Mon Sep 17 00:00:00 2001 From: Frank DeBlasio <35279583+fdeblasio@users.noreply.github.com> Date: Mon, 9 Dec 2024 04:15:03 -0500 Subject: [PATCH 15/26] Swapped DESELECT and CHECK_TAG to be in right places (#5794) --- src/item_menu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/item_menu.c b/src/item_menu.c index f9e16e1ef7..75751cae6f 100755 --- a/src/item_menu.c +++ b/src/item_menu.c @@ -280,8 +280,8 @@ static const struct MenuAction sItemMenuActions[] = { [ACTION_BATTLE_USE] = {gMenuText_Use, {ItemMenu_UseInBattle}}, [ACTION_CHECK] = {COMPOUND_STRING("CHECK"), {ItemMenu_UseOutOfBattle}}, [ACTION_WALK] = {COMPOUND_STRING("WALK"), {ItemMenu_UseOutOfBattle}}, - [ACTION_DESELECT] = {COMPOUND_STRING("CHECK TAG"), {ItemMenu_Register}}, - [ACTION_CHECK_TAG] = {COMPOUND_STRING("DESELECT"), {ItemMenu_CheckTag}}, + [ACTION_DESELECT] = {COMPOUND_STRING("DESELECT"), {ItemMenu_Register}}, + [ACTION_CHECK_TAG] = {COMPOUND_STRING("CHECK TAG"), {ItemMenu_CheckTag}}, [ACTION_CONFIRM] = {gMenuText_Confirm, {Task_FadeAndCloseBagMenu}}, [ACTION_SHOW] = {COMPOUND_STRING("SHOW"), {ItemMenu_Show}}, [ACTION_GIVE_FAVOR_LADY] = {gMenuText_Give2, {ItemMenu_GiveFavorLady}}, From 09a8d051d4d530edf43074c324783f8ab13fbde0 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Mon, 9 Dec 2024 12:28:31 +0100 Subject: [PATCH 16/26] Added the missing config to use new terrains (#5792) Co-authored-by: Hedara --- include/config/battle.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/config/battle.h b/include/config/battle.h index b0184838cb..f38be8949c 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -219,6 +219,7 @@ #define B_SECRET_POWER_ANIMATION GEN_LATEST // Secret Power's animations change depending on terrain and generation. #define B_NATURE_POWER_MOVES GEN_LATEST // Nature Power calls different moves depending on terrain and generation. See sNaturePowerMoves. #define B_CAMOUFLAGE_TYPES GEN_LATEST // Camouflage changes the user to different types depending on terrain and generation. See sTerrainToType. +#define B_NEW_TERRAIN_BACKGROUNDS FALSE // If set to TRUE, uses new terrain backgrounds for Electric, Misty, Grassy and Psychic Terrain. // Interface settings #define B_ABILITY_POP_UP TRUE // In Gen5+, the Pokémon abilities are displayed in a pop-up, when they activate in battle. From 5477033a19ee77ac5917e4db38c906fdbfebabfa Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Mon, 9 Dec 2024 05:51:18 -0600 Subject: [PATCH 17/26] Updated Ogerpon, Enamorus and Sinistcha sprites (#5793) --- graphics/pokemon/enamorus/back.png | Bin 841 -> 734 bytes graphics/pokemon/enamorus/front.png | Bin 832 -> 785 bytes graphics/pokemon/enamorus/normal.pal | 20 +-- graphics/pokemon/enamorus/shiny.pal | 24 +-- graphics/pokemon/enamorus/therian/back.png | Bin 710 -> 891 bytes graphics/pokemon/enamorus/therian/front.png | Bin 821 -> 867 bytes graphics/pokemon/enamorus/therian/normal.pal | 28 ++-- graphics/pokemon/enamorus/therian/shiny.pal | 28 ++-- graphics/pokemon/ogerpon/back.png | Bin 447 -> 515 bytes graphics/pokemon/ogerpon/cornerstone/back.png | Bin 537 -> 540 bytes .../pokemon/ogerpon/cornerstone/front.png | Bin 962 -> 947 bytes .../pokemon/ogerpon/cornerstone/normal.pal | 33 ++-- .../pokemon/ogerpon/cornerstone/shiny.pal | 33 ++-- graphics/pokemon/ogerpon/front.png | Bin 1043 -> 1007 bytes graphics/pokemon/ogerpon/hearthflame/back.png | Bin 533 -> 534 bytes .../pokemon/ogerpon/hearthflame/front.png | Bin 958 -> 947 bytes .../pokemon/ogerpon/hearthflame/normal.pal | 32 ++-- .../pokemon/ogerpon/hearthflame/shiny.pal | 32 ++-- graphics/pokemon/ogerpon/normal.pal | 33 ++-- graphics/pokemon/ogerpon/shiny.pal | 33 ++-- graphics/pokemon/ogerpon/wellspring/back.png | Bin 472 -> 534 bytes graphics/pokemon/ogerpon/wellspring/front.png | Bin 960 -> 909 bytes .../pokemon/ogerpon/wellspring/normal.pal | 32 ++-- graphics/pokemon/ogerpon/wellspring/shiny.pal | 32 ++-- graphics/pokemon/sinistcha/back.png | Bin 583 -> 591 bytes graphics/pokemon/sinistcha/front.png | Bin 646 -> 654 bytes graphics/pokemon/sinistcha/normal.pal | 23 +-- graphics/pokemon/sinistcha/shiny.pal | 25 +-- .../pokemon/species_info/gen_8_families.h | 4 +- .../pokemon/species_info/gen_9_families.h | 146 +++++++++--------- 30 files changed, 282 insertions(+), 276 deletions(-) diff --git a/graphics/pokemon/enamorus/back.png b/graphics/pokemon/enamorus/back.png index 1b2b00e218f9f00d05f649ab21fd56845f8afffc..2e7af720cfc05968495d84e24b5616d3bdbab889 100755 GIT binary patch delta 722 zcmV;@0xkW?2Hpjb7=H)@0001;w}I>c0004VQb$4nuFf3k0000mP)t-snbM?nJW)zY zN{t~Qz)v#tTobcqwWwEZ|HVA%hv(0Op0u>R5D*aj{QLj_00000T(YcO00079NklG|hZqrPn$3uzNW zS`XE2gzo>z-``bCTjvnulm&}W{jmc0qpo60D=Au=o1HzNeFqp-8n;V7eHRW zfK`}hgCPsR!X{2&Ha$@aq54IfAg~y)p33T%g{36@M0+=WJ{bTN)^a(d7nM*yB?8z3 z5P;N^A)69v34euQ04`!tHQWvPs$$guseZgee-!kPwn{_;8Si>;?mMTi#yw>s{X2s)u7@lwZA9s&f`>rA|K zLZ*^f=7FG_2cbf!_p^-E3XDo-a^NG0hhkMjwh9NJ)sq=641iwUc#>WSrM=J9;Xvc% zrnwo1fq$h00WfEGf>Iz~+52dBfChU3m`hNN=bnS_zN*EF06Kb#jkV`{gd0ssI207*qoM6N<$ Eg5C5tq5uE@ delta 830 zcmV-E1Ht^>1<3}G7=Hu<00013M{Ml?000McNliru=K>ZG2`{b^|JeWl02g#cSaefw zW^{L9a%BKVOhiylM<8}(av(DOV1ZP1_ zK>z@;j|==^1poj5Fi=cXMVZs3N=iz!w7vZN{16Zjb}~AXA%7m=be!`pF0M*f$1W-J zRFAtpUjM~B@8qxm0052siG%^3p!LMeSoHyF@vN&frW4IVDB0G0ScK7DR}525QO_43Iyb#1qBMe50!T(xg^%R zJmX0}|L?t%e1G!1vA{Rqx#y}`BIYw8uASh!5Lbl|!WA(~;zBG^KZ#v{&lwLgFK_|I zGYg9J9T4a5f-iZSq~4GqGPg6v3Moz^rd${D^9T z?aW4)?X+D?Bg)+thK(?D5TM$jsK#$Bo4Nt!a&|vP`i0+uJeor161b@9Zf-YMhDR4R`bkLDNw;mh7`stbM z;gk)a?GDtRvyr-m5s+t4!{n(QR_HPkcueZG4QQv=%}!=)JA$47*d>%BXnRH;5G4#t zfRwUyG+_YnP_{%D27Cb4nUf51;`M2|y+T0Q#Un0=cO4#Q*>R07*qo IM6N<$f}06olmGw# diff --git a/graphics/pokemon/enamorus/front.png b/graphics/pokemon/enamorus/front.png index c679b07e571f202cbeaeaf1bbe6459f76043c961..67493a1e6b1deef6ed020f2cbb38e7acd05cb54b 100755 GIT binary patch delta 773 zcmV+g1N!{H29XAk7=H)@0001;w}I>c0004VQb$4nuFf3k0000mP)t-snbM?oGCE31 zN|PZT$1W-JE-t%1Uam@4|HVA>RFB|voV2vP5D*aj{QLj_00000+%&-iJiBBci) z2o&+8W|jj4L1zgm_32V_iZK5ka?h6{$7K||g)g_8z%u%6v%YOiLxfM{4$Ba>vKbGH z1cv;6KN5tklz*K^<5HS>5EgTR*>2GCXm$aRl2w3LX_ujfhQ5>ppl;jNcmzOo>Q@0E zVE!#)(72AERT5V9+6C&yqc+q-6^E^dfPmWgY4zkBD$*y%`UJ3e1S;QK#ZROAP=qe+L6U7a(}pE{Dd9^Kb$q(Yn4Mpi|(0q za2rK~g$zB{VJXEkdIz8=8-TI~?*{=1eE>qqD*?J(g43jw`%{lblI%vp)*(^-oXHX1 zWDp*UU&4;(MAiv@Q1tL$$K8?1qv#V5dZ=@SKROe%* zgkG|85(XgjC<00DR)+&+0^q@8o3Logtj!2C2gAA1SluUabJX3t4gl_(kNxtR58T*A zL+x6cdOTRh-)noVDISFWW{Uvp-O{0yhCMh6qmp00N^)L_t(Y$F0>dPuoBg0Ds_fv3J{-Dq*Y7bgQb` zM>dL*U_>EQ3R0|y(1{_k%9H_J8MB?@i7Kc~=PraUg@BNbP7RaYq3W3b(BIHIKrL$C z4VC(2Ig#F%_b%u29YX&z49C8^Y4Sb|)GgErOdV|Fz>y3tAQN*zU?aS!12!_kXX;A@ z1SYi~DDX%NLVtVC4@2L^8h~oHDTf&#S2G4w^H7A$ia{1Mz$A{GCBr4!nW_=j4_s2! zPqiD;kT}SS8!+hj9qKP4tHt(VknASAKCQGEJAg|h{iJ_J%S^@qNL!8MBsn=%pzA=u zycR0_HO5Lk5agY`&YtkA#V((R0NPB_q%ZJd@37Q^o_~f>zDO_9%w1|m)p;0XS#~u& zU20fEu!He>USI@u80w0dS1z{{Vr(a%XPa5sv5C%W%XJ5rtJlHsf zJD|dV(xvO8t==*GBn&?PmgI5k4PS)|RCzCsog#bBD>~q?E-$jff@VEgTsm-qfhx{GlzkdUvG>?qkJ;hoWSpH9^ZiV=FS*y@j^6H-p^M>su_bRCh27= zb}l2`+r2swB0U#P?dxw!Aa=&XEzJ&MzN%kJAb*;~gGC{)%OQ-<$04{&88(gr32=Rd zhR}wN14?P>a~+rEC-H!dSVcf@0|Gw%6CnUFz6S`IolBSAD-n7gu!$1?UW?h?R)V`E zC9;JMgg1ad!1PoLBCE^#WFbN`b5$dEp#bq_kG9|7He^3%2Ds{{w|Sqg{9VGVkw{*| zQ!dOU1#{-)G9z`>NR`N}JXACbPnszDrxX7d?+)P|ss9?Y00000NkvXXu0mjft*>;| diff --git a/graphics/pokemon/enamorus/normal.pal b/graphics/pokemon/enamorus/normal.pal index 08f6e5ebf1..43c4eb7a07 100755 --- a/graphics/pokemon/enamorus/normal.pal +++ b/graphics/pokemon/enamorus/normal.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -153 211 165 -74 74 74 -180 180 189 -252 252 252 -16 16 16 +153 210 164 118 50 58 +74 74 74 147 33 30 -224 116 156 -243 46 46 -174 74 87 199 46 41 -243 84 143 +243 46 46 187 62 94 +174 74 87 255 197 60 -239 228 176 +243 84 143 +224 116 156 +180 180 189 +16 16 16 +252 252 252 +0 0 0 0 0 0 diff --git a/graphics/pokemon/enamorus/shiny.pal b/graphics/pokemon/enamorus/shiny.pal index 180ae687e5..edbd1c73cb 100644 --- a/graphics/pokemon/enamorus/shiny.pal +++ b/graphics/pokemon/enamorus/shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -152 208 160 +153 210 164 +117 60 81 74 74 74 +141 33 33 +192 79 50 +244 92 19 +179 102 181 +168 87 109 +255 197 60 +233 135 231 +207 131 158 180 180 189 -255 255 255 -0 0 0 -131 57 82 -164 24 24 -230 131 164 -255 90 0 -189 82 106 -222 74 41 -255 139 238 -205 98 189 -255 197 32 +16 16 16 +252 252 252 0 0 0 0 0 0 diff --git a/graphics/pokemon/enamorus/therian/back.png b/graphics/pokemon/enamorus/therian/back.png index a563156e4d1f0bfbd1794b70c0f5efd6268142ba..04a5286fc159cb9de072a6516241cbcac97adb7a 100644 GIT binary patch delta 880 zcmV-$1CRX11^Wh&7=H)@0001;w}I>c0004VQb$4nuFf3k0000mP)t-sn9!hbI8aDP zNQfXHz(_FgSP-yau&7XI_`o>mfZ)i0n6R+85D*af`1k+-00000sz1Q)0008{Nkl-XtQ3KBZ>@Ord}5rTha~pVCth8i35g@`Rsv8UlE7 zflmn(kOn}y2jJ%bNdSI4zXRZW$zl7LUjmwhmw+*gAfgk>9Uvh+0SJF$4KVt099T9fo=a@u6GO>K+{VI!Ggf$Vwq|{Ov5G2YT-40Y@vP44wMln1B(WIf!)$skgRxw3mY04}X^)GzV111)*)_r)x?u`z0U~ zq6cXCMI}8*TQs(P4?Q5)F?Ke(2$UXF3* zEePLKPUGr59}xQ-GypcDyZOuF1$6T7_sbvJ_bF3!NuWay=HqC9pRgcZuq)U_4sn=$ z)Rgf3e1Gh>t}m=zAg8VXYOmdJEL|Wk7Xp!ceg9rTch692S!Y+=V^?s7{7A#eef=S=1w65Y*6z-l{I{&tk0>M?)7-Jub?Y^z8fe4IQ12vE~NV1H3wj$gD#*JNQ=N+sEj#?a>|&N zTWKsS!19aB=f7Ok3WC|yH95j~OJb)F#Vi|f0Z3C85O@NV%T`PPx2nhKjlk;|N;P9|H0hJOuKoiZ?nGE-e40i80000rH delta 698 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 delta 433 zcmV;i0Z#sd1iu527=H)@0001;w}I>c0004VQb$4nuFf3k0000jP)t-sl+mF80RSp2 zDHWav8%7U3aWxTYL{o)YN=!+w*q{6T`io;Z0Hm3CQ77A-TxYv*Bme*bKuJVFR9J=W zl*x}?r696Ow&It~<3!vFv5g0Z=FxZQ5T)+kcUf}r&fzcEafS)D=kjqG({0;_W+=R|q zD1i00o1_w0Rw!%Bd-C(5b!QfBzWSJfE53k zzX;~|I0Jq$$A8}=%n;0F<=<-a-HW|D??ri()w~8){qt00E~-L_t(|obA#-OT$1I2JnLj zg=|?fUZF##wx`h1A#KG$m)<83E|95UAzh?`(A?&zqm5AEmVb^Seg!wbg0qW*Zs*8m;kbqp#C+6 zP73^81F#c7*w%Xn?4g{SaFc<^VT?hi2CQ^P1l5!)A_0;LA8LVPSr#jS(hd_!5Q{dT zgch&_$b+^6JAaGfDNQ>CvO)tkIk0uWv~nOSY8PQ{tbeEth+F`1lhqw5kckfT8bG$A zo8*RkO5RHj;);tVAa=-#UKK!uikI0V{Q{7c$o)ha@FB?n7%0$PoV|SvQa~6#a+6zswL0%@fTtB^Sh R%>V!Z00>D%PDHLkV1j<|;?Dp8 delta 524 zcmV+n0`vWx1epYo7=H)@0001;w}I>c0004VQb$4nuFf3k0000jP)t-sl+mF8001g1 zDHWavN=!*TaWxqm7;R&0g^Pi}06Yu=14}~PGAKeh0R$|l8wR4lnIIhk7Fi%S1Pj?UT|i<64%a3@aUmf$ zh(Krt=4&x1!VncApT!+iGR7blK_S%!!>{zfG@clIvzp6owopD8=*L&9175COdGxm#BiO(k>HEp z2%HxV&+EL;Aa8;3!q3;h(BbzH>@W-kUH&8RqXoV%=<}Z*d@K1i6!iFJj5yLGLE%pX zh{-qkc8XixhGHw6(2*ckLD|L1FS%5L&k?^l&3;So`F~tx%hR`=Xhd-}L8AQ)BO@#me O002ovP6b4+LSTXqzvD{) diff --git a/graphics/pokemon/ogerpon/cornerstone/front.png b/graphics/pokemon/ogerpon/cornerstone/front.png index 8e96be70e7c8b2c23299a744da89feb1e71aaae0..9b7f2792387428bc1e2c71509de805da7ee5df96 100644 GIT binary patch delta 937 zcmV;a16KUP2eSu|7=Hu<00013M{Ml?001yhOjJeg=Cm;}F_fH?5D*YSb1_=1Fn;0F<=<-a-HW|L&Xsi()ww2HIT!00TZrL_t(|oQ>5nNE=ZY0N@KJ zWc6JjV4eH}Z*a=xnafp03SO{Fg_3);i$m_<6@)?|!yR25B7fvf1<7<2p(!g#D8X*7__Zfq#7Iahja=QR+P!R*ST9heJ z7NQIScL^|q7k@g@Du!}&7lpEDgGW6O9!&LvAXpA%3K%m8FeuQOs4t}qWU2#hzl<#a zJb-o-*;4k#fCn=|RlqKEN&$@du@M38fPxU-5CqnjbcuL10x|WOG2Ei;uBS`jh$y9k ziK%|2*-}7^mME*$AgF(09`-Aot1j01h$sk;3PGvA)_*^$Rrs5(0%9<@7eoQiTf8_u zVqkx|!4j6(A%iM~6{__k@`xLzI1cyn?1JuxQHwHrO-qihVnj)=nDe#55@T_Wp+fZQ%zj z1C-eO{u<^5f{w+;fn^d>+HPasXROf?!z~O4rGRge(odDI^HyLX*hvE&SI!f)p7U0S zV0Sjv0WVavi9vgB`Lr0(5*LeShwi>#Y7} zF@V{@=_|?e=5&`zf1!3jvAYsT1#~QxbvJYw%AOh|mTF~P zr!MWDDxm4zl`wM<%-*LS#%8gZxG(3zh9#5{<<c0004VQb$4nuFf3k0000jP)t-sl+mF8001g1 zDHWavN=!*TaWxqm7;R&0g^PM&s$4k}6NUjgJ0Opk1BwTWrPwG?7ATWHeUaMS}-@+t-6X%p!^ck;~5A`CEAN!*g zh)DI*0CnMj1UqqFPXoZyA>XE-0PwyiR{w@Dz5H_h9f0@8&fNgyJ{o}2B|-F$9YR(; z^E&_r(j~zF8h?D!NE%|$-vM^a2f<1p|H?qRCMckk)Jw<+`|kQ%3jmbovk1Twh?+!P zq=4xZ-ti=z=mE(7u`t;689UH6F`UVpUI7^f zZAx=WuYU#*J)P9iaW+7(Qg74r6?Fr0tp5;(vqea+AE4GqWV|Z$XbIXD-U*m;=w*%L z46+52l9bR!(E&+{nbKi!xQkNnIzuZ|fQ-1ZMvxMwD8fD(`@+^oI1q$J5IC-4!L~pb zAsg?FW!pxCFD(K|4erkez`EPJ`h*~b$l8~10)N-FRyIH*+yKmlZi=LkD+V8c?F{gX zUd_QK2%dt4Mu0tKHNwTMf$b1tLU;qvD$iPR z;~TvqT6Iwe(1I_dUc14>bDk5(06k#RI|==hfU^;3)Z@6p#rYQe>*APgJ&CB4PY9zQ z0DlUFZwa=+1tEM#FarR5M`#9?Zwbx7@+F}gSiU5T03*;x1b?(*cLN0&elm+>ZX$|_ACcCKHh~5&U)vt3qA@>y_h`udJSY6&M zlX_T}1tZoy3TeI+?Dq8FkPXnqsafib7Bmw}&%8T|nW?=kvJ-lYHk|6-&VQnX_3oB)erIse{4-ke%1X2uEt00VkSL_t(|oW0dQXxmsE2k@sH zX!b*?+=?^3s;E%NaPA8p$}NV6GoKD=wxamyuzTbTMK2`N!GF=%SxU<_*x|S%6x8Hx zUYfyMhD>Q8i??34j)g4VOz!vO*p+NK-TJ_`;C=l4z4y~Ugudm-O%9fR$ejPKJUO!L zxyfP@EICef7OX=2D$U&h%DFGVa$JP;89>Vlr8tLh45|p1W&zbHEf?_`gj;r1A@iUD zfKdsSTty=@tAALfe^xf6S@ST)4>XbjM1sF)NS7()J|P5?bcJQ|<0|dYwGA8tOp3FB zmY3JMo!y{G%iPBiWRM^UV1wnYZY$&f!lIA>H-1lpe5<`50LX`ih+v7Nbds)-Z*J{Z zxcn6&awX`eB6u^Oe?~E_a07rNchWdX2nF+yh0rSxz<)vXb4h|e=aYH7OoI?w&AdN! zal9A(^bR5#{cXX=MtKU+A+0dne!)aXe1HC*HwG|d9hE<&Y=e6Ec1Jgk_XNiOd`bZn zG@-`~>vvxKW*mz{BZ|R^oEL8-PyPj^$&F+pb?+<(*QBfy*u512b%=|LOeM? zgFYky3V*oQ#?MEiLj5r;;t4q;ECt{a2-(MvcX7dg+!4{=r+zvC!-0Nvd4U1Q3a6H@ zk;e8EDDlzeCB_#Y214K!%f&1SP+c5#_o5NL7>$NP9NLbnH&_y=MjUZ58hTeoTikLy zy??!gaie1Kx-_~9_}$B+gF_cL0E`o^PpJy~e}BC>+0FX14w~Y?(}&0>ZJr{W01T-m17a~ zgMX&(Kn3&MWG67slJ|xp*v?xoSF=G_@L^l&d89DJAW^k!2galOh^6PJi*;%am|x7f z$JlhkHMi!}?CihG;pt3u7R1LTFdiU=t2cl`6~6SvfB=9x3xQS~z_(wleg%-P0F^AP zF#$7A;^~Vc0004VQb$4nuFf3k0000jP)t-sl+mF80RSp2 zDHWav8%7U3aWxTYL{o)YN=!+w*q{6T`io;Z0Hm3CQ77A-TxYv*Bme*dlu1NER9JfGLb7cl{Rt2+%7)2!wAa zM%AeP+Q0@d3rzBnB4G*1_1_GDAa7apub1nQf_O)703qa(CpP^=IyC>+0A>X+v*>fv zvy4Pde-2>Lx_|$YOUZ1>)bJi(48(9|pC)xbDFIW^IVj~tX)_Sd2sD8(nddC=xg``X zdi^;-LQbMnfQki(uRMhgxFGn#O;|+01^zMEL51gQ-=|n1mz);3K`X zOAvAy6IVfSr5d8jbH>lLkj{a{!zn-q(?V5Br>1d)Tr*HhS$7ov9#0`aFzPI^f|M$P zMWhw^D}S{I$UKg7py47dNFyVU$>$mvfNo1m8a@c9EuZm-MOcspNtI+z2#Egn9Lm0k z@pB=htb$=HFL-Q``3O;SK&_B`H^n_;t!;t=1WaN9OttP0dR+sUkNq%t)3f{^k->#^ zsTyIcWQo5g#C~rD$v@5W3=7F>SnEBhUaJT(=YRi%uev7HzaNA0?6}j z8nkU~)f>X>8jG|pqI|~+$n%EST@@NYpI|cm%uEg=1B@2J#=f!S+#!5GGO?Ba2C&~h z4~U-7oM4gkjFgff&B03e4iNnag)~Lk)R{tT7V;6`A3^m30D+Yd4PX`ykGRmwXDe;B zfPY@8{bnPa9FZYxa&Ks6!C>fTaCvWP-Is)q1YYs>^_1#ji0>CSJA!-g4 zaIZ0_15aTKNxmcQ=r_QocgXD`ka%+MdEAMdavAau0-!K8b_=l)00000NkvXXt^-0~ Ef_Ik83;+NC diff --git a/graphics/pokemon/ogerpon/hearthflame/back.png b/graphics/pokemon/ogerpon/hearthflame/back.png index d6d927f19d5a051631c1ef4b2bc6b6f425aa1f6f..73f95efbf2cafea2a6d0e259646f71ac17f71f51 100644 GIT binary patch delta 521 zcmV+k0`~ot1eOGl7=Hu<00013M{Ml?001yhOjJeg=Cn#mO4Xbg|K34Cb1_=1F%S?C zDJd!LIVqeF5K;&T|NsA_%@})XF#y&7i()zbplFN$00E&%L_t(|obA%RYJ*S|2k;b% zf}2ZxkP9I=WiT|9LYKHFq`lBCX&}_0gIl@y209glw%#RMpMRiZUM7oOljBSVIvf_AIoIxdq5~lCAX9-y*PZ(SL+pE9z`X}Z zb;vA{qXcsVezs8pU87S04zMwm05_*{MrNA65**B{2ltlmHfo?}9+;^+V*y8yDpp8M z&!^KFV~ks%0)MbHhc?ANV_$d-1xU@+x9qb3fVRaND9Hia0eG#?v4)jhfB;2n4Glq* z1IBmwqWq&No=H-I*yfxQy9o@EgvE@Q$ZAH!2=a)4D1jY@A#Z@j41)-86n#JnCEz&_ zi}r)4dW-s&MpOV1p#Vt*A{8*g3SdO*5JnQleE|Ci@PCr0GYTL&DlqN<<&06@*Thre zE)_UNymtYdAtJ`7fKXaL=9n#NKtxh!PfHLGR)WEk1f%U8`F$z?c0004VQb$4nuFf3k0000mP)t-sl+vUC001d0 zDG;3i<~%VuaWOH4tb-gF)#mp9#!9SdAe@=3F}~)cG%-p{O1+6%1%%aT0004#Nkl8vu4ejHS2$hxO4$} zNE$%?{r0j#d@N9c-dw!E_xscUCg=rA!2Cl2Ab*n;@ZOW~PX*baSOx1I=!Oc!1`W;z zVm_k^h**0=zy^&D<8z51IDfw*AWIwSLdp&q4Nh>qZl-;FUN_O4^$F9iCY zITdvI;}n;3Tn&XUuImXx6ByqPqI`wE0K5F^X>P!VFMmI}OF=!x);~`8fgr%Ob36!! zd=bbVeO0ao-}p2P5GpT%^#NiRK>F(i2q;@N{}ZqYAg>I6qHrw$?}>eZ@t@D$pdExd zrQIWF*ONDt{#1Z|0GF-=+=9oEPZm;FM}r6!!=4Z2A!rxEz(2*&ClLpC)rkNA002ov KPDHLkU;%>3gy2a4 diff --git a/graphics/pokemon/ogerpon/hearthflame/front.png b/graphics/pokemon/ogerpon/hearthflame/front.png index d8b9cb7b2346a9b49c50b60e3484b0c8dc3e03c4..098041cf76ae5b047a5e9c617c8c5c1ae8d5e481 100644 GIT binary patch delta 937 zcmV;a16KUL2eSu|7=Hu<00013M{Ml?001yhOjJeg=Cn#mO4Xbg|K34Cb1_=1F%S?C zDJd!LIVqeF5K;&T|NsB)oB(@jF#y&7i()ydz4YY(00TZrL_t(|oR!tVOWRN!2k;am z1y8;z73UE43Pq3hL8;qigH#XmGRW(>arU)!J1mz5yvRK0OMh-t2zh!L2-;*I$mYiE zQSqdw{RO*v=+X0juW7e7O_e=p3i*Bd{k{H@Hj46JYvPf5;@Kl2ky(^)V=v=sokNbu zh@u_?QWGJ7h%rjbF<=qIc>`I-V26niY?GYl?UPKNvHSp#7a)-@KtKTZeHShL1&*wX zgYGuga2*0%qXoU(Tk?Gfyd`;77w+85CusHl<{IV@1%<;jtG0tLGXT&vVncxMpUtAv z_UsP;SATMn5m4ZE>+DGzp-myyi-w76egp{57N@`4?K|NXOBRa&l`LS)Kep!X0$;ea z)TpsRu!b>a^L%y=X606BwE>gw)O&+c*Kk&;^OLrJ%qp~G)c}MEy-TXHvZ8uUAdCj3 zB@@8W^Zq@CNS-m$lwKNX00i0zw;w2VIK$R8?SC@g0R%RD++QDe>rj8KYpYkR1IY7W z;O8?gT(-O3I@dJqIs_y?&|zFO`KCJ--0D}@c!!x&njVBTmk|8w1#N~uCCdi=-b zs(&_^N=L+ZT3FV-!mRQGU<5d9}sx(}Kp z>Vnu!By~m89t2dQx&+!Xn$qHWREoN}1)!*-*vD2fy<#B=REUbZ8Y(i;v>YTvmEyjq zii~L)ps48;GjY00000 LNkvXXu0mjf+Ge!n delta 948 zcmV;l155m~2fhc87=H)@0001;w}I>c0004VQb$4nuFf3k0000mP)t-sl+vUC001d0 zDG;3i<~%VuaWOH4tb-gF)#mp9#!9SdAe@=3F}~)cG%-p{O1+6%1%%aT0009#Nklq@7xre7RjdIms#p)YQ|Q=Kxhf?ttL(TY4Q=_54TzP`T-^49LJ` zNvQ!?Ke+zFfC3iQ=LSfLD5Yfj>lq-@*Z?V0DU@&N8Ia!qh{6EX-vNM-M*}RS*kZc= z8Zc(o|2e>t(SHDx(-mOMe}6roH~ zH6TyZw9fqUyk<$HZixzD!YN>yUauDjst3Y0l>h=foB^iS%nn|Ytq{tw*lq|d5vKrz z5JX=*XsrNF=^l{U6yRWfO{&*!fblm5ICch7TSOk49ZX1cLIp@qdA2pAz5urR4MFr- zDhSez{(nH;^n;96_fj%|KqLn;{(b?gK4|l>GIj&cW`LGuN64LC34*}P#SzWW%b|)F zdIC09r?&=Vy}0?01{jw@bw71-*DJxZ?-8TaAop7-DxYQAc7_V*5epWN0WsJ{vRR_r z^^Ii%s0a+jgg|^iH-JrZ-_({qJRb`IFwdmTB!Bx-Ujd+(w!;h04S|DVb_>f9;C&M0 zz1ay-%P`k-`;1`vN|-STBf!IlBQn%l;44Ym0`!*Ugp&g@fKlWo*aN}?cO~6z>GXgd z>P51iPi#2gAMd4r^xwQ_;&NlV%0D1I-p=m`dqgu#a=>2QGTsqez4nB|BDfO*;Qsh4 zL4PlrXs|yLg6QR>{E6TOhF=M8VEBW{UO_Lwv-?y-Z-NM_|1VN%(}%io@P~pojGc2#>1{ zNH+D|Qm`+3VU1RZVnG1+8iRgYU27o=!7X;g9ldk`(pJz}rrWJe-sAyquGtCZY{-A@ W8$}4~HHMb}0000WlPuCx7J!FJNzQ z`F;F;e;jDq|GDntdCT6p&-uPjm>f=wj;vexyOw}s5jT!KTx#Z)cSSrojvX&mgNJSb zz_|}$MIMJ}hXnQ>R)~E7VH@aV;Mg2i@S_l2!si4!U=&3VvmYaXKRS2R^%dYPV0xVI zoDmCX2hbyLO@9U>#u$Ya5TH$>O-5kO*eeRmO*DH`a~9xWOGFNsi#>(8on-|GT)xvV zkmP_-ccW?axhcNHyabDkQYx|*NQ;hzP^THO0FXxn0tH!`rnCVX9fpwLEc$>FD4;oz zi}r)0dW!m%Mp6J7fq;1h5)2q=1t6kz5ym`S^Z}RyfPb63>?nYoVBpvR%8o-m*X6(D zy;R^F@!18SLq;4gfgq%QnMXFR0U1fG6DdI;SP8VL0*BSZ&-b(djIyGk4b&T@^rZy4 z0+W?>vfgt5A1xi%K_b{Bw5;Lp`Kytq3XmO8E5U~XYF-Ptg7XJ&k&ItQlUySJ0000< LMNUMnLIPldrc>k{ delta 458 zcmV;*0X6=X1lR+R7=H)@0001;w}I>c0004VQb$4nuFf3k0000mP)t-sl+mF8001g1 zDHWav3qW~2aWzUzNe^180Dk2)hNwqXWH-Iz)aLh-TOp}>N|>9g`=DGg00042Nklt9Uuc+#CbTN==8h54f+WDgt4(D01jsc@ z9-^QCE~Mcma?ThcGGs*o{=uTjulu+qQk(^ri|1iD#y0!CUBaE>5L#D}5RdXi(Bi8x_W6$B z0bfqBe3E%6{C41u1e64zLI7ouC6b(Lnx)CisFwz1|yU`;)uu;jJd&Mg0Z2U5`RMFH6g@WE85|pCV1(P zOqnw@9owd31`p}GljHhBYM@IWB!lng_kTK_WJUQe_2}^fK+_*+fN|#EK*}^<$pmaD zN;PKPqSO^ag9dhOcD+bxBs4vfX0xE!6oBr*3`W{vGgG8ma-D9i*!G;mVnA~%5_^o< zEH)vEpe|$e8Gm4!iWt%JeV@`*2DLc3-lS&fkb0fqwB<`+=U+|D=asvDCxB}CE{w=( z?$iZ#N^%+M^uQ2+j9MO}c(_2kT*T6XT0Q4FER*97RBd%Wx}$JI=%QYlJQ?CE#W`cr!c_%Uwzj;3Ho2 zU+QS#j7Y#k^ZxNsmk&XhJZv4@TqA_~5#S$2$A3~KZ8&gd*xrAtBeZapp9YFTmV{{U zUw;*#AAyMnR3(J?C4wOVog?DHI+=X_RBMwgW_1u6{E^D^I;3QvjizI$ohJ&JS&!P_ zEC%xoCBElK*2vbvm2P|rL7 z*n0y&Wr-R0VD>#3{m`V@5X26V))j>Q3NXUD0BDZwpty{zraKz|G@Zr%Y^7`SHWNUF zR&jSjWe%&0jf7T4+;ys~P!|mpwKng>ZUiZ8?1}~si?$=C2b?+q>N%N|SSnGIPs~jH Y27ghvGnl9eVE_OC07*qoM6N<$f)UA?t^fc4 delta 950 zcmV;n14;ai2fzoA7=H)@0001;w}I>c0004VQb$4nuFf3k0000mP)t-sl+mF8001g1 zDHWav3qW~2aWzUzNe^180Dk2)hNwqXWH-Iz)aLh-TOp}>N|>9g`=DGg0009%Nkltd`R41^6LDK6^!zilT8H&@qnO@ExWXXj%GA)&)?8GlZret-SpGySOHR35_5 zfUFk)n{PO zSA;KKJVgz!0Q+=E_J81UAG3#R0Hs18DuAc}a?4@> z5Ki=O00}1my@xY4uqIM~bX2+k%x3=pSn;!K2XPL_NsuhcE*$QF0eo5k2o->290A&a zm}xFqaB@fr-~d2q1_IGBjaFMi5DUm*r(Xi>FXa#%S%-SlTUn_EIRUl+fO(PhFWni` zX!2UyLVqY~DIb+vsDZkE&*<(3d+q}FnoQgb5T`vM_IC?~?W@>(ZN(a!=mkJCr|q54 zhDZTW=aY*6Np^q?34u=KgWfC|AUi&OmfuYRfF6LfHN$w4*zc>1qHa0O1cq zly?VP3~bv>0E|6A2-|jiW$XwFLH@RlXY67e(SIfcP%Oa2H-IdUkIJ|syR@JbKZq1tBEaL`V2AB1@OVCGdlFh77P*Rw3}`5vz!(P224NG|F2k z7~%4jVq-#rDu4$0lEI{ph1>5$$=%i)CL3=*yz?CGHcUETzdY0qE_%K7gmwM-vDyJv z#ehlCzr1p0}PA1FnmHTesnOy(l7zryYl z>RY$l!tFdvQ`KhxdbG&#&veTITJmU*ES#bqqx2RxjnjDVB#49neOZ!Zb@@x^re3UL z!AaIN2c(z!ZYfv+;A_f-s20fj(+#}>N-q_ZB`M#CJNgD_`V6^U1hO7l(fYU(WyRFaRJ}4>@NgkA*X8TOeJY zN_fO$pqEgGgnp;Ga?HbY_u6N{xvm8T1?J(~(!>Ti0005aNkl!n8yHkvjr~%3?>i)qWv0%>;FUqyc=O2cA$4N-AQ&=<9-6q2po$U=YD|I&q#9E zt9Ko8eF9J~q10zUFF_(VfIh-%faI~lOZ?OWCh)Sug_! zfXfz=fg`{rLVsV5eQk4PE zEoe-jqBJ)qLcr55q#m|_lp%!E2*&_Q5kjCrK-MXsX~7VnuHOR!0X&1W0A05hAjcB~ zex3oG+xOC`K9U;1t_j{(1Q+GKf0({R8$jNXD?o?441aLa5bsO*N@Vr4`OwFni%iq4TYtAsDMY&FC+0{O7?Ej) z;&=jP_#eX&P=N>F;RG>Nz<3YPKe|%E6cRJhcm23<{y72!Aem1#}C4>zXDugTc>wc?_hla zHh+pI0(>CEWl!jz>`%bz$L1_aP6XH!a0x9-S_#r0!8-u%v@Aa$q$J<_Z{4~zreDn3 w5z-|qs3$c5000hUSV?A0O#mtY000O800000007cclK=n!07*qoM6N<$g4sm;=>Px# diff --git a/graphics/pokemon/sinistcha/front.png b/graphics/pokemon/sinistcha/front.png index 4131a22b9f68f9c39c9323f9993f47aafa008971..eeb1b7a71a775b8baa64059d8a005d3d2b39b87d 100644 GIT binary patch delta 629 zcmV-*0*d{H1&#%fB!2;OQb$4nuFf3k0000mP)t-snbM>s8yieIIyq-0X+#@pTOeJY zN_fO$pqEgGgnp;Ga?HbY_u6N{xvm8T1?J(~(jJ}90006ENklM-DMNV$cBc2SEXvgJ=zk5Af-q01*x$7x9#V^O-`Peh>zeqYn_7&0090!ZQ(7 z4}k4Ote(qHst$$t*CS37VBH51y40sya2%16SsO_=J%9EOwbp9&0ABc%Q9cwswr|y1 zH4qmd5F*G-6x4*uL9KV#sbxne0>DKIYwDK#r~vhf=i&jp0_vwF?7eoZwZe}D56KC* zYCjiV^An;Kr`^rX3M; zUZ3N_$Z6xrG{e3yZOswK+>65+k4Z^f$H32o46mN8>jXYAkHioC|GT~bd2b`Y1hB3N P00000NkvXXu0mjfPVO0L delta 621 zcmV-z0+RiX1%?HXB!4YXOjJd4#iUF+I%z~3lZr&2nS$HWk*B(HEg>N@V#r7-9l8|eLK{3w zA>I+dP}`1yD@ry_p)@z}h9M%f9f2SK?=-=U(ZF%z{2QXro5T zm7fZjlmxt$X9~6ox?;8dM8OC5iYGkXJ~z~(4m@WaZh_&t)KstQ%JSCF(a(1B+d##r zltPwLKv3H`&VSMBSO!)jMfIYZ5HJLzA;K8E3_`wOTjF?|Vv00KPjMmhSH)j^Fd1nz;uLV7*)5U_m>6Pg1d- ziGawswLUOB&IXO5dF#jt2BronN|84l0dB&GCk426?0>J~8xy?((9Ia@gn(Li9;8I@ zI}8XgwMt5Wqi+Tt3BV%(c?WouQ-T8>bQj>sx=degJqa79l<$$j|@)01jnXNoGw=04e|g00;m8000000Mb*F00000NkvXX Hu0mjfC*KyY diff --git a/graphics/pokemon/sinistcha/normal.pal b/graphics/pokemon/sinistcha/normal.pal index 16008ccdf1..0697645151 100644 --- a/graphics/pokemon/sinistcha/normal.pal +++ b/graphics/pokemon/sinistcha/normal.pal @@ -1,18 +1,19 @@ JASC-PAL 0100 -15 -115 197 164 +16 +153 210 164 +37 27 27 76 58 58 +57 103 37 105 68 27 -147 138 68 -159 153 130 -219 210 145 -167 186 114 -45 33 33 -51 99 34 +106 91 32 93 158 74 120 196 99 -247 215 98 +160 151 80 +135 132 126 +167 186 114 +204 195 116 +247 218 103 +193 185 174 5 5 5 -208 210 193 -241 237 235 +230 225 219 diff --git a/graphics/pokemon/sinistcha/shiny.pal b/graphics/pokemon/sinistcha/shiny.pal index c769e9d1a1..6b9d62ab8c 100644 --- a/graphics/pokemon/sinistcha/shiny.pal +++ b/graphics/pokemon/sinistcha/shiny.pal @@ -1,18 +1,19 @@ JASC-PAL 0100 -15 -115 197 164 +16 +153 210 164 +10 48 0 32 88 15 -105 68 27 -147 138 68 -159 153 130 -219 210 145 -167 186 114 -45 33 33 -51 99 34 +57 103 37 +143 133 51 +106 91 32 93 158 74 120 196 99 -247 215 98 +160 151 80 +135 132 126 +167 186 114 +204 195 116 +247 218 103 +193 185 174 5 5 5 -208 210 193 -241 237 235 +230 225 219 diff --git a/src/data/pokemon/species_info/gen_8_families.h b/src/data/pokemon/species_info/gen_8_families.h index 37eefda7f9..fd86f22ddc 100644 --- a/src/data/pokemon/species_info/gen_8_families.h +++ b/src/data/pokemon/species_info/gen_8_families.h @@ -2655,7 +2655,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = //.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, .backPic = gMonBackPic_Dipplin, .backPicSize = MON_COORDS_SIZE(64, 64), - .backPicYOffset = 0, + .backPicYOffset = 1, //.backAnimId = BACK_ANIM_NONE, .palette = gMonPalette_Dipplin, .shinyPalette = gMonShinyPalette_Dipplin, @@ -7730,7 +7730,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = //.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, .backPic = gMonBackPic_EnamorusTherian, .backPicSize = MON_COORDS_SIZE(64, 64), - .backPicYOffset = 2, + .backPicYOffset = 0, //.backAnimId = BACK_ANIM_NONE, .palette = gMonPalette_EnamorusTherian, .shinyPalette = gMonShinyPalette_EnamorusTherian, diff --git a/src/data/pokemon/species_info/gen_9_families.h b/src/data/pokemon/species_info/gen_9_families.h index d617d36f1b..7402619b9a 100644 --- a/src/data/pokemon/species_info/gen_9_families.h +++ b/src/data/pokemon/species_info/gen_9_families.h @@ -7086,13 +7086,13 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = .trainerOffset = 0, .frontPic = gMonFrontPic_Sinistcha, .frontPicSize = MON_COORDS_SIZE(64, 64), - .frontPicYOffset = 10, + .frontPicYOffset = 3, .frontAnimFrames = sAnims_Sinistcha, //.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, .enemyMonElevation = 10, .backPic = gMonBackPic_Sinistcha, .backPicSize = MON_COORDS_SIZE(64, 64), - .backPicYOffset = 13, + .backPicYOffset = 4, //.backAnimId = BACK_ANIM_NONE, .palette = gMonPalette_Sinistcha, .shinyPalette = gMonShinyPalette_Sinistcha, @@ -7147,13 +7147,13 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = .trainerOffset = 0, .frontPic = gMonFrontPic_Sinistcha, .frontPicSize = MON_COORDS_SIZE(64, 64), - .frontPicYOffset = 10, + .frontPicYOffset = 3, .frontAnimFrames = sAnims_Sinistcha, //.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, .enemyMonElevation = 10, .backPic = gMonBackPic_Sinistcha, .backPicSize = MON_COORDS_SIZE(64, 64), - .backPicYOffset = 13, + .backPicYOffset = 4, //.backAnimId = BACK_ANIM_NONE, .palette = gMonPalette_Sinistcha, .shinyPalette = gMonShinyPalette_Sinistcha, @@ -7370,78 +7370,78 @@ const struct SpeciesInfo gSpeciesInfoGen9[] = #endif //P_FAMILY_FEZANDIPITI #if P_FAMILY_OGERPON -#define OGERPON_SPECIES_INFO(Form1, Form2, type, ability, color, iconpalette, isTeraform) \ - { \ - .baseHP = 80, \ - .baseAttack = 120, \ - .baseDefense = 84, \ - .baseSpeed = 110, \ - .baseSpAttack = 60, \ - .baseSpDefense = 96, \ - .types = MON_TYPES(TYPE_GRASS, type), \ - .forceTeraType = type, \ - .catchRate = 5, \ - .expYield = 275, \ - .evYield_Attack = 3, \ - .genderRatio = MON_FEMALE, \ - .eggCycles = 10, \ - .friendship = STANDARD_FRIENDSHIP, \ - .growthRate = GROWTH_SLOW, \ - .eggGroups = MON_EGG_GROUPS(EGG_GROUP_NO_EGGS_DISCOVERED), \ - .abilities = { ability, ABILITY_NONE }, \ - .bodyColor = color, \ - .speciesName = _("Ogerpon"), \ - .cryId = CRY_OGERPON, \ - .natDexNum = NATIONAL_DEX_OGERPON, \ - .categoryName = _("Mask"), \ - .height = 12, \ - .weight = 398, \ - .description = gOgerpon##Form1##MaskPokedexText, \ - .pokemonScale = 356, \ - .pokemonOffset = 17, \ - .trainerScale = 256, \ - .trainerOffset = 0, \ - .frontPic = gMonFrontPic_Ogerpon##Form2, \ - .frontPicSize = MON_COORDS_SIZE(64, 64), \ - .frontPicYOffset = 0, \ - .frontAnimFrames = sAnims_Ogerpon, \ - /*.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,*/ \ - .backPic = gMonBackPic_Ogerpon##Form2, \ - .backPicSize = MON_COORDS_SIZE(64, 64), \ - .backPicYOffset = 0, \ - /*.backAnimId = BACK_ANIM_NONE,*/ \ - .palette = gMonPalette_Ogerpon##Form2, \ - .shinyPalette = gMonShinyPalette_Ogerpon##Form2, \ - .iconSprite = gMonIcon_Ogerpon##Form1, \ - .iconPalIndex = iconpalette, \ - SHADOW(7, 13, SHADOW_SIZE_L) \ - FOOTPRINT(Ogerpon) \ - OVERWORLD( \ - sPicTable_Ogerpon##Form2, \ - SIZE_32x32, \ - SHADOW_SIZE_M, \ - TRACKS_FOOT, \ - gOverworldPalette_Ogerpon##Form2, \ - gShinyOverworldPalette_Ogerpon##Form2 \ - ) \ - .levelUpLearnset = sOgerponLevelUpLearnset, \ - .teachableLearnset = sOgerponTeachableLearnset, \ - .formSpeciesIdTable = sOgerponFormSpeciesIdTable, \ - .formChangeTable = sOgerponFormChangeTable, \ - .isLegendary = TRUE, \ - .isTeraForm = isTeraform, \ - .perfectIVCount = LEGENDARY_PERFECT_IV_COUNT, \ +#define OGERPON_SPECIES_INFO(Form1, Form2, type, ability, color, frontYOffset, backYOffset, iconpalette, isTeraform) \ + { \ + .baseHP = 80, \ + .baseAttack = 120, \ + .baseDefense = 84, \ + .baseSpeed = 110, \ + .baseSpAttack = 60, \ + .baseSpDefense = 96, \ + .types = MON_TYPES(TYPE_GRASS, type), \ + .forceTeraType = type, \ + .catchRate = 5, \ + .expYield = 275, \ + .evYield_Attack = 3, \ + .genderRatio = MON_FEMALE, \ + .eggCycles = 10, \ + .friendship = STANDARD_FRIENDSHIP, \ + .growthRate = GROWTH_SLOW, \ + .eggGroups = MON_EGG_GROUPS(EGG_GROUP_NO_EGGS_DISCOVERED), \ + .abilities = { ability, ABILITY_NONE }, \ + .bodyColor = color, \ + .speciesName = _("Ogerpon"), \ + .cryId = CRY_OGERPON, \ + .natDexNum = NATIONAL_DEX_OGERPON, \ + .categoryName = _("Mask"), \ + .height = 12, \ + .weight = 398, \ + .description = gOgerpon##Form1##MaskPokedexText, \ + .pokemonScale = 356, \ + .pokemonOffset = 17, \ + .trainerScale = 256, \ + .trainerOffset = 0, \ + .frontPic = gMonFrontPic_Ogerpon##Form2, \ + .frontPicSize = MON_COORDS_SIZE(64, 64), \ + .frontPicYOffset = frontYOffset, \ + .frontAnimFrames = sAnims_Ogerpon, \ + /*.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE,*/ \ + .backPic = gMonBackPic_Ogerpon##Form2, \ + .backPicSize = MON_COORDS_SIZE(64, 64), \ + .backPicYOffset = backYOffset, \ + /*.backAnimId = BACK_ANIM_NONE,*/ \ + .palette = gMonPalette_Ogerpon##Form2, \ + .shinyPalette = gMonShinyPalette_Ogerpon##Form2, \ + .iconSprite = gMonIcon_Ogerpon##Form1, \ + .iconPalIndex = iconpalette, \ + SHADOW(7, 13, SHADOW_SIZE_L) \ + FOOTPRINT(Ogerpon) \ + OVERWORLD( \ + sPicTable_Ogerpon##Form2, \ + SIZE_32x32, \ + SHADOW_SIZE_M, \ + TRACKS_FOOT, \ + gOverworldPalette_Ogerpon##Form2, \ + gShinyOverworldPalette_Ogerpon##Form2 \ + ) \ + .levelUpLearnset = sOgerponLevelUpLearnset, \ + .teachableLearnset = sOgerponTeachableLearnset, \ + .formSpeciesIdTable = sOgerponFormSpeciesIdTable, \ + .formChangeTable = sOgerponFormChangeTable, \ + .isLegendary = TRUE, \ + .isTeraForm = isTeraform, \ + .perfectIVCount = LEGENDARY_PERFECT_IV_COUNT, \ } - [SPECIES_OGERPON_TEAL] = OGERPON_SPECIES_INFO(Teal, Teal, TYPE_GRASS, ABILITY_DEFIANT, BODY_COLOR_GREEN, 1, FALSE), - [SPECIES_OGERPON_WELLSPRING] = OGERPON_SPECIES_INFO(Wellspring, Wellspring, TYPE_WATER, ABILITY_WATER_ABSORB, BODY_COLOR_BLUE, 0, FALSE), - [SPECIES_OGERPON_HEARTHFLAME] = OGERPON_SPECIES_INFO(Hearthflame, Hearthflame, TYPE_FIRE, ABILITY_MOLD_BREAKER, BODY_COLOR_RED, 0, FALSE), - [SPECIES_OGERPON_CORNERSTONE] = OGERPON_SPECIES_INFO(Cornerstone, Cornerstone, TYPE_ROCK, ABILITY_STURDY, BODY_COLOR_GRAY, 0, FALSE), + [SPECIES_OGERPON_TEAL] = OGERPON_SPECIES_INFO(Teal, Teal, TYPE_GRASS, ABILITY_DEFIANT, BODY_COLOR_GREEN, 1, 7, 1, FALSE), + [SPECIES_OGERPON_WELLSPRING] = OGERPON_SPECIES_INFO(Wellspring, Wellspring, TYPE_WATER, ABILITY_WATER_ABSORB, BODY_COLOR_BLUE, 1, 7, 0, FALSE), + [SPECIES_OGERPON_HEARTHFLAME] = OGERPON_SPECIES_INFO(Hearthflame, Hearthflame, TYPE_FIRE, ABILITY_MOLD_BREAKER, BODY_COLOR_RED, 1, 7, 0, FALSE), + [SPECIES_OGERPON_CORNERSTONE] = OGERPON_SPECIES_INFO(Cornerstone, Cornerstone, TYPE_ROCK, ABILITY_STURDY, BODY_COLOR_GRAY, 1, 7, 0, FALSE), #if P_TERA_FORMS - [SPECIES_OGERPON_TEAL_TERA] = OGERPON_SPECIES_INFO(Teal, TealTera, TYPE_GRASS, ABILITY_EMBODY_ASPECT_TEAL_MASK, BODY_COLOR_GREEN, 1, TRUE), - [SPECIES_OGERPON_WELLSPRING_TERA] = OGERPON_SPECIES_INFO(Wellspring, WellspringTera, TYPE_WATER, ABILITY_EMBODY_ASPECT_WELLSPRING_MASK, BODY_COLOR_BLUE, 0, TRUE), - [SPECIES_OGERPON_HEARTHFLAME_TERA] = OGERPON_SPECIES_INFO(Hearthflame, HearthflameTera, TYPE_FIRE, ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK, BODY_COLOR_RED, 0, TRUE), - [SPECIES_OGERPON_CORNERSTONE_TERA] = OGERPON_SPECIES_INFO(Cornerstone, CornerstoneTera, TYPE_ROCK, ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK, BODY_COLOR_GRAY, 0, TRUE), + [SPECIES_OGERPON_TEAL_TERA] = OGERPON_SPECIES_INFO(Teal, TealTera, TYPE_GRASS, ABILITY_EMBODY_ASPECT_TEAL_MASK, BODY_COLOR_GREEN, 0, 0, 1, TRUE), + [SPECIES_OGERPON_WELLSPRING_TERA] = OGERPON_SPECIES_INFO(Wellspring, WellspringTera, TYPE_WATER, ABILITY_EMBODY_ASPECT_WELLSPRING_MASK, BODY_COLOR_BLUE, 0, 0, 0, TRUE), + [SPECIES_OGERPON_HEARTHFLAME_TERA] = OGERPON_SPECIES_INFO(Hearthflame, HearthflameTera, TYPE_FIRE, ABILITY_EMBODY_ASPECT_HEARTHFLAME_MASK, BODY_COLOR_RED, 0, 0, 0, TRUE), + [SPECIES_OGERPON_CORNERSTONE_TERA] = OGERPON_SPECIES_INFO(Cornerstone, CornerstoneTera, TYPE_ROCK, ABILITY_EMBODY_ASPECT_CORNERSTONE_MASK, BODY_COLOR_GRAY, 0, 0, 0, TRUE), #endif //P_TERA_FORMS #endif //P_FAMILY_OGERPON From 75eaf890a29c1052e3e32f2cf2d958b594f6b33f Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Mon, 9 Dec 2024 13:21:30 +0100 Subject: [PATCH 18/26] Evolution level 1 learn (#5791) Co-authored-by: Hedara Co-authored-by: Bassoonian --- include/config/pokemon.h | 1 + src/pokemon.c | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/include/config/pokemon.h b/include/config/pokemon.h index 23015614c0..65542a6ccd 100644 --- a/include/config/pokemon.h +++ b/include/config/pokemon.h @@ -17,6 +17,7 @@ // GEN_1/2/3/4/5/6/7: Yellow, Crystal, RSE, HGSS, B2W2, ORAS, USUM learnsets respectively. // GEN_8: Use the following priority: BDSP for Gen1-4 Pokémon, then LA for species introduced in that game, then SwSh for species present in those games. Otherwise, use GEN_7. // GEN_9: SV For species present in those games. Otherwise use GEN_8. +#define P_EVOLUTION_LEVEL_1_LEARN GEN_LATEST // In Gen 8+, Pokémon evolving while at level 1 do not get the chance to learn their level 1 moves, while before they did. // Evolution settings #define P_FRIENDSHIP_EVO_THRESHOLD GEN_LATEST // Since Gen 8, Pokémon that evolve by friendship evolve at or above 160 friendship instead of 220. diff --git a/src/pokemon.c b/src/pokemon.c index 743f5b2771..026ceceed2 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -6661,7 +6661,8 @@ u16 MonTryLearningNewMoveEvolution(struct Pokemon *mon, bool8 firstMove) } while(learnset[sLearningMoveTableID].move != LEVEL_UP_MOVE_END) { - while (learnset[sLearningMoveTableID].level == 0 || learnset[sLearningMoveTableID].level == level) + while ((learnset[sLearningMoveTableID].level == 0 || learnset[sLearningMoveTableID].level == level) + && !(P_EVOLUTION_LEVEL_1_LEARN >= GEN_8 && learnset[sLearningMoveTableID].level == 1)) { gMoveToLearn = learnset[sLearningMoveTableID].move; sLearningMoveTableID++; From 3ad5de5fef46c0d052d171cf4266a152996bff3a Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:26:23 +0000 Subject: [PATCH 19/26] Adds missing Friend Ball friendship bonus upon catching (#5795) --- include/config/battle.h | 1 + src/battle_script_commands.c | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/include/config/battle.h b/include/config/battle.h index b15a32a664..0ac1eb04eb 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -179,6 +179,7 @@ #define B_DREAM_BALL_MODIFIER GEN_LATEST // In Gen8+, Dream Ball's catch multiplier is x4 when the target is asleep or has the ability Comatose. #define B_SPORT_BALL_MODIFIER GEN_LATEST // In Gen8+, Sport Ball's catch multiplier was reduced from x1.5 to x1. #define B_SAFARI_BALL_MODIFIER GEN_LATEST // In Gen8+, Safari Ball's catch multiplier was reduced from x1.5 to x1. +#define B_FRIEND_BALL_MODIFIER GEN_LATEST // In Gen8+, Friend Ball's friendship boost was reduced from 200 to 150. #define B_SERENE_GRACE_BOOST GEN_LATEST // In Gen5+, Serene Grace boosts the added flinch chance of King's Rock and Razor Fang. // Flag settings diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 6e95788859..df3d91b26e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2323,7 +2323,7 @@ static inline bool32 DoesBattlerNegateDamage(u32 battler) return FALSE; if (ability == ABILITY_DISGUISE && species == SPECIES_MIMIKYU) return TRUE; - if (ability == ABILITY_ICE_FACE && species == SPECIES_EISCUE && GetBattleMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_SPECIAL) + if (ability == ABILITY_ICE_FACE && species == SPECIES_EISCUE && GetBattleMoveCategory(gCurrentMove) == DAMAGE_CATEGORY_PHYSICAL) return TRUE; return FALSE; @@ -15700,13 +15700,18 @@ static void Cmd_handleballthrow(void) else gBattleCommunication[MULTISTRING_CHOOSER] = 1; - if (gLastUsedItem == BALL_HEAL) + if (ballId == BALL_HEAL) { MonRestorePP(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]]); HealStatusConditions(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], STATUS1_ANY, gBattlerTarget); gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp); } + else if (ballId == BALL_FRIEND) + { + u32 friendship = (B_FRIEND_BALL_MODIFIER >= GEN_8 ? 150 : 200); + SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_FRIENDSHIP, &friendship); + } } else // mon may be caught, calculate shakes { @@ -15761,6 +15766,11 @@ static void Cmd_handleballthrow(void) gBattleMons[gBattlerTarget].hp = gBattleMons[gBattlerTarget].maxHP; SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_HP, &gBattleMons[gBattlerTarget].hp); } + else if (ballId == BALL_FRIEND) + { + u32 friendship = (B_FRIEND_BALL_MODIFIER >= GEN_8 ? 150 : 200); + SetMonData(&gEnemyParty[gBattlerPartyIndexes[gBattlerTarget]], MON_DATA_FRIENDSHIP, &friendship); + } } else // not caught { From 4bff9f8ee9149e083ade3fe11256f29685949888 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 10 Dec 2024 21:48:31 +0100 Subject: [PATCH 20/26] Fixes simu hp reduction when no partner was on field (#5799) --- include/constants/pokemon.h | 5 +++-- src/battle_util.c | 2 +- src/pokemon.c | 7 +++++++ test/battle/spread_moves.c | 22 ++++++++++++++++++++++ 4 files changed, 33 insertions(+), 3 deletions(-) diff --git a/include/constants/pokemon.h b/include/constants/pokemon.h index ab0f6b8453..86ddde5032 100644 --- a/include/constants/pokemon.h +++ b/include/constants/pokemon.h @@ -323,8 +323,9 @@ enum EvolutionMode { // - Unown has 1 frame, presumably to avoid the work of animating all 28 of its forms #define MAX_MON_PIC_FRAMES 2 -#define BATTLE_ALIVE_EXCEPT_BATTLER 0 -#define BATTLE_ALIVE_SIDE 1 +#define BATTLE_ALIVE_EXCEPT_BATTLER 0 +#define BATTLE_ALIVE_EXCEPT_BATTLER_SIDE 1 +#define BATTLE_ALIVE_SIDE 2 #define SKIP_FRONT_ANIM (1 << 7) diff --git a/src/battle_util.c b/src/battle_util.c index 36c994f2aa..689f4e0d76 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3696,7 +3696,7 @@ u8 AtkCanceller_UnableToUseMove(u32 moveType) } } if (moveTarget == MOVE_TARGET_BOTH) - gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_SIDE, gBattlerAttacker); + gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER_SIDE, gBattlerAttacker); else gBattleStruct->numSpreadTargets = CountAliveMonsInBattle(BATTLE_ALIVE_EXCEPT_BATTLER, gBattlerAttacker); diff --git a/src/pokemon.c b/src/pokemon.c index 026ceceed2..d377af1c42 100644 --- a/src/pokemon.c +++ b/src/pokemon.c @@ -2074,6 +2074,13 @@ u8 CountAliveMonsInBattle(u8 caseId, u32 battler) retVal++; } break; + case BATTLE_ALIVE_EXCEPT_BATTLER_SIDE: + for (i = 0; i < MAX_BATTLERS_COUNT; i++) + { + if (i != battler && i != BATTLE_PARTNER(battler) && !(gAbsentBattlerFlags & (1u << i))) + retVal++; + } + break; case BATTLE_ALIVE_SIDE: for (i = 0; i < MAX_BATTLERS_COUNT; i++) { diff --git a/test/battle/spread_moves.c b/test/battle/spread_moves.c index 7b395a1cc2..5228e3041f 100644 --- a/test/battle/spread_moves.c +++ b/test/battle/spread_moves.c @@ -411,3 +411,25 @@ DOUBLE_BATTLE_TEST("Spread Moves: Doesn't affect message on both opposing mons") MESSAGE("It doesn't affect the opposing Pidgey and Hoothoot…"); } } + +DOUBLE_BATTLE_TEST("Spread Moves: Unless move hits every target user will not include partner in the target count") +{ + GIVEN { + PLAYER(SPECIES_SANDSLASH); + PLAYER(SPECIES_WYNAUT) { HP(1); } + PLAYER(SPECIES_RALTS); + OPPONENT(SPECIES_TORKOAL); + OPPONENT(SPECIES_TORKOAL); + } WHEN { + TURN { MOVE(opponentRight, MOVE_ICY_WIND); MOVE(playerLeft, MOVE_ROCK_SLIDE); SEND_OUT(playerRight, 2); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_ICY_WIND, opponentRight); + HP_BAR(playerLeft); + HP_BAR(playerRight); + + ANIMATION(ANIM_TYPE_MOVE, MOVE_ROCK_SLIDE, playerLeft); + HP_BAR(opponentLeft); + HP_BAR(opponentRight); + MESSAGE("It's super effective on the opposing Torkoal and Torkoal!"); + } +} From 7eee3b35c2a5d607d5f3b2037dc96067052e5347 Mon Sep 17 00:00:00 2001 From: Eduardo Quezada Date: Wed, 11 Dec 2024 05:05:09 -0300 Subject: [PATCH 21/26] Added missing tests + Fix Coaching/Crafty Shield interaction (#5796) Co-authored-by: hedara90 <90hedara@gmail.com> --- src/battle_util.c | 4 +- test/battle/ability/flower_gift.c | 27 +++++- test/battle/move_effect/coaching.c | 122 ++++++++++++++++++++++++- test/battle/move_effect/cosmic_power.c | 19 +++- test/test_runner.c | 5 + 5 files changed, 168 insertions(+), 9 deletions(-) diff --git a/src/battle_util.c b/src/battle_util.c index 9cb4da700b..d2f5314742 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -8633,8 +8633,8 @@ bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move) && IsMoveMakingContact(move, gBattlerAttacker) && GetBattlerAbility(gBattlerAttacker) == ABILITY_UNSEEN_FIST) return FALSE; - else if (gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD - && IS_MOVE_STATUS(move)) + else if ((gSideStatuses[GetBattlerSide(battlerDef)] & SIDE_STATUS_CRAFTY_SHIELD) + && IS_MOVE_STATUS(move) && gMovesInfo[move].effect != EFFECT_COACHING) return TRUE; else if (gMovesInfo[move].ignoresProtect) return FALSE; diff --git a/test/battle/ability/flower_gift.c b/test/battle/ability/flower_gift.c index 68712641e0..5ceb26c5c1 100644 --- a/test/battle/ability/flower_gift.c +++ b/test/battle/ability/flower_gift.c @@ -63,7 +63,32 @@ SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim back to normal when its abili } } -TO_DO_BATTLE_TEST("Forecast transforms Castform back to normal under Cloud Nine/Air Lock"); +SINGLE_BATTLE_TEST("Flower Gift transforms Cherrim back to normal under Cloud Nine/Air Lock") +{ + u32 species = 0, ability = 0; + PARAMETRIZE { species = SPECIES_PSYDUCK; ability = ABILITY_CLOUD_NINE; } + PARAMETRIZE { species = SPECIES_RAYQUAZA; ability = ABILITY_AIR_LOCK; } + GIVEN { + PLAYER(SPECIES_CHERRIM_OVERCAST) { Ability(ABILITY_FLOWER_GIFT); } + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(species) { Ability(ability); } + } WHEN { + TURN { MOVE(player, MOVE_SUNNY_DAY); } + TURN { SWITCH(opponent, 1); } + } SCENE { + // transforms + ABILITY_POPUP(player, ABILITY_FLOWER_GIFT); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Cherrim transformed!"); + // back to normal + ABILITY_POPUP(opponent, ability); + ABILITY_POPUP(player, ABILITY_FLOWER_GIFT); + ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_FORM_CHANGE, player); + MESSAGE("Cherrim transformed!"); + } THEN { + EXPECT_EQ(player->species, SPECIES_CHERRIM_OVERCAST); + } +} DOUBLE_BATTLE_TEST("Flower Gift increases the attack of Cherrim and its allies by 1.5x", s16 damageL, s16 damageR) { diff --git a/test/battle/move_effect/coaching.c b/test/battle/move_effect/coaching.c index 2f50aceab5..451ac80495 100644 --- a/test/battle/move_effect/coaching.c +++ b/test/battle/move_effect/coaching.c @@ -1,8 +1,120 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Coaching raises Attack and Defense of ally by 1 stage each"); -TO_DO_BATTLE_TEST("Coaching doesn't raise stats of the user"); -TO_DO_BATTLE_TEST("Coaching bypasses protection of allies"); -TO_DO_BATTLE_TEST("Coaching fails in single battles"); -TO_DO_BATTLE_TEST("Coaching fails if there's no ally"); +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_COACHING].effect == EFFECT_COACHING); +} + +DOUBLE_BATTLE_TEST("Coaching raises Attack and Defense of ally by 1 stage each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_COACHING, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft); + MESSAGE("Wynaut's Attack rose!"); + MESSAGE("Wynaut's Defense rose!"); + } +} + +DOUBLE_BATTLE_TEST("Coaching bypasses Protect") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_PROTECT].effect == EFFECT_PROTECT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerRight, MOVE_PROTECT); MOVE(playerLeft, MOVE_COACHING, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft); + MESSAGE("Wynaut's Attack rose!"); + MESSAGE("Wynaut's Defense rose!"); + } +} + +DOUBLE_BATTLE_TEST("Coaching bypasses Crafty Shield") +{ + GIVEN { + ASSUME(gMovesInfo[MOVE_CRAFTY_SHIELD].effect == EFFECT_PROTECT); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerRight, MOVE_CRAFTY_SHIELD); MOVE(playerLeft, MOVE_COACHING, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft); + MESSAGE("Wynaut's Attack rose!"); + MESSAGE("Wynaut's Defense rose!"); + } +} + +DOUBLE_BATTLE_TEST("Coaching fails if all allies are is semi-invulnerable") +{ + KNOWN_FAILING; // Coaching succeeds + GIVEN { + ASSUME(gMovesInfo[MOVE_FLY].effect == EFFECT_SEMI_INVULNERABLE); + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_HAWLUCHA); + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerRight, MOVE_FLY, target: opponentLeft); MOVE(playerLeft, MOVE_COACHING, target: playerRight); } + } SCENE { + MESSAGE("Hawlucha used Fly!"); + MESSAGE("Wobbuffet used Coaching!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft); + MESSAGE("Hawlucha's Attack rose!"); + MESSAGE("Hawlucha's Defense rose!"); + } + MESSAGE("But it failed!"); + } +} + +SINGLE_BATTLE_TEST("Coaching fails in single battles") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_COACHING); } + } SCENE { + MESSAGE("But it failed!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, player); + MESSAGE("Wynaut's Attack rose!"); + MESSAGE("Wynaut's Defense rose!"); + } + } +} + +DOUBLE_BATTLE_TEST("Coaching fails if there's no ally") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + PLAYER(SPECIES_WYNAUT) { HP(1); }; + OPPONENT(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(playerLeft, MOVE_TACKLE, target: playerRight); } + TURN { MOVE(playerLeft, MOVE_COACHING, target: playerRight); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_TACKLE, playerLeft); + MESSAGE("Wynaut fainted!"); + MESSAGE("Wobbuffet used Coaching!"); + NONE_OF { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COACHING, playerLeft); + MESSAGE("Wynaut's Attack rose!"); + MESSAGE("Wynaut's Defense rose!"); + } + MESSAGE("But it failed!"); + } +} diff --git a/test/battle/move_effect/cosmic_power.c b/test/battle/move_effect/cosmic_power.c index 8680e9f28e..3b52fbe046 100644 --- a/test/battle/move_effect/cosmic_power.c +++ b/test/battle/move_effect/cosmic_power.c @@ -1,4 +1,21 @@ #include "global.h" #include "test/battle.h" -TO_DO_BATTLE_TEST("Cosmic Power increases the user's Defense and Sp. Defense by 1 stage each"); +ASSUMPTIONS +{ + ASSUME(gMovesInfo[MOVE_COSMIC_POWER].effect == EFFECT_COSMIC_POWER); +} + +SINGLE_BATTLE_TEST("Cosmic Power increases the user's Defense and Sp. Defense by 1 stage each") +{ + GIVEN { + PLAYER(SPECIES_WOBBUFFET); + OPPONENT(SPECIES_WOBBUFFET); + } WHEN { + TURN { MOVE(player, MOVE_COSMIC_POWER); } + } SCENE { + ANIMATION(ANIM_TYPE_MOVE, MOVE_COSMIC_POWER, player); + MESSAGE("Wobbuffet's Defense rose!"); + MESSAGE("Wobbuffet's Sp. Def rose!"); + } +} diff --git a/test/test_runner.c b/test/test_runner.c index 1ff37fe8bc..d3196a20e1 100644 --- a/test/test_runner.c +++ b/test/test_runner.c @@ -356,9 +356,14 @@ top: if (gTestRunnerState.result == TEST_RESULT_PASS) { if (gTestRunnerState.result != gTestRunnerState.expectedResult) + { + Test_MgbaPrintf(":L%s:%d", gTestRunnerState.test->filename, SourceLine(0)); Test_MgbaPrintf(":U%s%s\e[0m", color, result); + } else + { Test_MgbaPrintf(":P%s%s\e[0m", color, result); + } } else if (gTestRunnerState.result == TEST_RESULT_ASSUMPTION_FAIL) Test_MgbaPrintf(":A%s%s\e[0m", color, result); From a669c4c10901ae2adf22bd907c07eb2aa2815c3a Mon Sep 17 00:00:00 2001 From: kittenchilly Date: Fri, 13 Dec 2024 08:26:12 -0600 Subject: [PATCH 22/26] New Enamorus-Incarnate sprite (#5797) --- graphics/pokemon/enamorus/anim_front.png | Bin 0 -> 1755 bytes graphics/pokemon/enamorus/back.png | Bin 734 -> 773 bytes graphics/pokemon/enamorus/front.png | Bin 785 -> 0 bytes graphics/pokemon/enamorus/normal.pal | 28 ++++++++-------- graphics/pokemon/enamorus/shiny.pal | 30 +++++++++--------- src/data/graphics/pokemon.h | 2 +- .../pokemon/species_info/gen_8_families.h | 4 +-- src/data/pokemon_graphics/front_pic_anims.h | 2 +- 8 files changed, 33 insertions(+), 33 deletions(-) create mode 100644 graphics/pokemon/enamorus/anim_front.png delete mode 100755 graphics/pokemon/enamorus/front.png diff --git a/graphics/pokemon/enamorus/anim_front.png b/graphics/pokemon/enamorus/anim_front.png new file mode 100644 index 0000000000000000000000000000000000000000..e4b21fc52aeb8b64b517601826a4875021dd5736 GIT binary patch literal 1755 zcmV<11|<23P)EX>4Tx04R}tkv&MmKpe$iQ^g_`hjx(SkfAzR5ET(zq>4qbP}&NuI+$Gg1x*@~ z6cyJ6ykH@F@r8h{K$3LSDQzS=msDr--A9s!_g> zb6MfM#aXS^S^J*+g~5WhlHoedVI;7GBvKF|qmBxyun?nFBgI6T_TwJ@h~rO@OD0zZ zj2sK7L51Y_!T;cQw`Os2!c7Xsf!-I}{ulxJc7ayIw!e>UyLAHipMfi_?J%DuE$-~a#sFi=cXMVZs3|NsBAw7qF+a}W>^?SZPf zQH6diM*quE$ueM_Bt0l7D6wsadrxjsGD~k7FRigaQvd(}32;bRa{vG?BLDy{BLR4& zKXw2B00(qQO+^Rj3uO|&v< zl17$^8=FLHFju4qhN}ZU*r;%GTwv9tFa&GmtFF^3l{SUzAL%`FxX~wLCi)2p%gR>>E7K8w?I1m8xI(MRw&g28UQd z{?v16IM&y4q?2pEF zf8>c2L)&F+=nMq)g0f?0aK5+F{;q91-QLzQYQU#u&29UrgKpbKvHu z7Rj|phE?H9F`JcnL^uazQ88B4|TUFYDWFvwP4%XafvTleEpYxoxgxWH5lF zR`I7+tJ5;99$0a@qSmc%Xvf@aeZ8td0TiV`b!E-k>hZ4x2oRe_F@Mrj03~Uu%Ql!H zVI+M4Caox1f_w=p%?SH!X7w7_Dh?p*7f0`j;x`;3SG(*I6k%@i* z3=z|XwYLbc%n%V>e6$($CWs+Iy0AKt0Ah%cF7`Wd0|gi&qKkMCVu+9~?()bP;u@xl zg>9reMobrr4tNdI1@Zkb5z}-4sr2#p-J*Z#@l*1rlM{e0B#r*uVEmMPZvyr#**T${ zKiJ5doKdJCp12`@+zi+i=trOR`2mbr(7oa2f8Jo{PUBoyl+&^Mngfb2#IWh9Jqi}# zT?rJkVV_rl%^z=I#iJW%GK^3oHa9DT}|>u`=@6F9`5e^44D3LIj8{)6+Xv%ez* zko}M^GUlELK<2x4`>2^|6EuSbIo`V4&D@tfscjEA%4ISLd3%Qk|M4Y(yIc_F)pkTHHxS%)>P0^yxa-v2&wsIzF5wxV+o@wP*4Oo% zeBj_b+Oyz}35*bcgUfKwf@>F`f8eB_z*zvhK~O+D4t4;@^hbc}0H6Y(09^BL1@x)_ zH3y`nABSoI9O|$e7&t7Tn_18Aq$v8afx3neoXD6kV>{Rf99ckA8P-3_*g&tVJWm2= z(02$%ecAPWqJLS>yXGbau0E6oKmbZA*z}5^GKv*?Lu57egjHS{cj)B@N` zm=A^$XjkLwpfo|$66A8OxeG{-^vtkWV7EsJ1yiDtzm_zjHbH8mmNAV9v M07*qoM6N<$f*H?OF#rGn delta 691 zcmV;k0!;md2HpjbH-FNkbv#i@N=l6(A;3>E^js6OX0@nSZU4nQ>4)dfgPydsy$}!( z{QUd?0000009>-HTmS$9TuDShR9JG|hZqrPn$3uzNWS`XE2gzo>z-``bCTjvnulz#=4d@dGk4Xr5z1=xOZx=vbzkpSkXM-UNz``a@U^YEb3ZeQ%oFK3mu%625mxZMy z{X}~=em)rh71nY&q!*P?KP3X#0}z1JlOdZDY6*p504`!tHQWvPs$$guseZn4DuPp{R2=s7Z-C_V9 zAe*k0XpfU0M8?NE@V2HewuoQK*f`x z5VfFO2rz=jBCagUx`qjy1wjk~xhr9U)dA8GXMF}R>VN3zG{Tw&c>eM^@QbadPeq6q z0=GKul?XbaBk@wlQyu~Y*6U2XbV8<*SmuGCn+KsnsQ0ss)e4MCW^&*oiHBlUL$(SB zpw*KZE)0NP-FT8-2&KKx)!{(n<)*nAhk>O80WfEGf>Iz~+52dBfChU3m`h`Sc006o&R`DYPkVRjU=R1NvA|uZyOXFsm1HfCeP#N)x zQ5W`Wk9E!V_AbxTuLO)I$HTV6z9oYPx#Fi=cXMVZp1b}~9jN=lO<9>*>z^DZvCK3=X$SO3L4^Hh)Ebey!by$}!({QUd? z000000Ngc#c>n+ck4Z#9R9J=0m)m;dFbISLwqz@y_kZ1;L5g$ewiSD|BtA4>=NAHm z<=gFlHHCfNW#rajdfizPp;W7apyOu1a(Y~G?%_Uu@FYOT)%x{IhTs9P2f+RTz@R~m zui1!1ZVpa>&-iJiBBci)2o&+8W|jj4L1zgm_32V_iZK5ka?h6{$7K||g)g_8z%u%6 zv%YOiLxfM{4$Ba>vKbGH1cv;6KN5tkl$}T8Qkr@Y7IT5wZqV{*b^(x*Re)D%m!XD+ zzLW%@Zrj#)1VDA_R{k;$Xz6A*f+bA{yk>HycW=K!+% zi&b=}-BX#A9ZhWyt1vKd%INX`;`>Fw%J3Ayxdxs9Kg7|dQ$a*S6r2!B0-!D_eYAs0 z3VJh8xaML=f>h^YrG#FxauNn0^e6&J?pB8bWdh*AW1FyO%B;-@GzY`E(OBIladXt& zyAA;En~(kSnh)IAMMLdcntD7~#@}muttlRa{$`5+>))6y0rYd&H~m5sH8#lK5Ol!< zCfw|=2wR$if7R0`oBAZco`8p~%t0Rnn_JyW@3D3Nt(@FG?bU&W7qG8@H`u7KpAZ9} z*O;IBSQkI~;6A1s=WzRlh3B;Y{{H0iWygm<9t29qi$|`#4UDII;=26-s*En^!SKK) P00000NkvXXu0mjf$JTVe diff --git a/graphics/pokemon/enamorus/normal.pal b/graphics/pokemon/enamorus/normal.pal index 43c4eb7a07..b8986ffd46 100755 --- a/graphics/pokemon/enamorus/normal.pal +++ b/graphics/pokemon/enamorus/normal.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -153 210 164 -118 50 58 -74 74 74 -147 33 30 -199 46 41 -243 46 46 -187 62 94 -174 74 87 -255 197 60 -243 84 143 -224 116 156 +153 211 165 +255 255 255 180 180 189 +105 106 115 16 16 16 -252 252 252 -0 0 0 -0 0 0 +237 129 170 +185 81 133 +126 44 70 +255 203 81 +201 50 96 +157 36 61 +40 40 40 +177 109 135 +123 79 110 +82 50 75 +111 26 47 diff --git a/graphics/pokemon/enamorus/shiny.pal b/graphics/pokemon/enamorus/shiny.pal index edbd1c73cb..41b6650a75 100644 --- a/graphics/pokemon/enamorus/shiny.pal +++ b/graphics/pokemon/enamorus/shiny.pal @@ -1,19 +1,19 @@ JASC-PAL 0100 16 -153 210 164 -117 60 81 -74 74 74 -141 33 33 -192 79 50 -244 92 19 -179 102 181 -168 87 109 -255 197 60 -233 135 231 -207 131 158 -180 180 189 +153 211 165 +255 255 255 +194 184 173 +115 107 104 16 16 16 -252 252 252 -0 0 0 -0 0 0 +251 142 224 +198 83 185 +127 58 131 +255 197 32 +246 81 4 +205 35 35 +40 40 40 +230 131 164 +189 82 106 +107 51 74 +140 29 49 diff --git a/src/data/graphics/pokemon.h b/src/data/graphics/pokemon.h index 39b11560d4..8801942e53 100644 --- a/src/data/graphics/pokemon.h +++ b/src/data/graphics/pokemon.h @@ -18880,7 +18880,7 @@ const u32 gObjectEventPic_Substitute[] = INCBIN_COMP("graphics/pokemon/question_ #endif //P_FAMILY_LANDORUS #if P_FAMILY_ENAMORUS - const u32 gMonFrontPic_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/front.4bpp.lz"); + const u32 gMonFrontPic_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/anim_front.4bpp.lz"); const u32 gMonPalette_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/normal.gbapal.lz"); const u32 gMonBackPic_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/back.4bpp.lz"); const u32 gMonShinyPalette_EnamorusIncarnate[] = INCBIN_U32("graphics/pokemon/enamorus/shiny.gbapal.lz"); diff --git a/src/data/pokemon/species_info/gen_8_families.h b/src/data/pokemon/species_info/gen_8_families.h index fd86f22ddc..ee08542523 100644 --- a/src/data/pokemon/species_info/gen_8_families.h +++ b/src/data/pokemon/species_info/gen_8_families.h @@ -7660,7 +7660,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .trainerOffset = 1, .frontPic = gMonFrontPic_EnamorusIncarnate, .frontPicSize = MON_COORDS_SIZE(64, 64), - .frontPicYOffset = 1, + .frontPicYOffset = 0, .frontAnimFrames = sAnims_EnamorusIncarnate, //.frontAnimId = ANIM_V_SQUISH_AND_BOUNCE, .enemyMonElevation = 7, @@ -7672,7 +7672,7 @@ const struct SpeciesInfo gSpeciesInfoGen8[] = .shinyPalette = gMonShinyPalette_EnamorusIncarnate, .iconSprite = gMonIcon_EnamorusIncarnate, .iconPalIndex = 1, - SHADOW(0, 17, SHADOW_SIZE_M) + SHADOW(-3, 19, SHADOW_SIZE_M) FOOTPRINT(Enamorus) OVERWORLD( sPicTable_EnamorusIncarnate, diff --git a/src/data/pokemon_graphics/front_pic_anims.h b/src/data/pokemon_graphics/front_pic_anims.h index deceeb0420..56ec319a57 100644 --- a/src/data/pokemon_graphics/front_pic_anims.h +++ b/src/data/pokemon_graphics/front_pic_anims.h @@ -9794,7 +9794,7 @@ PLACEHOLDER_ANIM_SINGLE_FRAME(Calyrex); #endif //P_FAMILY_CALYREX #if P_FAMILY_ENAMORUS -PLACEHOLDER_ANIM_SINGLE_FRAME(EnamorusIncarnate); +PLACEHOLDER_ANIM_TWO_FRAMES(EnamorusIncarnate); PLACEHOLDER_ANIM_SINGLE_FRAME(EnamorusTherian); #endif //P_FAMILY_ENAMORUS From 3b594e2f38902f8e4dd9ed5a9a062ee72e199714 Mon Sep 17 00:00:00 2001 From: hedara90 <90hedara@gmail.com> Date: Sun, 15 Dec 2024 21:11:13 +0100 Subject: [PATCH 23/26] Updating install instructions (#5610) Co-authored-by: Hedara --- INSTALL.md | 588 +++-------------------------- docs/install/chromeos/CHROME_OS.md | 14 + docs/install/linux/ARCH_LINUX.md | 6 + docs/install/linux/DEBIAN.md | 6 + docs/install/linux/NIXOS.md | 5 + docs/install/linux/OTHERS.md | 11 + docs/install/linux/UBUNTU.md | 6 + docs/install/mac/MAC_OS.md | 93 +++++ docs/install/windows/CYGWIN.md | 4 + docs/install/windows/MSYS2.md | 4 + docs/install/windows/WSL.md | 87 +++++ 11 files changed, 289 insertions(+), 535 deletions(-) create mode 100644 docs/install/chromeos/CHROME_OS.md create mode 100644 docs/install/linux/ARCH_LINUX.md create mode 100644 docs/install/linux/DEBIAN.md create mode 100644 docs/install/linux/NIXOS.md create mode 100644 docs/install/linux/OTHERS.md create mode 100644 docs/install/linux/UBUNTU.md create mode 100644 docs/install/mac/MAC_OS.md create mode 100644 docs/install/windows/CYGWIN.md create mode 100644 docs/install/windows/MSYS2.md create mode 100644 docs/install/windows/WSL.md diff --git a/INSTALL.md b/INSTALL.md index fc1aeb5ba8..25e6adb428 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -1,564 +1,82 @@ # Instructions +Install instructions for each supported operating system can be found in their respective directories under `docs/install/`. +Lines to those can be found under each heading. +This file only contains a short introduction to each supported system. +If you run into trouble, ask for help on Discord (see [README.md](README.md)). -These instructions explain how to set up the tools required to build **pokeemerald Expansion**, which assembles the source files into a ROM (pokeemerald.gba). - -These instructions come with notes which can be expanded by clicking the "Note..." text. -In general, you should not need to open these unless if you get an error or if you need additional clarification. - -If you run into trouble, ask for help on Discord or IRC (see [README.md](README.md)). +After completing the install instructions for your OS, proceed to [Building pokeemerald-expansion](#building-pokeemerald-expansion). ## Windows -Windows has instructions for building with three possible terminals, providing 3 different options in case the user stumbles upon unexpected errors. -- [Windows 10/11 (WSL1)](#windows-1011-wsl1) (**Fastest, highly recommended**, Windows 10 and 11 only) -- [Windows (msys2)](#windows-msys2) (Second fastest) -- [Windows (Cygwin)](#windows-cygwin) (Slowest) - -Unscientific benchmarks suggest **msys2 is 2x slower** than WSL1, and **Cygwin is 5-6x slower** than WSL1. - - -All of the Windows instructions assume that the default drive is C:\\. If this differs to your actual drive letter, then replace C with the correct drive letter when reading the instructions. +**Windows needs one of the systems to build the project** **A note of caution**: As Windows 7 and Windows 8 are officially unsupported by Microsoft, some maintainers are unwilling to maintain the Windows 7/8 instructions. Thus, these instructions may break in the future with fixes taking longer than fixes to the Windows 10/11 instructions. -## Windows 10/11 (WSL1) -WSL1 is the preferred terminal to build **pokeemerald Expansion**. The following instructions will explain how to install WSL1 (referred to interchangeably as WSL). -- If WSL (Debian or Ubuntu) is **not installed**, then go to [Installing WSL1](#Installing-WSL1). -- Otherwise, if WSL is installed, but it **hasn't previously been set up for another decompilation project**, then go to [Setting up WSL1](#Setting-up-WSL1). -- Otherwise, **open WSL** and go to [Choosing where to store pokeemerald Expansion (WSL1)](#Choosing-where-to-store-pokeemerald-expansion-WSL1). +On Windows, the project can be built using the following systems: +- WSL2, fastest +- WSL1, 7 times slower than WSL2 +- Msys2, 20 times slower than WSL2 (**NOTE**: Currently broken on pret upstream) +- Cygwin, 30 timer slower than WSL2 (**NOTE**: Currently broken on pret upstream) -### Installing WSL1 -1. Open [Windows Powershell **as Administrator**](https://i.imgur.com/QKmVbP9.png), and run the following commands (Right Click or Shift+Insert is paste in the Powershell). +**NOTE**: Only WSL systems are recommended. - ```powershell - wsl --install -d Ubuntu --enable-wsl1 - ``` +[WSL Install instructions](docs/install/windows/WSL.md) -2. Once the process finishes, restart your machine. +[Msys2 Install instructions](docs/install/windows/MSYS2.md) -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 - ``` -
- Note... - - > WSL may open automatically after restarting, but you can ignore it for now. -
- -### Setting up WSL1 -Some tips before proceeding: -- In WSL, Copy and Paste is either done via - - **right-click** (selection + right click to Copy, right click with no selection to Paste) - - **Ctrl+Shift+C/Ctrl+Shift+V** (enabled by right-clicking the title bar, going to Properties, then checking the checkbox next to "Use Ctrl+Shift+C/V as Copy/Paste"). -- Some of the commands that you'll run will ask for your WSL password and/or confirmation to perform the stated action. This is to be expected, just enter your WSL password and/or the yes action when necessary. - -1. Open **Ubuntu** (e.g. using Search). -2. WSL/Ubuntu will set up its own installation when it runs for the first time. Once WSL/Ubuntu finishes installing, it will ask for a username and password (to be input in). -
- Note... - - > When typing in the password, there will be no visible response, but the terminal will still read in input. -
- -3. Update WSL/Ubuntu before continuing. Do this by running the following command. These commands will likely take a long time to finish: - - ```bash - sudo apt update && sudo apt upgrade - ``` - -> Note: If the repository you plan to build has an **[older revision of the INSTALL.md](https://github.com/pret/pokeemerald/blob/571c598/INSTALL.md)**, then follow the [legacy WSL1 instructions](docs/legacy_WSL1_INSTALL.md) from here. - -4. Certain packages are required to build pokeemerald Expansion. Install these packages by running the following command: - - ```bash - sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev - ``` -
- Note... - - > If the above command does not work, try the above command but replacing `apt` with `apt-get`. -
- This will install GCC v10 on Ubuntu 22.04. pokeemerald Expansion works with GCC v10, but remote repositories and the RHH Team use GCC v13 for stricter error-checking. If you want to upgrade from v10 to v13, also follow the devkitpro install instructions. - -### Installing devkitARM on WSL1 - -1. Change directory to somewhere you can download a package, such as **C:\Users\\_\_\Downloads** (the Downloads location for most users). To do so, enter this command, where *\ is your **Windows** username: - - ```bash - cd /mnt/c/Users//Downloads - ``` - -2. Once the directory has been changed, run the following commands to install devkitARM. - - ```bash - sudo apt install wget - wget https://apt.devkitpro.org/install-devkitpro-pacman - chmod +x ./install-devkitpro-pacman - sudo ./install-devkitpro-pacman - sudo dkp-pacman -S gba-dev - ``` - The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. - -3. Run the following command to set devkitPro related environment variables (alternatively, close and re-open WSL): - - ```bash - source /etc/profile.d/devkit-env.sh - ``` - -devkitARM is now installed. - -### Installing Python on WSL1 - -To install Python on WSL1, simply run the following commands: - -```bash -sudo apt update && sudo apt upgrade -sudo apt install python3 -``` - -Python is now installed. - -### Choosing where to store pokeemerald Expansion (WSL1) -WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. So you're going to want to store pokeemerald Expansion within Windows. - -For example, say you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**. First, ensure that the folder already exists. Then, enter this command to **change directory** to said folder, where *\* is your **Windows** username: - -```bash -cd /mnt/c/Users//Desktop/decomps -``` - -
- Notes... - -> Note 1: The Windows C:\ drive is called /mnt/c/ in WSL. -> Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "/mnt/c/users//Desktop/decomp folder"`. -> Note 3: Windows path names are case-insensitive so adhering to capitalization isn't needed -
- -If this works, then proceed to [Installation](#installation). - -Otherwise, ask for help on Discord or IRC (see [README.md](README.md)), or continue reading below for [Windows instructions using msys2](#windows-msys2). - -## Windows (msys2) - -- If devkitARM is **not installed**, then go to [Installing devkitARM](#installing-devkitarm). -- If devkitARM is installed, but msys2 **hasn't previously been set up for another decompilation project**, then go to [Setting up msys2](#setting-up-msys2). -- Otherwise, **open msys2** and go to [Choosing where to store pokeemerald Expansion (msys2)](#choosing-where-to-store-pokeemerald-expansion-msys2). - -### Installing devkitARM -1. Download the devkitPro installer [here](https://github.com/devkitPro/installer/releases). -2. Run the devkitPro installer. In the "Choose Components" screen, uncheck everything except GBA Development unless if you plan to install other devkitPro components for other purposes. Keep the install location as C:\devkitPro and leave the Start Menu option unchanged. - -### Setting up msys2 - -Note that in msys2, Copy is Ctrl+Insert and Paste is Shift+Insert. - -1. Open msys2 at C:\devkitPro\msys2\msys2_shell.bat. - -2. Certain packages are required to build pokeemerald Expansion. Install these by running the following two commands: - - ```bash - pacman -Sy msys2-keyring - pacman -S make gcc zlib-devel git - ``` -
- Note... - - > The commands will ask for confirmation, just enter the yes action when prompted. -
- -3. Download [libpng](https://sourceforge.net/projects/libpng/files/libpng16/1.6.37/libpng-1.6.37.tar.xz/download). - -4. Change directory to where libpng was downloaded. By default, msys2 will start in the current user's profile folder, located at **C:\Users\\⁠_\_**, where *\* is your Windows username. In most cases, libpng should be saved within a subfolder of the profile folder. For example, if libpng was saved to **C:\Users\\_\_\Downloads** (the Downloads location for most users), enter this command: - - ```bash - cd Downloads - ``` - -
- Notes... - - > Note 1: While not shown, msys uses forward slashes `/` instead of backwards slashes `\` as the directory separator. - > Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "Downloads/My Downloads"`. - > Note 3: Windows path names are case-insensitive so adhering to capitalization isn’t needed. - > Note 4: If libpng was saved elsewhere, you will need to specify the full path to where libpng was downloaded, e.g. `cd c:/devkitpro/msys2` if it was saved there. -
- -5. Run the following commands to uncompress and install libpng. - - ```bash - tar xf libpng-1.6.37.tar.xz - cd libpng-1.6.37 - ./configure --prefix=/usr - make check - make install - ``` - -6. Then finally, run the following command to change back to the user profile folder. - - ```bash - cd - ``` - -### Installing Python on msys2 - -To install Python on msys2, simply run the following commands: - -```bash -pacman -S mingw-w64-x86_64-python3 -``` - -Python is now installed. - -### Choosing where to store pokeemerald Expansion (msys2) -At this point, you can choose a folder to store pokeemerald Expansion into. If you're okay with storing pokeemerald Expansion in the user profile folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald Expansion is stored when changing directory to the pokeemerald-expansion folder. - -For example, if you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps** (where *\* is your **Windows** username), enter this command: - -```bash -cd Desktop/decomps -``` - -If this works, then proceed to [Installation](#installation). - -Otherwise, ask for help on Discord or IRC (see [README.md](README.md)), or continue reading below for [Windows instructions using Cygwin](#windows-cygwin). - -## Windows (Cygwin) -1. If devkitARM is **not installed**, then follow the instructions used to [install devkitARM](#installing-devkitarm) for the msys2 setup before continuing. *Remember to not continue following the msys2 instructions by mistake!* - -2. - - If Cygwin is **not installed**, or does not have all of the required packages installed, then go to [Installing Cygwin](#installing-cygwin). - - If Cygwin is installed, but **is not configured to work with devkitARM**, then go to [Configuring devkitARM for Cygwin](#configuring-devkitarm-for-cygwin). - - Otherwise, **open Cygwin** and go to [Choosing where to store pokeemerald Expansion (Cygwin)](#choosing-where-to-store-pokeemerald-expansion-cygwin) - -### Installing Cygwin -1. Download [Cygwin](https://cygwin.com/install.html): setup-x86_64.exe for 64-bit Windows, setup-x86.exe for 32-bit. - -2. Run the Cygwin setup. Within the Cygwin setup, leave the default settings until the "Choose A Download Site" screen. - -3. At "Choose a Download Site", select any mirror within the Available Download Sites. - -4. At "Select Packages", set the view to "Full" (top left) and search for the following packages: - - `make` - - `git` - - `gcc-core` - - `gcc-g++` - - `libpng-devel` - - To quickly find these, use the search bar and type the name of each package. Ensure that the selected package name is the **exact** same as the one you're trying to download, e.g. `cmake` is **NOT** the same as `make`. - -5. For each package, double click on the text that says "**Skip**" next to each package to select the most recent version to install. If the text says anything other than "**Skip**", (e.g. Keep or a version number), then the package is or will be installed and you don't need to do anything. - -6. Once all required packages have been selected, finish the installation. - -### Configuring devkitARM for Cygwin - -Note that in Cygwin, Copy is Ctrl+Insert and Paste is Shift+Insert. - -1. Open **Cygwin**. - -2. Run the following commands to configure devkitPro to work with Cygwin. - - ```bash - export DEVKITPRO=/cygdrive/c/devkitpro - echo export DEVKITPRO=$DEVKITPRO >> ~/.bashrc - export DEVKITARM=$DEVKITPRO/devkitARM - echo export DEVKITARM=$DEVKITARM >> ~/.bashrc - ``` - -
- Note... - - > Replace the drive letter c with the actual drive letter if it is not c. -
- -### Choosing where to store pokeemerald Expansion (Cygwin) - -Cygwin has its own file system that's within Windows, at **C:\cygwin64\home\\_\_**. If you don't want to store pokeemerald Expansion there, you'll need to account for where ppokeemerald Expansion is stored when **changing directory** to the pokeemerald-expansion folder. - -For example, if you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**, enter this command, where *\* is your **Windows** username: -```bash -cd c:/Users//Desktop/decomps -``` -Note that the directory **must exist** in Windows. If you want to store pokeemerald Expansion in a dedicated folder that doesn't exist (e.g. the example provided above), then create the folder (e.g. using Windows Explorer) before executing the `cd` command. - -
- Notes... - -> Note 1: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "c:/users//Desktop/decomp folder"`. -> Note 2: Windows path names are case-insensitive so adhering to capitalization isn't needed -
- -If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)). - -## macOS -1. If the Xcode Command Line Tools are not installed, download the tools [here](https://developer.apple.com/xcode/resources/), open your Terminal, and run the following command: - - ```bash - xcode-select --install - ``` - -2. - If libpng is **not installed**, then go to [Installing libpng (macOS)](#installing-libpng-macos). - - If pkg-config is **not installed**, then go to [Installing pkg-config (macos)](#installing-pkg-config-macos). - - If devkitARM is **not installed**, then go to [Installing devkitARM (macOS)](#installing-devkitarm-macos). - - Otherwise, **open the Terminal** and go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos) - -### Installing libpng (macOS) -
- Note for advanced users... - -> This guide installs libpng via Homebrew as it is the easiest method, however advanced users can install libpng through other means if they so desire. -
- -1. Open the Terminal. -2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website. -3. Run the following command to install libpng. - - ```bash - brew install libpng - ``` - libpng is now installed. - - Continue to [Installing pkg-config (macOS)](#installing-pkg-config-macos) if **pkg-config is not installed**. Otherwise, continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**. - - If both pkg-config and devkitARM are already installed, go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos). - -### Installing pkg-config (macOS) -
- Note for advanced users... - -> This guide installs pkg-config via Homebrew as it is the easiest method, however advanced users can install pkg-config through other means if they so desire. -
- -1. Open the Terminal. -2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website. -3. Run the following command to install libpng. - - ```bash - brew install pkg-config - ``` - pkg-config is now installed. - - Continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**, otherwise, go to [Choosing where to store pokeemerald Expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos). - -### Installing devkitARM (macOS) -1. Download the `devkitpro-pacman-installer.pkg` package from [here](https://github.com/devkitPro/pacman/releases). -2. Open the package to install devkitPro pacman. -3. In the Terminal, run the following commands to install devkitARM: - - ```bash - sudo dkp-pacman -Sy - sudo dkp-pacman -S gba-dev - sudo dkp-pacman -S devkitarm-rules - ``` - - The command with gba-dev will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. - -4. After the tools are installed, devkitARM must now be made accessible from anywhere by the system. To do so, run the following commands: - - ```bash - export DEVKITPRO=/opt/devkitpro - echo "export DEVKITPRO=$DEVKITPRO" >> ~/.zshrc - export DEVKITARM=$DEVKITPRO/devkitARM - echo "export DEVKITARM=$DEVKITARM" >> ~/.zshrc - - echo "if [ -f ~/.zshrc ]; then . ~/.zshrc; fi" >> ~/.zprofile - ``` - *Note: Starting with macOS 10.15, the default Unix shell is now zsh. If you migrated from an older version of macOS, you might still be using bash. You can check my running `echo $0` in the terminal.* -
- If your terminal is using bash instead of zsh... - - ```bash - export DEVKITPRO=/opt/devkitpro - echo "export DEVKITPRO=$DEVKITPRO" >> ~/.bashrc - export DEVKITARM=$DEVKITPRO/devkitARM - echo "export DEVKITARM=$DEVKITARM" >> ~/.bashrc - - echo "if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile - ``` -
- -### Installing Python (macOS) -1. Download the latest Python package from [here](https://www.python.org/downloads/). -2. Open the package to install Python. - -Python is now installed. - -### Choosing where to store pokeemerald Expansion (macOS) -At this point, you can choose a folder to store pokeemerald Expansion into. If you're okay with storing pokeemerald Expansion in the user folder, then proceed to [Installation](#installation). Otherwise, you'll need to account for where pokeemerald Expansion is stored when changing directory to the pokeemerald-expansion folder. - -For example, if you want to store pokeemerald Expansion in **~/Desktop/decomps**, enter this command to **change directory** to the desired folder: -```bash -cd Desktop/decomps -``` -Note that the directory **must exist** in the folder system. If you want to store pokeemerald Expansion in a dedicated folder that doesn't exist (e.g. the example provided above), then create the folder (e.g. using Finder) before executing the `cd` command. - -
- Note... - -> Note: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "Desktop/decomp folder"` -
- -If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)). +[Cygwin Install instructions](docs/install/windows/CYGWIN.md) ## Linux -Open Terminal and enter the following commands, depending on which distro you're using. +The project can be built on any Linux distribution. +Distributions with instructions: +- [Ubuntu](docs/install/linux/UBUNTU.md) +- [Debian](docs/install/linux/DEBIAN.md) +- [Arch Linux](docs/install/linux/ARCH_LINUX.md) +- [NixOS](docs/install/linux/NIXOS.md) -### Debian/Ubuntu-based distributions -Run the following command to install the necessary packages: -```bash -sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev -``` -Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux). -
- Note for legacy repos... +Other distributions have to infer what to do from [general instructions](docs/install/linux/OTHERS.md). -> If the repository you plan to build has an **[older revision of the INSTALL.md](https://github.com/pret/pokeemerald/blob/571c598/INSTALL.md)**, -> then you will have to install devkitARM. Install all the above packages except for the arm-none-eabi packages, and follow the instructions to -> [install devkitARM on Debian/Ubuntu-based distributions](#installing-devkitarm-on-debianubuntu-based-distributions). -
+## Mac +Some extra considerations exist to get the testing system working. -### Installing devkitARM on Debian/Ubuntu-based distributions +[Mac instructions](docs/install/mac/MAC_OS.md) -1. Change directory to somewhere you can download a packages, like a Downloads folder. Then, run the following commands to install devkitARM: +## ChromeOS +Only tested on x86_64 based systems. - ```bash - wget https://apt.devkitpro.org/install-devkitpro-pacman - chmod +x ./install-devkitpro-pacman - sudo ./install-devkitpro-pacman - sudo dkp-pacman -S gba-dev - ``` - The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. +[Chrome OS instructions](docs/install/chromeos/CHROME_OS.md) -4. Run the following command to set devkitPro related environment variables (alternatively, close and re-open the Terminal): - - ```bash - source /etc/profile.d/devkit-env.sh - ``` - -devkitARM is now installed. - -### Arch Linux -Run this command as root to install the necessary packages: -```bash -pacman -S base-devel arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-newlib git libpng -``` - -### Installing devkitARM on Arch Linux - -1. Follow [devkitPro's instructions](https://devkitpro.org/wiki/devkitPro_pacman#Customising_Existing_Pacman_Install) to configure `pacman` to download devkitPro packages. -2. Install `gba-dev`: run the following command as root. +# Building pokeemerald-expansion +Follow these steps to build `pokeemerald-expansion`. +1. Navigate to the directory you want to keep the project in, be aware of any system specific limitations. +2. Download `pokeemerald-expansion` with `git` ```console - pacman -S gba-dev - ``` - This will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. - -3. Run the following command to set devkitPro related environment variables (alternatively, close and re-open the Terminal): - - ```bash - source /etc/profile.d/devkit-env.sh - ``` - -devkitARM is now installed. - -Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux). - -### NixOS -Run the following command to start an interactive shell with the necessary packages: -```bash -nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng -``` -Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux). - -### NixOS -Run the following command to start an interactive shell with the necessary packages: -```bash -nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng -``` -Then proceed to [Choosing where to store pokeemerald Expansion (Linux)](#choosing-where-to-store-pokeemerald-expansion-linux). - -### Other distributions -_(Specific instructions for other distributions would be greatly appreciated!)_ - -1. Try to find the required software in its repositories: - - `gcc` - - `g++` - - `make` - - `git` - - `libpng-dev` - -2. Follow the instructions [here](https://devkitpro.org/wiki/devkitPro_pacman) to install devkitPro pacman. As a reminder, the goal is to configure an existing pacman installation to recognize devkitPro's repositories. -3. Once devkitPro pacman is configured, run the following commands: - - ```bash - sudo pacman -Sy - sudo pacman -S gba-dev - ``` - - The last command will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. - -### Installing Python in Linux -Installing Python depends on your distribution, please refere to the instructions [here](https://docs.python-guide.org/starting/install3/linux/). - -### Choosing where to store pokeemerald Expansion (Linux) -At this point, you can choose a folder to store pokeemerald Expansion into. If so, you'll have to account for the modified folder path when changing directory to the pokeemerald-expansion folder. - -If this works, then proceed to [Installation](#installation). Otherwise, ask for help on Discord or IRC (see [README.md](README.md)). - -## Installation - -
- Note for Windows users... - -> Consider adding an exception for the `pokeemerald-expansion` and/or `decomps` folder in Windows Security using -> [these instructions](https://support.microsoft.com/help/4028485). This prevents Microsoft Defender from -> scanning them which might improve performance while building. -
- -1. If pokeemerald Expansion is not already downloaded (some users may prefer to download pokeemerald Expansion via a git client like GitHub Desktop), run: - - ```bash git clone https://github.com/rh-hideout/pokeemerald-expansion ``` +3. Navigate to the newly downloaded project. -
- Note for WSL1... + ```console + cd pokeemerald-expansion + ``` +4. Build the project. - > If you get an error stating `fatal: could not set 'core.filemode' to 'false'`, then run the following commands: - > ```bash - > cd - > sudo umount /mnt/c - > sudo mount -t drvfs C: /mnt/c -o metadata,noatime - > cd - > ``` - > Where *\* is the path of the folder [where you chose to store pokeemerald Expansion](#Choosing-where-to-store-pokeemerald-expansion-WSL1). Then run the `git clone` command again. -
+ ```console + make + ``` +5. If everything worked correctly, something very similar to this should be seen. -Now you're ready to build pokeemerald Expansion. - -## Build pokeemerald Expansion - -If you aren't in the pokeemerald-expansion directory already, then **change directory** to the pokeemerald-expansion folder: -```bash -cd pokeemerald-expansion -``` -To build **pokeemerald.gba** (Note: to speed up builds, see [Parallel builds](#parallel-builds)): -```bash -make -``` -If it has built successfully you will have the output file **pokeemerald.gba** in your project folder. -
-Note for Windows... -> If you switched terminals since the last build (e.g. from msys2 to WSL1), you must run `make clean-tools` once before any subsequent `make` commands. -
+ ```console + arm-none-eabi-ld: warning: ../../pokeemerald.elf has a LOAD segment with RWX permissions + Memory region Used Size Region Size %age Used + EWRAM: 243354 B 256 KB 92.83% + IWRAM: 30492 B 32 KB 93.05% + ROM: 26072244 B 32 MB 77.70% + cd build/modern && arm-none-eabi-ld -T ../../ld_script_modern.ld --print-memory-usage -o ../../pokeemerald.elf | cat + tools/gbafix/gbafix pokeemerald.elf -t"POKEMON EMER" -cBPEE -m01 -r0 --silent + arm-none-eabi-objcopy -O binary pokeemerald.elf pokeemerald.gba + tools/gbafix/gbafix pokeemerald.gba -p --silent + ``` + And the build ROM will be in the directory as `pokeemerald.gba`. # Building guidance diff --git a/docs/install/chromeos/CHROME_OS.md b/docs/install/chromeos/CHROME_OS.md new file mode 100644 index 0000000000..7fa57e5968 --- /dev/null +++ b/docs/install/chromeos/CHROME_OS.md @@ -0,0 +1,14 @@ +# Instructions for ChromeOS + +1. Enable the Linux terminal by following the instructions on [this page](https://chromeos.dev/en/productivity/terminal). Be sure to allocate enough space for the Linux install. +2. After the Linux terminal has finished installing, run the following command in the terminal to update and upgrade the Linux terminal: + + ```console + sudo apt update && apt upgrade + ``` +3. Then install all dependencies by running the following command: + + ```console + sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3 + ``` +**NOTE**: The project must be kept in a directory inside the Linux filesystem, for example under `~/Decomps/pokeemerald-expansion` diff --git a/docs/install/linux/ARCH_LINUX.md b/docs/install/linux/ARCH_LINUX.md new file mode 100644 index 0000000000..1d69e5c39c --- /dev/null +++ b/docs/install/linux/ARCH_LINUX.md @@ -0,0 +1,6 @@ +# Arch Linux instructions +## Installing dependencies +Run the following command from the command line: +```console +sudo pacman -S base-devel arm-none-eabi-binutils arm-none-eabi-gcc arm-none-eabi-newlib git libpng python +``` diff --git a/docs/install/linux/DEBIAN.md b/docs/install/linux/DEBIAN.md new file mode 100644 index 0000000000..a63d3f985e --- /dev/null +++ b/docs/install/linux/DEBIAN.md @@ -0,0 +1,6 @@ +# Debian instructions +## Installing dependencies +Open a terminal and run the following command from the command line: +```console +sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3 +``` diff --git a/docs/install/linux/NIXOS.md b/docs/install/linux/NIXOS.md new file mode 100644 index 0000000000..6c613466b6 --- /dev/null +++ b/docs/install/linux/NIXOS.md @@ -0,0 +1,5 @@ +# NixOS instructions +Run the following command to start an interactive shell with the necessary packages: +```bash +nix-shell -p pkgsCross.arm-embedded.stdenv.cc git pkg-config libpng +``` diff --git a/docs/install/linux/OTHERS.md b/docs/install/linux/OTHERS.md new file mode 100644 index 0000000000..eb83331ed9 --- /dev/null +++ b/docs/install/linux/OTHERS.md @@ -0,0 +1,11 @@ +# Instructions for other distributions +1. Try to find the required software in its repositories: + - `gcc` + - `g++` + - `arm-none-eabi-gcc` + - `arm-none-eabi-binutils` + - `arm-none-eabi-newlib` + - `make` + - `git` + - `libpng-dev` + - `python3` diff --git a/docs/install/linux/UBUNTU.md b/docs/install/linux/UBUNTU.md new file mode 100644 index 0000000000..41beb8067a --- /dev/null +++ b/docs/install/linux/UBUNTU.md @@ -0,0 +1,6 @@ +# Ubuntu instructions +## Installing dependencies +Open a terminal and run the following command from the command line: +```console +sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3 +``` diff --git a/docs/install/mac/MAC_OS.md b/docs/install/mac/MAC_OS.md new file mode 100644 index 0000000000..8ffa4df089 --- /dev/null +++ b/docs/install/mac/MAC_OS.md @@ -0,0 +1,93 @@ +# Instructions for macOS +1. If the Xcode Command Line Tools are not installed, download the tools [here](https://developer.apple.com/xcode/resources/), open your Terminal, and run the following command: + + ```bash + xcode-select --install + ``` + +2. - If libpng is **not installed**, then go to [Installing libpng (macOS)](#installing-libpng-macos). + - If pkg-config is **not installed**, then go to [Installing pkg-config (macos)](#installing-pkg-config-macos). + - If devkitARM is **not installed**, then go to [Installing devkitARM (macOS)](#installing-devkitarm-macos). + - Otherwise, **open the Terminal** and go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos) + +### Installing libpng (macOS) +
+ Note for advanced users... + +> This guide installs libpng via Homebrew as it is the easiest method, however advanced users can install libpng through other means if they so desire. +
+ +1. Open the Terminal. +2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website. +3. Run the following command to install libpng. + + ```bash + brew install libpng + ``` + libpng is now installed. + + Continue to [Installing pkg-config (macOS)](#installing-pkg-config-macos) if **pkg-config is not installed**. Otherwise, continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**. + + If both pkg-config and devkitARM are already installed, go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos). + +### Installing pkg-config (macOS) +
+ Note for advanced users... + +> This guide installs pkg-config via Homebrew as it is the easiest method, however advanced users can install pkg-config through other means if they so desire. +
+ +1. Open the Terminal. +2. If Homebrew is not installed, then install [Homebrew](https://brew.sh/) by following the instructions on the website. +3. Run the following command to install libpng. + + ```bash + brew install pkg-config + ``` + pkg-config is now installed. + + Continue to [Installing devkitARM (macOS)](#installing-devkitarm-macos) if **devkitARM is not installed**, otherwise, go to [Choosing where to store pokeemerald-expansion (macOS)](#choosing-where-to-store-pokeemerald-expansion-macos). + +### Installing devkitARM (macOS) +1. Download the `devkitpro-pacman-installer.pkg` package from [here](https://github.com/devkitPro/pacman/releases). +2. Open the package to install devkitPro pacman. +3. In the Terminal, run the following commands to install devkitARM: + + ```bash + sudo dkp-pacman -Sy + sudo dkp-pacman -S gba-dev + sudo dkp-pacman -S devkitarm-rules + ``` + + The command with gba-dev will ask for the selection of packages to install. Just press Enter to install all of them, followed by entering Y to proceed with the installation. + +4. After the tools are installed, devkitARM must now be made accessible from anywhere by the system. To do so, run the following commands: + + ```bash + export DEVKITPRO=/opt/devkitpro + echo "export DEVKITPRO=$DEVKITPRO" >> ~/.zshrc + export DEVKITARM=$DEVKITPRO/devkitARM + echo "export DEVKITARM=$DEVKITARM" >> ~/.zshrc + + echo "if [ -f ~/.zshrc ]; then . ~/.zshrc; fi" >> ~/.zprofile + ``` + *Note: Starting with macOS 10.15, the default Unix shell is now zsh. If you migrated from an older version of macOS, you might still be using bash. You can check my running `echo $0` in the terminal.* +
+ If your terminal is using bash instead of zsh... + + ```bash + export DEVKITPRO=/opt/devkitpro + echo "export DEVKITPRO=$DEVKITPRO" >> ~/.bashrc + export DEVKITARM=$DEVKITPRO/devkitARM + echo "export DEVKITARM=$DEVKITARM" >> ~/.bashrc + + echo "if [ -f ~/.bashrc ]; then . ~/.bashrc; fi" >> ~/.bash_profile + ``` +
+ +### Installing Python (macOS) +1. Download the latest Python package from [here](https://www.python.org/downloads/). +2. Open the package to install Python. + +Python is now installed. + diff --git a/docs/install/windows/CYGWIN.md b/docs/install/windows/CYGWIN.md new file mode 100644 index 0000000000..c9ca728c22 --- /dev/null +++ b/docs/install/windows/CYGWIN.md @@ -0,0 +1,4 @@ +# cygwin +Don't, just don't. +Currently doesn't work on current Expansion versions. +This is a bug from upstream pret `pokeemerald`. diff --git a/docs/install/windows/MSYS2.md b/docs/install/windows/MSYS2.md new file mode 100644 index 0000000000..ce7176b912 --- /dev/null +++ b/docs/install/windows/MSYS2.md @@ -0,0 +1,4 @@ +# msys2 +Don't, just don't. +Currently doesn't work on current Expansion versions. +This is a bug from upstream pret `pokeemerald`. diff --git a/docs/install/windows/WSL.md b/docs/install/windows/WSL.md new file mode 100644 index 0000000000..9534966488 --- /dev/null +++ b/docs/install/windows/WSL.md @@ -0,0 +1,87 @@ +# Windows WSL instructions +## Choosing WSL version +If you must store your project on the Windows file system (under /mnt/c/), you should use WSL1. +If you want the best performance and least amount of issues with Windows interfering with compiling the project, use WSL2 and store the project on the Linux file system (under ~/). +## Installing WSL +1. Open [Windows Powershell **as Administrator**](https://i.imgur.com/QKmVbP9.png), and run the following commands (Right Click or Shift+Insert is paste in the Powershell). + + ```powershell + wsl --install -d Ubuntu --enable-wsl1 + ``` + +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. + + ```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. + + ```powershell + wsl --set-version Ubuntu 2 + ``` + +
+ Note... + + > WSL may open automatically after restarting, but you can ignore it for now. +
+ +## Installing dependencies +Some tips before proceeding: +- In WSL, Copy and Paste is either done via + - **right-click** (selection + right click to Copy, right click with no selection to Paste) + - **Ctrl+Shift+C/Ctrl+Shift+V** (enabled by right-clicking the title bar, going to Properties, then checking the checkbox next to "Use Ctrl+Shift+C/V as Copy/Paste"). +- Some of the commands that you'll run will ask for your WSL password and/or confirmation to perform the stated action. This is to be expected, just enter your WSL password and/or the yes action when necessary. + +1. Open **Ubuntu** (e.g. using Search). +2. WSL/Ubuntu will set up its own installation when it runs for the first time. Once WSL/Ubuntu finishes installing, it will ask for a username and password (to be input in). +
+ Note... + + > When typing in the password, there will be no visible response, but the terminal will still read in input. +
+ +3. Update WSL/Ubuntu before continuing. Do this by running the following command. These commands will likely take a long time to finish: + + ```bash + sudo apt update && sudo apt upgrade + ``` + +4. Certain packages are required to build pokeemerald Expansion. Install these packages by running the following command: + + ```bash + sudo apt install build-essential binutils-arm-none-eabi gcc-arm-none-eabi libnewlib-arm-none-eabi git libpng-dev python3 + ``` + +## Choosing a location to store pokeemerald Expansion, WSL1 +WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. So you're going to want to store pokeemerald Expansion within Windows. + +For example, say you want to store pokeemerald Expansion in **C:\Users\\_\_\Desktop\decomps**. First, ensure that the folder already exists. Then, enter this command to **change directory** to said folder, where *\* is your **Windows** username: + +```bash +cd /mnt/c/Users//Desktop/decomps +``` + +
+ Notes... + +> Note 1: The Windows C:\ drive is called /mnt/c/ in WSL. +> Note 2: If the path has spaces, then the path must be wrapped with quotations, e.g. `cd "/mnt/c/users//Desktop/decomp folder"`. +> Note 3: Windows path names are case-insensitive so adhering to capitalization isn't needed +
+ +## Choosing a location to store pokeemerald Expansion, WSL2 +WSL has its own file system that's not natively accessible from Windows, but Windows files *are* accessible from WSL. But accessing files on the Windows file system with WSL2 is very slow, so you're going to want to store pokeemerald Expansion within WSL2. +To access the files on the WSL filesystem from Windowsm, you have to open the WSL filesystem as a network attached storage in the file explorer, it should be at the bottom of the left sidebar as "Ubuntu". + +Thus you're going to make sure that you're in the WSL filesystem, then create the folder for decomps if it doesn't already exist, then move into that folder. + +```bash +cd ~/ +mkdir decomps +cd decomps +``` From a2aba3f86abb229d2c2c3c6a0330da22ae1d7f84 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Tue, 17 Dec 2024 23:21:12 +0100 Subject: [PATCH 24/26] Changes target TURN_DAMAGED and MAX_HP to inlines (#5822) --- include/battle.h | 16 +++-- include/battle_ai_util.h | 2 +- src/battle_ai_main.c | 16 ++--- src/battle_ai_util.c | 12 ++-- src/battle_main.c | 2 +- src/battle_script_commands.c | 30 +++++----- src/battle_util.c | 110 +++++++++++++++++------------------ 7 files changed, 98 insertions(+), 90 deletions(-) diff --git a/include/battle.h b/include/battle.h index aa21a88a12..8dc45b9ff0 100644 --- a/include/battle.h +++ b/include/battle.h @@ -869,10 +869,6 @@ STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLER #define IS_MOVE_STATUS(move)(gMovesInfo[move].category == DAMAGE_CATEGORY_STATUS) #define IS_MOVE_RECOIL(move)(gMovesInfo[move].recoil > 0 || gMovesInfo[move].effect == EFFECT_RECOIL_IF_MISS) -#define BATTLER_MAX_HP(battlerId)(gBattleMons[battlerId].hp == gBattleMons[battlerId].maxHP) -#define TARGET_TURN_DAMAGED ((gSpecialStatuses[gBattlerTarget].physicalDmg != 0 || gSpecialStatuses[gBattlerTarget].specialDmg != 0) || (gBattleStruct->enduredDamage & (1u << gBattlerTarget))) -#define BATTLER_TURN_DAMAGED(battlerId) ((gSpecialStatuses[battlerId].physicalDmg != 0 || gSpecialStatuses[battlerId].specialDmg != 0) || (gBattleStruct->enduredDamage & (1u << battler))) - /* Checks if 'battlerId' is any of the types. * Passing multiple types is more efficient than calling this multiple * times with one type because it shares the 'GetBattlerTypes' result. */ @@ -1196,6 +1192,18 @@ extern bool8 gLastUsedBallMenuPresent; extern u8 gPartyCriticalHits[PARTY_SIZE]; extern u8 gCategoryIconSpriteId; +static inline bool32 IsBattlerTurnDamaged(u32 battler) +{ + return gSpecialStatuses[battler].physicalDmg != 0 + || gSpecialStatuses[battler].specialDmg != 0 + || gBattleStruct->enduredDamage & (1u << battler); +} + +static inline bool32 IsBattlerAtMaxHp(u32 battler) +{ + return gBattleMons[battler].hp == gBattleMons[battler].maxHP; +} + static inline u32 GetBattlerPosition(u32 battler) { return gBattlerPositions[battler]; diff --git a/include/battle_ai_util.h b/include/battle_ai_util.h index 56dd8aa6e1..729d173933 100644 --- a/include/battle_ai_util.h +++ b/include/battle_ai_util.h @@ -44,7 +44,7 @@ void RestoreBattlerData(u32 battlerId); u32 GetAIChosenMove(u32 battlerId); u32 GetTotalBaseStat(u32 species); bool32 IsTruantMonVulnerable(u32 battlerAI, u32 opposingBattler); -bool32 AtMaxHp(u32 battler); +bool32 AI_BattlerAtMaxHp(u32 battler); u32 GetHealthPercentage(u32 battler); bool32 IsBattlerTrapped(u32 battler, bool32 switching); s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler2, u32 moveConsidered); diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index d988142beb..033599154e 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -1663,7 +1663,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) } else { - if (AtMaxHp(battlerAtk)) + if (AI_BattlerAtMaxHp(battlerAtk)) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] >= 80) ADJUST_SCORE(-5); // do it if nothing better @@ -1802,7 +1802,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_RESTORE_HP: case EFFECT_SOFTBOILED: case EFFECT_ROOST: - if (AtMaxHp(battlerAtk)) + if (AI_BattlerAtMaxHp(battlerAtk)) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] >= 90) ADJUST_SCORE(-9); //No point in healing, but should at least do it if nothing better @@ -1812,7 +1812,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) case EFFECT_MOONLIGHT: if ((AI_GetWeather(aiData) & (B_WEATHER_RAIN | B_WEATHER_SANDSTORM | B_WEATHER_HAIL | B_WEATHER_SNOW | B_WEATHER_FOG))) ADJUST_SCORE(-3); - else if (AtMaxHp(battlerAtk)) + else if (AI_BattlerAtMaxHp(battlerAtk)) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] >= 90) ADJUST_SCORE(-9); //No point in healing, but should at least do it if nothing better @@ -1822,7 +1822,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); else if (battlerDef == BATTLE_PARTNER(battlerAtk)) break; //Always heal your ally - else if (AtMaxHp(battlerAtk)) + else if (AI_BattlerAtMaxHp(battlerAtk)) ADJUST_SCORE(-10); else if (aiData->hpPercents[battlerAtk] >= 90) ADJUST_SCORE(-8); //No point in healing, but should at least do it if nothing better @@ -2390,7 +2390,7 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) { if (gStatuses3[battlerDef] & STATUS3_HEAL_BLOCK) return 0; // cannot even select - if (AtMaxHp(battlerDef)) + if (AI_BattlerAtMaxHp(battlerDef)) ADJUST_SCORE(-10); else if (gBattleMons[battlerDef].hp > gBattleMons[battlerDef].maxHP / 2) ADJUST_SCORE(-5); @@ -2559,8 +2559,8 @@ static s32 AI_CheckBadMove(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) ADJUST_SCORE(-10); break; case EFFECT_JUNGLE_HEALING: - if (AtMaxHp(battlerAtk) - && AtMaxHp(BATTLE_PARTNER(battlerAtk)) + if (AI_BattlerAtMaxHp(battlerAtk) + && AI_BattlerAtMaxHp(BATTLE_PARTNER(battlerAtk)) && !(gBattleMons[battlerAtk].status1 & STATUS1_ANY) && !(gBattleMons[BATTLE_PARTNER(battlerAtk)].status1 & STATUS1_ANY)) ADJUST_SCORE(-10); @@ -2685,7 +2685,7 @@ static s32 AI_DoubleBattle(u32 battlerAtk, u32 battlerDef, u32 move, s32 score) if (IsMoveEffectWeather(move)) ADJUST_SCORE(-10); break; - } + } } // check partner move effect // Adjust for always crit moves diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 228e5202c5..a6415edd7c 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -290,7 +290,7 @@ u32 GetHealthPercentage(u32 battlerId) return (u32)((100 * gBattleMons[battlerId].hp) / gBattleMons[battlerId].maxHP); } -bool32 AtMaxHp(u32 battlerId) +bool32 AI_BattlerAtMaxHp(u32 battlerId) { if (AI_DATA->hpPercents[battlerId] == 100) return TRUE; @@ -1142,7 +1142,7 @@ s32 AI_WhoStrikesFirst(u32 battlerAI, u32 battler, u32 moveConsidered) static bool32 CanEndureHit(u32 battler, u32 battlerTarget, u32 move) { - if (!BATTLER_MAX_HP(battlerTarget) || gMovesInfo[move].effect == EFFECT_MULTI_HIT) + if (!AI_BattlerAtMaxHp(battlerTarget) || gMovesInfo[move].effect == EFFECT_MULTI_HIT) return FALSE; if (gMovesInfo[move].strikeCount > 1 && !(gMovesInfo[move].effect == EFFECT_DRAGON_DARTS && IsValidDoubleBattle(battlerTarget))) return FALSE; @@ -1564,7 +1564,7 @@ bool32 ShouldTryOHKO(u32 battlerAtk, u32 battlerDef, u32 atkAbility, u32 defAbil gPotentialItemEffectBattler = battlerDef; if (holdEffect == HOLD_EFFECT_FOCUS_BAND && (Random() % 100) < AI_DATA->holdEffectParams[battlerDef]) return FALSE; //probabilistically speaking, focus band should activate so dont OHKO - else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && AtMaxHp(battlerDef)) + else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && AI_BattlerAtMaxHp(battlerDef)) return FALSE; if (!DoesBattlerIgnoreAbilityChecks(atkAbility, move) && defAbility == ABILITY_STURDY) @@ -2761,7 +2761,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov return SHOULD_PIVOT; // Won't get the two turns, pivot if (!IS_MOVE_STATUS(move) && ((AI_DATA->shouldSwitch & (1u << battlerAtk)) - || (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH + || (AI_BattlerAtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH || (B_STURDY >= GEN_5 && defAbility == ABILITY_STURDY) || defAbility == ABILITY_MULTISCALE || defAbility == ABILITY_SHADOW_SHIELD)))) @@ -2769,7 +2769,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov } else if (!hasStatBoost) { - if (!IS_MOVE_STATUS(move) && (AtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH + if (!IS_MOVE_STATUS(move) && (AI_BattlerAtMaxHp(battlerDef) && (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH || (B_STURDY >= GEN_5 && defAbility == ABILITY_STURDY) || defAbility == ABILITY_MULTISCALE || defAbility == ABILITY_SHADOW_SHIELD))) @@ -2848,7 +2848,7 @@ enum AIPivot ShouldPivot(u32 battlerAtk, u32 battlerDef, u32 defAbility, u32 mov // can knock out foe in 2 hits if (IS_MOVE_STATUS(move) && ((AI_DATA->shouldSwitch & (1u << battlerAtk)) //Damaging move //&& (switchScore >= SWITCHING_INCREASE_RESIST_ALL_MOVES + SWITCHING_INCREASE_KO_FOE //remove hazards - || (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH && AtMaxHp(battlerDef)))) + || (AI_DATA->holdEffects[battlerDef] == HOLD_EFFECT_FOCUS_SASH && AI_BattlerAtMaxHp(battlerDef)))) return DONT_PIVOT; // Pivot to break the sash else return CAN_TRY_PIVOT; diff --git a/src/battle_main.c b/src/battle_main.c index 25f69d44b0..7c02c7abcf 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -4854,7 +4854,7 @@ s8 GetMovePriority(u32 battler, u16 move) return gMovesInfo[MOVE_MAX_GUARD].priority; if (ability == ABILITY_GALE_WINGS - && (B_GALE_WINGS < GEN_7 || BATTLER_MAX_HP(battler)) + && (B_GALE_WINGS < GEN_7 || IsBattlerAtMaxHp(battler)) && gMovesInfo[move].type == TYPE_FLYING) { priority++; diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index df3d91b26e..5a16340e50 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -2208,12 +2208,12 @@ static void Cmd_adjustdamage(void) RecordItemEffectBattle(battlerDef, holdEffect); gSpecialStatuses[battlerDef].focusBanded = TRUE; } - else if (B_STURDY >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && BATTLER_MAX_HP(battlerDef)) + else if (B_STURDY >= GEN_5 && GetBattlerAbility(battlerDef) == ABILITY_STURDY && IsBattlerAtMaxHp(battlerDef)) { RecordAbilityBattle(battlerDef, ABILITY_STURDY); gSpecialStatuses[battlerDef].sturdied = TRUE; } - else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && BATTLER_MAX_HP(battlerDef)) + else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(battlerDef)) { RecordItemEffectBattle(battlerDef, holdEffect); gSpecialStatuses[battlerDef].focusSashed = TRUE; @@ -5997,7 +5997,7 @@ static void Cmd_moveend(void) && gBattlerAttacker != gBattlerTarget && GetBattlerSide(gBattlerAttacker) != GetBattlerSide(gBattlerTarget) && MoveResultHasEffect(gBattlerTarget) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && gMovesInfo[gCurrentMove].power != 0 && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { @@ -6282,7 +6282,7 @@ static void Cmd_moveend(void) if (gBattlerAttacker != gBattlerTarget && gMovesInfo[gCurrentMove].category != DAMAGE_CATEGORY_STATUS && MoveResultHasEffect(gBattlerTarget) - && TARGET_TURN_DAMAGED) + && IsBattlerTurnDamaged(gBattlerTarget)) { gBattleStruct->timesGotHit[GetBattlerSide(gBattlerTarget)][gBattlerPartyIndexes[gBattlerTarget]]++; } @@ -6563,7 +6563,7 @@ static void Cmd_moveend(void) && gBattleMons[gBattlerAttacker].item == ITEM_NONE && gBattleMons[gBattlerTarget].item != ITEM_NONE && IsBattlerAlive(gBattlerAttacker) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && CanStealItem(gBattlerAttacker, gBattlerTarget, gBattleMons[gBattlerTarget].item) && !gSpecialStatuses[gBattlerAttacker].gemBoost // In base game, gems are consumed after magician would activate. && !(gWishFutureKnock.knockedOffMons[GetBattlerSide(gBattlerTarget)] & (1u << gBattlerPartyIndexes[gBattlerTarget])) @@ -6609,7 +6609,7 @@ static void Cmd_moveend(void) continue; // Since we check if battler was damaged, we don't need to check move result. // In fact, doing so actually prevents multi-target moves from activating eject button properly - if (!BATTLER_TURN_DAMAGED(battler)) + if (!IsBattlerTurnDamaged(battler)) continue; } else if (ejectPackBattlers & (1u << battler)) @@ -6704,7 +6704,7 @@ static void Cmd_moveend(void) if (redCardBattlers & (1u << battler) && IsBattlerAlive(battler) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && BATTLER_TURN_DAMAGED(battler) + && IsBattlerTurnDamaged(battler) && CanBattlerSwitch(gBattlerAttacker)) { gLastUsedItem = gBattleMons[battler].item; @@ -6753,7 +6753,7 @@ static void Cmd_moveend(void) // Attacker is mon who made contact, battler is mon with pickpocket if (battler != gBattlerAttacker // Cannot pickpocket yourself && GetBattlerAbility(battler) == ABILITY_PICKPOCKET // Target must have pickpocket ability - && BATTLER_TURN_DAMAGED(battler) // Target needs to have been damaged + && IsBattlerTurnDamaged(battler) // Target needs to have been damaged && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) // Subsitute unaffected && IsBattlerAlive(battler) // Battler must be alive to pickpocket && gBattleMons[battler].item == ITEM_NONE // Pickpocketer can't have an item already @@ -8514,7 +8514,7 @@ static bool32 TryCheekPouch(u32 battler, u32 itemId) && GetBattlerAbility(battler) == ABILITY_CHEEK_POUCH && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) && gBattleStruct->ateBerry[GetBattlerSide(battler)] & (1u << gBattlerPartyIndexes[battler]) - && !BATTLER_MAX_HP(battler)) + && !IsBattlerAtMaxHp(battler)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 3; if (gBattleStruct->moveDamage[battler] == 0) @@ -9585,7 +9585,7 @@ static void Cmd_various(void) case VARIOUS_JUMP_IF_FULL_HP: { VARIOUS_ARGS(const u8 *jumpInstr); - if (BATTLER_MAX_HP(battler)) + if (IsBattlerAtMaxHp(battler)) gBattlescriptCurrInstr = cmd->jumpInstr; else gBattlescriptCurrInstr = cmd->nextInstr; @@ -9687,7 +9687,7 @@ static void Cmd_various(void) { VARIOUS_ARGS(const u8 *failInstr); if ((gStatuses3[battler] & (STATUS3_SEMI_INVULNERABLE | STATUS3_HEAL_BLOCK)) - || BATTLER_MAX_HP(battler) + || IsBattlerAtMaxHp(battler) || !gBattleMons[battler].hp || !(IsBattlerGrounded(battler))) { @@ -12696,7 +12696,7 @@ static void Cmd_tryKO(void) gSpecialStatuses[gBattlerTarget].focusBanded = TRUE; RecordItemEffectBattle(gBattlerTarget, holdEffect); } - else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && BATTLER_MAX_HP(gBattlerTarget)) + else if (holdEffect == HOLD_EFFECT_FOCUS_SASH && IsBattlerAtMaxHp(gBattlerTarget)) { gSpecialStatuses[gBattlerTarget].focusSashed = TRUE; RecordItemEffectBattle(gBattlerTarget, holdEffect); @@ -17238,7 +17238,7 @@ void BS_TryHealPulse(void) { NATIVE_ARGS(const u8 *failInstr); - if (BATTLER_MAX_HP(gBattlerTarget)) + if (IsBattlerAtMaxHp(gBattlerTarget)) { gBattlescriptCurrInstr = cmd->failInstr; } @@ -17495,7 +17495,7 @@ void BS_TryActivateGulpMissile(void) if (MoveResultHasEffect(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT && GetBattlerAbility(gBattlerTarget) == ABILITY_GULP_MISSILE) { @@ -17696,7 +17696,7 @@ void BS_TryHitSwitchTarget(void) if (IsBattlerAlive(gBattlerAttacker) && IsBattlerAlive(gBattlerTarget) && MoveResultHasEffect(gBattlerTarget) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && gSpecialStatuses[gBattlerAttacker].parentalBondState != PARENTAL_BOND_1ST_HIT && GetBattlerAbility(gBattlerTarget) != ABILITY_GUARD_DOG) { diff --git a/src/battle_util.c b/src/battle_util.c index ced04e91d1..fe671a8204 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -2255,7 +2255,7 @@ u8 DoBattlerEndTurnEffects(void) else if (gBattleWeather & (B_WEATHER_HAIL | B_WEATHER_SNOW) && ability == ABILITY_ICE_BODY && !(gStatuses3[battler] & (STATUS3_UNDERGROUND | STATUS3_UNDERWATER)) - && !BATTLER_MAX_HP(battler) + && !IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { gBattleScripting.battler = battler; @@ -2282,7 +2282,7 @@ u8 DoBattlerEndTurnEffects(void) break; case ENDTURN_INGRAIN: // ingrain if ((gStatuses3[battler] & STATUS3_ROOTED) - && !BATTLER_MAX_HP(battler) + && !IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) && IsBattlerAlive(battler)) { @@ -2294,7 +2294,7 @@ u8 DoBattlerEndTurnEffects(void) break; case ENDTURN_AQUA_RING: // aqua ring if ((gStatuses3[battler] & STATUS3_AQUA_RING) - && !BATTLER_MAX_HP(battler) + && !IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK) && IsBattlerAlive(battler)) { @@ -2372,7 +2372,7 @@ u8 DoBattlerEndTurnEffects(void) { if (ability == ABILITY_POISON_HEAL) { - if (!BATTLER_MAX_HP(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + if (!IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; if (gBattleStruct->moveDamage[battler] == 0) @@ -2400,7 +2400,7 @@ u8 DoBattlerEndTurnEffects(void) { if (ability == ABILITY_POISON_HEAL) { - if (!BATTLER_MAX_HP(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + if (!IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { gBattleStruct->moveDamage[battler] = GetNonDynamaxMaxHP(battler) / 8; if (gBattleStruct->moveDamage[battler] == 0) @@ -5148,7 +5148,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 // Dry Skin works similarly to Rain Dish in Rain case ABILITY_RAIN_DISH: if (IsBattlerWeatherAffected(battler, B_WEATHER_RAIN) - && !BATTLER_MAX_HP(battler) + && !IsBattlerAtMaxHp(battler) && !(gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { BattleScriptPushCursorAndCallback(BattleScript_RainDishActivates); @@ -5403,7 +5403,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { case MOVE_ABSORBED_BY_DRAIN_HP_ABILITY: gBattleStruct->pledgeMove = FALSE; - if (BATTLER_MAX_HP(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK)) + if (IsBattlerAtMaxHp(battler) || (B_HEAL_BLOCKING >= GEN_5 && gStatuses3[battler] & STATUS3_HEAL_BLOCK)) { if ((gProtectStructs[gBattlerAttacker].notFirstStrike)) gBattlescriptCurrInstr = BattleScript_MonMadeMoveUseless; @@ -5475,7 +5475,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 { case ABILITY_JUSTIFIED: if (MoveResultHasEffect(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && moveType == TYPE_DARK && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) @@ -5489,7 +5489,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_RATTLED: if (MoveResultHasEffect(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && (moveType == TYPE_DARK || moveType == TYPE_BUG || moveType == TYPE_GHOST) && CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN)) @@ -5503,7 +5503,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_WATER_COMPACTION: if (MoveResultHasEffect(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && moveType == TYPE_WATER && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)) @@ -5518,7 +5518,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_STAMINA: if (MoveResultHasEffect(battler) && gBattlerAttacker != gBattlerTarget - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && CompareStat(battler, STAT_DEF, MAX_STAT_STAGE, CMP_LESS_THAN)) { @@ -5531,7 +5531,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_BERSERK: if (MoveResultHasEffect(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && HadMoreThanHalfHpNowDoesnt(battler) && (gMultiHitCounter == 0 || gMultiHitCounter == 1) @@ -5548,7 +5548,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_EMERGENCY_EXIT: case ABILITY_WIMP_OUT: if (MoveResultHasEffect(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) // Had more than half of hp before, now has less && HadMoreThanHalfHpNowDoesnt(battler) @@ -5566,7 +5566,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_WEAK_ARMOR: if (MoveResultHasEffect(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && IS_MOVE_PHYSICAL(gCurrentMove) && (CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) // Don't activate if both Speed and Defense cannot be raised. @@ -5582,7 +5582,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_CURSED_BODY: if (MoveResultHasEffect(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && gDisableStructs[gBattlerAttacker].disabledMove == MOVE_NONE && IsBattlerAlive(gBattlerAttacker) && !IsAbilityOnSide(gBattlerAttacker, ABILITY_AROMA_VEIL) @@ -5602,7 +5602,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_MUMMY: if (MoveResultHasEffect(battler) && IsBattlerAlive(gBattlerAttacker) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker) && gBattleStruct->overwrittenAbilities[gBattlerAttacker] != GetBattlerAbility(gBattlerTarget) @@ -5627,7 +5627,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_WANDERING_SPIRIT: if (MoveResultHasEffect(battler) && IsBattlerAlive(gBattlerAttacker) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker) && !(GetActiveGimmick(gBattlerTarget) == GIMMICK_DYNAMAX) @@ -5651,7 +5651,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_ANGER_POINT: if (MoveResultHasEffect(battler) && gSpecialStatuses[battler].criticalHit - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && CompareStat(battler, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN)) { @@ -5665,7 +5665,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (MoveResultHasEffect(battler) && move != MOVE_STRUGGLE && gMovesInfo[move].power != 0 - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && !IS_BATTLER_OF_TYPE(battler, moveType) && moveType != TYPE_STELLAR && moveType != TYPE_MYSTERY @@ -5684,7 +5684,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerAttacker) && (CompareStat(gBattlerAttacker, STAT_SPEED, MIN_STAT_STAGE, CMP_GREATER_THAN) || GetBattlerAbility(gBattlerAttacker) == ABILITY_MIRROR_ARMOR) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker)) { @@ -5701,7 +5701,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (MoveResultHasEffect(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker)) { @@ -5780,7 +5780,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && MoveResultHasEffect(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && CanBeSlept(gBattlerAttacker, ability, NOT_BLOCKED_BY_SLEEP_CLAUSE) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker)) @@ -5804,7 +5804,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (MoveResultHasEffect(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && CanBePoisoned(gBattlerTarget, gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker)) @@ -5825,7 +5825,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (MoveResultHasEffect(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && CanBeParalyzed(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker)) @@ -5845,7 +5845,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && (IsMoveMakingContact(move, gBattlerAttacker)) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && CanBeBurned(gBattlerAttacker, GetBattlerAbility(gBattlerAttacker)) && (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_FLAME_BODY, 30) : RandomChance(RNG_FLAME_BODY, 1, 3))) { @@ -5861,7 +5861,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (MoveResultHasEffect(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && (B_ABILITY_TRIGGER_CHANCE >= GEN_4 ? RandomPercentage(RNG_CUTE_CHARM, 30) : RandomChance(RNG_CUTE_CHARM, 1, 3)) && !(gBattleMons[gBattlerAttacker].status2 & STATUS2_INFATUATION) @@ -5878,7 +5878,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 } break; case ABILITY_ILLUSION: - if (gBattleStruct->illusion[gBattlerTarget].on && !gBattleStruct->illusion[gBattlerTarget].broken && TARGET_TURN_DAMAGED) + if (gBattleStruct->illusion[gBattlerTarget].on && !gBattleStruct->illusion[gBattlerTarget].broken && IsBattlerTurnDamaged(gBattlerTarget)) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_IllusionOff; @@ -5889,7 +5889,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 if (MoveResultHasEffect(gBattlerTarget) && IsBattlerAlive(gBattlerAttacker) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED) + && IsBattlerTurnDamaged(gBattlerTarget)) { gEffectBattler = gBattlerTarget; BattleScriptPushCursor(); @@ -5899,7 +5899,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_STEAM_ENGINE: if (MoveResultHasEffect(gBattlerTarget) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && CompareStat(battler, STAT_SPEED, MAX_STAT_STAGE, CMP_LESS_THAN) && (moveType == TYPE_FIRE || moveType == TYPE_WATER)) @@ -5914,7 +5914,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SAND_SPIT: if (MoveResultHasEffect(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && !(gBattleWeather & B_WEATHER_SANDSTORM && WEATHER_HAS_EFFECT)) { if (gBattleWeather & B_WEATHER_PRIMAL_ANY && WEATHER_HAS_EFFECT) @@ -5935,7 +5935,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_PERISH_BODY: if (MoveResultHasEffect(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && (IsMoveMakingContact(move, gBattlerAttacker)) @@ -5956,7 +5956,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_GULP_MISSILE: if (MoveResultHasEffect(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(battler) && gBattleMons[gBattlerTarget].species != SPECIES_CRAMORANT) { @@ -5987,7 +5987,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_SEED_SOWER: if (MoveResultHasEffect(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && TryChangeBattleTerrain(gBattlerTarget, STATUS_FIELD_GRASSY_TERRAIN, &gFieldTimers.terrainTimer)) { @@ -5998,7 +5998,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_THERMAL_EXCHANGE: if (MoveResultHasEffect(gBattlerTarget) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget) && CompareStat(gBattlerTarget, STAT_ATK, MAX_STAT_STAGE, CMP_LESS_THAN) && moveType == TYPE_FIRE) @@ -6013,7 +6013,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_ANGER_SHELL: if (MoveResultHasEffect(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && (gMultiHitCounter == 0 || gMultiHitCounter == 1) // Activates after all hits from a multi-hit move. && IsBattlerAlive(gBattlerTarget) && HadMoreThanHalfHpNowDoesnt(gBattlerTarget) @@ -6031,7 +6031,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 case ABILITY_ELECTROMORPHOSIS: if (MoveResultHasEffect(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && IsBattlerAlive(gBattlerTarget)) { BattleScriptPushCursor(); @@ -6044,7 +6044,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && (!gBattleStruct->isSkyBattle) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && IS_MOVE_PHYSICAL(gCurrentMove) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && (gSideTimers[GetBattlerSide(gBattlerAttacker)].toxicSpikesAmount != 2)) { SWAP(gBattlerAttacker, gBattlerTarget, i); @@ -6065,7 +6065,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget)) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(move, gBattlerAttacker) - && TARGET_TURN_DAMAGED // Need to actually hit the target + && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target && RandomPercentage(RNG_POISON_TOUCH, 30)) { gBattleScripting.moveEffect = MOVE_EFFECT_POISON; @@ -6081,7 +6081,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && CanBePoisoned(gBattlerAttacker, gBattlerTarget, GetBattlerAbility(gBattlerTarget)) - && TARGET_TURN_DAMAGED // Need to actually hit the target + && IsBattlerTurnDamaged(gBattlerTarget) // Need to actually hit the target && RandomWeighted(RNG_TOXIC_CHAIN, 7, 3)) { gBattleScripting.moveEffect = MOVE_EFFECT_TOXIC; @@ -6097,7 +6097,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 && IsBattlerAlive(gBattlerTarget) && !gProtectStructs[gBattlerAttacker].confusionSelfDmg && RandomChance(RNG_STENCH, 1, 10) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && !MoveHasAdditionalEffect(gCurrentMove, MOVE_EFFECT_FLINCH)) { gBattleScripting.moveEffect = MOVE_EFFECT_FLINCH; @@ -6109,7 +6109,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32 break; case ABILITY_GULP_MISSILE: if ((gBattleMons[gBattlerAttacker].species == SPECIES_CRAMORANT) - && ((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) + && ((gCurrentMove == MOVE_SURF && IsBattlerTurnDamaged(gBattlerTarget)) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER) && TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT)) { BattleScriptPushCursor(); @@ -6911,7 +6911,7 @@ static u8 TrySetEnigmaBerry(u32 battler) { if (IsBattlerAlive(battler) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) - && ((BATTLER_TURN_DAMAGED(battler) && gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements) + && ((IsBattlerTurnDamaged(battler) && gBattleStruct->moveResultFlags[battler] & MOVE_RESULT_SUPER_EFFECTIVE) || gBattleScripting.overrideBerryRequirements) && !(gBattleScripting.overrideBerryRequirements && gBattleMons[battler].hp == gBattleMons[battler].maxHP) && (B_HEAL_BLOCKING < GEN_5 || !(gStatuses3[battler] & STATUS3_HEAL_BLOCK))) { @@ -6935,7 +6935,7 @@ static u8 DamagedStatBoostBerryEffect(u32 battler, u8 statId, u8 category) || (!DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && GetBattleMoveCategory(gCurrentMove) == category && battler != gBattlerAttacker - && BATTLER_TURN_DAMAGED(battler))) + && IsBattlerTurnDamaged(battler))) ) { BufferStatChange(battler, statId, STRINGID_STATROSE); @@ -7992,7 +7992,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) atkHoldEffectParam *= 2; if (gBattleStruct->moveDamage[battler] != 0 // Need to have done damage && MoveResultHasEffect(gBattlerTarget) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && !gMovesInfo[gCurrentMove].ignoresKingsRock && gBattleMons[gBattlerTarget].hp && RandomPercentage(RNG_HOLD_EFFECT_FLINCH, atkHoldEffectParam) @@ -8084,7 +8084,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) switch (battlerHoldEffect) { case HOLD_EFFECT_AIR_BALLOON: - if (TARGET_TURN_DAMAGED) + if (IsBattlerTurnDamaged(gBattlerTarget)) { effect = ITEM_EFFECT_OTHER; BattleScriptPushCursor(); @@ -8092,7 +8092,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_ROCKY_HELMET: - if (TARGET_TURN_DAMAGED + if (IsBattlerTurnDamaged(gBattlerTarget) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) && IsBattlerAlive(gBattlerAttacker) @@ -8110,7 +8110,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_WEAKNESS_POLICY: if (IsBattlerAlive(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && gBattleStruct->moveResultFlags[gBattlerTarget] & MOVE_RESULT_SUPER_EFFECTIVE) { effect = ITEM_STATS_CHANGE; @@ -8120,7 +8120,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_SNOWBALL: if (IsBattlerAlive(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && moveType == TYPE_ICE) { effect = ITEM_STATS_CHANGE; @@ -8131,7 +8131,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_LUMINOUS_MOSS: if (IsBattlerAlive(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && moveType == TYPE_WATER) { effect = ITEM_STATS_CHANGE; @@ -8142,7 +8142,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_CELL_BATTERY: if (IsBattlerAlive(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && moveType == TYPE_ELECTRIC) { effect = ITEM_STATS_CHANGE; @@ -8153,7 +8153,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_ABSORB_BULB: if (IsBattlerAlive(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && moveType == TYPE_WATER) { effect = ITEM_STATS_CHANGE; @@ -8167,7 +8167,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_JABOCA_BERRY: // consume and damage attacker if used physical move if (IsBattlerAlive(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && IS_MOVE_PHYSICAL(gCurrentMove) && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) @@ -8187,7 +8187,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) break; case HOLD_EFFECT_ROWAP_BERRY: // consume and damage attacker if used special move if (IsBattlerAlive(battler) - && TARGET_TURN_DAMAGED + && IsBattlerTurnDamaged(gBattlerTarget) && !DoesSubstituteBlockMove(gBattlerAttacker, battler, gCurrentMove) && IS_MOVE_SPECIAL(gCurrentMove) && GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD) @@ -8224,7 +8224,7 @@ u32 ItemBattleEffects(enum ItemEffect caseID, u32 battler, bool32 moveTurn) } break; case HOLD_EFFECT_STICKY_BARB: - if (TARGET_TURN_DAMAGED + if (IsBattlerTurnDamaged(gBattlerTarget) && MoveResultHasEffect(gBattlerTarget) && GetBattlerHoldEffect(gBattlerAttacker, TRUE) != HOLD_EFFECT_PROTECTIVE_PADS && IsMoveMakingContact(gCurrentMove, gBattlerAttacker) @@ -10101,7 +10101,7 @@ static inline uq4_12_t GetDefenderAbilitiesModifier(u32 move, u32 moveType, u32 { case ABILITY_MULTISCALE: case ABILITY_SHADOW_SHIELD: - if (BATTLER_MAX_HP(battlerDef)) + if (IsBattlerAtMaxHp(battlerDef)) return UQ_4_12(0.5); break; case ABILITY_FILTER: From a60a23474b1fd286f598cd17a63dc0744bae25cd Mon Sep 17 00:00:00 2001 From: PhallenTree <168426989+PhallenTree@users.noreply.github.com> Date: Thu, 19 Dec 2024 12:15:58 +0000 Subject: [PATCH 25/26] Fixes moves based on Dragon Darts with strikeCount > 2 always hitting the same battler from the second hit onwards (#5830) --- src/battle_script_commands.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 5a16340e50..1d1a842797 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -1734,7 +1734,6 @@ static void AccuracyCheck(bool32 recalcDragonDarts, const u8 *nextInstr, const u { // Smart target to partner if miss gBattlerTarget = BATTLE_PARTNER(battlerDef); - gBattleStruct->moveResultFlags[battlerDef] &= ~MOVE_RESULT_MISSED; AccuracyCheck(TRUE, nextInstr, failInstr, move); return; } @@ -6511,7 +6510,7 @@ static void Cmd_moveend(void) else { if (gMovesInfo[gCurrentMove].effect == EFFECT_DRAGON_DARTS - && gBattleStruct->moveTarget[gBattlerAttacker] == gBattlerTarget // Haven't already changed targets + && !(gBattleStruct->moveResultFlags[BATTLE_PARTNER(gBattlerTarget)] & MOVE_RESULT_MISSED) // didn't miss the other target && CanTargetPartner(gBattlerAttacker, gBattlerTarget) && !TargetFullyImmuneToCurrMove(gBattlerAttacker, BATTLE_PARTNER(gBattlerTarget))) gBattlerTarget = BATTLE_PARTNER(gBattlerTarget); // Target the partner in doubles for second hit. From f27bf843cb0f319fafcfaf2368229680fe6bd9c5 Mon Sep 17 00:00:00 2001 From: Alex <93446519+AlexOn1ine@users.noreply.github.com> Date: Fri, 20 Dec 2024 10:49:40 +0100 Subject: [PATCH 26/26] Changes Various defines to an Enum (#5839) --- include/constants/battle_script_commands.h | 264 ++++++++++----------- src/battle_script_commands.c | 3 +- 2 files changed, 134 insertions(+), 133 deletions(-) diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 3b3faa5790..50e39b767e 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -88,138 +88,138 @@ #define CMP_COMMON_BITS 4 #define CMP_NO_COMMON_BITS 5 -// Cmd_various -#define VARIOUS_CANCEL_MULTI_TURN_MOVES 0 -#define VARIOUS_IS_RUNNING_IMPOSSIBLE 1 -#define VARIOUS_GET_MOVE_TARGET 2 -#define VARIOUS_GET_BATTLER_FAINTED 3 -#define VARIOUS_RESET_SWITCH_IN_ABILITY_BITS 4 -#define VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP 5 -#define VARIOUS_RESET_PLAYER_FAINTED 6 -#define VARIOUS_PALACE_FLAVOR_TEXT 7 -#define VARIOUS_ARENA_JUDGMENT_WINDOW 8 -#define VARIOUS_ARENA_OPPONENT_MON_LOST 9 -#define VARIOUS_ARENA_PLAYER_MON_LOST 10 -#define VARIOUS_ARENA_BOTH_MONS_LOST 11 -#define VARIOUS_EMIT_YESNOBOX 12 -#define VARIOUS_DRAW_ARENA_REF_TEXT_BOX 13 -#define VARIOUS_ERASE_ARENA_REF_TEXT_BOX 14 -#define VARIOUS_ARENA_JUDGMENT_STRING 15 -#define VARIOUS_ARENA_WAIT_STRING 16 -#define VARIOUS_WAIT_CRY 17 -#define VARIOUS_RETURN_OPPONENT_MON1 18 -#define VARIOUS_RETURN_OPPONENT_MON2 19 -#define VARIOUS_VOLUME_DOWN 20 -#define VARIOUS_VOLUME_UP 21 -#define VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT 22 -#define VARIOUS_PALACE_TRY_ESCAPE_STATUS 23 -#define VARIOUS_SET_TELEPORT_OUTCOME 24 -#define VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC 25 -#define VARIOUS_STAT_TEXT_BUFFER 26 -#define VARIOUS_SWITCHIN_ABILITIES 27 -#define VARIOUS_INSTANT_HP_DROP 28 -#define VARIOUS_CLEAR_STATUS 29 -#define VARIOUS_RESTORE_PP 30 -#define VARIOUS_TRY_ACTIVATE_MOXIE 31 -#define VARIOUS_TRY_ACTIVATE_FELL_STINGER 32 -#define VARIOUS_PLAY_MOVE_ANIMATION 33 -#define VARIOUS_SET_LUCKY_CHANT 34 -#define VARIOUS_SUCKER_PUNCH_CHECK 35 -#define VARIOUS_SET_SIMPLE_BEAM 36 -#define VARIOUS_TRY_ENTRAINMENT 37 -#define VARIOUS_SET_LAST_USED_ABILITY 38 -#define VARIOUS_INVERT_STAT_STAGES 39 -#define VARIOUS_TRY_ME_FIRST 40 -#define VARIOUS_JUMP_IF_BATTLE_END 41 -#define VARIOUS_TRY_ELECTRIFY 42 -#define VARIOUS_TRY_REFLECT_TYPE 43 -#define VARIOUS_TRY_SOAK 44 -#define VARIOUS_HANDLE_MEGA_EVO 45 -#define VARIOUS_TRY_LAST_RESORT 46 -#define VARIOUS_SET_ARG_TO_BATTLE_DAMAGE 47 -#define VARIOUS_TRY_AUTOTOMIZE 48 -#define VARIOUS_ABILITY_POPUP 49 -#define VARIOUS_JUMP_IF_TARGET_ALLY 50 -#define VARIOUS_TRY_SYNCHRONOISE 51 -#define VARIOUS_PSYCHO_SHIFT 52 -#define VARIOUS_CURE_STATUS 53 -#define VARIOUS_POWER_TRICK 54 -#define VARIOUS_AFTER_YOU 55 -#define VARIOUS_BESTOW 56 -#define VARIOUS_JUMP_IF_NOT_GROUNDED 57 -#define VARIOUS_HANDLE_TRAINER_SLIDE_MSG 58 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF 59 -#define VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON 60 -#define VARIOUS_SET_AURORA_VEIL 61 -#define VARIOUS_TRY_THIRD_TYPE 62 -#define VARIOUS_ACUPRESSURE 63 -#define VARIOUS_SET_POWDER 64 -#define VARIOUS_SPECTRAL_THIEF 65 -#define VARIOUS_GRAVITY_ON_AIRBORNE_MONS 66 -#define VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS 67 -#define VARIOUS_JUMP_IF_ROAR_FAILS 68 -#define VARIOUS_TRY_INSTRUCT 69 -#define VARIOUS_JUMP_IF_NOT_BERRY 70 -#define VARIOUS_TRACE_ABILITY 71 -#define VARIOUS_UPDATE_NICK 72 -#define VARIOUS_TRY_ILLUSION_OFF 73 -#define VARIOUS_SET_SPRITEIGNORE0HP 74 -#define VARIOUS_HANDLE_FORM_CHANGE 75 -#define VARIOUS_GET_STAT_VALUE 76 -#define VARIOUS_JUMP_IF_FULL_HP 77 -#define VARIOUS_LOSE_TYPE 78 -#define VARIOUS_TRY_ACTIVATE_SOULHEART 79 -#define VARIOUS_TRY_ACTIVATE_RECEIVER 80 -#define VARIOUS_TRY_ACTIVATE_BEAST_BOOST 81 -#define VARIOUS_TRY_FRISK 82 -#define VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED 83 -#define VARIOUS_TRY_FAIRY_LOCK 84 -#define VARIOUS_JUMP_IF_NO_ALLY 85 -#define VARIOUS_POISON_TYPE_IMMUNITY 86 -#define VARIOUS_JUMP_IF_HOLD_EFFECT 87 -#define VARIOUS_INFATUATE_WITH_BATTLER 88 -#define VARIOUS_SET_LAST_USED_ITEM 89 -#define VARIOUS_PARALYZE_TYPE_IMMUNITY 90 -#define VARIOUS_JUMP_IF_ABSENT 91 -#define VARIOUS_DESTROY_ABILITY_POPUP 92 -#define VARIOUS_TOTEM_BOOST 93 -#define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 94 -#define VARIOUS_MOVEEND_ITEM_EFFECTS 95 -#define VARIOUS_TERRAIN_SEED 96 -#define VARIOUS_MAKE_INVISIBLE 97 -#define VARIOUS_ROOM_SERVICE 98 -#define VARIOUS_EERIE_SPELL_PP_REDUCE 99 -#define VARIOUS_JUMP_IF_TEAM_HEALTHY 100 -#define VARIOUS_TRY_HEAL_QUARTER_HP 101 -#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 102 -#define VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER 103 -#define VARIOUS_GET_ROTOTILLER_TARGETS 104 -#define VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED 105 -#define VARIOUS_TRY_ACTIVATE_BATTLE_BOND 106 -#define VARIOUS_CONSUME_BERRY 107 -#define VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL 108 -#define VARIOUS_JUMP_IF_SPECIES 109 -#define VARIOUS_UPDATE_ABILITY_POPUP 110 -#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 111 -#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 112 -#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 113 -#define VARIOUS_TRY_NO_RETREAT 114 -#define VARIOUS_CHECK_POLTERGEIST 115 -#define VARIOUS_CUT_1_3_HP_RAISE_STATS 116 -#define VARIOUS_TRY_END_NEUTRALIZING_GAS 117 -#define VARIOUS_JUMP_IF_UNDER_200 118 -#define VARIOUS_SET_SKY_DROP 119 -#define VARIOUS_CLEAR_SKY_DROP 120 -#define VARIOUS_SKY_DROP_YAWN 121 -#define VARIOUS_CURE_CERTAIN_STATUSES 122 -#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 123 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 124 -#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 125 -#define VARIOUS_SAVE_BATTLER_ITEM 126 -#define VARIOUS_RESTORE_BATTLER_ITEM 127 -#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 128 -#define VARIOUS_SWAP_SIDE_STATUSES 129 -#define VARIOUS_SWAP_STATS 130 +enum CmdVarious +{ + VARIOUS_CANCEL_MULTI_TURN_MOVES, + VARIOUS_IS_RUNNING_IMPOSSIBLE, + VARIOUS_GET_MOVE_TARGET, + VARIOUS_GET_BATTLER_FAINTED, + VARIOUS_RESET_SWITCH_IN_ABILITY_BITS, + VARIOUS_UPDATE_CHOICE_MOVE_ON_LVL_UP, + VARIOUS_RESET_PLAYER_FAINTED, + VARIOUS_PALACE_FLAVOR_TEXT, + VARIOUS_ARENA_JUDGMENT_WINDOW, + VARIOUS_ARENA_OPPONENT_MON_LOST, + VARIOUS_ARENA_PLAYER_MON_LOST, + VARIOUS_ARENA_BOTH_MONS_LOST, + VARIOUS_EMIT_YESNOBOX, + VARIOUS_DRAW_ARENA_REF_TEXT_BOX, + VARIOUS_ERASE_ARENA_REF_TEXT_BOX, + VARIOUS_ARENA_JUDGMENT_STRING, + VARIOUS_ARENA_WAIT_STRING, + VARIOUS_WAIT_CRY, + VARIOUS_RETURN_OPPONENT_MON1, + VARIOUS_RETURN_OPPONENT_MON2, + VARIOUS_VOLUME_DOWN, + VARIOUS_VOLUME_UP, + VARIOUS_SET_ALREADY_STATUS_MOVE_ATTEMPT, + VARIOUS_PALACE_TRY_ESCAPE_STATUS, + VARIOUS_SET_TELEPORT_OUTCOME, + VARIOUS_PLAY_TRAINER_DEFEATED_MUSIC, + VARIOUS_STAT_TEXT_BUFFER, + VARIOUS_SWITCHIN_ABILITIES, + VARIOUS_INSTANT_HP_DROP, + VARIOUS_CLEAR_STATUS, + VARIOUS_RESTORE_PP, + VARIOUS_TRY_ACTIVATE_MOXIE, + VARIOUS_TRY_ACTIVATE_FELL_STINGER, + VARIOUS_PLAY_MOVE_ANIMATION, + VARIOUS_SET_LUCKY_CHANT, + VARIOUS_SUCKER_PUNCH_CHECK, + VARIOUS_SET_SIMPLE_BEAM, + VARIOUS_TRY_ENTRAINMENT, + VARIOUS_SET_LAST_USED_ABILITY, + VARIOUS_INVERT_STAT_STAGES, + VARIOUS_TRY_ME_FIRST, + VARIOUS_JUMP_IF_BATTLE_END, + VARIOUS_TRY_ELECTRIFY, + VARIOUS_TRY_SOAK, + VARIOUS_TRY_LAST_RESORT, + VARIOUS_SET_ARG_TO_BATTLE_DAMAGE, + VARIOUS_TRY_AUTOTOMIZE, + VARIOUS_ABILITY_POPUP, + VARIOUS_JUMP_IF_TARGET_ALLY, + VARIOUS_TRY_SYNCHRONOISE, + VARIOUS_PSYCHO_SHIFT, + VARIOUS_CURE_STATUS, + VARIOUS_POWER_TRICK, + VARIOUS_AFTER_YOU, + VARIOUS_BESTOW, + VARIOUS_JUMP_IF_NOT_GROUNDED, + VARIOUS_HANDLE_TRAINER_SLIDE_MSG, + VARIOUS_TRY_TRAINER_SLIDE_MSG_FIRST_OFF, + VARIOUS_TRY_TRAINER_SLIDE_MSG_LAST_ON, + VARIOUS_SET_AURORA_VEIL, + VARIOUS_TRY_THIRD_TYPE, + VARIOUS_ACUPRESSURE, + VARIOUS_SET_POWDER, + VARIOUS_SPECTRAL_THIEF, + VARIOUS_GRAVITY_ON_AIRBORNE_MONS, + VARIOUS_CHECK_IF_GRASSY_TERRAIN_HEALS, + VARIOUS_JUMP_IF_ROAR_FAILS, + VARIOUS_TRY_INSTRUCT, + VARIOUS_JUMP_IF_NOT_BERRY, + VARIOUS_TRACE_ABILITY, + VARIOUS_UPDATE_NICK, + VARIOUS_TRY_ILLUSION_OFF, + VARIOUS_SET_SPRITEIGNORE0HP, + VARIOUS_HANDLE_FORM_CHANGE, + VARIOUS_GET_STAT_VALUE, + VARIOUS_JUMP_IF_FULL_HP, + VARIOUS_LOSE_TYPE, + VARIOUS_TRY_ACTIVATE_SOULHEART, + VARIOUS_TRY_ACTIVATE_RECEIVER, + VARIOUS_TRY_ACTIVATE_BEAST_BOOST, + VARIOUS_TRY_FRISK, + VARIOUS_JUMP_IF_SHIELDS_DOWN_PROTECTED, + VARIOUS_TRY_FAIRY_LOCK, + VARIOUS_JUMP_IF_NO_ALLY, + VARIOUS_POISON_TYPE_IMMUNITY, + VARIOUS_JUMP_IF_HOLD_EFFECT, + VARIOUS_INFATUATE_WITH_BATTLER, + VARIOUS_SET_LAST_USED_ITEM, + VARIOUS_PARALYZE_TYPE_IMMUNITY, + VARIOUS_JUMP_IF_ABSENT, + VARIOUS_DESTROY_ABILITY_POPUP, + VARIOUS_TOTEM_BOOST, + VARIOUS_TRY_ACTIVATE_GRIM_NEIGH, + VARIOUS_MOVEEND_ITEM_EFFECTS, + VARIOUS_TERRAIN_SEED, + VARIOUS_MAKE_INVISIBLE, + VARIOUS_ROOM_SERVICE, + VARIOUS_EERIE_SPELL_PP_REDUCE, + VARIOUS_JUMP_IF_TEAM_HEALTHY, + VARIOUS_TRY_HEAL_QUARTER_HP, + VARIOUS_JUMP_IF_PRANKSTER_BLOCKED, + VARIOUS_TRY_TO_CLEAR_PRIMAL_WEATHER, + VARIOUS_GET_ROTOTILLER_TARGETS, + VARIOUS_JUMP_IF_NOT_ROTOTILLER_AFFECTED, + VARIOUS_TRY_ACTIVATE_BATTLE_BOND, + VARIOUS_CONSUME_BERRY, + VARIOUS_JUMP_IF_CANT_REVERT_TO_PRIMAL, + VARIOUS_JUMP_IF_SPECIES, + VARIOUS_UPDATE_ABILITY_POPUP, + VARIOUS_JUMP_IF_WEATHER_AFFECTED, + VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED, + VARIOUS_SET_ATTACKER_STICKY_WEB_USER, + VARIOUS_TRY_NO_RETREAT, + VARIOUS_CHECK_POLTERGEIST, + VARIOUS_CUT_1_3_HP_RAISE_STATS, + VARIOUS_TRY_END_NEUTRALIZING_GAS, + VARIOUS_JUMP_IF_UNDER_200, + VARIOUS_SET_SKY_DROP, + VARIOUS_CLEAR_SKY_DROP, + VARIOUS_SKY_DROP_YAWN, + VARIOUS_CURE_CERTAIN_STATUSES, + VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES, + VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY, + VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT, + VARIOUS_SAVE_BATTLER_ITEM, + VARIOUS_RESTORE_BATTLER_ITEM, + VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM, + VARIOUS_SWAP_SIDE_STATUSES, + VARIOUS_SWAP_STATS, +}; // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 1 diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 1d1a842797..863dcc6f0e 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -9464,13 +9464,14 @@ static void Cmd_various(void) s32 i; u8 data[10]; u32 battler, bits; + enum CmdVarious variousId = cmd->id; if (gBattleControllerExecFlags) return; battler = GetBattlerForBattleScript(cmd->battler); - switch (cmd->id) + switch (variousId) { // Roar will fail in a double wild battle when used by the player against one of the two alive wild mons. // Also when an opposing wild mon uses it againt its partner.
- Note for advanced users: WSL2... - -> WSL2 is an option and is even faster than WSL1 if files are stored on the WSL2 file system, but some tools may have trouble interacting -> with the WSL2 file system over the network drive. For example, tools which use Qt versions before 5.15.2 such as porymap -> may have problems with parsing the \\wsl$ network drive path. -