Sky Drop Fixes/Refactor (#9185)
Some checks failed
CI / build (push) Has been cancelled
CI / docs_validate (push) Has been cancelled
CI / allcontributors (push) Has been cancelled

This commit is contained in:
Alex 2026-02-16 18:22:53 +01:00 committed by GitHub
parent ae9b313e97
commit 89fbaef8ba
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 211 additions and 195 deletions

View File

@ -1462,10 +1462,6 @@
.4byte \jumpInstr
.endm
.macro trytwoturnmovespowerherbformchange
callnative BS_TryTwoTurnMovesPowerHerbFormChange
.endm
.macro tryquash failInstr:req
callnative BS_TryQuash
.4byte \failInstr
@ -2100,20 +2096,6 @@
.4byte \failInstr
.endm
.macro jumpifunder200 jumpInstr:req
callnative BS_JumpIfUnder200
.4byte \jumpInstr
.endm
.macro setskydrop
callnative BS_SetSkyDrop
.endm
.macro clearskydrop failInstr:req
callnative BS_ClearSkyDrop
.4byte \failInstr
.endm
.macro skydropyawn
callnative BS_SkyDropYawn
.endm

View File

@ -397,15 +397,17 @@ BattleScript_EffectRevivalBlessingSendOut:
goto BattleScript_MoveEnd
BattleScript_StealthRockActivates::
setstealthrock BattleScript_MoveEnd
setstealthrock BattleScript_StealthRockActivatesRet
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_StealthRockActivatesRet:
return
BattleScript_SpikesActivates::
trysetspikes BattleScript_MoveEnd
trysetspikes BattleScript_SpikesActivatesRet
printfromtable gDmgHazardsStringIds
waitmessage B_WAIT_TIME_LONG
BattleScript_SpikesActivatesRet:
return
BattleScript_EffectTeatime::
@ -503,58 +505,6 @@ BattleScript_BeakBlastBurn::
call BattleScript_MoveEffectBurn
return
BattleScript_EffectSkyDrop::
attackcanceler
jumpifvolatile BS_ATTACKER, VOLATILE_MULTIPLETURNS, BattleScript_SkyDropTurn2
accuracycheck BattleScript_MoveMissedPause
jumpifsubstituteblocks BattleScript_ButItFailed
jumpiftargetally BattleScript_ButItFailed
jumpifunder200 BattleScript_SkyDropWork
pause B_WAIT_TIME_SHORT
printstring STRINGID_TARGETTOOHEAVY
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_SkyDropWork:
setskydrop
call BattleScript_FirstChargingTurnAfterAttackString
goto BattleScript_MoveEnd
BattleScript_SkyDropTurn2:
call BattleScript_TwoTurnMovesSecondTurnRet
clearskydrop BattleScript_SkyDropChangedTarget
jumpiftype BS_TARGET, TYPE_FLYING, BattleScript_SkyDropFlyingType
goto BattleScript_HitFromDamageCalc
BattleScript_SkyDropFlyingType:
makevisible BS_TARGET
printstring STRINGID_ITDOESNTAFFECT
waitmessage B_WAIT_TIME_LONG
makevisible BS_ATTACKER
jumpifvolatile BS_TARGET, VOLATILE_CONFUSION, BattleScript_SkyDropFlyingAlreadyConfused
jumpifvolatile BS_TARGET, VOLATILE_RAMPAGE_TURNS, BattleScript_SkyDropFlyingConfuseLock
goto BattleScript_MoveEnd
BattleScript_SkyDropChangedTarget:
pause B_WAIT_TIME_SHORT
setmoveresultflags MOVE_RESULT_FAILED
resultmessage
waitmessage B_WAIT_TIME_LONG
makevisible BS_ATTACKER
goto BattleScript_MoveEnd
BattleScript_FirstChargingTurnAfterAttackString:
setsemiinvulnerablebit @ only for moves with EFFECT_SEMI_INVULNERABLE/EFFECT_SKY_DROP
setchargingturn
twoturnmoveschargestringandanimation
setadditionaleffects @ only onChargeTurnOnly effects will work here
return
BattleScript_SkyDropFlyingConfuseLock:
seteffectprimary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_CONFUSION
BattleScript_SkyDropFlyingAlreadyConfused:
clearvolatile BS_TARGET, VOLATILE_RAMPAGE_TURNS
jumpifvolatile BS_TARGET, VOLATILE_CONFUSION, BattleScript_MoveEnd
setbyte BS_ATTACKER, BS_TARGET
goto BattleScript_ThrashConfuses
BattleScript_EffectFling::
attackcanceler
accuracycheck BattleScript_FlingMissed
@ -2835,14 +2785,6 @@ BattleScript_AlreadyParalyzed::
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_PowerHerbActivation::
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_POWERHERB
waitmessage B_WAIT_TIME_LONG
removeitem BS_ATTACKER
trytwoturnmovespowerherbformchange @ Edge case for Cramorant ability Gulp Missile
return
BattleScript_EffectGeomancy::
attackcanceler
jumpifstat BS_ATTACKER, CMP_LESS_THAN, STAT_SPATK, MAX_STAT_STAGE, BattleScript_GeomancyDoMoveAnim
@ -2871,21 +2813,22 @@ BattleScript_GeomancyTrySpeed::
BattleScript_GeomancyEnd::
goto BattleScript_MoveEnd
BattleScript_PowerHerbActivation::
playanimation BS_ATTACKER, B_ANIM_HELD_ITEM_EFFECT
printstring STRINGID_POWERHERB
waitmessage B_WAIT_TIME_LONG
removeitem BS_ATTACKER
return
BattleScript_TwoTurnMoveCharging::
waitmessage B_WAIT_TIME_LONG
twoturnmoveschargestringandanimation
setadditionaleffects @ only onChargeTurnOnly effects will work here
return
BattleScript_FromTwoTurnMovesSecondTurnRet:
call BattleScript_TwoTurnMovesSecondTurnRet
accuracycheck BattleScript_MoveMissedPause
goto BattleScript_HitFromDamageCalc
BattleScript_TwoTurnMovesSecondTurn::
attackcanceler
call BattleScript_TwoTurnMovesSecondTurnRet
goto BattleScript_HitFromAccCheck
BattleScript_SkyDropCharging::
call BattleScript_TwoTurnMoveCharging
goto BattleScript_MoveEnd
BattleScript_TwoTurnMovesSecondTurnRet:
setbyte sB_ANIM_TURN, 1
@ -2894,6 +2837,39 @@ BattleScript_TwoTurnMovesSecondTurnRet:
clearsemiinvulnerablebit @ only for moves with EFFECT_SEMI_INVULNERABLE/EFFECT_SKY_DROP
return
BattleScript_SkyDropTargetTooHeavy::
pause B_WAIT_TIME_SHORT
printstring STRINGID_TARGETTOOHEAVY
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_SkyDropFlyingType::
makevisible BS_TARGET
printstring STRINGID_ITDOESNTAFFECT
waitmessage B_WAIT_TIME_LONG
makevisible BS_ATTACKER
jumpifvolatile BS_TARGET, VOLATILE_CONFUSION, BattleScript_SkyDropFlyingAlreadyConfused
jumpifvolatile BS_TARGET, VOLATILE_RAMPAGE_TURNS, BattleScript_SkyDropFlyingConfuseLock
return
BattleScript_SkyDropFlyingConfuseLock:
seteffectprimary BS_ATTACKER, BS_TARGET, MOVE_EFFECT_CONFUSION
BattleScript_SkyDropFlyingAlreadyConfused:
clearvolatile BS_TARGET, VOLATILE_RAMPAGE_TURNS
jumpifvolatile BS_TARGET, VOLATILE_CONFUSION, BattleScript_SkyDropFlyingAlreadyConfusedRet
setbyte BS_ATTACKER, BS_TARGET
call BattleScript_ThrashConfusesRet
BattleScript_SkyDropFlyingAlreadyConfusedRet:
return
BattleScript_SkyDropNoTarget::
pause B_WAIT_TIME_SHORT
setmoveresultflags MOVE_RESULT_FAILED
resultmessage
waitmessage B_WAIT_TIME_LONG
makevisible BS_ATTACKER
goto BattleScript_MoveEnd
BattleScript_EffectSubstitute::
attackcanceler
waitstate
@ -5435,10 +5411,6 @@ BattleScript_UltraBurst::
switchinabilities BS_SCRIPTING
end3
BattleScript_TwoTurnMovesSecondTurnFormChange::
call BattleScript_BattlerFormChangeInstant
goto BattleScript_FromTwoTurnMovesSecondTurnRet
BattleScript_BattlerFormChange::
pause 5
call BattleScript_AbilityPopUpScripting
@ -5453,12 +5425,6 @@ BattleScript_BattlerFormChangeFromAfterAnimation::
jumpifability BS_TARGET, ABILITY_DISGUISE, BattleScript_ApplyDisguiseFormChangeHPLoss
return
BattleScript_BattlerFormChangeInstant::
handleformchange BS_SCRIPTING, 0
playanimation BS_SCRIPTING, B_ANIM_FORM_CHANGE_INSTANT
waitanimation
goto BattleScript_BattlerFormChangeFromAfterAnimation
BattleScript_BattlerFormChangeDisguise::
call BattleScript_AbilityPopUpScripting
pause B_WAIT_TIME_LONG

View File

@ -52,7 +52,6 @@ extern const u8 BattleScript_Pausex20[];
extern const u8 BattleScript_LevelUp[];
extern const u8 BattleScript_WeatherContinues[];
extern const u8 BattleScript_WeatherFaded[];
extern const u8 BattleScript_DamagingWeatherContinues[];
extern const u8 BattleScript_DamagingWeather[];
extern const u8 BattleScript_FogEnded_Ret[];
extern const u8 BattleScript_IceBodyHeal[];
@ -164,8 +163,6 @@ extern const u8 BattleScript_MoveEffectConfusion[];
extern const u8 BattleScript_MoveEffectRecoil[];
extern const u8 BattleScript_FaintAttackerForExplosion[];
extern const u8 BattleScript_MaxHp50Recoil[];
extern const u8 BattleScript_DoRecoil33[];
extern const u8 BattleScript_Recoil33End[];
extern const u8 BattleScript_ItemSteal[];
extern const u8 BattleScript_WeatherAbilityActivates[];
extern const u8 BattleScript_TraceActivates[];
@ -182,7 +179,6 @@ extern const u8 BattleScript_MonMadeMoveUseless[];
extern const u8 BattleScript_FlashFireBoost[];
extern const u8 BattleScript_AbilityNoStatLoss[];
extern const u8 BattleScript_ItemNoStatLoss[];
extern const u8 BattleScript_ItemNoStatLossSpicyExtract[];
extern const u8 BattleScript_ObliviousPreventsAttraction[];
extern const u8 BattleScript_FlinchPrevention[];
extern const u8 BattleScript_OwnTempoPrevents[];
@ -347,7 +343,6 @@ extern const u8 BattleScript_BattlerFormChange[];
extern const u8 BattleScript_BattlerFormChangeEnd2[];
extern const u8 BattleScript_BattlerFormChangeNoPopup[];
extern const u8 BattleScript_BattlerFormChangeDisguise[];
extern const u8 BattleScript_AttackerFormChangeWithString[];
extern const u8 BattleScript_TargetFormChange[];
extern const u8 BattleScript_AnticipationActivates[];
extern const u8 BattleScript_SlowStartEnds[];
@ -374,7 +369,6 @@ extern const u8 BattleScript_RaiseStatOnFaintingTarget[];
extern const u8 BattleScript_QuickClawActivation[];
extern const u8 BattleScript_QuickDrawActivation[];
extern const u8 BattleScript_CustapBerryActivation[];
extern const u8 BattleScript_MicleBerryActivateEnd2[];
extern const u8 BattleScript_MicleBerryActivate[];
extern const u8 BattleScript_JabocaRowapBerryActivates[];
extern const u8 BattleScript_NotAffectedAbilityPopUp[];
@ -500,7 +494,6 @@ extern const u8 BattleScript_AlreadyBurned[];
extern const u8 BattleScript_PrintAbilityMadeIneffective[];
extern const u8 BattleScript_ItDoesntAffectFoe[];
extern const u8 BattleScript_FirstTurnSwitchInEvents[];
extern const u8 BattleScript_FickleBeamDoubled[];
extern const u8 BattleScript_QuestionForfeitBattle[];
extern const u8 BattleScript_ForfeitBattleGaveMoney[];
extern const u8 BattleScript_AbilityPopUp[];
@ -511,6 +504,7 @@ extern const u8 BattleScript_SleepTalkAttackstring[];
extern const u8 BattleScript_NaturePowerAttackstring[];
extern const u8 BattleScript_PokemonCantUseTheMove[];
extern const u8 BattleScript_TwoTurnMoveCharging[];
extern const u8 BattleScript_SkyDropCharging[];
extern const u8 BattleScript_PowerHerbActivation[];
extern const u8 BattleScript_Explosion[];
extern const u8 BattleScript_ActivateSwitchInAbility[];
@ -520,6 +514,9 @@ extern const u8 BattleScript_BeatUpAttackMessage[];
extern const u8 BattleScript_MagnitudeMessage[];
extern const u8 BattleScript_FickleBeamMessage[];
extern const u8 BattleScript_BeforeSnoreMessage[];
extern const u8 BattleScript_SkyDropTargetTooHeavy[];
extern const u8 BattleScript_SkyDropFlyingType[];
extern const u8 BattleScript_SkyDropNoTarget[];
// zmoves
extern const u8 BattleScript_ZMoveActivateDamaging[];
@ -535,7 +532,6 @@ extern const u8 BattleScript_EffectRaiseStatAllies[];
extern const u8 BattleScript_EffectLowerStatFoes[];
extern const u8 BattleScript_EffectSetWeather[];
extern const u8 BattleScript_EffectSetTerrain[];
extern const u8 BattleScript_EffectStonesurge[];
extern const u8 BattleScript_EffectSteelsurge[];
extern const u8 BattleScript_DamageNonTypesStarts[];
extern const u8 BattleScript_DamageNonTypesContinues[];
@ -653,13 +649,8 @@ extern const u8 BattleScript_EffectMoonlight[];
extern const u8 BattleScript_EffectWeather[];
extern const u8 BattleScript_EffectBellyDrum[];
extern const u8 BattleScript_EffectPsychUp[];
extern const u8 BattleScript_EffectSkullBash[];
extern const u8 BattleScript_EffectFutureSight[];
extern const u8 BattleScript_EffectGust[];
extern const u8 BattleScript_EffectSolarBeam[];
extern const u8 BattleScript_EffectTeleport[];
extern const u8 BattleScript_EffectBeatUp[];
extern const u8 BattleScript_EffectSemiInvulnerable[];
extern const u8 BattleScript_EffectDefenseCurl[];
extern const u8 BattleScript_EffectSoftboiled[];
extern const u8 BattleScript_EffectStockpile[];
@ -689,7 +680,6 @@ extern const u8 BattleScript_EffectHitEscape[];
extern const u8 BattleScript_EffectMudSport[];
extern const u8 BattleScript_EffectTickle[];
extern const u8 BattleScript_EffectCosmicPower[];
extern const u8 BattleScript_EffectSkyUppercut[];
extern const u8 BattleScript_EffectBulkUp[];
extern const u8 BattleScript_EffectPlaceholder[];
extern const u8 BattleScript_EffectWaterSport[];
@ -790,8 +780,6 @@ extern const u8 BattleScript_EffectTarShot[];
extern const u8 BattleScript_EffectPoltergeist[];
extern const u8 BattleScript_EffectOctolock[];
extern const u8 BattleScript_EffectClangorousSoul[];
extern const u8 BattleScript_EffectSkyDrop[];
extern const u8 BattleScript_EffectMeteorBeam[];
extern const u8 BattleScript_EffectCourtChange[];
extern const u8 BattleScript_EffectExtremeEvoboost[];
extern const u8 BattleScript_EffectDarkVoid[];
@ -804,7 +792,6 @@ extern const u8 BattleScript_EffectCorrosiveGas[];
extern const u8 BattleScript_MoveEffectSaltCure[];
extern const u8 BattleScript_ChillyReceptionMessage[];
extern const u8 BattleScript_EffectWeatherAndSwitch[];
extern const u8 BattleScript_EffectBrickBreak[];
extern const u8 BattleScript_EffectDoodle[];
extern const u8 BattleScript_EffectFilletAway[];
extern const u8 BattleScript_EffectShedTail[];

View File

@ -1462,15 +1462,83 @@ static bool32 CanTwoTurnMoveFireThisTurn(struct BattleContext *ctx)
return TRUE;
}
static enum CancelerResult HandleSkyDropResult(struct BattleContext *ctx)
{
if (gBattleMons[ctx->battlerAtk].volatiles.multipleTurns) // Second turn
{
gBattleScripting.animTurn = 1;
gBattleScripting.animTargetsHit = 0;
gBattleMons[ctx->battlerAtk].volatiles.multipleTurns = FALSE;
gBattleMons[ctx->battlerAtk].volatiles.semiInvulnerable = STATE_NONE;
gBattleMons[ctx->battlerDef].volatiles.semiInvulnerable = STATE_NONE;
gBattleStruct->skyDropTargets[gBattlerTarget] = SKY_DROP_NO_TARGET;
// Sky Drop fails if target already fainted
if (gBattleStruct->skyDropTargets[ctx->battlerAtk] == SKY_DROP_NO_TARGET)
{
gBattlescriptCurrInstr = BattleScript_SkyDropNoTarget;
return CANCELER_RESULT_FAILURE;
}
gBattleStruct->skyDropTargets[ctx->battlerAtk] = SKY_DROP_NO_TARGET;
return CANCELER_RESULT_SUCCESS;
}
if (IsBattlerAlly(ctx->battlerAtk, ctx->battlerDef))
{
gBattlescriptCurrInstr = BattleScript_ButItFailed;
return CANCELER_RESULT_FAILURE;
}
else if (gBattleMons[ctx->battlerDef].volatiles.semiInvulnerable != STATE_NONE)
{
gBattlescriptCurrInstr = BattleScript_ButItFailed;
return CANCELER_RESULT_FAILURE;
}
else if (DoesSubstituteBlockMove(ctx->battlerAtk, ctx->battlerDef, ctx->move))
{
gBattlescriptCurrInstr = BattleScript_ButItFailed;
return CANCELER_RESULT_FAILURE;
}
else if (GetBattlerWeight(gBattlerTarget) >= 2000)
{
gBattlescriptCurrInstr = BattleScript_SkyDropTargetTooHeavy;
return CANCELER_RESULT_FAILURE;
}
// First turn
gBattleMons[ctx->battlerDef].volatiles.multipleTurns = 0;
gBattleMons[ctx->battlerDef].volatiles.uproarTurns = 0;
gBattleMons[ctx->battlerDef].volatiles.bideTurns = 0;
gBattleMons[ctx->battlerDef].volatiles.rolloutTimer = 0;
gBattleMons[ctx->battlerDef].volatiles.furyCutterCounter = 0;
if (gSideTimers[GetBattlerSide(ctx->battlerDef)].followmeTimer != 0 && gSideTimers[GetBattlerSide(ctx->battlerDef)].followmeTarget == ctx->battlerDef)
gSideTimers[GetBattlerSide(ctx->battlerDef)].followmeTimer = 0;
gBattleStruct->skyDropTargets[ctx->battlerAtk] = ctx->battlerDef;
gBattleStruct->skyDropTargets[ctx->battlerDef] = ctx->battlerAtk;
gLockedMoves[ctx->battlerAtk] = ctx->move;
gProtectStructs[ctx->battlerAtk].chargingTurn = TRUE;
gBattleMons[ctx->battlerAtk].volatiles.multipleTurns = TRUE;
gBattleMons[ctx->battlerAtk].volatiles.semiInvulnerable = STATE_ON_AIR;
gBattleMons[ctx->battlerDef].volatiles.semiInvulnerable = STATE_SKY_DROP;
gBattlescriptCurrInstr = BattleScript_SkyDropCharging;
return CANCELER_RESULT_BREAK;
}
static enum CancelerResult CancelerCharging(struct BattleContext *ctx)
{
if (!gBattleMoveEffects[GetMoveEffect(ctx->move)].twoTurnEffect
|| GetMoveEffect(ctx->move) == EFFECT_SKY_DROP)
if (!gBattleMoveEffects[GetMoveEffect(ctx->move)].twoTurnEffect)
return CANCELER_RESULT_SUCCESS;
enum CancelerResult result = CANCELER_RESULT_SUCCESS;
if (gBattleMons[ctx->battlerAtk].volatiles.multipleTurns) // Second turn
if (GetMoveEffect(ctx->move) == EFFECT_SKY_DROP)
{
result = HandleSkyDropResult(ctx);
}
else if (gBattleMons[ctx->battlerAtk].volatiles.multipleTurns) // Second turn
{
gBattleScripting.animTurn = 1;
gBattleScripting.animTargetsHit = 0;
@ -1677,6 +1745,14 @@ static enum CancelerResult CancelerTargetFailure(struct BattleContext *ctx)
BattleScriptCall(BattleScript_ItDoesntAffectFoe);
targetAvoidedAttack = TRUE;
}
else if (GetMoveEffect(ctx->move) == EFFECT_SKY_DROP
&& !gProtectStructs[ctx->battlerAtk].chargingTurn
&& IS_BATTLER_OF_TYPE(ctx->battlerDef, TYPE_FLYING))
{
gBattleStruct->moveResultFlags[ctx->battlerDef] = MOVE_RESULT_NO_EFFECT;
BattleScriptCall(BattleScript_SkyDropFlyingType);
targetAvoidedAttack = TRUE;
}
else
{
CalcTypeEffectivenessMultiplier(ctx);
@ -2264,7 +2340,7 @@ static enum MoveEndResult MoveEndAttackerVisible(void)
if (IsBattlerUnaffectedByMove(gBattlerTarget)
|| !IsSemiInvulnerable(gBattlerAttacker, CHECK_ALL)
|| gBattleStruct->unableToUseMove)
|| (gBattleStruct->unableToUseMove && gBattleMons[gBattlerAttacker].volatiles.semiInvulnerable != STATE_SKY_DROP))
{
BtlController_EmitSpriteInvisibility(gBattlerAttacker, B_COMM_TO_CONTROLLER, FALSE);
MarkBattlerForControllerExec(gBattlerAttacker);
@ -2281,8 +2357,7 @@ static enum MoveEndResult MoveEndTargetVisible(void)
{
enum MoveEndResult result = MOVEEND_RESULT_CONTINUE;
if (!gSpecialStatuses[gBattlerTarget].restoredBattlerSprite && gBattlerTarget < gBattlersCount
&& !IsSemiInvulnerable(gBattlerTarget, CHECK_ALL))
if (!gSpecialStatuses[gBattlerTarget].restoredBattlerSprite && !IsSemiInvulnerable(gBattlerTarget, CHECK_ALL))
{
BtlController_EmitSpriteInvisibility(gBattlerTarget, B_COMM_TO_CONTROLLER, FALSE);
MarkBattlerForControllerExec(gBattlerTarget);

View File

@ -12491,22 +12491,6 @@ void BS_TryTidyUp(void)
}
}
void BS_TryTwoTurnMovesPowerHerbFormChange(void)
{
NATIVE_ARGS();
if (TryBattleFormChange(gBattlerAttacker, FORM_CHANGE_BATTLE_HP_PERCENT_DURING_MOVE, GetBattlerAbility(gBattlerAttacker)))
{
// Doesn't need to set B_ANIM_FORM_CHANGE_INSTANT, as it was already handled on the first turn
gBattleScripting.battler = gBattlerAttacker;
gBattlescriptCurrInstr = BattleScript_TwoTurnMovesSecondTurnFormChange;
}
else
{
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
void BS_TryQuash(void)
{
NATIVE_ARGS(const u8 *failInstr);
@ -14557,62 +14541,6 @@ void BS_TryHealQuarterHealth(void)
gBattlescriptCurrInstr = cmd->nextInstr; // can heal
}
void BS_JumpIfUnder200(void)
{
NATIVE_ARGS(const u8 *jumpInstr);
// If the Pokemon is less than 200 kg, or weighing less than 441 lbs, then Sky Drop will work. Otherwise, it will fail.
if (GetBattlerWeight(gBattlerTarget) < 2000)
gBattlescriptCurrInstr = cmd->jumpInstr;
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_SetSkyDrop(void)
{
NATIVE_ARGS();
gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_SKY_DROP;
/* skyDropTargets holds the information of who is in a particular instance of Sky Drop.
This is needed in the case that multiple Pokemon use Sky Drop in the same turn or if
the target of a Sky Drop faints while in the air.*/
gBattleStruct->skyDropTargets[gBattlerAttacker] = gBattlerTarget;
gBattleStruct->skyDropTargets[gBattlerTarget] = gBattlerAttacker;
// End any multiturn effects caused by the target except VOLATILE_RAMPAGE_TURNS
gBattleMons[gBattlerTarget].volatiles.multipleTurns = 0;
gBattleMons[gBattlerTarget].volatiles.uproarTurns = 0;
gBattleMons[gBattlerTarget].volatiles.bideTurns = 0;
gBattleMons[gBattlerTarget].volatiles.rolloutTimer = 0;
gBattleMons[gBattlerTarget].volatiles.furyCutterCounter = 0;
// End any Follow Me/Rage Powder effects caused by the target
if (gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer != 0 && gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTarget == gBattlerTarget)
gSideTimers[GetBattlerSide(gBattlerTarget)].followmeTimer = 0;
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_ClearSkyDrop(void)
{
NATIVE_ARGS(const u8 *failInstr);
// Check to see if the initial target of this Sky Drop fainted before the 2nd turn of Sky Drop.
// If so, make the move fail. If not, clear all of the statuses and continue the move.
if (gBattleStruct->skyDropTargets[gBattlerAttacker] == SKY_DROP_NO_TARGET)
{
gBattlescriptCurrInstr = cmd->failInstr;
}
else
{
gBattleStruct->skyDropTargets[gBattlerAttacker] = SKY_DROP_NO_TARGET;
gBattleStruct->skyDropTargets[gBattlerTarget] = SKY_DROP_NO_TARGET;
gBattleMons[gBattlerTarget].volatiles.semiInvulnerable = STATE_NONE;
gBattlescriptCurrInstr = cmd->nextInstr;
}
// Confuse target if they were in the middle of Petal Dance/Outrage/Thrash when targeted.
if (gBattleMons[gBattlerTarget].volatiles.rampageTurns)
gBattleScripting.moveEffect = MOVE_EFFECT_CONFUSION;
}
void BS_SkyDropYawn(void)
{
NATIVE_ARGS();

View File

@ -1981,7 +1981,7 @@ const struct BattleMoveEffect gBattleMoveEffects[NUM_BATTLE_MOVE_EFFECTS] =
[EFFECT_SKY_DROP] =
{
.battleScript = BattleScript_EffectSkyDrop,
.battleScript = BattleScript_EffectHit,
.battleTvScore = 0, // TODO: Assign points
.twoTurnEffect = TRUE,
.semiInvulnerableEffect = TRUE,

View File

@ -1,6 +1,11 @@
#include "global.h"
#include "test/battle.h"
ASSUMPTIONS
{
ASSUME(GetMoveEffect(MOVE_ELECTRIFY) == EFFECT_ELECTRIFY);
}
SINGLE_BATTLE_TEST("Electrify makes the target's move Electric-type for the remainder of the turn (single move)")
{
GIVEN {

View File

@ -135,3 +135,76 @@ SINGLE_BATTLE_TEST("Sky Drop fails if the targe is in a semi-invulnerable state"
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, player);
}
}
DOUBLE_BATTLE_TEST("Sky Drop will be canceled if it is electrified and holding a target with Volt Absorb")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_LANTURN) { Ability(ABILITY_VOLT_ABSORB); }
OPPONENT(SPECIES_MACHAMP) { Ability(ABILITY_NO_GUARD); }
} WHEN {
TURN { MOVE(opponentRight, MOVE_CELEBRATE, target: playerLeft); MOVE(playerLeft, MOVE_SKY_DROP, target: opponentLeft); }
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); SKIP_TURN(playerLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponentRight);
ABILITY_POPUP(opponentLeft, ABILITY_VOLT_ABSORB);
NOT HP_BAR(opponentLeft);
}
}
SINGLE_BATTLE_TEST("Sky Drop fails if the target fainted while it was held on air")
{
GIVEN {
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET) { HP(1); Status1(STATUS1_BURN); }
OPPONENT(SPECIES_WYNAUT);
} WHEN {
TURN { MOVE(player, MOVE_SKY_DROP); SEND_OUT(opponent, 1); }
TURN { SKIP_TURN(player); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, player);
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, player);
}
}
DOUBLE_BATTLE_TEST("Sky Drop will be canceled if it is electrified and holding a target with Volt Absorb before checking if it is a flying Type")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_ELECTRIFY) == EFFECT_ELECTRIFY);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WATTREL) { Ability(ABILITY_VOLT_ABSORB); }
OPPONENT(SPECIES_MACHAMP) { Ability(ABILITY_NO_GUARD); }
} WHEN {
TURN { MOVE(opponentRight, MOVE_CELEBRATE, target: playerLeft); MOVE(playerLeft, MOVE_SKY_DROP, target: opponentLeft); }
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); SKIP_TURN(playerLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, playerLeft);
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponentRight);
NOT MESSAGE("It doesn't affect the opposing Wattrel…");
ABILITY_POPUP(opponentLeft, ABILITY_VOLT_ABSORB);
NOT HP_BAR(opponentLeft);
}
}
DOUBLE_BATTLE_TEST("Sky Drop does not trigger Volt Absorb on it's charge turn")
{
GIVEN {
ASSUME(GetMoveEffect(MOVE_ELECTRIFY) == EFFECT_ELECTRIFY);
PLAYER(SPECIES_WOBBUFFET);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_LANTURN) { Ability(ABILITY_VOLT_ABSORB); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
TURN { MOVE(opponentRight, MOVE_ELECTRIFY, target: playerLeft); MOVE(playerLeft, MOVE_SKY_DROP, target: opponentLeft); }
TURN { SKIP_TURN(playerLeft); }
} SCENE {
ANIMATION(ANIM_TYPE_MOVE, MOVE_ELECTRIFY, opponentRight);
ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, playerLeft);
NOT ABILITY_POPUP(opponentLeft, ABILITY_VOLT_ABSORB);
HP_BAR(opponentLeft); // Drop turn. Not affected by electrify anymore
}
}