Merge branch 'battle_engine' of https://github.com/rh-hideout/pokeemerald-expansion into last_ball

This commit is contained in:
ghoulslash 2021-10-06 13:54:40 -04:00
commit ee3a2c97ee
20 changed files with 419 additions and 81 deletions

View file

@ -1797,6 +1797,11 @@
.4byte \ptr
.endm
.macro jumpifpranksterblocked battler:req, ptr:req
various \battler, VARIOUS_JUMP_IF_PRANKSTER_BLOCKED
.4byte \ptr
.endm
.macro eeriespellppreduce ptr:req
various BS_TARGET, VARIOUS_EERIE_SPELL_PP_REDUCE
.4byte \ptr
@ -1920,6 +1925,12 @@
1:
.endm
.macro jumpifflowerveilattacker jumpptr:req
jumpifnottype BS_ATTACKER, TYPE_GRASS, 1f
jumpifability BS_ATTACKER_SIDE, ABILITY_FLOWER_VEIL, \jumpptr
1:
.endm
.macro setallytonexttarget jumpptr:req
jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f
addbyte gBattlerTarget, 0x2

View file

@ -532,7 +532,7 @@ gBattleAnims_Moves::
.4byte Move_QUASH
.4byte Move_ACROBATICS
.4byte Move_REFLECT_TYPE
.4byte Move_RETALITATE
.4byte Move_RETALIATE
.4byte Move_FINAL_GAMBIT
.4byte Move_BESTOW
.4byte Move_INFERNO
@ -822,6 +822,7 @@ gBattleAnims_General::
.4byte General_SlideOffScreen @ B_ANIM_SLIDE_OFFSCREEN
.4byte General_RestoreBg @ B_ANIM_RESTORE_BG
.4byte General_TotemFlare @ B_ANIM_TOTEM_FLARE
.4byte General_GulpMissile @ B_ANIM_GULP_MISSILE
.align 2
gBattleAnims_Special::
@ -5610,7 +5611,7 @@ Move_REFLECT_TYPE:
blendoff
end
Move_RETALITATE:
Move_RETALIATE:
loadspritegfx ANIM_TAG_CUT @Cut
monbg ANIM_DEF_PARTNER
setalpha 9, 8
@ -24397,6 +24398,20 @@ General_TotemFlare::
clearmonbg ANIM_ATTACKER
end
General_GulpMissile: @ Tackle anim (placeholder)
loadspritegfx ANIM_TAG_IMPACT
monbg ANIM_ATTACKER
setalpha 12, 8
createsprite gHorizontalLungeSpriteTemplate, ANIM_ATTACKER, 2, 4, 4
delay 6
createsprite gBasicHitSplatSpriteTemplate, ANIM_ATTACKER, 2, 0, 0, ANIM_ATTACKER, 2
createvisualtask AnimTask_ShakeMon, 2, ANIM_ATTACKER, 3, 0, 6, 1
playsewithpan SE_M_COMET_PUNCH, SOUND_PAN_TARGET
waitforvisualfinish
clearmonbg ANIM_ATTACKER
blendoff
end
RainbowEndureEffect:
launchtemplate gBlueEndureEnergySpriteTemplate 0x2 0x4 0x0 0xffe8 0x1a 0x2
delay 0x3

View file

@ -252,7 +252,7 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectHit @ EFFECT_ROUND
.4byte BattleScript_EffectHit @ EFFECT_BRINE
.4byte BattleScript_EffectHit @ EFFECT_VENOSHOCK
.4byte BattleScript_EffectHit @ EFFECT_RETALITATE
.4byte BattleScript_EffectHit @ EFFECT_RETALIATE
.4byte BattleScript_EffectBulldoze @ EFFECT_BULLDOZE
.4byte BattleScript_EffectHit @ EFFECT_FOUL_PLAY
.4byte BattleScript_EffectHit @ EFFECT_PSYSHOCK
@ -379,6 +379,7 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectDecorate @ EFFECT_DECORATE
.4byte BattleScript_EffectHit @ EFFECT_SNIPE_SHOT
.4byte BattleScript_EffectTripleHit @ EFFECT_TRIPLE_HIT
.4byte BattleScript_EffectRecoilHP25 @ EFFECT_RECOIL_HP_25
BattleScript_EffectDecorate:
attackcanceler
@ -3867,19 +3868,25 @@ BattleScript_EffectPerishSong::
waitanimation
printstring STRINGID_FAINTINTHREE
waitmessage B_WAIT_TIME_LONG
setbyte sBATTLER, 0
setbyte gBattlerTarget, 0
BattleScript_PerishSongLoop::
jumpifability BS_SCRIPTING, ABILITY_SOUNDPROOF, BattleScript_PerishSongNotAffected
jumpifability BS_TARGET, ABILITY_SOUNDPROOF, BattleScript_PerishSongBlocked
jumpifpranksterblocked BS_TARGET, BattleScript_PerishSongNotAffected
BattleScript_PerishSongLoopIncrement::
addbyte sBATTLER, 1
jumpifbytenotequal sBATTLER, gBattlersCount, BattleScript_PerishSongLoop
addbyte gBattlerTarget, 1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_PerishSongLoop
goto BattleScript_MoveEnd
BattleScript_PerishSongNotAffected::
BattleScript_PerishSongBlocked::
printstring STRINGID_PKMNSXBLOCKSY2
waitmessage B_WAIT_TIME_LONG
goto BattleScript_PerishSongLoopIncrement
BattleScript_PerishSongNotAffected:
printstring STRINGID_ITDOESNTAFFECT
waitmessage B_WAIT_TIME_LONG
goto BattleScript_PerishSongLoopIncrement
BattleScript_EffectSandstorm::
attackcanceler
attackstring
@ -4905,6 +4912,12 @@ BattleScript_EffectRecoil50:
setmoveeffect MOVE_EFFECT_RECOIL_50 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
goto BattleScript_EffectHit
BattleScript_EffectRecoilHP25:
setmoveeffect MOVE_EFFECT_RECOIL_HP_25 | MOVE_EFFECT_AFFECTS_USER | MOVE_EFFECT_CERTAIN
jumpifnotmove MOVE_STRUGGLE, BattleScript_EffectHit
incrementgamestat GAME_STAT_USED_STRUGGLE
goto BattleScript_EffectHit
BattleScript_EffectTeeterDance::
attackcanceler
attackstring
@ -5994,6 +6007,76 @@ BattleScript_PerishBodyActivates::
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000
return
BattleScript_GulpMissileGorging::
call BattleScript_AbilityPopUp
playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE, NULL
waitanimation
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000
effectivenesssound
hitanimation BS_ATTACKER
waitstate
jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_GulpMissileNoDmgGorging
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
tryfaintmon BS_ATTACKER, FALSE, NULL
getbattlerfainted BS_ATTACKER
jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_GulpMissileNoSecondEffectGorging
BattleScript_GulpMissileNoDmgGorging:
handleformchange BS_TARGET, 0
playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL
waitanimation
swapattackerwithtarget
setmoveeffect MOVE_EFFECT_PARALYSIS
seteffectprimary
swapattackerwithtarget
return
BattleScript_GulpMissileNoSecondEffectGorging:
handleformchange BS_TARGET, 0
playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL
waitanimation
return
BattleScript_GulpMissileGulping::
call BattleScript_AbilityPopUp
playanimation BS_ATTACKER, B_ANIM_GULP_MISSILE, NULL
waitanimation
orword gHitMarker, HITMARKER_IGNORE_SUBSTITUTE | HITMARKER_x100000
effectivenesssound
hitanimation BS_ATTACKER
waitstate
jumpifability BS_ATTACKER, ABILITY_MAGIC_GUARD, BattleScript_GulpMissileNoDmgGulping
healthbarupdate BS_ATTACKER
datahpupdate BS_ATTACKER
tryfaintmon BS_ATTACKER, FALSE, NULL
getbattlerfainted BS_ATTACKER
jumpifbyte CMP_EQUAL, gBattleCommunication, TRUE, BattleScript_GulpMissileNoSecondEffectGulping
jumpifability BS_ATTACKER, ABILITY_CLEAR_BODY, BattleScript_GulpMissileNoSecondEffectGulping
jumpifability BS_ATTACKER, ABILITY_FULL_METAL_BODY, BattleScript_GulpMissileNoSecondEffectGulping
jumpifability BS_ATTACKER, ABILITY_WHITE_SMOKE, BattleScript_GulpMissileNoSecondEffectGulping
jumpifflowerveilattacker BattleScript_GulpMissileNoSecondEffectGulping
BattleScript_GulpMissileNoDmgGulping:
handleformchange BS_TARGET, 0
playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL
waitanimation
swapattackerwithtarget @ to make gStatDownStringIds down below print the right battler
setstatchanger STAT_DEF, 1, TRUE
statbuffchange STAT_BUFF_NOT_PROTECT_AFFECTED, BattleScript_GulpMissileGorgingTargetDefenseCantGoLower
setgraphicalstatchangevalues
playanimation BS_TARGET, B_ANIM_STATS_CHANGE, sB_ANIM_ARG1
printfromtable gStatDownStringIds
waitmessage B_WAIT_TIME_LONG
swapattackerwithtarget @ restore the battlers, just in case
return
BattleScript_GulpMissileNoSecondEffectGulping:
handleformchange BS_TARGET, 0
playanimation BS_TARGET, B_ANIM_FORM_CHANGE, NULL
waitanimation
return
BattleScript_GulpMissileGorgingTargetDefenseCantGoLower:
printstring STRINGID_STATSWONTDECREASE
waitmessage B_WAIT_TIME_LONG
return
BattleScript_PerishSongCountGoesDown::
printstring STRINGID_PKMNPERISHCOUNTFELL
waitmessage B_WAIT_TIME_LONG
@ -6328,6 +6411,17 @@ BattleScript_MagicCoatBounce::
setmagiccoattarget BS_ATTACKER
return
BattleScript_MagicCoatBouncePrankster::
attackstring
ppreduce
pause B_WAIT_TIME_SHORT
printfromtable gMagicCoatBounceStringIds
waitmessage B_WAIT_TIME_LONG
printstring STRINGID_ITDOESNTAFFECT
waitmessage B_WAIT_TIME_LONG
orhalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
goto BattleScript_MoveEnd
BattleScript_SnatchedMove::
attackstring
ppreduce
@ -7624,6 +7718,19 @@ BattleScript_AbilityStatusEffect::
seteffectsecondary
return
BattleScript_BattleBondActivatesOnMoveEndAttacker::
pause 5
copybyte gBattlerAbility, gBattlerAttacker
call BattleScript_AbilityPopUp
printstring STRINGID_ATTACKERBECAMEFULLYCHARGED
handleformchange BS_ATTACKER, 0
handleformchange BS_ATTACKER, 1
playanimation BS_ATTACKER, B_ANIM_FORM_CHANGE, NULL
waitanimation
handleformchange BS_ATTACKER, 2
printstring STRINGID_ATTACKERBECAMEASHSPECIES
return
BattleScript_DancerActivates::
call BattleScript_AbilityPopUp
waitmessage B_WAIT_TIME_SHORT
@ -8310,3 +8417,12 @@ BattleScript_EjectPackActivate_End2::
BattleScript_EjectPackActivates::
jumpifcantswitch BS_SCRIPTING, BattleScript_EjectButtonEnd
goto BattleScript_EjectPackActivate_Ret
BattleScript_DarkTypePreventsPrankster::
attackstring
ppreduce
pause B_WAIT_TIME_SHORT
printstring STRINGID_ITDOESNTAFFECT
waitmessage B_WAIT_TIME_LONG
orhalfword gMoveResultFlags, MOVE_RESULT_NO_EFFECT
goto BattleScript_MoveEnd

View file

@ -150,6 +150,7 @@ struct ProtectStruct
u32 touchedProtectLike:1;
u32 disableEjectPack:1;
u32 statFell:1;
u32 pranksterElevated:1;
u32 physicalDmg;
u32 specialDmg;
u8 physicalBattlerId;

View file

@ -97,6 +97,7 @@ extern const u8 BattleScript_SelectingImprisonedMove[];
extern const u8 BattleScript_SelectingImprisonedMoveInPalace[];
extern const u8 BattleScript_GrudgeTakesPp[];
extern const u8 BattleScript_MagicCoatBounce[];
extern const u8 BattleScript_MagicCoatBouncePrankster[];
extern const u8 BattleScript_SnatchedMove[];
extern const u8 BattleScript_EnduredMsg[];
extern const u8 BattleScript_OneHitKOMsg[];
@ -384,5 +385,9 @@ extern const u8 BattleScript_MentalHerbCureEnd2[];
extern const u8 BattleScript_TerrainPreventsEnd2[];
extern const u8 BattleScript_MistyTerrainPrevents[];
extern const u8 BattleScript_ElectricTerrainPrevents[];
extern const u8 BattleScript_DarkTypePreventsPrankster[];
extern const u8 BattleScript_GulpMissileGorging[];
extern const u8 BattleScript_GulpMissileGulping[];
extern const u8 BattleScript_BattleBondActivatesOnMoveEndAttacker[];
#endif // GUARD_BATTLE_SCRIPTS_H

View file

@ -153,6 +153,7 @@ bool32 CompareStat(u8 battlerId, u8 statId, u8 cmpTo, u8 cmpKind);
bool32 TryRoomService(u8 battlerId);
void BufferStatChange(u8 battlerId, u8 statId, u8 stringId);
void DoBurmyFormChange(u32 monId);
bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef);
// ability checks
bool32 IsRolePlayBannedAbilityAtk(u16 ability);

View file

@ -347,7 +347,8 @@
#define MOVE_EFFECT_THROAT_CHOP 0x43
#define MOVE_EFFECT_INCINERATE 0x44
#define MOVE_EFFECT_BUG_BITE 0x45
#define NUM_MOVE_EFFECTS 0x46
#define MOVE_EFFECT_RECOIL_HP_25 0x46
#define NUM_MOVE_EFFECTS 0x47
#define MOVE_EFFECT_AFFECTS_USER 0x4000
#define MOVE_EFFECT_CERTAIN 0x8000

View file

@ -523,6 +523,7 @@
#define B_ANIM_SLIDE_OFFSCREEN 26 // for Emergency Exit
#define B_ANIM_RESTORE_BG 27 // for Terrain Endings
#define B_ANIM_TOTEM_FLARE 28 // Totem boosts aura flare
#define B_ANIM_GULP_MISSILE 29
// special animations table (gBattleAnims_Special)
#define B_ANIM_LVL_UP 0

View file

@ -40,6 +40,11 @@
#define SPECIES_BURMY 0
#define SPECIES_BURMY_SANDY_CLOAK 10013
#define SPECIES_BURMY_TRASH_CLOAK 10014
#define SPECIES_CRAMORANT 0
#define SPECIES_CRAMORANT_GORGING 10015
#define SPECIES_CRAMORANT_GULPING 10016
#define SPECIES_GRENINJA_BATTLE_BOND 0
#define SPECIES_GRENINJA_ASH 10017
#endif
// Items with peculiar battle effects.
@ -124,10 +129,12 @@
#define B_GALE_WINGS GEN_7 // In Gen7+ requires full HP to trigger.
#define B_STANCE_CHANGE_FAIL GEN_7 // In Gen7+, Stance Change fails if the Pokémon is unable to use a move because of confusion, paralysis, etc. In Gen6, it doesn't.
#define B_GHOSTS_ESCAPE GEN_7 // In Gen6+, Ghost-type Pokémon can escape even when blocked by abilities such as Shadow Tag.
#define B_SHADOW_TAG_ESCAPE GEN_7 // In Gen4+, if both sides have a Pokémon with Shadow Tag, all battlers can escape. Before, neither side could escape this situation.
#define B_MOODY_ACC_EVASION GEN_8 // In Gen8, Moody CANNOT raise Accuracy and Evasion anymore.
#define B_FLASH_FIRE_FROZEN GEN_7 // In Gen5+, Flash Fire can trigger even when frozen, when it couldn't before.
#define B_SYNCHRONIZE_NATURE GEN_8 // In Gen8, if the Pokémon with Synchronize is leading the party, it's 100% guaranteed that wild Pokémon will have the same ability, as opposed to 50% previously.
#define B_UPDATED_INTIMIDATE GEN_8 // In Gen8, Intimidate doesn't work on opponents with the Inner Focus, Scrappy, Own Tempo or Oblivious abilities.
#define B_PRANKSTER_DARK_TYPES GEN_7 // In Gen7+, Prankster-elevated status moves do not affect Dark type Pokémon.
// Item settings
#define B_HP_BERRIES GEN_7 // In Gen4+, berries which restore hp activate immediately after HP drops to half. In Gen3, the effect occurs at the end of the turn.

View file

@ -236,7 +236,7 @@
#define EFFECT_ROUND 230
#define EFFECT_BRINE 231
#define EFFECT_VENOSHOCK 232
#define EFFECT_RETALITATE 233
#define EFFECT_RETALIATE 233
#define EFFECT_BULLDOZE 234
#define EFFECT_FOUL_PLAY 235
#define EFFECT_PSYSHOCK 236
@ -363,7 +363,8 @@
#define EFFECT_DECORATE 357
#define EFFECT_SNIPE_SHOT 358
#define EFFECT_TRIPLE_HIT 359
#define EFFECT_RECOIL_HP_25 360
#define NUM_BATTLE_MOVE_EFFECTS 360
#define NUM_BATTLE_MOVE_EFFECTS 361
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H

View file

@ -183,6 +183,7 @@
#define VARIOUS_JUMP_IF_TEAM_HEALTHY 111
#define VARIOUS_TRY_HEAL_QUARTER_HP 112
#define VARIOUS_REMOVE_TERRAIN 113
#define VARIOUS_JUMP_IF_PRANKSTER_BLOCKED 114
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0

View file

@ -578,8 +578,10 @@
#define STRINGID_ATKGOTOVERINFATUATION 574
#define STRINGID_TORMENTEDNOMORE 575
#define STRINGID_HEALBLOCKEDNOMORE 576
#define STRINGID_ATTACKERBECAMEFULLYCHARGED 577
#define STRINGID_ATTACKERBECAMEASHSPECIES 578
#define BATTLESTRINGS_COUNT 577
#define BATTLESTRINGS_COUNT 579
// The below IDs are all indexes into battle message tables,
// used to determine which of a set of messages to print.

View file

@ -520,6 +520,9 @@ static s16 AI_CheckBadMove(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
u32 i;
u16 predictedMove = gLastMoves[battlerDef]; // TODO better move prediction
SetTypeBeforeUsingMove(move, battlerAtk);
GET_MOVE_TYPE(move, moveType);
if (IsTargetingPartner(battlerAtk, battlerDef))
return score;
@ -2472,7 +2475,10 @@ static s16 AI_DoubleBattle(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
bool32 attackerHasBadAbility = (GetAbilityRating(AI_DATA->atkAbility) < 0);
bool32 partnerHasBadAbility = (GetAbilityRating(atkPartnerAbility) < 0);
u16 predictedMove = gLastMoves[battlerDef]; //for now
SetTypeBeforeUsingMove(move, battlerAtk);
GET_MOVE_TYPE(move, moveType);
// check what effect partner is using
if (AI_DATA->partnerMove != 0)
{
@ -4751,7 +4757,10 @@ static s16 AI_HPAware(u8 battlerAtk, u8 battlerDef, u16 move, s16 score)
{
u16 effect = gBattleMoves[move].effect;
u8 moveType = gBattleMoves[move].type;
SetTypeBeforeUsingMove(move, battlerAtk);
GET_MOVE_TYPE(move, moveType);
if (IsTargetingPartner(battlerAtk, battlerDef))
{
if ((effect == EFFECT_HEAL_PULSE || effect == EFFECT_HIT_ENEMY_HEAL_ALLY)

View file

@ -2213,6 +2213,7 @@ void LaunchBattleAnimation(const u8 *const animsTable[], u16 tableId, bool8 isMo
case B_ANIM_DOOM_DESIRE_HIT:
case B_ANIM_WISH_HEAL:
case B_ANIM_MEGA_EVOLUTION:
case B_ANIM_GULP_MISSILE:
hideHpBoxes = TRUE;
break;
default:

View file

@ -1053,6 +1053,7 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl)
if (gBattleStruct->mega.evolvedPartyIds[GetBattlerSide(battler)] & gBitTable[gBattlerPartyIndexes[battler]])
{
objVram = ConvertIntToDecimalStringN(text, lvl, STR_CONV_MODE_LEFT_ALIGN, 3);
xPos = 5 * (3 - (objVram - (text + 2))) - 1;
}
else
{
@ -1060,6 +1061,7 @@ static void UpdateLvlInHealthbox(u8 healthboxSpriteId, u8 lvl)
text[1] = CHAR_LV_2;
objVram = ConvertIntToDecimalStringN(text + 2, lvl, STR_CONV_MODE_LEFT_ALIGN, 3);
xPos = 5 * (3 - (objVram - (text + 2)));
}
xPos = 5 * (3 - (objVram - (text + 2)));
@ -1507,18 +1509,12 @@ void DestroyMegaTriggerSprite(void)
gBattleStruct->mega.triggerSpriteId = 0xFF;
}
static const s8 sIndicatorPosSingles[][2] =
static const s8 sIndicatorPositions[][2] =
{
[B_POSITION_PLAYER_LEFT] = {53, -8},
[B_POSITION_OPPONENT_LEFT] = {45, -8},
};
static const s8 sIndicatorPosDoubles[][2] =
{
[B_POSITION_PLAYER_LEFT] = {53, -8},
[B_POSITION_OPPONENT_LEFT] = {45, -8},
[B_POSITION_PLAYER_RIGHT] = {53, -8},
[B_POSITION_OPPONENT_RIGHT] = {45, -8},
[B_POSITION_PLAYER_LEFT] = {52, -9},
[B_POSITION_OPPONENT_LEFT] = {44, -9},
[B_POSITION_PLAYER_RIGHT] = {52, -9},
[B_POSITION_OPPONENT_RIGHT] = {44, -9},
};
u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which)
@ -1531,16 +1527,15 @@ u32 CreateMegaIndicatorSprite(u32 battlerId, u32 which)
position = GetBattlerPosition(battlerId);
GetBattlerHealthboxCoords(battlerId, &x, &y);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
x += sIndicatorPosDoubles[position][0];
y += sIndicatorPosDoubles[position][1];
}
else
{
x += sIndicatorPosSingles[position][0];
y += sIndicatorPosSingles[position][1];
}
x += sIndicatorPositions[position][0];
y += sIndicatorPositions[position][1];
if (gBattleMons[battlerId].level >= 100)
x -= 4;
else if (gBattleMons[battlerId].level < 10)
x += 5;
spriteId = CreateSpriteAtEnd(&sSpriteTemplate_MegaIndicator, x, y, 0);
gSprites[gSprites[gHealthboxSpriteIds[battlerId]].oam.affineParam].hOther_IndicatorSpriteId = spriteId;

View file

@ -3096,6 +3096,7 @@ void FaintClearSetData(void)
gProtectStructs[gActiveBattler].usedGravityPreventedMove = 0;
gProtectStructs[gActiveBattler].usedThroatChopPreventedMove = 0;
gProtectStructs[gActiveBattler].statRaised = 0;
gProtectStructs[gActiveBattler].statFell = 0;
gDisableStructs[gActiveBattler].isFirstTurn = 2;
@ -3466,10 +3467,13 @@ static void TryDoEventsBeforeFirstTurn(void)
return;
// Set invalid mons as absent(for example when starting a double battle with only one pokemon).
for (i = 0; i < gBattlersCount; i++)
if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI))
{
if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE)
gAbsentBattlerFlags |= gBitTable[i];
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleMons[i].hp == 0 || gBattleMons[i].species == SPECIES_NONE)
gAbsentBattlerFlags |= gBitTable[i];
}
}
if (gBattleStruct->switchInAbilitiesCounter == 0)
@ -3683,7 +3687,7 @@ u8 IsRunningFromBattleImpossible(void)
return 0;
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
return 0;
if (gBattleMons[gActiveBattler].ability == ABILITY_RUN_AWAY)
if (GetBattlerAbility(gActiveBattler) == ABILITY_RUN_AWAY)
return 0;
if ((i = IsAbilityPreventingEscape(gActiveBattler)))
@ -4315,6 +4319,7 @@ s8 GetChosenMovePriority(u32 battlerId)
{
u16 move;
gProtectStructs[battlerId].pranksterElevated = 0;
if (gProtectStructs[battlerId].noValidMoves)
move = MOVE_STRUGGLE;
else
@ -4336,6 +4341,7 @@ s8 GetMovePriority(u32 battlerId, u16 move)
}
else if (GetBattlerAbility(battlerId) == ABILITY_PRANKSTER && IS_MOVE_STATUS(move))
{
gProtectStructs[battlerId].pranksterElevated = 1;
priority++;
}
else if (gBattleMoves[move].effect == EFFECT_GRASSY_GLIDE && gFieldStatuses & STATUS_FIELD_GRASSY_TERRAIN && IsBattlerGrounded(battlerId))

View file

@ -704,10 +704,13 @@ static const u8 sText_EjectButtonActivate[] = _("{B_SCR_ACTIVE_NAME_WITH_PREFIX}
static const u8 sText_AttackerGotOverInfatuation[] =_("{B_ATK_NAME_WITH_PREFIX} got over\nits infatuation!");
static const u8 sText_TormentedNoMore[] = _("{B_ATK_NAME_WITH_PREFIX} is\ntormented no more!");
static const u8 sText_HealBlockedNoMore[] = _("{B_ATK_NAME_WITH_PREFIX} is cured of\nits heal block!");
static const u8 sText_AttackerBecameFullyCharged[] = _("{B_ATK_NAME_WITH_PREFIX} became fully charged\ndue to its bond with its trainer!\p");
static const u8 sText_AttackerBecameAshSpecies[] = _("{B_ATK_NAME_WITH_PREFIX} became Ash-{B_BUFF1}!\p");
const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
{
[STRINGID_ATTACKERBECAMEASHSPECIES - 12] = sText_AttackerBecameAshSpecies,
[STRINGID_ATTACKERBECAMEFULLYCHARGED - 12] = sText_AttackerBecameFullyCharged,
[STRINGID_HEALBLOCKEDNOMORE - 12] = sText_HealBlockedNoMore,
[STRINGID_TORMENTEDNOMORE - 12] = sText_TormentedNoMore,
[STRINGID_ATKGOTOVERINFATUATION - 12] = sText_AttackerGotOverInfatuation,

View file

@ -1416,8 +1416,17 @@ static void Cmd_attackcanceler(void)
gProtectStructs[gBattlerTarget].bounceMove = 0;
gProtectStructs[gBattlerTarget].usesBouncedMove = 1;
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
if (BlocksPrankster(gCurrentMove, gBattlerTarget, gBattlerAttacker))
{
// Opponent used a prankster'd magic coat -> reflected status move should fail against a dark-type attacker
gBattlerTarget = gBattlerAttacker;
gBattlescriptCurrInstr = BattleScript_MagicCoatBouncePrankster;
}
else
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_MagicCoatBounce;
}
return;
}
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE
@ -3058,7 +3067,7 @@ void SetMoveEffect(bool32 primary, u32 certain)
gBattlescriptCurrInstr++;
}
else if (gBattleMons[gBattlerTarget].item
&& gBattleMons[gBattlerTarget].ability == ABILITY_STICKY_HOLD)
&& GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD)
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_NoItemSteal;
@ -3168,6 +3177,14 @@ void SetMoveEffect(bool32 primary, u32 certain)
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoilWithStatus;
break;
case MOVE_EFFECT_RECOIL_HP_25: // Struggle
gBattleMoveDamage = (gBattleMons[gEffectBattler].maxHP) / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_MoveEffectRecoil;
break;
case MOVE_EFFECT_THRASH:
if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE)
{
@ -5092,6 +5109,7 @@ static void Cmd_moveend(void)
MoveValuesCleanUp();
gBattleScripting.moveEffect = gBattleScripting.savedMoveEffect;
BattleScriptPush(gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect]);
gBattleStruct->atkCancellerTracker = 0; // Run all cancellers on next target
gBattlescriptCurrInstr = BattleScript_FlushMessageBox;
return;
}
@ -5183,6 +5201,7 @@ static void Cmd_moveend(void)
u8 battler = battlers[i];
if (IsBattlerAlive(battler)
&& gProtectStructs[battler].statFell
&& gProtectStructs[battler].disableEjectPack == 0
&& GetBattlerHoldEffect(battler, TRUE) == HOLD_EFFECT_EJECT_PACK
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker)) // Does not activate if attacker used Parting Shot and can switch out
&& CountUsablePartyMons(battler) > 0) // Has mon to switch into
@ -6573,6 +6592,7 @@ static void Cmd_jumptocalledmove(void)
else
gChosenMove = gCurrentMove = gCalledMove;
gBattleStruct->atkCancellerTracker = 0;
gBattlescriptCurrInstr = gBattleScriptsForMoveEffects[gBattleMoves[gCurrentMove].effect];
}
@ -7273,7 +7293,7 @@ u32 IsLeafGuardProtected(u32 battler)
bool32 IsShieldsDownProtected(u32 battler)
{
return (gBattleMons[battler].ability == ABILITY_SHIELDS_DOWN
&& gBattleMons[battler].species == SPECIES_MINIOR);
&& GetFormIdFromFormSpeciesId(gBattleMons[battler].species) < GetFormIdFromFormSpeciesId(SPECIES_MINIOR_CORE_RED)); // Minior is not in core form
}
u32 IsAbilityStatusProtected(u32 battler)
@ -7898,15 +7918,15 @@ static void Cmd_various(void)
gBattlescriptCurrInstr += 7;
return;
case VARIOUS_SET_SIMPLE_BEAM:
if (IsEntrainmentTargetOrSimpleBeamBannedAbility(gBattleMons[gActiveBattler].ability))
if (IsEntrainmentTargetOrSimpleBeamBannedAbility(gBattleMons[gBattlerTarget].ability)
|| gBattleMons[gBattlerTarget].ability == ABILITY_SIMPLE)
{
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
}
else
{
gBattleMons[gActiveBattler].ability = ABILITY_SIMPLE;
gBattleMons[gBattlerTarget].ability = ABILITY_SIMPLE;
gBattlescriptCurrInstr += 7;
break;
}
return;
case VARIOUS_TRY_ENTRAINMENT:
@ -8127,7 +8147,8 @@ static void Cmd_various(void)
// Change species.
if (gBattlescriptCurrInstr[3] == 0)
{
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species);
if (!gBattleTextBuff1)
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gActiveBattler].species);
BtlController_EmitSetMonData(0, REQUEST_SPECIES_BATTLE, gBitTable[gBattlerPartyIndexes[gActiveBattler]], 2, &gBattleMons[gActiveBattler].species);
MarkBattlerForControllerExec(gActiveBattler);
}
@ -8721,6 +8742,12 @@ static void Cmd_various(void)
}
gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; // remove the terrain
break;
case VARIOUS_JUMP_IF_PRANKSTER_BLOCKED:
if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gActiveBattler))
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
else
gBattlescriptCurrInstr += 7;
return;
}
gBattlescriptCurrInstr += 3;
@ -9103,7 +9130,7 @@ bool8 UproarWakeUpCheck(u8 battlerId)
for (i = 0; i < gBattlersCount; i++)
{
if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || gBattleMons[battlerId].ability == ABILITY_SOUNDPROOF)
if (!(gBattleMons[i].status2 & STATUS2_UPROAR) || GetBattlerAbility(battlerId) == ABILITY_SOUNDPROOF)
continue;
gBattleScripting.battler = i;
@ -9425,9 +9452,7 @@ static u32 ChangeStatBuffs(s8 statValue, u32 statId, u32 flags, const u8 *BS_ptr
}
else
{
// Check eject pack. disableEjectPack set for edge cases (e.g. attacking weak armor'd eject pack holder with u-turn)
if (gProtectStructs[gActiveBattler].disableEjectPack == 0)
gProtectStructs[gActiveBattler].statFell = 1;
gProtectStructs[gActiveBattler].statFell = 1; // Eject pack, lash out
gBattleCommunication[MULTISTRING_CHOOSER] = (gBattlerTarget == gActiveBattler); // B_MSG_ATTACKER_STAT_FELL or B_MSG_DEFENDER_STAT_FELL
}
}
@ -10754,7 +10779,7 @@ static void Cmd_healpartystatus(void)
else
party = gEnemyParty;
if (gBattleMons[gBattlerAttacker].ability != ABILITY_SOUNDPROOF)
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_SOUNDPROOF)
{
gBattleMons[gBattlerAttacker].status1 = 0;
gBattleMons[gBattlerAttacker].status2 &= ~(STATUS2_NIGHTMARE);
@ -10770,7 +10795,7 @@ static void Cmd_healpartystatus(void)
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE
&& !(gAbsentBattlerFlags & gBitTable[gActiveBattler]))
{
if (gBattleMons[gActiveBattler].ability != ABILITY_SOUNDPROOF)
if (GetBattlerAbility(gActiveBattler) != ABILITY_SOUNDPROOF)
{
gBattleMons[gActiveBattler].status1 = 0;
gBattleMons[gActiveBattler].status2 &= ~(STATUS2_NIGHTMARE);
@ -10883,7 +10908,8 @@ static void Cmd_trysetperishsong(void)
for (i = 0; i < gBattlersCount; i++)
{
if (gStatuses3[i] & STATUS3_PERISH_SONG
|| gBattleMons[i].ability == ABILITY_SOUNDPROOF)
|| GetBattlerAbility(i) == ABILITY_SOUNDPROOF
|| BlocksPrankster(gCurrentMove, gBattlerAttacker, i))
{
notAffectedCount++;
}
@ -11598,7 +11624,7 @@ static void Cmd_tryswapitems(void) // trick
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 1);
}
// check if ability prevents swapping
else if (gBattleMons[gBattlerTarget].ability == ABILITY_STICKY_HOLD)
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_STICKY_HOLD)
{
gBattlescriptCurrInstr = BattleScript_StickyHoldActivates;
gLastUsedAbility = gBattleMons[gBattlerTarget].ability;

View file

@ -994,6 +994,11 @@ static const u8 sAbilitiesAffectedByMoldBreaker[] =
[ABILITY_FLUFFY] = 1,
[ABILITY_QUEENLY_MAJESTY] = 1,
[ABILITY_WATER_BUBBLE] = 1,
[ABILITY_MIRROR_ARMOR] = 1,
[ABILITY_PUNK_ROCK] = 1,
[ABILITY_ICE_SCALES] = 1,
[ABILITY_ICE_FACE] = 1,
[ABILITY_PASTEL_VEIL] = 1,
};
static const u8 sAbilitiesNotTraced[ABILITIES_COUNT] =
@ -1274,7 +1279,7 @@ void PressurePPLose(u8 target, u8 attacker, u16 move)
{
int moveIndex;
if (gBattleMons[target].ability != ABILITY_PRESSURE)
if (GetBattlerAbility(target) != ABILITY_PRESSURE)
return;
for (moveIndex = 0; moveIndex < MAX_MON_MOVES; moveIndex++)
@ -1306,7 +1311,7 @@ void PressurePPLoseOnUsingImprison(u8 attacker)
for (i = 0; i < gBattlersCount; i++)
{
if (atkSide != GetBattlerSide(i) && gBattleMons[i].ability == ABILITY_PRESSURE)
if (atkSide != GetBattlerSide(i) && GetBattlerAbility(i) == ABILITY_PRESSURE)
{
for (j = 0; j < MAX_MON_MOVES; j++)
{
@ -1339,7 +1344,7 @@ void PressurePPLoseOnUsingPerishSong(u8 attacker)
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleMons[i].ability == ABILITY_PRESSURE && i != attacker)
if (GetBattlerAbility(i) == ABILITY_PRESSURE && i != attacker)
{
for (j = 0; j < MAX_MON_MOVES; j++)
{
@ -2734,8 +2739,8 @@ u8 DoBattlerEndTurnEffects(void)
{
gStatuses3[gActiveBattler] -= STATUS3_YAWN_TURN(1);
if (!(gStatuses3[gActiveBattler] & STATUS3_YAWN) && !(gBattleMons[gActiveBattler].status1 & STATUS1_ANY)
&& gBattleMons[gActiveBattler].ability != ABILITY_VITAL_SPIRIT
&& gBattleMons[gActiveBattler].ability != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBattler)
&& GetBattlerAbility(gActiveBattler) != ABILITY_VITAL_SPIRIT
&& GetBattlerAbility(gActiveBattler) != ABILITY_INSOMNIA && !UproarWakeUpCheck(gActiveBattler)
&& !IsLeafGuardProtected(gActiveBattler))
{
CancelMultiTurnMoves(gActiveBattler);
@ -3098,6 +3103,7 @@ enum
CANCELLER_POWDER_MOVE,
CANCELLER_POWDER_STATUS,
CANCELLER_THROAT_CHOP,
CANCELLER_PRANKSTER,
CANCELLER_END,
CANCELLER_PSYCHIC_TERRAIN,
CANCELLER_END2,
@ -3131,7 +3137,7 @@ u8 AtkCanceller_UnableToUseMove(void)
else
{
u8 toSub;
if (gBattleMons[gBattlerAttacker].ability == ABILITY_EARLY_BIRD)
if (GetBattlerAbility(gBattlerAttacker) == ABILITY_EARLY_BIRD)
toSub = 2;
else
toSub = 1;
@ -3141,7 +3147,7 @@ u8 AtkCanceller_UnableToUseMove(void)
gBattleMons[gBattlerAttacker].status1 -= toSub;
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)
{
if (gCurrentMove != MOVE_SNORE && gCurrentMove != MOVE_SLEEP_TALK)
if (gChosenMove != MOVE_SNORE && gChosenMove != MOVE_SLEEP_TALK)
{
gBattlescriptCurrInstr = BattleScript_MoveUsedIsAsleep;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
@ -3425,6 +3431,18 @@ u8 AtkCanceller_UnableToUseMove(void)
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_PRANKSTER:
if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gBattlerTarget)
&& !(IS_MOVE_STATUS(gCurrentMove) && GetBattlerAbility(gBattlerTarget) == ABILITY_MAGIC_BOUNCE))
{
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE) || !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_BOTH | MOVE_TARGET_FOES_AND_ALLY)))
CancelMultiTurnMoves(gBattlerAttacker); // Don't cancel moves that can hit two targets bc one target might not be protected
gBattleScripting.battler = gBattlerAbility = gBattlerTarget;
gBattlescriptCurrInstr = BattleScript_DarkTypePreventsPrankster;
effect = 1;
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_END:
break;
}
@ -3728,6 +3746,8 @@ static bool32 ShouldChangeFormHpBased(u32 battler)
{ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET, 2},
{ABILITY_SHIELDS_DOWN, SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW, 2},
{ABILITY_SCHOOLING, SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI, 4},
{ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GORGING, 2},
{ABILITY_GULP_MISSILE, SPECIES_CRAMORANT, SPECIES_CRAMORANT_GULPING, 1},
};
u32 i;
@ -4980,6 +5000,42 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
effect++;
}
break;
case ABILITY_GULP_MISSILE:
if (!(gMoveResultFlags & MOVE_RESULT_NO_EFFECT)
&& !gProtectStructs[gBattlerAttacker].confusionSelfDmg
&& TARGET_TURN_DAMAGED
&& IsBattlerAlive(battler))
{
if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GORGING)
{
gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species;
gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT;
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
{
gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
}
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_GulpMissileGorging;
effect++;
}
else if (gBattleMons[gBattlerTarget].species == SPECIES_CRAMORANT_GULPING)
{
gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerTarget]] = gBattleMons[gBattlerTarget].species;
gBattleMons[gBattlerTarget].species = SPECIES_CRAMORANT;
if (GetBattlerAbility(gBattlerAttacker) != ABILITY_MAGIC_GUARD)
{
gBattleMoveDamage = gBattleMons[gBattlerAttacker].maxHP / 4;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
}
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_GulpMissileGulping;
effect++;
}
}
break;
}
break;
case ABILITYEFFECT_MOVE_END_ATTACKER: // Same as above, but for attacker
@ -5016,6 +5072,27 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
effect++;
}
break;
case ABILITY_GULP_MISSILE:
if (((gCurrentMove == MOVE_SURF && TARGET_TURN_DAMAGED) || gStatuses3[gBattlerAttacker] & STATUS3_UNDERWATER)
&& (effect = ShouldChangeFormHpBased(gBattlerAttacker)))
{
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_AttackerFormChange;
effect++;
}
break;
case ABILITY_BATTLE_BOND:
if (gBattleMons[gBattlerAttacker].species == SPECIES_GRENINJA_BATTLE_BOND
&& gBattleResults.opponentFaintCounter != 0
&& CalculateEnemyPartyCount() > 1)
{
PREPARE_SPECIES_BUFFER(gBattleTextBuff1, gBattleMons[gBattlerAttacker].species);
gBattleStruct->changedSpecies[gBattlerPartyIndexes[gBattlerAttacker]] = gBattleMons[gBattlerAttacker].species;
gBattleMons[gBattlerAttacker].species = SPECIES_GRENINJA_ASH;
BattleScriptPushCursor();
gBattlescriptCurrInstr = BattleScript_BattleBondActivatesOnMoveEndAttacker;
}
break;
}
break;
case ABILITYEFFECT_MOVE_END_OTHER: // Abilities that activate on *another* battler's moveend: Dancer, Soul-Heart, Receiver, Symbiosis
@ -5338,11 +5415,15 @@ u32 IsAbilityOnFieldExcept(u32 battlerId, u32 ability)
u32 IsAbilityPreventingEscape(u32 battlerId)
{
u32 id;
if (B_GHOSTS_ESCAPE >= GEN_6 && IS_BATTLER_OF_TYPE(battlerId, TYPE_GHOST))
return 0;
if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) && gBattleMons[battlerId].ability != ABILITY_SHADOW_TAG)
#if B_GHOSTS_ESCAPE >= GEN_6
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_GHOST))
return 0;
#endif
#if B_SHADOW_TAG_ESCAPE >= GEN_4
if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG)) && gBattleMons[battlerId].ability != ABILITY_SHADOW_TAG)
#else
if (id = IsAbilityOnOpposingSide(battlerId, ABILITY_SHADOW_TAG))
#endif
return id;
if ((id = IsAbilityOnOpposingSide(battlerId, ABILITY_ARENA_TRAP)) && IsBattlerGrounded(battlerId))
return id;
@ -6009,6 +6090,7 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
break;
case HOLD_EFFECT_EJECT_PACK:
if (gProtectStructs[battlerId].statFell
&& gProtectStructs[battlerId].disableEjectPack == 0
&& !(gCurrentMove == MOVE_PARTING_SHOT && CanBattlerSwitch(gBattlerAttacker))) // Does not activate if attacker used Parting Shot and can switch out
{
gProtectStructs[battlerId].statFell = FALSE;
@ -6117,7 +6199,20 @@ u8 ItemBattleEffects(u8 caseID, u8 battlerId, bool8 moveTurn)
break;
case HOLD_EFFECT_BLACK_SLUDGE:
if (IS_BATTLER_OF_TYPE(battlerId, TYPE_POISON))
{
goto LEFTOVERS;
}
else if (GetBattlerAbility(battlerId) != ABILITY_MAGIC_GUARD && !moveTurn)
{
gBattleMoveDamage = gBattleMons[battlerId].maxHP / 8;
if (gBattleMoveDamage == 0)
gBattleMoveDamage = 1;
BattleScriptExecute(BattleScript_ItemHurtEnd2);
effect = ITEM_HP_CHANGE;
RecordItemEffectBattle(battlerId, battlerHoldEffect);
PREPARE_ITEM_BUFFER(gBattleTextBuff1, gLastUsedItem);
}
break;
case HOLD_EFFECT_LEFTOVERS:
LEFTOVERS:
if (gBattleMons[battlerId].hp < gBattleMons[battlerId].maxHP && !moveTurn)
@ -6847,7 +6942,11 @@ u8 GetMoveTarget(u16 move, u8 setTarget)
moveTarget = setTarget - 1;
else
moveTarget = gBattleMoves[move].target;
// Special cases
if (move == MOVE_CURSE && !IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
moveTarget = MOVE_TARGET_USER;
switch (moveTarget)
{
case MOVE_TARGET_SELECTED:
@ -7238,7 +7337,7 @@ static const u16 sWeightToDamageTable[] =
};
static const u8 sSpeedDiffPowerTable[] = {40, 60, 80, 120, 150};
static const u8 sHeatCrushPowerTable[] = {40, 40, 60, 80, 100, 120};
static const u8 sHeatCrashPowerTable[] = {40, 40, 60, 80, 100, 120};
static const u8 sTrumpCardPowerTable[] = {200, 80, 60, 50, 40};
const struct TypePower gNaturalGiftTable[] =
@ -7410,7 +7509,7 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
if (gBattleMons[battlerAtk].pp[i] >= ARRAY_COUNT(sTrumpCardPowerTable))
basePower = sTrumpCardPowerTable[ARRAY_COUNT(sTrumpCardPowerTable) - 1];
else
basePower = sTrumpCardPowerTable[i];
basePower = sTrumpCardPowerTable[gBattleMons[battlerAtk].pp[i]];
}
break;
case EFFECT_ACROBATICS:
@ -7433,10 +7532,10 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
break;
case EFFECT_HEAT_CRASH:
weight = GetBattlerWeight(battlerAtk) / GetBattlerWeight(battlerDef);
if (weight >= ARRAY_COUNT(sHeatCrushPowerTable))
basePower = sHeatCrushPowerTable[ARRAY_COUNT(sHeatCrushPowerTable) - 1];
if (weight >= ARRAY_COUNT(sHeatCrashPowerTable))
basePower = sHeatCrashPowerTable[ARRAY_COUNT(sHeatCrashPowerTable) - 1];
else
basePower = sHeatCrushPowerTable[i];
basePower = sHeatCrashPowerTable[i];
break;
case EFFECT_PUNISHMENT:
basePower = 60 + (CountBattlerStatIncreases(battlerDef, FALSE) * 20);
@ -7495,6 +7594,15 @@ static u16 CalcMoveBasePower(u16 move, u8 battlerAtk, u8 battlerDef)
break;
}
// move-specific base power changes
switch (move)
{
case MOVE_WATER_SHURIKEN:
if (gBattleMons[battlerAtk].species == SPECIES_GRENINJA_ASH)
basePower = 20;
break;
}
if (basePower == 0)
basePower = 1;
return basePower;
@ -7758,7 +7866,7 @@ static u32 CalcMoveBasePowerAfterModifiers(u16 move, u8 battlerAtk, u8 battlerDe
if (gBattleMons[battlerDef].status1 & STATUS1_PSN_ANY)
MulModifier(&modifier, UQ_4_12(2.0));
break;
case EFFECT_RETALITATE:
case EFFECT_RETALIATE:
// todo
break;
case EFFECT_SOLARBEAM:
@ -8136,6 +8244,7 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
u32 abilityDef = GetBattlerAbility(battlerDef);
u32 defSide = GET_BATTLER_SIDE(battlerDef);
u16 finalModifier = UQ_4_12(1.0);
u16 itemDef = gBattleMons[battlerDef].item;
// check multiple targets in double battle
if (GetMoveTargetCount(move, battlerAtk, battlerDef) >= 2)
@ -8256,7 +8365,8 @@ static u32 CalcFinalDmg(u32 dmg, u16 move, u8 battlerAtk, u8 battlerDef, u8 move
// berries reducing dmg
case HOLD_EFFECT_RESIST_BERRY:
if (moveType == GetBattlerHoldEffectParam(battlerDef)
&& (moveType == TYPE_NORMAL || typeEffectivenessModifier >= UQ_4_12(2.0)))
&& (moveType == TYPE_NORMAL || typeEffectivenessModifier >= UQ_4_12(2.0))
&& !UnnerveOn(battlerDef, itemDef))
{
if (abilityDef == ABILITY_RIPEN)
MulModifier(&finalModifier, UQ_4_12(0.25));
@ -8657,6 +8767,9 @@ void UndoFormChange(u32 monId, u32 side, bool32 isSwitchingOut)
{SPECIES_MINIOR_METEOR_VIOLET, SPECIES_MINIOR_CORE_VIOLET},
{SPECIES_MINIOR_METEOR_YELLOW, SPECIES_MINIOR_CORE_YELLOW},
{SPECIES_WISHIWASHI_SCHOOL, SPECIES_WISHIWASHI},
{SPECIES_CRAMORANT_GORGING, SPECIES_CRAMORANT},
{SPECIES_CRAMORANT_GULPING, SPECIES_CRAMORANT},
{SPECIES_GRENINJA_ASH, SPECIES_GRENINJA_BATTLE_BOND},
};
if (isSwitchingOut) // Don't revert Mimikyu Busted when switching out
@ -9241,3 +9354,17 @@ void DoBurmyFormChange(u32 monId)
}
}
}
bool32 BlocksPrankster(u16 move, u8 battlerPrankster, u8 battlerDef)
{
#if B_PRANKSTER_DARK_TYPES >= GEN_7
if (gProtectStructs[battlerPrankster].pranksterElevated
&& GetBattlerSide(battlerPrankster) != GetBattlerSide(battlerDef)
&& !(gBattleMoves[gCurrentMove].target & (MOVE_TARGET_OPPONENTS_FIELD | MOVE_TARGET_DEPENDS)) // Don't block hazards, assist-type moves
&& IS_BATTLER_OF_TYPE(battlerDef, TYPE_DARK) // Only Dark-types can block Prankster'd
&& !(gStatuses3[battlerDef] & STATUS3_SEMI_INVULNERABLE))
return TRUE;
else
#endif
return FALSE;
}

View file

@ -2599,11 +2599,12 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
#if B_UPDATED_MOVE_DATA >= GEN_4
.accuracy = 0,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.effect = EFFECT_RECOIL_HP_25,
#else
.accuracy = 100,
.flags = FLAG_MAKES_CONTACT | FLAG_PROTECT_AFFECTED | FLAG_MIRROR_MOVE_AFFECTED | FLAG_KINGS_ROCK_AFFECTED,
.effect = EFFECT_RECOIL_25,
#endif
.effect = EFFECT_RECOIL_25,
.power = 50,
.type = TYPE_NORMAL,
.pp = 1,
@ -3424,6 +3425,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_HEAL_BELL] =
{
#if B_UPDATED_MOVE_DATA != GEN_5
.flags = FLAG_SNATCH_AFFECTED | FLAG_SOUND,
#else
.flags = FLAG_SNATCH_AFFECTED,
#endif
.effect = EFFECT_HEAL_BELL,
.power = 0,
.type = TYPE_NORMAL,
@ -3432,7 +3438,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_USER,
.priority = 0,
.flags = FLAG_SNATCH_AFFECTED | FLAG_SOUND,
.split = SPLIT_STATUS,
},
@ -5338,6 +5343,11 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_HOWL] =
{
#if B_UPDATED_MOVE_DATA >= GEN_8
.flags = FLAG_SNATCH_AFFECTED | FLAG_SOUND,
#else
.flags = FLAG_SNATCH_AFFECTED,
#endif
.effect = EFFECT_ATTACK_UP,
.power = 0,
.type = TYPE_NORMAL,
@ -5346,7 +5356,6 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
.secondaryEffectChance = 0,
.target = MOVE_TARGET_USER,
.priority = 0,
.flags = FLAG_SNATCH_AFFECTED | FLAG_SOUND,
.split = SPLIT_STATUS,
},
@ -8097,7 +8106,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_RETALIATE] =
{
.effect = EFFECT_RETALITATE,
.effect = EFFECT_RETALIATE,
.power = 70,
.type = TYPE_NORMAL,
.accuracy = 100,
@ -10226,7 +10235,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_PSYCHIC_FANGS] =
{
.effect = EFFECT_BRICK_BREAK,
.power = 75,
.power = 85,
.type = TYPE_PSYCHIC,
.accuracy = 100,
.pp = 15,