Adds Ability Shield activation message (#7224)

This commit is contained in:
PhallenTree 2025-06-26 13:42:32 +01:00 committed by GitHub
parent 6f7dac6d11
commit a82aa618fb
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
9 changed files with 111 additions and 30 deletions

View File

@ -2461,6 +2461,11 @@
.4byte \jumpInstr .4byte \jumpInstr
.endm .endm
.macro tryactivateabilityshield battler:req
callnative BS_TryActivateAbilityShield
.byte \battler
.endm
.macro setallytonexttarget jumpInstr:req .macro setallytonexttarget jumpInstr:req
jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f jumpifbyte CMP_GREATER_THAN, gBattlerTarget, 0x1, 1f
addbyte gBattlerTarget, 0x2 addbyte gBattlerTarget, 0x2

View File

@ -7176,9 +7176,20 @@ BattleScript_AbilityCantRaiseDefenderStat::
restoreattacker restoreattacker
return return
BattleScript_AbilityShieldProtects::
saveattacker
copybyte gBattlerAttacker, gBattlerAbility
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT
waitanimation
printstring STRINGID_ABILITYSHIELDPROTECTS
waitmessage B_WAIT_TIME_LONG
restoreattacker
return
BattleScript_AbilityPopUpTarget:: BattleScript_AbilityPopUpTarget::
copybyte gBattlerAbility, gBattlerTarget copybyte gBattlerAbility, gBattlerTarget
BattleScript_AbilityPopUp:: BattleScript_AbilityPopUp::
tryactivateabilityshield BS_ABILITY_BATTLER
.if B_ABILITY_POP_UP == TRUE .if B_ABILITY_POP_UP == TRUE
showabilitypopup BS_ABILITY_BATTLER showabilitypopup BS_ABILITY_BATTLER
pause 40 pause 40
@ -7428,14 +7439,10 @@ BattleScript_TryIntimidateHoldEffectsRet:
BattleScript_IntimidateActivates:: BattleScript_IntimidateActivates::
savetarget savetarget
.if B_ABILITY_POP_UP == TRUE call BattleScript_AbilityPopUp
showabilitypopup BS_ATTACKER
pause B_WAIT_TIME_LONG
destroyabilitypopup destroyabilitypopup
.endif
setbyte gBattlerTarget, 0 setbyte gBattlerTarget, 0
BattleScript_IntimidateLoop: BattleScript_IntimidateLoop:
jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_IntimidateLoopIncrement
jumpiftargetally BattleScript_IntimidateLoopIncrement jumpiftargetally BattleScript_IntimidateLoopIncrement
jumpifabsent BS_TARGET, BattleScript_IntimidateLoopIncrement jumpifabsent BS_TARGET, BattleScript_IntimidateLoopIncrement
jumpifvolatile BS_TARGET, VOLATILE_SUBSTITUTE, BattleScript_IntimidateLoopIncrement jumpifvolatile BS_TARGET, VOLATILE_SUBSTITUTE, BattleScript_IntimidateLoopIncrement
@ -7488,16 +7495,12 @@ BattleScript_IntimidateInReverse::
BattleScript_SupersweetSyrupActivates:: BattleScript_SupersweetSyrupActivates::
savetarget savetarget
.if B_ABILITY_POP_UP == TRUE call BattleScript_AbilityPopUp
showabilitypopup BS_ATTACKER
pause B_WAIT_TIME_LONG
destroyabilitypopup destroyabilitypopup
.endif
printstring STRINGID_SUPERSWEETAROMAWAFTS printstring STRINGID_SUPERSWEETAROMAWAFTS
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
setbyte gBattlerTarget, 0 setbyte gBattlerTarget, 0
BattleScript_SupersweetSyrupLoop: BattleScript_SupersweetSyrupLoop:
jumpifbyteequal gBattlerTarget, gBattlerAttacker, BattleScript_SupersweetSyrupLoopIncrement
jumpiftargetally BattleScript_SupersweetSyrupLoopIncrement jumpiftargetally BattleScript_SupersweetSyrupLoopIncrement
jumpifabsent BS_TARGET, BattleScript_SupersweetSyrupLoopIncrement jumpifabsent BS_TARGET, BattleScript_SupersweetSyrupLoopIncrement
jumpifvolatile BS_TARGET, VOLATILE_SUBSTITUTE, BattleScript_SupersweetSyrupLoopIncrement jumpifvolatile BS_TARGET, VOLATILE_SUBSTITUTE, BattleScript_SupersweetSyrupLoopIncrement
@ -7510,8 +7513,12 @@ BattleScript_SupersweetSyrupEffect:
printfromtable gStatDownStringIds printfromtable gStatDownStringIds
BattleScript_SupersweetSyrupEffect_WaitString: BattleScript_SupersweetSyrupEffect_WaitString:
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
saveattacker
savetarget
copybyte sBATTLER, gBattlerTarget copybyte sBATTLER, gBattlerTarget
call BattleScript_TryIntimidateHoldEffects call BattleScript_TryIntimidateHoldEffects
restoreattacker
restoretarget
BattleScript_SupersweetSyrupLoopIncrement: BattleScript_SupersweetSyrupLoopIncrement:
addbyte gBattlerTarget, 1 addbyte gBattlerTarget, 1
jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_SupersweetSyrupLoop jumpifbytenotequal gBattlerTarget, gBattlersCount, BattleScript_SupersweetSyrupLoop
@ -7977,6 +7984,11 @@ BattleScript_ProteanActivates::
waitmessage B_WAIT_TIME_LONG waitmessage B_WAIT_TIME_LONG
return return
BattleScript_AbilityAvoidsDamage::
call BattleScript_AbilityPopUp
printfromtable gMissStringIds @ waitmessage is executed next so no waitmessage here
return
BattleScript_TeraShellDistortingTypeMatchups:: BattleScript_TeraShellDistortingTypeMatchups::
pause B_WAIT_TIME_SHORTEST pause B_WAIT_TIME_SHORTEST
call BattleScript_AbilityPopUpScripting call BattleScript_AbilityPopUpScripting

View File

@ -243,6 +243,8 @@ extern const u8 BattleScript_ConsumableStatRaiseRet[];
extern const u8 BattleScript_BerryFocusEnergyRet[]; extern const u8 BattleScript_BerryFocusEnergyRet[];
extern const u8 BattleScript_BerryFocusEnergyEnd2[]; extern const u8 BattleScript_BerryFocusEnergyEnd2[];
extern const u8 BattleScript_ActionSelectionItemsCantBeUsed[]; extern const u8 BattleScript_ActionSelectionItemsCantBeUsed[];
extern const u8 BattleScript_AbilityAvoidsDamage[];
extern const u8 BattleScript_AbilityShieldProtects[];
extern const u8 BattleScript_ArenaTurnBeginning[]; extern const u8 BattleScript_ArenaTurnBeginning[];
extern const u8 BattleScript_PalacePrintFlavorText[]; extern const u8 BattleScript_PalacePrintFlavorText[];
extern const u8 BattleScript_ArenaDoJudgment[]; extern const u8 BattleScript_ArenaDoJudgment[];

View File

@ -257,7 +257,8 @@ bool32 TryPrimalReversion(u32 battler);
bool32 IsNeutralizingGasOnField(void); bool32 IsNeutralizingGasOnField(void);
bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability); bool32 IsMoldBreakerTypeAbility(u32 battler, u32 ability);
u32 GetBattlerAbilityIgnoreMoldBreaker(u32 battler); u32 GetBattlerAbilityIgnoreMoldBreaker(u32 battler);
u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker); u32 GetBattlerAbilityNoAbilityShield(u32 battler);
u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityShield);
u32 GetBattlerAbility(u32 battler); u32 GetBattlerAbility(u32 battler);
u32 IsAbilityOnSide(u32 battler, u32 ability); u32 IsAbilityOnSide(u32 battler, u32 ability);
u32 IsAbilityOnOpposingSide(u32 battler, u32 ability); u32 IsAbilityOnOpposingSide(u32 battler, u32 ability);

View File

@ -738,6 +738,7 @@ enum StringID
STRINGID_TOXICSPIKESBADLYPOISONED, STRINGID_TOXICSPIKESBADLYPOISONED,
STRINGID_POWERCONSTRUCTPRESENCEOFMANY, STRINGID_POWERCONSTRUCTPRESENCEOFMANY,
STRINGID_POWERCONSTRUCTTRANSFORM, STRINGID_POWERCONSTRUCTTRANSFORM,
STRINGID_ABILITYSHIELDPROTECTS,
STRINGID_COUNT STRINGID_COUNT
}; };

View File

@ -897,6 +897,7 @@ const u8 *const gBattleStringsTable[STRINGID_COUNT] =
[STRINGID_QUESTIONFORFEITBATTLE] = COMPOUND_STRING("Would you like to give up on this battle and quit now? Quitting the battle is the same as losing the battle."), [STRINGID_QUESTIONFORFEITBATTLE] = COMPOUND_STRING("Would you like to give up on this battle and quit now? Quitting the battle is the same as losing the battle."),
[STRINGID_POWERCONSTRUCTPRESENCEOFMANY] = COMPOUND_STRING("You sense the presence of many!"), [STRINGID_POWERCONSTRUCTPRESENCEOFMANY] = COMPOUND_STRING("You sense the presence of many!"),
[STRINGID_POWERCONSTRUCTTRANSFORM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} transformed into its Complete Forme!"), [STRINGID_POWERCONSTRUCTTRANSFORM] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX} transformed into its Complete Forme!"),
[STRINGID_ABILITYSHIELDPROTECTS] = COMPOUND_STRING("{B_ATK_NAME_WITH_PREFIX}'s Ability is protected by the effects of its {B_LAST_ITEM}!"),
}; };
const u16 gTrainerUsedItemStringIds[] = const u16 gTrainerUsedItemStringIds[] =

View File

@ -2879,8 +2879,15 @@ static void Cmd_resultmessage(void)
return; return;
} }
if (gBattleStruct->missStringId[gBattlerTarget] > B_MSG_AVOIDED_ATK) // Wonder Guard or Levitate - show the ability pop-up if (gBattleStruct->missStringId[gBattlerTarget] > B_MSG_AVOIDED_ATK) // Wonder Guard or Levitate
CreateAbilityPopUp(gBattlerTarget, gBattleMons[gBattlerTarget].ability, IsDoubleBattle()); {
gBattlerAbility = gBattlerTarget;
gBattleCommunication[MULTISTRING_CHOOSER] = gBattleStruct->missStringId[gBattlerTarget];
gBattlescriptCurrInstr = cmd->nextInstr;
BattleScriptCall(BattleScript_AbilityAvoidsDamage);
return;
}
gBattleCommunication[MSG_DISPLAY] = 1; gBattleCommunication[MSG_DISPLAY] = 1;
stringId = gMissStringIds[gBattleStruct->missStringId[gBattlerTarget]]; stringId = gMissStringIds[gBattleStruct->missStringId[gBattlerTarget]];
} }
@ -18601,3 +18608,18 @@ void BS_JumpIfAbilityCantBeSuppressed(void)
else else
gBattlescriptCurrInstr = cmd->nextInstr; gBattlescriptCurrInstr = cmd->nextInstr;
} }
void BS_TryActivateAbilityShield(void)
{
NATIVE_ARGS(u8 battler);
u32 battler = GetBattlerForBattleScript(cmd->battler);
gBattlescriptCurrInstr = cmd->nextInstr;
if (GetBattlerAbilityNoAbilityShield(battler) != GetBattlerAbility(battler))
{
gLastUsedItem = gBattleMons[battler].item;
RecordItemEffectBattle(battler, GetItemHoldEffect(gLastUsedItem));
BattleScriptCall(BattleScript_AbilityShieldProtects);
}
}

View File

@ -3878,7 +3878,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
case ABILITY_INTIMIDATE: case ABILITY_INTIMIDATE:
if (!gSpecialStatuses[battler].switchInAbilityDone) if (!gSpecialStatuses[battler].switchInAbilityDone)
{ {
gBattlerAttacker = battler; gBattlerAbility = gBattlerAttacker = battler;
gSpecialStatuses[battler].switchInAbilityDone = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE;
SET_STATCHANGER(STAT_ATK, 1, TRUE); SET_STATCHANGER(STAT_ATK, 1, TRUE);
BattleScriptPushCursorAndCallback(BattleScript_IntimidateActivates); BattleScriptPushCursorAndCallback(BattleScript_IntimidateActivates);
@ -3889,7 +3889,7 @@ u32 AbilityBattleEffects(u32 caseID, u32 battler, u32 ability, u32 special, u32
if (!gSpecialStatuses[battler].switchInAbilityDone if (!gSpecialStatuses[battler].switchInAbilityDone
&& !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup) && !gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup)
{ {
gBattlerAttacker = battler; gBattlerAbility = gBattlerAttacker = battler;
gSpecialStatuses[battler].switchInAbilityDone = TRUE; gSpecialStatuses[battler].switchInAbilityDone = TRUE;
gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup = TRUE; gBattleStruct->partyState[GetBattlerSide(battler)][gBattlerPartyIndexes[battler]].supersweetSyrup = TRUE;
BattleScriptPushCursorAndCallback(BattleScript_SupersweetSyrupActivates); BattleScriptPushCursorAndCallback(BattleScript_SupersweetSyrupActivates);
@ -5415,19 +5415,24 @@ static inline bool32 CanBreakThroughAbility(u32 battlerAtk, u32 battlerDef, u32
&& gCurrentTurnActionNumber < gBattlersCount); && gCurrentTurnActionNumber < gBattlersCount);
} }
u32 GetBattlerAbilityNoAbilityShield(u32 battler)
{
return GetBattlerAbilityInternal(battler, FALSE, TRUE);
}
u32 GetBattlerAbilityIgnoreMoldBreaker(u32 battler) u32 GetBattlerAbilityIgnoreMoldBreaker(u32 battler)
{ {
return GetBattlerAbilityInternal(battler, TRUE); return GetBattlerAbilityInternal(battler, TRUE, FALSE);
} }
u32 GetBattlerAbility(u32 battler) u32 GetBattlerAbility(u32 battler)
{ {
return GetBattlerAbilityInternal(battler, FALSE); return GetBattlerAbilityInternal(battler, FALSE, FALSE);
} }
u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker) u32 GetBattlerAbilityInternal(u32 battler, u32 ignoreMoldBreaker, u32 noAbilityShield)
{ {
bool32 hasAbilityShield = GetBattlerHoldEffectIgnoreAbility(battler, TRUE) == HOLD_EFFECT_ABILITY_SHIELD; bool32 hasAbilityShield = !noAbilityShield && GetBattlerHoldEffectIgnoreAbility(battler, TRUE) == HOLD_EFFECT_ABILITY_SHIELD;
bool32 abilityCantBeSuppressed = gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed; bool32 abilityCantBeSuppressed = gAbilitiesInfo[gBattleMons[battler].ability].cantBeSuppressed;
if (abilityCantBeSuppressed) if (abilityCantBeSuppressed)

View File

@ -6,7 +6,7 @@ ASSUMPTIONS
ASSUME(gItemsInfo[ITEM_ABILITY_SHIELD].holdEffect == HOLD_EFFECT_ABILITY_SHIELD); ASSUME(gItemsInfo[ITEM_ABILITY_SHIELD].holdEffect == HOLD_EFFECT_ABILITY_SHIELD);
} }
SINGLE_BATTLE_TEST("Ability Shield prevents Neutralizing Gas") SINGLE_BATTLE_TEST("Ability Shield protects against Neutralizing Gas")
{ {
u32 item; u32 item;
@ -22,12 +22,14 @@ SINGLE_BATTLE_TEST("Ability Shield prevents Neutralizing Gas")
ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS); ABILITY_POPUP(opponent, ABILITY_NEUTRALIZING_GAS);
MESSAGE("Neutralizing gas filled the area!"); MESSAGE("Neutralizing gas filled the area!");
if (item == ITEM_ABILITY_SHIELD) { if (item == ITEM_ABILITY_SHIELD) {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Torkoal's Ability is protected by the effects of its Ability Shield!");
ABILITY_POPUP(player, ABILITY_DROUGHT); ABILITY_POPUP(player, ABILITY_DROUGHT);
MESSAGE("Torkoal's Drought intensified the sun's rays!");
} else { } else {
NONE_OF { NONE_OF {
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_HELD_ITEM_EFFECT, player);
MESSAGE("Torkoal's Ability is protected by the effects of its Ability Shield!");
ABILITY_POPUP(player, ABILITY_DROUGHT); ABILITY_POPUP(player, ABILITY_DROUGHT);
MESSAGE("Torkoal's Drought intensified the sun's rays!");
} }
} }
} }
@ -41,17 +43,18 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Mold Breaker")
PARAMETRIZE { item = ITEM_NONE; } PARAMETRIZE { item = ITEM_NONE; }
GIVEN { GIVEN {
PLAYER(SPECIES_SHEDINJA) { Ability(ABILITY_WONDER_GUARD); Item(item); } ASSUME(GetMoveType(MOVE_EARTHQUAKE) == TYPE_GROUND);
OPPONENT(SPECIES_TINKATON) { Ability(ABILITY_MOLD_BREAKER); } PLAYER(SPECIES_FLYGON) { Ability(ABILITY_LEVITATE); Item(item); }
OPPONENT(SPECIES_EXCADRILL) { Ability(ABILITY_MOLD_BREAKER); }
} WHEN { } WHEN {
TURN { MOVE(opponent, MOVE_GIGATON_HAMMER); } TURN { MOVE(opponent, MOVE_EARTHQUAKE); }
} SCENE { } SCENE {
if (item == ITEM_ABILITY_SHIELD) { if (item == ITEM_ABILITY_SHIELD) {
NONE_OF { ABILITY_POPUP(player, ABILITY_LEVITATE);
MESSAGE("Shedinja fainted!"); NOT HP_BAR(player);
}
} else { } else {
MESSAGE("Shedinja fainted!"); NOT ABILITY_POPUP(player, ABILITY_LEVITATE);
HP_BAR(player);
} }
} }
} }
@ -64,10 +67,12 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Mycelium Might")
PARAMETRIZE { item = ITEM_NONE; } PARAMETRIZE { item = ITEM_NONE; }
GIVEN { GIVEN {
ASSUME(GetMoveEffect(MOVE_SPORE) == EFFECT_NON_VOLATILE_STATUS);
ASSUME(GetMoveNonVolatileStatus(MOVE_SPORE) == MOVE_EFFECT_SLEEP);
PLAYER(SPECIES_VIGOROTH) { Ability(ABILITY_VITAL_SPIRIT); Item(item); } PLAYER(SPECIES_VIGOROTH) { Ability(ABILITY_VITAL_SPIRIT); Item(item); }
OPPONENT(SPECIES_TOEDSCOOL) { Ability(ABILITY_MYCELIUM_MIGHT); } OPPONENT(SPECIES_TOEDSCOOL) { Ability(ABILITY_MYCELIUM_MIGHT); }
} WHEN { } WHEN {
TURN { MOVE(opponent, MOVE_SPORE); MOVE(player, MOVE_SPORE); } TURN { MOVE(opponent, MOVE_SPORE); }
} SCENE { } SCENE {
if (item == ITEM_ABILITY_SHIELD) { if (item == ITEM_ABILITY_SHIELD) {
@ -90,6 +95,7 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Sunsteel Strike")
PARAMETRIZE { item = ITEM_NONE; } PARAMETRIZE { item = ITEM_NONE; }
GIVEN { GIVEN {
ASSUME(MoveIgnoresTargetAbility(MOVE_SUNSTEEL_STRIKE));
PLAYER(SPECIES_SHEDINJA) { Ability(ABILITY_WONDER_GUARD); Item(item); } PLAYER(SPECIES_SHEDINJA) { Ability(ABILITY_WONDER_GUARD); Item(item); }
OPPONENT(SPECIES_WOBBUFFET); OPPONENT(SPECIES_WOBBUFFET);
} WHEN { } WHEN {
@ -104,3 +110,29 @@ SINGLE_BATTLE_TEST("Ability Shield protects against Sunsteel Strike")
} }
} }
} }
SINGLE_BATTLE_TEST("Ability Shield protects against Skill Swap")
{
u32 item;
PARAMETRIZE { item = ITEM_ABILITY_SHIELD; }
PARAMETRIZE { item = ITEM_NONE; }
GIVEN {
ASSUME(GetMoveEffect(MOVE_SKILL_SWAP) == EFFECT_SKILL_SWAP);
PLAYER(SPECIES_GYARADOS) { Ability(ABILITY_INTIMIDATE); Item(item); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponent, MOVE_SKILL_SWAP); }
} SCENE {
if (item == ITEM_ABILITY_SHIELD) {
NONE_OF {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
}
} else {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKILL_SWAP, opponent);
ABILITY_POPUP(opponent, ABILITY_INTIMIDATE);
}
}
}