Added Sky Drop

This commit is contained in:
W1serV1ser 2021-11-20 11:44:48 -08:00
parent 377c313771
commit c2f81cd5f5
13 changed files with 484 additions and 51 deletions

View File

@ -2055,3 +2055,25 @@
1:
.endm
@ Will jump to script pointer if the target weighs less than 200 kg, or 441 lbs.
.macro jumpifunder200 battler:req, ptr:req
various \battler, VARIOUS_JUMP_IF_UNDER_200
.4byte \ptr
.endm
@ Sets the sky drop status and does all other necessary operations
.macro setskydrop
various 0, VARIOUS_SET_SKY_DROP
.endm
@ Clears the sky drop status and does all other necessary operations.
@ If the target fainted in before this script is called, it goes to the given script.
.macro clearskydrop ptr:req
various 0, VARIOUS_CLEAR_SKY_DROP
.4byte \ptr
.endm
@ Accounts for if the target of Sky Drop was in confuse_lock when the attacker falls asleep due to Yawn.
.macro skydropyawn
various 0, VARIOUS_SKY_DROP_YAWN
.endm

View File

@ -403,6 +403,65 @@ gBattleScriptsForMoveEffects::
.4byte BattleScript_EffectOctolock @ EFFECT_OCTOLOCK
.4byte BattleScript_EffectClangorousSoul @ EFFECT_CLANGOROUS_SOUL
.4byte BattleScript_EffectHit @ EFFECT_BOLT_BEAK
.4byte BattleScript_EffectSkyDrop @ EFFECT_SKY_DROP
BattleScript_EffectSkyDrop:
jumpifstatus2 BS_ATTACKER, STATUS2_MULTIPLETURNS, BattleScript_SkyDropTurn2
attackcanceler
ppreduce
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
jumpifsubstituteblocks BattleScript_ButItFailed
jumpiftargetally BattleScript_ButItFailed
jumpifunder200 BS_TARGET, BattleScript_SkyDropWork
pause B_WAIT_TIME_SHORT
printstring STRINGID_TARGETTOOHEAVY
waitmessage B_WAIT_TIME_LONG
goto BattleScript_MoveEnd
BattleScript_SkyDropWork:
setskydrop
setbyte sTWOTURN_STRINGID, B_MSG_TURN1_SKY_DROP
setsemiinvulnerablebit
call BattleScriptFirstChargingTurnAfterAttackString
goto BattleScript_MoveEnd
BattleScript_SkyDropTurn2:
attackcanceler
setmoveeffect MOVE_EFFECT_CHARGING
setbyte sB_ANIM_TURN, 0x1
clearstatusfromeffect BS_ATTACKER
orword gHitMarker, HITMARKER_NO_PPDEDUCT
argumenttomoveeffect
clearsemiinvulnerablebit
attackstring
clearskydrop BattleScript_SkyDropChangedTarget
jumpiftype BS_TARGET, TYPE_FLYING, BattleScript_SkyDropFlyingType
goto BattleScript_HitFromCritCalc
BattleScript_SkyDropFlyingType:
makevisible BS_TARGET
printstring STRINGID_ITDOESNTAFFECT
waitmessage B_WAIT_TIME_LONG
makevisible BS_ATTACKER
jumpifstatus2 BS_TARGET, STATUS2_CONFUSION, BattleScript_SkyDropFlyingAlreadyConfused
jumpifstatus2 BS_TARGET, STATUS2_LOCK_CONFUSE, BattleScript_SkyDropFlyingConfuseLock
goto BattleScript_MoveEnd
BattleScript_SkyDropChangedTarget:
pause B_WAIT_TIME_SHORT
orhalfword gMoveResultFlags, MOVE_RESULT_FAILED
resultmessage
waitmessage B_WAIT_TIME_LONG
makevisible BS_ATTACKER
goto BattleScript_MoveEnd
BattleScript_SkyDropFlyingConfuseLock:
setmoveeffect MOVE_EFFECT_CONFUSION
seteffectprimary
BattleScript_SkyDropFlyingAlreadyConfused:
setmoveeffect MOVE_EFFECT_THRASH
clearstatusfromeffect BS_TARGET
jumpifstatus2 BS_TARGET, STATUS2_CONFUSION, BattleScript_MoveEnd
setbyte BS_ATTACKER, BS_TARGET
goto BattleScript_ThrashConfuses
BattleScript_EffectShellSideArm:
shellsidearmcheck
@ -3400,6 +3459,7 @@ BattleScriptFirstChargingTurn::
printstring STRINGID_EMPTYSTRING3
ppreduce
attackstring
BattleScriptFirstChargingTurnAfterAttackString:
pause B_WAIT_TIME_LONG
copybyte cMULTISTRING_CHOOSER, sTWOTURN_STRINGID
printfromtable gFirstTurnOfTwoStringIds
@ -7511,7 +7571,10 @@ BattleScript_YawnMakesAsleep::
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_EFFECT_BATTLER
waitstate
jumpifstatus3 BS_EFFECT_BATTLER, STATUS3_SKY_DROPPED, BattleScript_YawnEnd
makevisible BS_EFFECT_BATTLER
skydropyawn
BattleScript_YawnEnd:
end2
BattleScript_EmbargoEndTurn::

View File

@ -616,6 +616,7 @@ struct BattleStruct
u8 blunderPolicy:1; // should blunder policy activate
u8 ballSpriteIds[2]; // item gfx, window gfx
u8 stickyWebUser;
u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle.
};
#define GET_MOVE_TYPE(move, typeArg) \

View File

@ -170,6 +170,7 @@
#define STATUS3_AQUA_RING (1 << 28)
#define STATUS3_LASER_FOCUS (1 << 29)
#define STATUS3_POWER_TRICK (1 << 30)
#define STATUS3_SKY_DROPPED (1 << 31) // Target of Sky Drop
#define STATUS3_SEMI_INVULNERABLE (STATUS3_UNDERGROUND | STATUS3_ON_AIR | STATUS3_UNDERWATER | STATUS3_PHANTOM_FORCE)
#define STATUS4_ELECTRIFIED (1 << 0)
@ -359,7 +360,9 @@
#define MOVE_EFFECT_RECOIL_HP_25 0x46
#define MOVE_EFFECT_RELIC_SONG 0x47
#define MOVE_EFFECT_TRAP_BOTH 0x48
#define NUM_MOVE_EFFECTS 0x49
#define MOVE_EFFECT_SKY_DROP 0x49
#define NUM_MOVE_EFFECTS 0x50
#define MOVE_EFFECT_AFFECTS_USER 0x4000
#define MOVE_EFFECT_CERTAIN 0x8000

View File

@ -386,7 +386,8 @@
#define EFFECT_OCTOLOCK 380
#define EFFECT_CLANGOROUS_SOUL 381
#define EFFECT_BOLT_BEAK 382
#define EFFECT_SKY_DROP 383
#define NUM_BATTLE_MOVE_EFFECTS 383
#define NUM_BATTLE_MOVE_EFFECTS 384
#endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H

View File

@ -208,6 +208,10 @@
#define VARIOUS_SET_OCTOLOCK 135
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 136
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 137
#define VARIOUS_JUMP_IF_UNDER_200 138
#define VARIOUS_SET_SKY_DROP 139
#define VARIOUS_CLEAR_SKY_DROP 140
#define VARIOUS_SKY_DROP_YAWN 141
// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0
@ -265,18 +269,19 @@
#define MOVEEND_ITEM_EFFECTS_ALL 15
#define MOVEEND_KINGSROCK 16 // These item effects will occur each strike of a multi-hit move
#define MOVEEND_SUBSTITUTE 17
#define MOVEEND_UPDATE_LAST_MOVES 18
#define MOVEEND_MIRROR_MOVE 19
#define MOVEEND_NEXT_TARGET 20 // Everything up until here is handled for each strike of a multi-hit move
#define MOVEEND_EJECT_BUTTON 21
#define MOVEEND_RED_CARD 22
#define MOVEEND_EJECT_PACK 23
#define MOVEEND_LIFEORB_SHELLBELL 24 // Includes shell bell, throat spray, etc
#define MOVEEND_PICKPOCKET 25
#define MOVEEND_DANCER 26
#define MOVEEND_EMERGENCY_EXIT 27
#define MOVEEND_CLEAR_BITS 28
#define MOVEEND_COUNT 29
#define MOVEEND_SKY_DROP_CONFUSE 18
#define MOVEEND_UPDATE_LAST_MOVES 19
#define MOVEEND_MIRROR_MOVE 20
#define MOVEEND_NEXT_TARGET 21 // Everything up until here is handled for each strike of a multi-hit move
#define MOVEEND_EJECT_BUTTON 22
#define MOVEEND_RED_CARD 23
#define MOVEEND_EJECT_PACK 24
#define MOVEEND_LIFEORB_SHELLBELL 25 // Includes shell bell, throat spray, etc
#define MOVEEND_PICKPOCKET 26
#define MOVEEND_DANCER 27
#define MOVEEND_EMERGENCY_EXIT 28
#define MOVEEND_CLEAR_BITS 29
#define MOVEEND_COUNT 30
// switch cases
#define B_SWITCH_NORMAL 0

View File

@ -592,25 +592,27 @@
#define STRINGID_STRONGWINDSDISSIPATED 588
#define STRINGID_MYSTERIOUSAIRCURRENTBLOWSON 589
#define STRINGID_ATTACKWEAKENEDBSTRONGWINDS 590
#define STRINGID_STUFFCHEEKSCANTSELECT 592
#define STRINGID_PKMNREVERTEDTOPRIMAL 593
#define STRINGID_BUTPOKEMONCANTUSETHEMOVE 594
#define STRINGID_BUTHOOPACANTUSEIT 595
#define STRINGID_BROKETHROUGHPROTECTION 596
#define STRINGID_ABILITYALLOWSONLYMOVE 597
#define STRINGID_SWAPPEDABILITIES 598
#define STRINGID_PASTELVEILPROTECTED 599
#define STRINGID_PASTELVEILENTERS 600
#define STRINGID_BATTLERTYPECHANGEDTO 601
#define STRINGID_BOTHCANNOLONGERESCAPE 602
#define STRINGID_CANTESCAPEDUETOUSEDMOVE 603
#define STRINGID_PKMNBECAMEWEAKERTOFIRE 604
#define STRINGID_ABOUTTOUSEPOLTERGEIST 605
#define STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE 606
#define STRINGID_NEUTRALIZINGGASENTERS 607
#define STRINGID_NEUTRALIZINGGASOVER 608
#define STRINGID_STUFFCHEEKSCANTSELECT 591
#define STRINGID_PKMNREVERTEDTOPRIMAL 592
#define STRINGID_BUTPOKEMONCANTUSETHEMOVE 593
#define STRINGID_BUTHOOPACANTUSEIT 594
#define STRINGID_BROKETHROUGHPROTECTION 595
#define STRINGID_ABILITYALLOWSONLYMOVE 596
#define STRINGID_SWAPPEDABILITIES 597
#define STRINGID_PASTELVEILPROTECTED 598
#define STRINGID_PASTELVEILENTERS 599
#define STRINGID_BATTLERTYPECHANGEDTO 600
#define STRINGID_BOTHCANNOLONGERESCAPE 601
#define STRINGID_CANTESCAPEDUETOUSEDMOVE 602
#define STRINGID_PKMNBECAMEWEAKERTOFIRE 603
#define STRINGID_ABOUTTOUSEPOLTERGEIST 604
#define STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE 605
#define STRINGID_NEUTRALIZINGGASENTERS 606
#define STRINGID_NEUTRALIZINGGASOVER 607
#define STRINGID_TARGETTOOHEAVY 608
#define STRINGID_PKMNTOOKTARGETHIGH 609
#define BATTLESTRINGS_COUNT 609
#define BATTLESTRINGS_COUNT 610
// The below IDs are all indexes into battle message tables,
// used to determine which of a set of messages to print.
@ -661,6 +663,7 @@
#define B_MSG_TURN1_PHANTOM_FORCE 8
#define B_MSG_TURN1_GEOMANCY 9
#define B_MSG_TURN1_FREEZE_SHOCK 10
#define B_MSG_TURN1_SKY_DROP 11
// gMoveWeatherChangeStringIds
#define B_MSG_STARTED_RAIN 0

View File

@ -793,7 +793,9 @@ static bool8 ShouldUseItem(void)
u8 validMons = 0;
bool8 shouldUse = FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT)
// If teaming up with player and Pokemon is on the right, or Pokemon is currently held by Sky Drop
if ((gBattleTypeFlags & BATTLE_TYPE_INGAME_PARTNER && GetBattlerPosition(gActiveBattler) == B_POSITION_PLAYER_RIGHT)
|| gStatuses3[gActiveBattler] & STATUS3_SKY_DROPPED)
return FALSE;
if (gStatuses3[gActiveBattler] & STATUS3_EMBARGO)

View File

@ -2945,6 +2945,12 @@ static void BattleStartClearSetData(void)
}
gSwapDamageCategory = FALSE; // Photon Geyser, Shell Side Arm, Light That Burns the Sky
// Clear skyDropTargets data
for (i = 0; i < 4; i++)
{
gBattleStruct->skyDropTargets[i] = 0xFF;
}
}
void SwitchInClearSetData(void)
@ -3081,6 +3087,56 @@ void FaintClearSetData(void)
gBattleMons[i].status2 &= ~(STATUS2_INFATUATED_WITH(gActiveBattler));
if ((gBattleMons[i].status2 & STATUS2_WRAPPED) && *(gBattleStruct->wrappedBy + i) == gActiveBattler)
gBattleMons[i].status2 &= ~(STATUS2_WRAPPED);
// If the fainted mon was holding another Pokemon in Sky Drop, release the mon and clear Sky Drop data
if (gActiveBattler == gBattleStruct->skyDropTargets[0] && i == gBattleStruct->skyDropTargets[1])
{
gBattleStruct->skyDropTargets[0] = 0xFF;
gBattleStruct->skyDropTargets[1] = 0xFF;
gStatuses3[i] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
gSprites[gBattlerSpriteIds[i]].invisible = FALSE;
// If the target was sky dropped in the middle of using Outrage/Petal Dance/Thrash,
// confuse them upon release and print "confused via fatigue" message and animation.
if (gBattleMons[i].status2 & STATUS2_LOCK_CONFUSE)
{
gBattleMons[i].status2 &= ~(STATUS2_LOCK_CONFUSE);
// If the released mon can be confused, do so.
// Don't use CanBeConfused here, since it can cause issues in edge cases.
if (!(GetBattlerAbility(i) == ABILITY_OWN_TEMPO
|| gBattleMons[i].status2 & STATUS2_CONFUSION
|| IsBattlerTerrainAffected(i, STATUS_FIELD_MISTY_TERRAIN)))
{
gBattleMons[i].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
gBattlerAttacker = i;
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 2;
}
}
}
else if (gActiveBattler == gBattleStruct->skyDropTargets[2] && i == gBattleStruct->skyDropTargets[3])
{
gBattleStruct->skyDropTargets[2] = 0xFF;
gBattleStruct->skyDropTargets[3] = 0xFF;
gStatuses3[i] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
gSprites[gBattlerSpriteIds[i]].invisible = FALSE;
if (gBattleMons[i].status2 & STATUS2_LOCK_CONFUSE)
{
gBattleMons[i].status2 &= ~(STATUS2_LOCK_CONFUSE);
gEffectBattler = i;
if (!(GetBattlerAbility(i) == ABILITY_OWN_TEMPO
|| gBattleMons[i].status2 & STATUS2_CONFUSION
|| IsBattlerTerrainAffected(i, STATUS_FIELD_MISTY_TERRAIN)))
{
gBattleMons[i].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
gBattlerAttacker = i;
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 2;
}
}
}
}
gActionSelectionCursor[gActiveBattler] = 0;
@ -3160,6 +3216,12 @@ void FaintClearSetData(void)
UndoFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FALSE);
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]);
// If the fainted Pokemon was being held by Sky Drop, clear their Sky Drop data.
if (gActiveBattler == gBattleStruct->skyDropTargets[1])
gBattleStruct->skyDropTargets[1] = 0xFF;
else if (gActiveBattler == gBattleStruct->skyDropTargets[3])
gBattleStruct->skyDropTargets[3] = 0xFF;
}
static void DoBattleIntro(void)
@ -3897,10 +3959,12 @@ static void HandleTurnActionSelectionState(void)
}
break;
case B_ACTION_USE_ITEM:
if (gBattleTypeFlags & (BATTLE_TYPE_LINK
if ((gBattleTypeFlags & (BATTLE_TYPE_LINK
| BATTLE_TYPE_FRONTIER_NO_PYRAMID
| BATTLE_TYPE_EREADER_TRAINER
| BATTLE_TYPE_RECORDED_LINK))
// Or if currently held by Sky Drop
|| gStatuses3[gActiveBattler] & STATUS3_SKY_DROPPED)
{
RecordedBattle_ClearBattlerAction(gActiveBattler, 1);
gSelectionBattleScripts[gActiveBattler] = BattleScript_ActionSelectionItemsCantBeUsed;

View File

@ -431,6 +431,8 @@ static const u8 sText_ExclamationMark4[] = _("!");
static const u8 sText_ExclamationMark5[] = _("!");
static const u8 sText_Accuracy[] = _("accuracy");
static const u8 sText_Evasiveness[] = _("evasiveness");
static const u8 sText_PkmnTookTargetHigh[] = _("{B_ATK_NAME_WITH_PREFIX} took {B_DEF_NAME_WITH_PREFIX}\ninto the air!");
static const u8 sText_TargetTooHeavy[] = _("But the target\nwas too heavy!");
const u8 * const gStatNamesTable[NUM_BATTLE_STATS] =
{
@ -1334,6 +1336,8 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_PKMNBECAMEWEAKERTOFIRE - 12] = sText_PkmnBecameWeakerToFire,
[STRINGID_ABOUTTOUSEPOLTERGEIST - 12] = sText_PkmnAboutToBeAttackedByItsItem,
[STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE - 12] = sText_CantEscapeBecauseOfCurrentMove,
[STRINGID_PKMNTOOKTARGETHIGH - 12] = sText_PkmnTookTargetHigh,
[STRINGID_TARGETTOOHEAVY - 12] = sText_TargetTooHeavy,
};
const u16 gMentalHerbCureStringIds[] =
@ -1548,6 +1552,7 @@ const u16 gFirstTurnOfTwoStringIds[] =
[B_MSG_TURN1_PHANTOM_FORCE] = STRINGID_VANISHEDINSTANTLY,
[B_MSG_TURN1_GEOMANCY] = STRINGID_PKNMABSORBINGPOWER,
[B_MSG_TURN1_FREEZE_SHOCK] = STRINGID_CLOAKEDINAFREEZINGLIGHT,
[B_MSG_TURN1_SKY_DROP] = STRINGID_PKMNTOOKTARGETHIGH,
};
// Index copied from move's index in sTrappingMoves

View File

@ -1089,7 +1089,7 @@ static const u16 sMoveEffectsForbiddenToInstruct[] =
EFFECT_SEMI_INVULNERABLE,
//EFFECT_SHELL_TRAP,
EFFECT_SKETCH,
//EFFECT_SKY_DROP,
EFFECT_SKY_DROP,
EFFECT_SKULL_BASH,
EFFECT_SLEEP_TALK,
EFFECT_SOLARBEAM,
@ -1609,13 +1609,15 @@ static bool32 AccuracyCalcHelper(u16 move)
JumpIfMoveFailed(7, move);
return TRUE;
}
else if (GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD)
// If the attacker has the ability No Guard and they aren't targeting a Pokemon involved in a Sky Drop with the move Sky Drop, move hits.
else if (GetBattlerAbility(gBattlerAttacker) == ABILITY_NO_GUARD && (move != MOVE_SKY_DROP || (gBattlerTarget != gBattleStruct->skyDropTargets[0] && gBattlerTarget != gBattleStruct->skyDropTargets[1] && gBattlerTarget != gBattleStruct->skyDropTargets[2] && gBattlerTarget != gBattleStruct->skyDropTargets[3])))
{
if (!JumpIfMoveFailed(7, move))
RecordAbilityBattle(gBattlerAttacker, ABILITY_NO_GUARD);
return TRUE;
}
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_NO_GUARD)
// If the target has the ability No Guard and they aren't involved in a Sky Drop or the current move isn't Sky Drop, move hits.
else if (GetBattlerAbility(gBattlerTarget) == ABILITY_NO_GUARD && (move != MOVE_SKY_DROP || (gBattlerTarget != gBattleStruct->skyDropTargets[0] && gBattlerTarget != gBattleStruct->skyDropTargets[1] && gBattlerTarget != gBattleStruct->skyDropTargets[2] && gBattlerTarget != gBattleStruct->skyDropTargets[3])))
{
if (!JumpIfMoveFailed(7, move))
RecordAbilityBattle(gBattlerTarget, ABILITY_NO_GUARD);
@ -1623,8 +1625,7 @@ static bool32 AccuracyCalcHelper(u16 move)
}
if ((gStatuses3[gBattlerTarget] & STATUS3_PHANTOM_FORCE)
|| (!(gBattleMoves[move].flags & FLAG_DMG_IN_AIR) && gStatuses3[gBattlerTarget] & STATUS3_ON_AIR)
|| (!(gBattleMoves[move].flags & FLAG_DMG_2X_IN_AIR) && gStatuses3[gBattlerTarget] & STATUS3_ON_AIR)
|| (!(gBattleMoves[move].flags & FLAG_DMG_IN_AIR || gBattleMoves[move].flags & FLAG_DMG_2X_IN_AIR) && gStatuses3[gBattlerTarget] & STATUS3_ON_AIR)
|| (!(gBattleMoves[move].flags & FLAG_DMG_UNDERGROUND) && gStatuses3[gBattlerTarget] & STATUS3_UNDERGROUND)
|| (!(gBattleMoves[move].flags & FLAG_DMG_UNDERWATER) && gStatuses3[gBattlerTarget] & STATUS3_UNDERWATER))
{
@ -2930,9 +2931,20 @@ void SetMoveEffect(bool32 primary, u32 certain)
{
gBattleMons[gEffectBattler].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); // 2-5 turns
// If the confusion is activating due to being released from Sky Drop, go to "confused due to fatigue" script.
// Otherwise, do normal confusion script.
if(gCurrentMove == MOVE_SKY_DROP)
{
gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE);
gBattlerAttacker = gEffectBattler;
gBattlescriptCurrInstr = BattleScript_ThrashConfuses;
}
else
{
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect];
}
}
break;
case MOVE_EFFECT_FLINCH:
if (GetBattlerAbility(gEffectBattler) == ABILITY_INNER_FOCUS)
@ -5141,6 +5153,28 @@ static void Cmd_moveend(void)
}
gBattleScripting.moveendState++;
break;
case MOVEEND_SKY_DROP_CONFUSE: // If a Pokemon was released from Sky Drop and was in LOCK_CONFUSE, go to "confused due to fatigue scripts and clear Sky Drop data.
for (i = 0; i < gBattlersCount; i++)
{
if (gBattleStruct->skyDropTargets[0] == 0xFE - i)
{
gBattlerAttacker = gBattleStruct->skyDropTargets[1];
gBattlescriptCurrInstr = BattleScript_ThrashConfuses;
gBattleStruct->skyDropTargets[0] = 0xFF;
gBattleStruct->skyDropTargets[1] = 0xFF;
return;
}
else if (gBattleStruct->skyDropTargets[2] == 0xFE - i)
{
gBattlerAttacker = gBattleStruct->skyDropTargets[3];
gBattlescriptCurrInstr = BattleScript_ThrashConfuses;
gBattleStruct->skyDropTargets[2] = 0xFF;
gBattleStruct->skyDropTargets[3] = 0xFF;
return;
}
}
gBattleScripting.moveendState++;
break;
case MOVEEND_UPDATE_LAST_MOVES:
if (gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE))
gBattleStruct->lastMoveFailed |= gBitTable[gBattlerAttacker];
@ -7680,7 +7714,8 @@ static void Cmd_various(void)
}
return;
case VARIOUS_GRAVITY_ON_AIRBORNE_MONS:
if (gStatuses3[gActiveBattler] & STATUS3_ON_AIR)
// Cancel all multiturn moves of IN_AIR Pokemon except those being targeted by Sky Drop.
if (gStatuses3[gActiveBattler] & STATUS3_ON_AIR && !(gActiveBattler == gBattleStruct->skyDropTargets[1] || gActiveBattler == gBattleStruct->skyDropTargets[3]))
CancelMultiTurnMoves(gActiveBattler);
gStatuses3[gActiveBattler] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR);
@ -8892,7 +8927,7 @@ static void Cmd_various(void)
MarkBattlerForControllerExec(gActiveBattler);
}
if (gBattleMons[gActiveBattler].pp[i] == 0)
if (gBattleMons[gActiveBattler].pp[i] == 0 && !(gActiveBattler == gBattleStruct->skyDropTargets[0] || gActiveBattler == gBattleStruct->skyDropTargets[2]))
CancelMultiTurnMoves(gActiveBattler);
gBattlescriptCurrInstr += 7; // continue
@ -8959,6 +8994,101 @@ static void Cmd_various(void)
gFieldStatuses &= ~STATUS_FIELD_TERRAIN_ANY; // remove the terrain
TryToRevertMimicry(); // restore the types of Pokémon with Mimicry
break;
case VARIOUS_JUMP_IF_UNDER_200:
// If the Pokemon is less than 200 kg, or weighing less than 441 lbs, then Sky Drop will work. Otherwise, it will fail.
if (GetPokedexHeightWeight(SpeciesToNationalPokedexNum(gBattleMons[gBattlerTarget].species), 1) < 441)
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
else
gBattlescriptCurrInstr += 7;
return;
case VARIOUS_SET_SKY_DROP:
gStatuses3[gBattlerTarget] |= (STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
/* skyDropTargets holds the information of who is the attacker and the target 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.*/
if (gBattleStruct->skyDropTargets[0] == 0xFF)
{
gBattleStruct->skyDropTargets[0] = gBattlerAttacker;
gBattleStruct->skyDropTargets[1] = gBattlerTarget;
}
else
{
gBattleStruct->skyDropTargets[2] = gBattlerAttacker;
gBattleStruct->skyDropTargets[3] = gBattlerTarget;
}
// End any multiturn effects caused by the target
gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_MULTIPLETURNS);
gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_UPROAR);
gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_BIDE);
gDisableStructs[gBattlerTarget].rolloutTimer = 0;
gDisableStructs[gBattlerTarget].furyCutterCounter = 0;
break;
case VARIOUS_CLEAR_SKY_DROP:
if (gBattleStruct->skyDropTargets[0] == gBattlerAttacker)
{
// 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[1] == 0xFF)
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
else
{
gStatuses3[gBattlerTarget] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
gBattlescriptCurrInstr += 7;
}
// Clear skyDropTargets data
gBattleStruct->skyDropTargets[0] = 0xFF;
gBattleStruct->skyDropTargets[1] = 0xFF;
}
else
{
if (gBattleStruct->skyDropTargets[3] == 0xFF)
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
else
{
gStatuses3[gBattlerTarget] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
gBattlescriptCurrInstr += 7;
}
gBattleStruct->skyDropTargets[2] = 0xFF;
gBattleStruct->skyDropTargets[3] = 0xFF;
}
// Confuse target if they were in the middle of Petal Dance/Outrage/Thrash when targeted.
if (gBattleMons[gBattlerTarget].status2 & STATUS2_LOCK_CONFUSE)
gBattleScripting.moveEffect = (MOVE_EFFECT_CONFUSION | MOVE_EFFECT_CERTAIN);
return;
case VARIOUS_SKY_DROP_YAWN: // If the mon that's sleeping due to Yawn was holding a Pokemon in Sky Drop, release the target and clear Sky Drop data.
if (gEffectBattler == gBattleStruct->skyDropTargets[0])
{
gEffectBattler = gBattleStruct->skyDropTargets[1];
gBattleStruct->skyDropTargets[0] = 0xFF;
gBattleStruct->skyDropTargets[1] = 0xFF;
gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE);
if (CanBeConfused(gEffectBattler))
{
gBattlerAttacker = gEffectBattler;
gBattleMons[gBattlerTarget].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
gBattlescriptCurrInstr = BattleScript_ThrashConfuses;
return;
}
}
else if (gEffectBattler == gBattleStruct->skyDropTargets[2])
{
gEffectBattler = gBattleStruct->skyDropTargets[3];
gBattleStruct->skyDropTargets[2] = 0xFF;
gBattleStruct->skyDropTargets[3] = 0xFF;
gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE);
if (CanBeConfused(gEffectBattler))
{
gBattlerAttacker = gEffectBattler;
gBattleMons[gBattlerTarget].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
gBattlescriptCurrInstr = BattleScript_ThrashConfuses;
return;
}
}
break;
case VARIOUS_JUMP_IF_PRANKSTER_BLOCKED:
if (BlocksPrankster(gCurrentMove, gBattlerAttacker, gActiveBattler, TRUE))
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
@ -11351,7 +11481,8 @@ static void Cmd_tryspiteppreduce(void)
gBattlescriptCurrInstr += 5;
if (gBattleMons[gBattlerTarget].pp[i] == 0)
// Don't cut off Sky Drop if pp is brought to zero.
if (gBattleMons[gBattlerTarget].pp[i] == 0 && !(gBattlerTarget == gBattleStruct->skyDropTargets[0] || gBattlerTarget == gBattleStruct->skyDropTargets[2]))
CancelMultiTurnMoves(gBattlerTarget);
}
else
@ -11997,6 +12128,7 @@ static void Cmd_setsemiinvulnerablebit(void)
{
case MOVE_FLY:
case MOVE_BOUNCE:
case MOVE_SKY_DROP:
gStatuses3[gBattlerAttacker] |= STATUS3_ON_AIR;
break;
case MOVE_DIG:

View File

@ -224,6 +224,7 @@ bool32 IsAffectedByFollowMe(u32 battlerAtk, u32 defSide, u32 move)
if (gSideTimers[defSide].followmeTimer == 0
|| gBattleMons[gSideTimers[defSide].followmeTarget].hp == 0
|| gBattleMoves[move].effect == EFFECT_SNIPE_SHOT
|| gBattleMoves[move].effect == EFFECT_SKY_DROP
|| ability == ABILITY_PROPELLER_TAIL || ability == ABILITY_STALWART)
return FALSE;
@ -1420,13 +1421,124 @@ void MarkBattlerReceivedLinkData(u8 battlerId)
void CancelMultiTurnMoves(u8 battler)
{
u8 i;
gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS);
gBattleMons[battler].status2 &= ~(STATUS2_LOCK_CONFUSE);
gBattleMons[battler].status2 &= ~(STATUS2_UPROAR);
gBattleMons[battler].status2 &= ~(STATUS2_BIDE);
// Don't clear battler's semi-invulnerable bits if they are held by Sky Drop.
if (gBattleStruct->skyDropTargets[1] != battler && gBattleStruct->skyDropTargets[3] != battler)
gStatuses3[battler] &= ~(STATUS3_SEMI_INVULNERABLE);
// Check to see if this Pokemon was in the middle of using Sky Drop. If so, release the target.
if (gBattleStruct->skyDropTargets[0] == battler)
{
// Sets skyDropTargets[1] to be the battler id for the target
for(i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if(gBattleStruct->skyDropTargets[1] == i)
{
// Clears sky dropped and on_air statuses
gStatuses3[i] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
// Makes both attacker and target's sprites visible
gSprites[gBattlerSpriteIds[battler]].invisible = FALSE;
gSprites[gBattlerSpriteIds[i]].invisible = FALSE;
// If target was sky dropped in the middle of Outrage/Thrash/Petal Dance,
// confuse them upon release and display "confused by fatigue" message & animation.
// Don't do this if this CancelMultiTurnMoves is caused by falling asleep via Yawn.
if (gBattleMons[i].status2 & STATUS2_LOCK_CONFUSE && gBattleStruct->turnEffectsTracker != 24)
{
gBattleMons[i].status2 &= ~(STATUS2_LOCK_CONFUSE);
// If the target can be confused, confuse them.
// Don't use CanBeConfused, can cause issues in edge cases.
if (!(GetBattlerAbility(i) == ABILITY_OWN_TEMPO
|| gBattleMons[i].status2 & STATUS2_CONFUSION
|| IsBattlerTerrainAffected(i, STATUS_FIELD_MISTY_TERRAIN)))
{
gBattleMons[i].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
// If this CancelMultiTurnMoves is occuring due to attackcanceller or VARIOUS_GRAVITY_ON_AIRBORNE_MONS
if (gBattlescriptCurrInstr[0] == 0x0 || (gBattlescriptCurrInstr[0] == 0x76 && gBattlescriptCurrInstr[2] == 76))
gBattleStruct->skyDropTargets[0] = 0xFE - battler;
// If this CancelMultiTurnMoves is occuring due to cancelmultiturnmoves script
else if (gBattlescriptCurrInstr[0] == 0x76 && gBattlescriptCurrInstr[2] == 0)
{
gBattlerAttacker = i;
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 3;
}
// If this CancelMultiTurnMoves is occuring due to receiving Sleep/Freeze status
else if (gBattleScripting.moveEffect <= PRIMARY_STATUS_MOVE_EFFECT)
{
gBattlerAttacker = i;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 1;
}
}
}
break;
}
}
// Clear skyDropTargets data, unless this CancelMultiTurnMoves is caused by Yawn, attackcanceler, or VARIOUS_GRAVITY_ON_AIRBORNE_MONS
if (!(gBattleMons[gBattleStruct->skyDropTargets[1]].status2 & STATUS2_LOCK_CONFUSE) && gBattleStruct->skyDropTargets[0] < 4)
{
gBattleStruct->skyDropTargets[0] = 0xFF;
gBattleStruct->skyDropTargets[1] = 0xFF;
}
}
else if (gBattleStruct->skyDropTargets[2] == battler)
{
for(i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if(gBattleStruct->skyDropTargets[3] == i)
{
gStatuses3[i] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
gSprites[gBattlerSpriteIds[battler]].invisible = FALSE;
gSprites[gBattlerSpriteIds[i]].invisible = FALSE;
if (gBattleMons[i].status2 & STATUS2_LOCK_CONFUSE && gBattleStruct->turnEffectsTracker != 24)
{
gBattleMons[i].status2 &= ~(STATUS2_LOCK_CONFUSE);
if (!(GetBattlerAbility(i) == ABILITY_OWN_TEMPO
|| gBattleMons[i].status2 & STATUS2_CONFUSION
|| IsBattlerTerrainAffected(i, STATUS_FIELD_MISTY_TERRAIN)))
{
gBattleMons[i].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
if (gBattlescriptCurrInstr[0] == 0x0 || (gBattlescriptCurrInstr[0] == 0x76 && gBattlescriptCurrInstr[2] == 76))
gBattleStruct->skyDropTargets[2] = 0xFE - battler;
else if (gBattlescriptCurrInstr[0] == 0x76 && gBattlescriptCurrInstr[2] == 0)
{
gBattlerAttacker = i;
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 3;
}
else if (gBattleScripting.moveEffect <= PRIMARY_STATUS_MOVE_EFFECT)
{
gBattlerAttacker = i;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 1;
}
}
}
break;
}
}
if (!(gBattleMons[gBattleStruct->skyDropTargets[3]].status2 & STATUS2_LOCK_CONFUSE) && gBattleStruct->skyDropTargets[2] < 4)
{
gBattleStruct->skyDropTargets[2] = 0xFF;
gBattleStruct->skyDropTargets[3] = 0xFF;
}
}
gDisableStructs[battler].rolloutTimer = 0;
gDisableStructs[battler].furyCutterCounter = 0;
}
@ -2771,7 +2883,8 @@ u8 DoBattlerEndTurnEffects(void)
gBattleStruct->turnEffectsTracker++;
break;
case ENDTURN_THRASH: // thrash
if (gBattleMons[gActiveBattler].status2 & STATUS2_LOCK_CONFUSE)
// Don't decrement STATUS2_LOCK_CONFUSE if the target is held by Sky Drop
if (gBattleMons[gActiveBattler].status2 & STATUS2_LOCK_CONFUSE && !(gStatuses3[gActiveBattler] & STATUS3_SKY_DROPPED))
{
gBattleMons[gActiveBattler].status2 -= STATUS2_LOCK_CONFUSE_TURN(1);
if (WasUnableToUseMove(gActiveBattler))
@ -3211,6 +3324,7 @@ void TryClearRageAndFuryCutter(void)
enum
{
CANCELLER_FLAGS,
CANCELLER_SKY_DROP,
CANCELLER_ASLEEP,
CANCELLER_FROZEN,
CANCELLER_TRUANT,
@ -3247,6 +3361,16 @@ u8 AtkCanceller_UnableToUseMove(void)
gStatuses3[gBattlerAttacker] &= ~(STATUS3_GRUDGE);
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_SKY_DROP:
// If Pokemon is being held in Sky Drop
if (gStatuses3[gBattlerAttacker] & STATUS3_SKY_DROPPED)
{
gBattlescriptCurrInstr = BattleScript_MoveEnd;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
effect = 1;
}
gBattleStruct->atkCancellerTracker++;
break;
case CANCELLER_ASLEEP: // check being asleep
if (gBattleMons[gBattlerAttacker].status1 & STATUS1_SLEEP)
{
@ -3438,7 +3562,7 @@ u8 AtkCanceller_UnableToUseMove(void)
if ((gBattleMons[gBattlerAttacker].status1 & STATUS1_PARALYSIS) && (Random() % 4) == 0)
{
gProtectStructs[gBattlerAttacker].prlzImmobility = TRUE;
// This is removed in Emerald for some reason
// This is removed in Emerald because it is called in BattleScript_MoveUsedIsParalyzed.
//CancelMultiTurnMoves(gBattlerAttacker);
gBattlescriptCurrInstr = BattleScript_MoveUsedIsParalyzed;
gHitMarker |= HITMARKER_UNABLE_TO_USE_MOVE;
@ -4886,7 +5010,9 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u16 ability, u8 special, u16 move
&& !(TestSheerForceFlag(gBattlerAttacker, gCurrentMove))
&& (CanBattlerSwitch(battler) || !(gBattleTypeFlags & BATTLE_TYPE_TRAINER))
&& !(gBattleTypeFlags & BATTLE_TYPE_ARENA)
&& CountUsablePartyMons(battler) > 0)
&& CountUsablePartyMons(battler) > 0
// Not currently held by Sky Drop
&& !(gStatuses3[battler] & STATUS3_SKY_DROPPED))
{
gBattleResources->flags->flags[battler] |= RESOURCE_FLAG_EMERGENCY_EXIT;
effect++;
@ -5748,6 +5874,8 @@ bool32 CanBattlerEscape(u32 battlerId) // no ability check
return FALSE;
else if (gFieldStatuses & STATUS_FIELD_FAIRY_LOCK)
return FALSE;
else if (gStatuses3[battlerId] & STATUS3_SKY_DROPPED)
return FALSE;
else
return TRUE;
}
@ -9129,6 +9257,10 @@ bool32 CanMegaEvolve(u8 battlerId)
return FALSE;
}
// Check if mon is currently held by Sky Drop
if (gStatuses3[battlerId] & STATUS3_SKY_DROPPED)
return FALSE;
// Gets mon data.
if (GetBattlerSide(battlerId) == B_SIDE_OPPONENT)
mon = &gEnemyParty[gBattlerPartyIndexes[battlerId]];

View File

@ -8009,7 +8009,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] =
[MOVE_SKY_DROP] =
{
.effect = EFFECT_PLACEHOLDER, // Needs a custom move effect
.effect = EFFECT_SKY_DROP,
.power = 60,
.type = TYPE_FLYING,
.accuracy = 100,