diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 69e45ddea..66c82f39e 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1022,7 +1022,7 @@ .4byte \ptr .endm - .macro trydobeatup endPtr:req, failPtr:req + .macro trydobeatup endPtr=NULL, failPtr=NULL .byte 0xc4 .4byte \endPtr .4byte \failPtr @@ -1941,6 +1941,31 @@ .macro shellsidearmcheck various BS_ATTACKER, VARIOUS_SHELL_SIDE_ARM_CHECK .endm + + .macro jumpifrodaffected battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_ROD + .4byte \ptr + .endm + + .macro jumpifabsorbaffected battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_ABSORB + .4byte \ptr + .endm + + .macro jumpifmotoraffected battler:req, ptr:req + various \battler, VARIOUS_JUMP_IF_MOTOR + .4byte \ptr + .endm + + .macro jumpifteanoberry ptr:req + various BS_ATTACKER, VARIOUS_TEATIME_TARGETS + .4byte \ptr + .endm + + .macro jumpifteainvulnerable battler:req, ptr:req + various \battler, VARIOUS_TEATIME_INVUL + .4byte \ptr + .endm .macro jumpifcantfling battler:req, ptr:req various \battler, VARIOUS_JUMP_IF_CANT_FLING diff --git a/data/battle_anim_scripts.s b/data/battle_anim_scripts.s index 1deac0890..e19f4c993 100644 --- a/data/battle_anim_scripts.s +++ b/data/battle_anim_scripts.s @@ -13478,7 +13478,18 @@ Move_DRAGON_DARTS:: end Move_TEATIME:: - goto Move_MILK_DRINK + loadspritegfx ANIM_TAG_TEAPOT + loadspritegfx ANIM_TAG_THOUGHT_BUBBLE + createsprite gThoughtBubbleSpriteTemplate, ANIM_ATTACKER, 11, 0, 100 + playsewithpan SE_M_ICY_WIND, SOUND_PAN_ATTACKER + delay 6 + createsprite gTeapotSpriteTemplate, ANIM_ATTACKER, 12, 0 + createvisualtask AnimTask_RockMonBackAndForth, 5, ANIM_ATTACKER, 2, 0 + createvisualtask AnimTask_RockMonBackAndForth, 5, ANIM_ATK_PARTNER, 2, 0 + delay 24 + loopsewithpan SE_M_HEAL_BELL, SOUND_PAN_ATTACKER, 22, 3 + waitforvisualfinish + end Move_OCTOLOCK:: loadspritegfx ANIM_TAG_TENDRILS diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 9d307b8b9..4845b49aa 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -416,6 +416,74 @@ gBattleScriptsForMoveEffects:: .4byte BattleScript_EffectDoubleShock @ EFFECT_DOUBLE_SHOCK .4byte BattleScript_EffectSpecialAttackUpHit @ EFFECT_SPECIAL_ATTACK_UP_HIT .4byte BattleScript_EffectVictoryDance @ EFFECT_VICTORY_DANCE + .4byte BattleScript_EffectTeatime @ EFFECT_TEATIME + +BattleScript_EffectTeatime:: + attackcanceler + attackstring + ppreduce + jumpifteanoberry BattleScript_ButItFailed +@ at least one battler is affected + attackanimation + waitanimation +BattleScript_TeatimeLoop: + jumpifteainvulnerable BS_TARGET, BattleScript_Teatimevul + jumpifrodaffected BS_TARGET, BattleScript_Teatimerod + jumpifabsorbaffected BS_TARGET, BattleScript_Teatimesorb + jumpifmotoraffected BS_TARGET, BattleScript_Teatimemotor + orword gHitMarker, HITMARKER_NO_ANIMATIONS | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE + setbyte sBERRY_OVERRIDE, TRUE @ override the requirements for eating berries + consumeberry BS_TARGET, TRUE @ consume the berry, then restore the item from changedItems + bicword gHitMarker, HITMARKER_NO_ANIMATIONS | HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_IGNORE_DISGUISE + setbyte sBERRY_OVERRIDE, FALSE + removeitem BS_TARGET + moveendto MOVEEND_NEXT_TARGET + jumpifnexttargetvalid BattleScript_TeatimeLoop + moveendcase MOVEEND_CLEAR_BITS + goto BattleScript_MoveEnd +BattleScript_Teatimevul: + moveendto MOVEEND_NEXT_TARGET + jumpifnexttargetvalid BattleScript_TeatimeLoop + moveendcase MOVEEND_CLEAR_BITS + goto BattleScript_MoveEnd +BattleScript_Teatimesorb: + copybyte gBattlerAbility, gBattlerTarget + call BattleScript_AbilityPopUp + moveendto MOVEEND_NEXT_TARGET + jumpifnexttargetvalid BattleScript_TeatimeLoop + moveendcase MOVEEND_CLEAR_BITS + goto BattleScript_MoveEnd +BattleScript_Teatimerod: + copybyte gBattlerAbility, gBattlerTarget + call BattleScript_AbilityPopUp + playstatchangeanimation BS_TARGET, BIT_SPATK, STAT_CHANGE_BY_TWO + setstatchanger STAT_SPATK, 1, FALSE + statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_TeatimeBuffer + printfromtable gStatUpStringIds + waitmessage 0x40 + moveendto MOVEEND_NEXT_TARGET + jumpifnexttargetvalid BattleScript_TeatimeLoop + moveendcase MOVEEND_CLEAR_BITS + goto BattleScript_MoveEnd +BattleScript_Teatimemotor: + copybyte gBattlerAbility, gBattlerTarget + call BattleScript_AbilityPopUp + playstatchangeanimation BS_TARGET, BIT_SPEED, STAT_CHANGE_BY_TWO + setstatchanger STAT_SPEED, 1, FALSE + statbuffchange STAT_CHANGE_ALLOW_PTR, BattleScript_TeatimeBuffer + jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 0x2, BattleScript_TeatimeBuffer + printfromtable gStatUpStringIds + waitmessage 0x40 + moveendto MOVEEND_NEXT_TARGET + jumpifnexttargetvalid BattleScript_TeatimeLoop + moveendcase MOVEEND_CLEAR_BITS + goto BattleScript_MoveEnd +BattleScript_TeatimeBuffer: + moveendto MOVEEND_NEXT_TARGET + jumpifnexttargetvalid BattleScript_TeatimeLoop + moveendcase MOVEEND_CLEAR_BITS + goto BattleScript_MoveEnd BattleScript_AffectionBasedEndurance:: playanimation BS_TARGET, B_ANIM_AFFECTION_HANGED_ON @@ -5220,10 +5288,18 @@ BattleScript_EffectTeleportNew: BattleScript_EffectTeleportNewEnd: goto BattleScript_MoveEnd -.if B_BEAT_UP < GEN_5 BattleScript_EffectBeatUp:: attackcanceler accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE +.if B_BEAT_UP >= GEN_5 + attackstring + ppreduce + critcalc + damagecalc + adjustdamage + trydobeatup + goto BattleScript_HitFromAtkAnimation +.else attackstring pause B_WAIT_TIME_SHORT ppreduce @@ -5253,12 +5329,6 @@ BattleScript_BeatUpAttack:: goto BattleScript_BeatUpLoop BattleScript_BeatUpEnd:: end -.else -BattleScript_EffectBeatUp:: - attackcanceler - accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE - addbyte gBattleCommunication, 1 - goto BattleScript_HitFromAtkString .endif BattleScript_EffectSemiInvulnerable:: @@ -8415,12 +8485,13 @@ BattleScript_IntimidateLoop: .endif jumpifability BS_TARGET, ABILITY_GUARD_DOG, BattleScript_IntimidateInReverse BattleScript_IntimidateEffect: - copybyte sBATTLER, gBattlerTarget - statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED | MOVE_EFFECT_CERTAIN, NULL + copybyte sBATTLER, gBattlerAttacker + statbuffchange STAT_CHANGE_NOT_PROTECT_AFFECTED | STAT_CHANGE_ALLOW_PTR, BattleScript_IntimidateLoopIncrement setgraphicalstatchangevalues playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1 printstring STRINGID_PKMNCUTSATTACKWITH waitmessage B_WAIT_TIME_LONG + copybyte sBATTLER, gBattlerTarget call BattleScript_TryAdrenalineOrb BattleScript_IntimidateLoopIncrement: addbyte gBattlerTarget, 1 diff --git a/graphics/battle_anims/sprites/new/teapot.pal b/graphics/battle_anims/sprites/new/teapot.pal new file mode 100644 index 000000000..f8319ce12 --- /dev/null +++ b/graphics/battle_anims/sprites/new/teapot.pal @@ -0,0 +1,19 @@ +JASC-PAL +0100 +16 +10 247 12 +144 141 173 +255 255 255 +207 232 255 +106 104 120 +190 211 255 +166 169 214 +214 171 113 +162 119 89 +72 71 81 +251 255 211 +232 207 121 +255 255 153 +124 86 73 +0 0 0 +0 0 0 diff --git a/graphics/battle_anims/sprites/new/teapot.png b/graphics/battle_anims/sprites/new/teapot.png new file mode 100644 index 000000000..6be0680df Binary files /dev/null and b/graphics/battle_anims/sprites/new/teapot.png differ diff --git a/include/battle.h b/include/battle.h index 228ba769d..aafc3d2f6 100644 --- a/include/battle.h +++ b/include/battle.h @@ -612,7 +612,7 @@ struct BattleStruct u8 debugBattler; u8 magnitudeBasePower; u8 presentBasePower; - u8 roostTypes[MAX_BATTLERS_COUNT][3]; + u8 roostTypes[MAX_BATTLERS_COUNT][2]; u8 savedBattlerTarget; bool8 ateBoost[MAX_BATTLERS_COUNT]; u8 activeAbilityPopUps; // as bits for each battler @@ -651,6 +651,7 @@ struct BattleStruct u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle. // When using a move which hits multiple opponents which is then bounced by a target, we need to make sure, the move hits both opponents, the one with bounce, and the one without. u8 attackerBeforeBounce:2; + u8 beatUpSlot:3; u8 targetsDone[MAX_BATTLERS_COUNT]; // Each battler as a bit. u16 overwrittenAbilities[MAX_BATTLERS_COUNT]; // abilities overwritten during battle (keep separate from battle history in case of switching) }; diff --git a/include/battle_util.h b/include/battle_util.h index 18af25c68..1a05c246c 100644 --- a/include/battle_util.h +++ b/include/battle_util.h @@ -144,6 +144,7 @@ u16 CalcTypeEffectivenessMultiplier(u16 move, u8 moveType, u8 battlerAtk, u8 bat u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilityDef); u16 GetTypeModifier(u8 atkType, u8 defType); s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId); +s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp); u16 GetMegaEvolutionSpecies(u16 preEvoSpecies, u16 heldItemId); u16 GetPrimalReversionSpecies(u16 preEvoSpecies, u16 heldItemId); u16 GetWishMegaEvolutionSpecies(u16 preEvoSpecies, u16 moveId1, u16 moveId2, u16 moveId3, u16 moveId4); diff --git a/include/config/battle.h b/include/config/battle.h index 3f06f54da..c060cb0cc 100644 --- a/include/config/battle.h +++ b/include/config/battle.h @@ -38,6 +38,7 @@ #define B_STEEL_RESISTANCES GEN_LATEST // In Gen6+, Steel-type Pokémon are no longer resistant to Dark-type and Ghost-type moves. #define B_PRANKSTER_DARK_TYPES GEN_LATEST // In Gen7+, Prankster-elevated status moves do not affect Dark type Pokémon. #define B_SHEER_COLD_IMMUNITY GEN_LATEST // In Gen7+, Ice-types are immune to Sheer Cold +#define B_ROOST_PURE_FLYING GEN_LATEST // In Gen5+, Roost makes pure Flying-types into Normal-type. // Turn settings #define B_BINDING_TURNS GEN_LATEST // In Gen5+, binding moves last for 4-5 turns instead of 2-5 turns. (With Grip Claw, 7 and 5 turns respectively.) diff --git a/include/constants/battle_anim.h b/include/constants/battle_anim.h index 52b20ecaa..0e8aaea83 100644 --- a/include/constants/battle_anim.h +++ b/include/constants/battle_anim.h @@ -394,6 +394,8 @@ #define ANIM_TAG_OMEGA_SYMBOL (ANIM_SPRITES_START + 382) #define ANIM_TAG_STEEL_BEAM (ANIM_SPRITES_START + 383) #define ANIM_TAG_POLTERGEIST (ANIM_SPRITES_START + 384) +#define ANIM_TAG_TEAPOT (ANIM_SPRITES_START + 385) + // battlers #define ANIM_ATTACKER 0 diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index 122660c05..89613f277 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -397,7 +397,9 @@ #define EFFECT_DOUBLE_SHOCK 391 #define EFFECT_SPECIAL_ATTACK_UP_HIT 392 #define EFFECT_VICTORY_DANCE 393 +#define EFFECT_TEATIME 394 + +#define NUM_BATTLE_MOVE_EFFECTS 395 -#define NUM_BATTLE_MOVE_EFFECTS 394 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 61f69587c..8f9ce0af8 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -247,9 +247,14 @@ #define VARIOUS_GET_BATTLER_SIDE 156 #define VARIOUS_CHECK_PARENTAL_BOND_COUNTER 157 #define VARIOUS_SWAP_STATS 158 -#define VARIOUS_TRY_WIND_RIDER_POWER 159 -#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 160 -#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 161 +#define VARIOUS_JUMP_IF_ROD 159 +#define VARIOUS_JUMP_IF_ABSORB 160 +#define VARIOUS_JUMP_IF_MOTOR 161 +#define VARIOUS_TEATIME_INVUL 162 +#define VARIOUS_TEATIME_TARGETS 163 +#define VARIOUS_TRY_WIND_RIDER_POWER 164 +#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 165 +#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 166 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/graphics.h b/include/graphics.h index 512038b5f..78074a9d3 100644 --- a/include/graphics.h +++ b/include/graphics.h @@ -9957,6 +9957,8 @@ extern const u32 gBattleAnimSpriteGfx_Tornado[]; extern const u32 gBattleAnimSpritePal_Tornado[]; extern const u32 gBattleAnimSpriteGfx_ZMoveSymbol[]; extern const u32 gBattleAnimSpritePal_ZMoveSymbol[]; +extern const u32 gBattleAnimSpriteGfx_Teapot[]; +extern const u32 gBattleAnimSpritePal_Teapot[]; extern const u32 gBattleAnimBgImage_Dark[]; extern const u32 gBattleAnimBgImage_Ghost[]; diff --git a/src/battle_ai_main.c b/src/battle_ai_main.c index 384c50d88..92866a7c2 100644 --- a/src/battle_ai_main.c +++ b/src/battle_ai_main.c @@ -2702,7 +2702,7 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score) switch (gBattleMoves[AI_DATA->partnerMove].effect) { case EFFECT_HELPING_HAND: - if (IS_MOVE_STATUS(move)) + if (!IS_MOVE_STATUS(move)) score += 5; break; case EFFECT_PERISH_SONG: diff --git a/src/battle_ai_util.c b/src/battle_ai_util.c index 128f223a1..ef97ab9a1 100644 --- a/src/battle_ai_util.c +++ b/src/battle_ai_util.c @@ -2429,19 +2429,41 @@ static bool32 PartyBattlerShouldAvoidHazards(u8 currBattler, u8 switchBattler) { struct Pokemon *mon = GetPartyBattlerPartyData(currBattler, switchBattler); u16 ability = GetMonAbility(mon); // we know our own party data - u16 holdEffect = GetBattlerHoldEffect(GetMonData(mon, MON_DATA_HELD_ITEM), TRUE); + u16 holdEffect; + u16 species = GetMonData(mon, MON_DATA_SPECIES); u32 flags = gSideStatuses[GetBattlerSide(currBattler)] & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK | SIDE_STATUS_STICKY_WEB | SIDE_STATUS_TOXIC_SPIKES); + s32 hazardDamage = 0; + u8 type1 = gSpeciesInfo[species].type1; + u8 type2 = gSpeciesInfo[species].type2; + u32 maxHp = GetMonData(mon, MON_DATA_MAX_HP); if (flags == 0) return FALSE; - if (ability == ABILITY_MAGIC_GUARD || ability == ABILITY_LEVITATE - || holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS) + if (ability == ABILITY_MAGIC_GUARD) + return FALSE; + if (gFieldStatuses & STATUS_FIELD_MAGIC_ROOM || ability == ABILITY_KLUTZ) + holdEffect = HOLD_EFFECT_NONE; + else + holdEffect = gItems[GetMonData(mon, MON_DATA_HELD_ITEM)].holdEffect; + if (holdEffect == HOLD_EFFECT_HEAVY_DUTY_BOOTS) return FALSE; - if (flags & (SIDE_STATUS_SPIKES | SIDE_STATUS_STEALTH_ROCK) && GetMonData(mon, MON_DATA_HP) < (GetMonData(mon, MON_DATA_MAX_HP) / 8)) - return TRUE; + if (flags & SIDE_STATUS_STEALTH_ROCK) + hazardDamage += GetStealthHazardDamageByTypesAndHP(gBattleMoves[MOVE_STEALTH_ROCK].type, type1, type2, maxHp); + if (flags & SIDE_STATUS_SPIKES && ((type1 != TYPE_FLYING && type2 != TYPE_FLYING + && ability != ABILITY_LEVITATE && holdEffect != HOLD_EFFECT_AIR_BALLOON) + || holdEffect == HOLD_EFFECT_IRON_BALL || gFieldStatuses & STATUS_FIELD_GRAVITY)) + { + u8 spikesDmg = maxHp / ((5 - gSideTimers[GetBattlerSide(currBattler)].spikesAmount) * 2); + if (spikesDmg == 0) + spikesDmg = 1; + hazardDamage += spikesDmg; + } + + if (hazardDamage >= GetMonData(mon, MON_DATA_HP)) + return TRUE; return FALSE; } diff --git a/src/battle_anim_effects_1.c b/src/battle_anim_effects_1.c index 0db7f69d5..ea36b2eac 100644 --- a/src/battle_anim_effects_1.c +++ b/src/battle_anim_effects_1.c @@ -2447,6 +2447,39 @@ const struct SpriteTemplate gFollowMeFingerSpriteTemplate = .callback = AnimFollowMeFinger, }; +const union AffineAnimCmd gTeaAffineAnimCmds1[] = +{ + AFFINEANIMCMD_FRAME(0x10, 0x10, 0, 0), + AFFINEANIMCMD_FRAME(0x1E, 0x1E, 0, 8), + AFFINEANIMCMD_END, +}; + +const union AffineAnimCmd gTeaAffineAnimCmds2[] = +{ + AFFINEANIMCMD_FRAME(0x0, 0x0, -3, 11), + AFFINEANIMCMD_FRAME(0x0, 0x0, 3, 11), + AFFINEANIMCMD_LOOP(2), + AFFINEANIMCMD_FRAME(0xFFE2, 0xFFE2, 0, 8), + AFFINEANIMCMD_END, +}; + +const union AffineAnimCmd *const gTeaAffineAnimTable[] = +{ + gTeaAffineAnimCmds1, + gTeaAffineAnimCmds2, +}; + +const struct SpriteTemplate gTeapotSpriteTemplate = +{ + .tileTag = ANIM_TAG_TEAPOT, + .paletteTag = ANIM_TAG_TEAPOT, + .oam = &gOamData_AffineDouble_ObjNormal_64x64, + .anims = gDummySpriteAnimTable, + .images = NULL, + .affineAnims = gTeaAffineAnimTable, + .callback = AnimMetronomeFinger, +}; + const union AnimCmd gTauntFingerAnimCmds1[] = { ANIMCMD_FRAME(0, 1), diff --git a/src/battle_main.c b/src/battle_main.c index 27ed4a6c3..56b009cbb 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -101,7 +101,7 @@ static void SetActionsAndBattlersTurnOrder(void); static void UpdateBattlerPartyOrdersOnSwitch(void); static bool8 AllAtActionConfirmed(void); static void TryChangeTurnOrder(void); -static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void); +static void CheckChosenMoveForEffectsBeforeTurnStarts(void); static void CheckMegaEvolutionBeforeTurn(void); static void CheckQuickClaw_CustapBerryActivation(void); static void FreeResetData_ReturnToOvOrDoEvolutions(void); @@ -3039,6 +3039,7 @@ static void BattleStartClearSetData(void) gBattleStruct->stickyWebUser = 0xFF; gBattleStruct->appearedInBattle = 0; + gBattleStruct->beatUpSlot = 0; for (i = 0; i < PARTY_SIZE; i++) { @@ -4887,7 +4888,7 @@ static void CheckMegaEvolutionBeforeTurn(void) } #if B_MEGA_EVO_TURN_ORDER <= GEN_6 - gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts; + gBattleMainFunc = CheckChosenMoveForEffectsBeforeTurnStarts; gBattleStruct->focusPunchBattlerId = 0; #else gBattleMainFunc = TryChangeTurnOrder; // This will just do nothing if no mon has mega evolved @@ -4912,11 +4913,11 @@ static void TryChangeTurnOrder(void) } } } - gBattleMainFunc = CheckFocusPunch_ClearVarsBeforeTurnStarts; + gBattleMainFunc = CheckChosenMoveForEffectsBeforeTurnStarts; gBattleStruct->focusPunchBattlerId = 0; } -static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void) +static void CheckChosenMoveForEffectsBeforeTurnStarts(void) { u32 i; @@ -4930,7 +4931,7 @@ static void CheckFocusPunch_ClearVarsBeforeTurnStarts(void) && !(gDisableStructs[gBattlerAttacker].truantCounter) && !(gProtectStructs[gActiveBattler].noValidMoves)) { - switch(gChosenMoveByBattler[gActiveBattler]) + switch (gChosenMoveByBattler[gActiveBattler]) { case MOVE_FOCUS_PUNCH: BattleScriptExecute(BattleScript_FocusPunchSetUp); diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index a979400ab..ec4d72a08 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -4802,22 +4802,24 @@ static void Cmd_setroost(void) { gBattleStruct->roostTypes[gBattlerAttacker][0] = TYPE_FLYING; gBattleStruct->roostTypes[gBattlerAttacker][1] = TYPE_FLYING; - gBattleStruct->roostTypes[gBattlerAttacker][2] = TYPE_FLYING; +#if B_ROOST_PURE_FLYING >= GEN_5 SET_BATTLER_TYPE(gBattlerAttacker, TYPE_NORMAL); +#else + SET_BATTLER_TYPE(gBattlerAttacker, TYPE_MYSTERY); +#endif } - // Dual Type with Flying Type. - else if ((gBattleMons[gBattlerAttacker].type1 == TYPE_FLYING && gBattleMons[gBattlerAttacker].type2 != TYPE_FLYING) - ||(gBattleMons[gBattlerAttacker].type2 == TYPE_FLYING && gBattleMons[gBattlerAttacker].type1 != TYPE_FLYING)) + // Dual type with flying type. + else if (gBattleMons[gBattlerAttacker].type1 == TYPE_FLYING || gBattleMons[gBattlerAttacker].type2 == TYPE_FLYING) { gBattleStruct->roostTypes[gBattlerAttacker][0] = gBattleMons[gBattlerAttacker].type1; gBattleStruct->roostTypes[gBattlerAttacker][1] = gBattleMons[gBattlerAttacker].type2; if (gBattleMons[gBattlerAttacker].type1 == TYPE_FLYING) gBattleMons[gBattlerAttacker].type1 = TYPE_MYSTERY; - if (gBattleMons[gBattlerAttacker].type2 == TYPE_FLYING) + else if (gBattleMons[gBattlerAttacker].type2 == TYPE_FLYING) gBattleMons[gBattlerAttacker].type2 = TYPE_MYSTERY; } // Non-flying type. - else if (!IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_FLYING)) + else { gBattleStruct->roostTypes[gBattlerAttacker][0] = gBattleMons[gBattlerAttacker].type1; gBattleStruct->roostTypes[gBattlerAttacker][1] = gBattleMons[gBattlerAttacker].type2; @@ -7921,35 +7923,34 @@ static bool32 HasAttackerFaintedTarget(void) static void HandleTerrainMove(u16 move) { u32 statusFlag = 0; - u8 *timer = NULL; switch (gBattleMoves[move].effect) { case EFFECT_MISTY_TERRAIN: - statusFlag = STATUS_FIELD_MISTY_TERRAIN, timer = &gFieldTimers.terrainTimer; + statusFlag = STATUS_FIELD_MISTY_TERRAIN; gBattleCommunication[MULTISTRING_CHOOSER] = 0; break; case EFFECT_GRASSY_TERRAIN: - statusFlag = STATUS_FIELD_GRASSY_TERRAIN, timer = &gFieldTimers.terrainTimer; + statusFlag = STATUS_FIELD_GRASSY_TERRAIN; gBattleCommunication[MULTISTRING_CHOOSER] = 1; break; case EFFECT_ELECTRIC_TERRAIN: - statusFlag = STATUS_FIELD_ELECTRIC_TERRAIN, timer = &gFieldTimers.terrainTimer; + statusFlag = STATUS_FIELD_ELECTRIC_TERRAIN; gBattleCommunication[MULTISTRING_CHOOSER] = 2; break; case EFFECT_PSYCHIC_TERRAIN: - statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN, timer = &gFieldTimers.terrainTimer; + statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; gBattleCommunication[MULTISTRING_CHOOSER] = 3; break; case EFFECT_HIT_SET_REMOVE_TERRAIN: switch (gBattleMoves[move].argument) { case 0: //genesis supernova - statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN, timer = &gFieldTimers.terrainTimer; + statusFlag = STATUS_FIELD_PSYCHIC_TERRAIN; gBattleCommunication[MULTISTRING_CHOOSER] = 3; break; case 1: //splintered stormshards - if (!(gFieldStatuses & (STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN))) + if (!(gFieldStatuses & STATUS_FIELD_TERRAIN_ANY)) { //no terrain to remove -> jump to battle script pointer gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); @@ -7957,7 +7958,7 @@ static void HandleTerrainMove(u16 move) else { // remove all terrain - gFieldStatuses &= ~(STATUS_FIELD_MISTY_TERRAIN | STATUS_FIELD_GRASSY_TERRAIN | STATUS_FIELD_ELECTRIC_TERRAIN | STATUS_FIELD_PSYCHIC_TERRAIN); + gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; gBattleCommunication[MULTISTRING_CHOOSER] = 4; gBattlescriptCurrInstr += 7; } @@ -7977,9 +7978,9 @@ static void HandleTerrainMove(u16 move) gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; gFieldStatuses |= statusFlag; if (GetBattlerHoldEffect(gBattlerAttacker, TRUE) == HOLD_EFFECT_TERRAIN_EXTENDER) - *timer = 8; + gFieldTimers.terrainTimer = 8; else - *timer = 5; + gFieldTimers.terrainTimer = 5; gBattlescriptCurrInstr += 7; } } @@ -8130,6 +8131,67 @@ static bool32 IsRototillerAffected(u32 battlerId) return TRUE; } + +static bool32 IsAbilityRodAffected(void) +{ + u32 moveType; + + if (gBattleStruct->dynamicMoveType == 0) + moveType = gBattleMoves[gCurrentMove].type; + else if (!(gBattleStruct->dynamicMoveType & 0x40)) + moveType = gBattleStruct->dynamicMoveType & 0x3F; + else + moveType = gBattleMoves[gCurrentMove].type; + + if (moveType == TYPE_ELECTRIC && GetBattlerAbility(gBattlerTarget) == ABILITY_LIGHTNING_ROD) + return TRUE; + else + return FALSE; +} + +static bool32 IsAbilityMotorAffected(void) +{ + u32 moveType; + + if (gBattleStruct->dynamicMoveType == 0) + moveType = gBattleMoves[gCurrentMove].type; + else if (!(gBattleStruct->dynamicMoveType & 0x40)) + moveType = gBattleStruct->dynamicMoveType & 0x3F; + else + moveType = gBattleMoves[gCurrentMove].type; + + if (moveType == TYPE_ELECTRIC && GetBattlerAbility(gBattlerTarget) == ABILITY_MOTOR_DRIVE) + return TRUE; + else + return FALSE; +} + +static bool32 IsAbilityAbsorbAffected(void) +{ + u32 moveType; + + if (gBattleStruct->dynamicMoveType == 0) + moveType = gBattleMoves[gCurrentMove].type; + else if (!(gBattleStruct->dynamicMoveType & 0x40)) + moveType = gBattleStruct->dynamicMoveType & 0x3F; + else + moveType = gBattleMoves[gCurrentMove].type; + + if (moveType == TYPE_ELECTRIC && GetBattlerAbility(gBattlerTarget) == ABILITY_VOLT_ABSORB) + return TRUE; + else + return FALSE; +} + +static bool32 IsTeatimeAffected(u32 battlerId) +{ + if (ItemId_GetPocket(gBattleMons[battlerId].item) != POCKET_BERRIES) + return FALSE; // Only berries + if (gStatuses3[battlerId] & STATUS3_SEMI_INVULNERABLE) + return FALSE; // Teatime doesn't affected semi-invulnerable battlers + return TRUE; +} + #define COURTCHANGE_SWAP(status, structField, temp) \ { \ temp = gSideStatuses[B_SIDE_PLAYER]; \ @@ -10032,7 +10094,7 @@ static void Cmd_various(void) gBattleMons[gActiveBattler].item = gLastUsedItem; break; case VARIOUS_SET_BEAK_BLAST: - gProtectStructs[gBattlerAttacker].beakBlastCharge = TRUE; + gProtectStructs[gActiveBattler].beakBlastCharge = TRUE; break; case VARIOUS_SWAP_SIDE_STATUSES: CourtChangeSwapSideStatuses(); @@ -10099,6 +10161,45 @@ static void Cmd_various(void) PREPARE_STAT_BUFFER(gBattleTextBuff1, statId); } break; + case VARIOUS_TEATIME_TARGETS: + { + u32 count = 0; + + for (i = 0; i < gBattlersCount; i++) + { + if (IsTeatimeAffected(i)) + count++; + } + if (count == 0) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); // Teatime fails + else + gBattlescriptCurrInstr += 7; + } + return; + case VARIOUS_TEATIME_INVUL: + if (ItemId_GetPocket(gBattleMons[gActiveBattler].item) == POCKET_BERRIES && !(gStatuses3[gBattlerTarget] & (STATUS3_SEMI_INVULNERABLE))) + gBattlescriptCurrInstr += 7; + else + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + return; + case VARIOUS_JUMP_IF_ROD: + if (IsAbilityRodAffected()) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + else + gBattlescriptCurrInstr += 7; + return; + case VARIOUS_JUMP_IF_MOTOR: + if (IsAbilityMotorAffected()) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + else + gBattlescriptCurrInstr += 7; + return; + case VARIOUS_JUMP_IF_ABSORB: + if (IsAbilityAbsorbAffected()) + gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3); + else + gBattlescriptCurrInstr += 7; + return; case VARIOUS_TRY_WIND_RIDER_POWER: { u16 ability = GetBattlerAbility(gActiveBattler); @@ -10802,7 +10903,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr else if ((activeBattlerAbility == ABILITY_CLEAR_BODY || activeBattlerAbility == ABILITY_FULL_METAL_BODY || activeBattlerAbility == ABILITY_WHITE_SMOKE) - && !certain && gCurrentMove != MOVE_CURSE) + && !affectsUser && !certain && gCurrentMove != MOVE_CURSE) { if (flags == STAT_CHANGE_ALLOW_PTR) { @@ -11952,8 +12053,9 @@ static void Cmd_trysetencore(void) } if (gLastMoves[gBattlerTarget] == MOVE_STRUGGLE - || gLastMoves[gBattlerTarget] == MOVE_ENCORE - || gLastMoves[gBattlerTarget] == MOVE_MIRROR_MOVE) + || gLastMoves[gBattlerTarget] == MOVE_ENCORE + || gLastMoves[gBattlerTarget] == MOVE_MIRROR_MOVE + || gLastMoves[gBattlerTarget] == MOVE_SHELL_TRAP) { i = MAX_MON_MOVES; } @@ -12881,6 +12983,10 @@ static void Cmd_trysetfutureattack(void) static void Cmd_trydobeatup(void) { +#if B_BEAT_UP >= GEN_5 + gBattleStruct->beatUpSlot++; + gBattlescriptCurrInstr += 9; +#else struct Pokemon *party; if (GetBattlerSide(gBattlerAttacker) == B_SIDE_PLAYER) @@ -12924,6 +13030,7 @@ static void Cmd_trydobeatup(void) else gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 5); } +#endif } static void Cmd_setsemiinvulnerablebit(void) diff --git a/src/battle_util.c b/src/battle_util.c index 4eb44daa7..5a9b15518 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -60,6 +60,7 @@ static bool32 IsUnnerveAbilityOnOpposingSide(u8 battlerId); static u8 GetFlingPowerFromItemId(u16 itemId); static void SetRandomMultiHitCounter(); static u32 GetBattlerItemHoldEffectParam(u8 battlerId, u16 item); +static u16 GetInverseTypeMultiplier(u16 multiplier); extern const u8 *const gBattleScriptsForMoveEffects[]; extern const u8 *const gBattlescriptsForRunningByItem[]; @@ -229,8 +230,9 @@ static u8 CalcBeatUpPower(void) party = gPlayerParty; else party = gEnemyParty; - // Party slot is set in the battle script for Beat Up - species = GetMonData(&party[gBattleCommunication[0] - 1], MON_DATA_SPECIES); + + // Party slot is incremented by the battle script for Beat Up after this damage calculation + species = GetMonData(&party[gBattleStruct->beatUpSlot], MON_DATA_SPECIES); basePower = (gSpeciesInfo[species].baseAttack / 10) + 5; return basePower; @@ -418,7 +420,7 @@ void HandleAction_UseMove(void) battlerAbility = GetBattlerAbility(gActiveBattler); RecordAbilityBattle(gActiveBattler, gBattleMons[gActiveBattler].ability); - if (battlerAbility == ABILITY_LIGHTNING_ROD) + if (battlerAbility == ABILITY_LIGHTNING_ROD && gCurrentMove != MOVE_TEATIME) gSpecialStatuses[gActiveBattler].lightningRodRedirected = TRUE; else if (battlerAbility == ABILITY_STORM_DRAIN) gSpecialStatuses[gActiveBattler].stormDrainRedirected = TRUE; @@ -1261,38 +1263,6 @@ static const u16 sTypeEffectivenessTable[NUMBER_OF_MON_TYPES][NUMBER_OF_MON_TYPE {X(1.0), X(2.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(2.0), X(1.0)}, // fairy }; -static const u16 sInverseTypeEffectivenessTable[NUMBER_OF_MON_TYPES][NUMBER_OF_MON_TYPES] = -{ -// normal fight flying poison ground rock bug ghost steel mystery fire water grass electric psychic ice dragon dark fairy - {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(2.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // normal - {X(0.5), X(1.0), X(2.0), X(2.0), X(1.0), X(0.5), X(2.0), X(2.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(0.5), X(1.0), X(0.5), X(2.0)}, // fight - {X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(2.0), X(0.5), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(0.5), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // flying - {X(1.0), X(1.0), X(1.0), X(2.0), X(2.0), X(2.0), X(1.0), X(2.0), X(2.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5)}, // poison - {X(1.0), X(1.0), X(2.0), X(0.5), X(1.0), X(0.5), X(2.0), X(1.0), X(0.5), X(1.0), X(0.5), X(1.0), X(2.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // ground - {X(1.0), X(2.0), X(0.5), X(1.0), X(2.0), X(1.0), X(0.5), X(1.0), X(2.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0)}, // rock - {X(1.0), X(2.0), X(2.0), X(2.0), X(1.0), X(1.0), X(1.0), X(2.0), X(2.0), X(1.0), X(2.0), X(1.0), X(0.5), X(1.0), X(0.5), X(1.0), X(1.0), X(0.5), X(2.0)}, // bug - #if B_STEEL_RESISTANCES >= GEN_6 - {X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(2.0), X(1.0)}, // ghost - #else - {X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(2.0), X(1.0)}, // ghost - #endif - {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(2.0), X(1.0), X(2.0), X(2.0), X(1.0), X(2.0), X(1.0), X(0.5), X(1.0), X(1.0), X(0.5)}, // steel - {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0)}, // mystery - {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(0.5), X(1.0), X(0.5), X(1.0), X(2.0), X(2.0), X(0.5), X(1.0), X(1.0), X(0.5), X(2.0), X(1.0), X(1.0)}, // fire - {X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(2.0), X(2.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0)}, // water - {X(1.0), X(1.0), X(2.0), X(2.0), X(0.5), X(0.5), X(2.0), X(1.0), X(2.0), X(1.0), X(2.0), X(0.5), X(2.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0)}, // grass - {X(1.0), X(1.0), X(0.5), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(2.0), X(2.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0)}, // electric - {X(1.0), X(0.5), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(2.0), X(1.0)}, // psychic - {X(1.0), X(1.0), X(0.5), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(2.0), X(2.0), X(0.5), X(1.0), X(1.0), X(2.0), X(0.5), X(1.0), X(1.0)}, // ice - {X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(2.0)}, // dragon - #if B_STEEL_RESISTANCES >= GEN_6 - {X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(2.0), X(2.0)}, // dark - #else - {X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(1.0), X(1.0), X(2.0), X(2.0)}, // dark - #endif - {X(1.0), X(0.5), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(2.0), X(1.0), X(2.0), X(1.0), X(1.0), X(1.0), X(1.0), X(1.0), X(0.5), X(0.5), X(1.0)}, // fairy -}; - #undef X // code @@ -3917,7 +3887,7 @@ u8 AtkCanceller_UnableToUseMove(void) gMultiHitCounter++; } - gBattleCommunication[0] = 0; // For later + gBattleStruct->beatUpSlot = 0; PREPARE_BYTE_NUMBER_BUFFER(gBattleScripting.multihitString, 1, 0) } #endif @@ -8255,6 +8225,11 @@ bool32 IsBattlerProtected(u8 battlerId, u16 move) else if (gProtectStructs[battlerId].protected) return FALSE; } + + if (move == MOVE_TEATIME) + { + return FALSE; + } // Protective Pads doesn't stop Unseen Fist from bypassing Protect effects, so IsMoveMakingContact() isn't used here. // This means extra logic is needed to handle Shell Side Arm. @@ -9932,20 +9907,32 @@ u16 CalcPartyMonTypeEffectivenessMultiplier(u16 move, u16 speciesDef, u16 abilit return modifier; } +static u16 GetInverseTypeMultiplier(u16 multiplier) +{ + switch (multiplier) + { + case UQ_4_12(0.0): + case UQ_4_12(0.5): + return UQ_4_12(2.0); + case UQ_4_12(2.0): + return UQ_4_12(0.5); + case UQ_4_12(1.0): + default: + return UQ_4_12(1.0); + } +} + u16 GetTypeModifier(u8 atkType, u8 defType) { #if B_FLAG_INVERSE_BATTLE != 0 if (FlagGet(B_FLAG_INVERSE_BATTLE)) - return sInverseTypeEffectivenessTable[atkType][defType]; + return GetInverseTypeMultiplier(sTypeEffectivenessTable[atkType][defType]); #endif return sTypeEffectivenessTable[atkType][defType]; } -s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId) +s32 GetStealthHazardDamageByTypesAndHP(u8 hazardType, u8 type1, u8 type2, u32 maxHp) { - u8 type1 = gBattleMons[battlerId].type1; - u8 type2 = gBattleMons[battlerId].type2; - u32 maxHp = gBattleMons[battlerId].maxHP; s32 dmg = 0; u16 modifier = UQ_4_12(1.0); @@ -9988,6 +9975,15 @@ s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId) return dmg; } +s32 GetStealthHazardDamage(u8 hazardType, u8 battlerId) +{ + u8 type1 = gBattleMons[battlerId].type1; + u8 type2 = gBattleMons[battlerId].type2; + u32 maxHp = gBattleMons[battlerId].maxHP; + + return GetStealthHazardDamageByTypesAndHP(hazardType, type1, type2, maxHp); +} + bool32 IsPartnerMonFromSameTrainer(u8 battlerId) { if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT && gBattleTypeFlags & BATTLE_TYPE_TWO_OPPONENTS) diff --git a/src/data/battle_anim.h b/src/data/battle_anim.h index e6e03f06c..5be53fe66 100644 --- a/src/data/battle_anim.h +++ b/src/data/battle_anim.h @@ -1450,6 +1450,7 @@ const struct CompressedSpriteSheet gBattleAnimPicTable[] = {gBattleAnimSpriteGfx_OmegaSymbol, 0x0200, ANIM_TAG_OMEGA_SYMBOL}, {gBattleAnimSpriteGfx_Orbs, 0x0180, ANIM_TAG_STEEL_BEAM}, {gBattleAnimSpriteGfx_AuraSphere, 0x200, ANIM_TAG_POLTERGEIST}, + {gBattleAnimSpriteGfx_Teapot, 0x1800, ANIM_TAG_TEAPOT}, }; const struct CompressedSpritePalette gBattleAnimPaletteTable[] = @@ -1900,6 +1901,7 @@ const struct CompressedSpritePalette gBattleAnimPaletteTable[] = {gBattleAnimSpritePal_OmegaSymbol, ANIM_TAG_OMEGA_SYMBOL}, {gBattleAnimSpritePal_SteelBeam, ANIM_TAG_STEEL_BEAM}, {gBattleAnimSpritePal_Poltergeist, ANIM_TAG_POLTERGEIST}, + {gBattleAnimSpritePal_Teapot, ANIM_TAG_TEAPOT}, }; const struct BattleAnimBackground gBattleAnimBackgroundTable[] = diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index e5d3306ce..f5cc351f2 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -12351,13 +12351,13 @@ const struct BattleMove gBattleMoves[MOVES_COUNT_Z] = [MOVE_TEATIME] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_TEATIME, .power = 0, .type = TYPE_NORMAL, .accuracy = 0, .pp = 10, .secondaryEffectChance = 0, - .target = MOVE_TARGET_ALL_BATTLERS, + .target = MOVE_TARGET_USER, .priority = 0, .flags = 0, .split = SPLIT_STATUS, diff --git a/src/graphics.c b/src/graphics.c index 0126150fd..b8ba41666 100644 --- a/src/graphics.c +++ b/src/graphics.c @@ -286,6 +286,8 @@ const u32 gBattleAnimSpritePal_Tornado[] = INCBIN_U32("graphics/battle_anims/spr const u32 gBattleAnimSpriteGfx_ZMoveSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/z_move_symbol.4bpp.lz"); const u32 gBattleAnimSpritePal_ZMoveSymbol[] = INCBIN_U32("graphics/battle_anims/sprites/z_move_symbol.gbapal.lz"); +const u32 gBattleAnimSpriteGfx_Teapot[] = INCBIN_U32("graphics/battle_anims/sprites/new/teapot.4bpp.lz"); +const u32 gBattleAnimSpritePal_Teapot[] = INCBIN_U32("graphics/battle_anims/sprites/new/teapot.gbapal.lz"); // Battle anims const u32 gBattleAnimSpriteGfx_Bubble[] = INCBIN_U32("graphics/battle_anims/sprites/bubble.4bpp.lz");