Merge pull request #1923 from WiserVisor/battle_engine

Added Sky Drop to Battle Engine
This commit is contained in:
Eduardo Quezada D'Ottone 2022-01-07 18:14:40 -03:00 committed by GitHub
commit 97baedbd5e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
13 changed files with 398 additions and 54 deletions

View File

@ -2061,3 +2061,26 @@
jumpifsideaffecting BS_TARGET, SIDE_STATUS_SAFEGUARD, \jumpptr
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
@ -7528,7 +7588,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

@ -606,6 +606,7 @@ struct BattleStruct
u8 ballSpriteIds[2]; // item gfx, window gfx
u8 stickyWebUser;
u8 appearedInBattle; // Bitfield to track which Pokemon appeared in battle. Used for Burmy's form change
u8 skyDropTargets[MAX_BATTLERS_COUNT]; // For Sky Drop, to account for if multiple Pokemon use Sky Drop in a double battle.
};
#define F_DYNAMIC_TYPE_1 (1 << 6)

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)
@ -361,7 +362,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

@ -225,6 +225,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
@ -282,18 +286,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

@ -795,7 +795,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

@ -2926,6 +2926,7 @@ static void BattleStartClearSetData(void)
gBattleStruct->lastTakenMoveFrom[i][2] = 0;
gBattleStruct->lastTakenMoveFrom[i][3] = 0;
gBattleStruct->AI_monToSwitchIntoId[i] = PARTY_SIZE;
gBattleStruct->skyDropTargets[i] = 0xFF;
}
gLastUsedMove = 0;
@ -3215,6 +3216,45 @@ void FaintClearSetData(void)
UndoFormChange(gBattlerPartyIndexes[gActiveBattler], GET_BATTLER_SIDE(gActiveBattler), FALSE);
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
UndoMegaEvolution(gBattlerPartyIndexes[gActiveBattler]);
// If the fainted mon was involved in a Sky Drop
if (gBattleStruct->skyDropTargets[gActiveBattler] != 0xFF)
{
// Get battler id of the other Pokemon involved in this Sky Drop
u8 otherSkyDropper = gBattleStruct->skyDropTargets[gActiveBattler];
// Clear Sky Drop data
gBattleStruct->skyDropTargets[gActiveBattler] = 0xFF;
gBattleStruct->skyDropTargets[otherSkyDropper] = 0xFF;
// If the other Pokemon involved in this Sky Drop was the target, not the attacker
if (gStatuses3[otherSkyDropper] & STATUS3_SKY_DROPPED)
{
// Release the target and take them out of the semi-invulnerable state
gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
// Make the target's sprite visible
gSprites[gBattlerSpriteIds[otherSkyDropper]].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[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE)
{
gBattleMons[otherSkyDropper].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(otherSkyDropper) == ABILITY_OWN_TEMPO
|| gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION
|| IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN)))
{
gBattleMons[otherSkyDropper].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
gBattlerAttacker = otherSkyDropper;
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 2;
}
}
}
}
}
static void DoBattleIntro(void)
@ -3953,10 +3993,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

@ -427,6 +427,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] =
{
@ -1330,6 +1332,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[] =
@ -1544,6 +1548,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

@ -1096,7 +1096,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_SOLAR_BEAM,
@ -1617,13 +1617,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 || gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF))
{
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 || gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF))
{
if (!JumpIfMoveFailed(7, move))
RecordAbilityBattle(gBattlerTarget, ABILITY_NO_GUARD);
@ -1631,8 +1633,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 | 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))
{
@ -2939,9 +2940,20 @@ void SetMoveEffect(bool32 primary, u32 certain)
else
{
gBattleMons[gEffectBattler].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2); // 2-5 turns
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = sMoveEffectBS_Ptrs[gBattleScripting.moveEffect];
// 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:
@ -5198,6 +5210,33 @@ 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[i] == 0xFE)
{
u8 targetId;
// Find the battler id of the Pokemon that was held by Sky Drop
for (targetId = 0; targetId < gBattlersCount; targetId++)
{
if (gBattleStruct->skyDropTargets[targetId] == i)
break;
}
// Set gBattlerAttacker to the battler id of the target
gBattlerAttacker = targetId;
// Jump to "confused due to fatigue" script
gBattlescriptCurrInstr = BattleScript_ThrashConfuses;
// Clear skyDropTargets data
gBattleStruct->skyDropTargets[i] = 0xFF;
gBattleStruct->skyDropTargets[targetId] = 0xFF;
return;
}
}
gBattleScripting.moveendState++;
break;
case MOVEEND_UPDATE_LAST_MOVES:
if (gMoveResultFlags & (MOVE_RESULT_FAILED | MOVE_RESULT_DOESNT_AFFECT_FOE))
gBattleStruct->lastMoveFailed |= gBitTable[gBattlerAttacker];
@ -7756,10 +7795,11 @@ 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 && !(gStatuses3[gActiveBattler] & STATUS3_SKY_DROPPED))
CancelMultiTurnMoves(gActiveBattler);
gStatuses3[gActiveBattler] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR);
gStatuses3[gActiveBattler] &= ~(STATUS3_MAGNET_RISE | STATUS3_TELEKINESIS | STATUS3_ON_AIR | STATUS3_SKY_DROPPED);
break;
case VARIOUS_SPECTRAL_THIEF:
// Raise stats
@ -8968,7 +9008,7 @@ static void Cmd_various(void)
MarkBattlerForControllerExec(gActiveBattler);
}
if (gBattleMons[gActiveBattler].pp[i] == 0)
if (gBattleMons[gActiveBattler].pp[i] == 0 && gBattleStruct->skyDropTargets[gActiveBattler] == 0xFF)
CancelMultiTurnMoves(gActiveBattler);
gBattlescriptCurrInstr += 7; // continue
@ -9035,6 +9075,71 @@ 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 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 STATUS2_LOCK_CONFUSE
gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_MULTIPLETURNS);
gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_UPROAR);
gBattleMons[gBattlerTarget].status2 &= ~(STATUS2_BIDE);
gDisableStructs[gBattlerTarget].rolloutTimer = 0;
gDisableStructs[gBattlerTarget].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;
break;
case VARIOUS_CLEAR_SKY_DROP:
// 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] == 0xFF)
gBattlescriptCurrInstr = T1_READ_PTR(gBattlescriptCurrInstr + 3);
else
{
gBattleStruct->skyDropTargets[gBattlerAttacker] = 0xFF;
gBattleStruct->skyDropTargets[gBattlerTarget] = 0xFF;
gStatuses3[gBattlerTarget] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
gBattlescriptCurrInstr += 7;
}
// 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 (gBattleStruct->skyDropTargets[gEffectBattler] != 0xFF && !(gStatuses3[gEffectBattler] & STATUS3_SKY_DROPPED))
{
// Set the target of Sky Drop as gEffectBattler
gEffectBattler = gBattleStruct->skyDropTargets[gEffectBattler];
// Clear skyDropTargets data
gBattleStruct->skyDropTargets[gBattleStruct->skyDropTargets[gEffectBattler]] = 0xFF;
gBattleStruct->skyDropTargets[gEffectBattler] = 0xFF;
// If the target was in the middle of Outrage/Thrash/etc. when targeted by Sky Drop, confuse them on release and do proper animation
if (gBattleMons[gEffectBattler].status2 & STATUS2_LOCK_CONFUSE && CanBeConfused(gEffectBattler))
{
gBattleMons[gEffectBattler].status2 &= ~(STATUS2_LOCK_CONFUSE);
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);
@ -11428,7 +11533,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 && gBattleStruct->skyDropTargets[gBattlerTarget] == 0xFF)
CancelMultiTurnMoves(gBattlerTarget);
}
else
@ -12074,6 +12180,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;
@ -1413,12 +1414,80 @@ void MarkBattlerReceivedLinkData(u8 battlerId)
void CancelMultiTurnMoves(u8 battler)
{
gBattleMons[battler].status2 &= ~STATUS2_MULTIPLETURNS;
gBattleMons[battler].status2 &= ~STATUS2_LOCK_CONFUSE;
gBattleMons[battler].status2 &= ~STATUS2_UPROAR;
gBattleMons[battler].status2 &= ~STATUS2_BIDE;
u8 i;
gBattleMons[battler].status2 &= ~(STATUS2_MULTIPLETURNS);
gBattleMons[battler].status2 &= ~(STATUS2_LOCK_CONFUSE);
gBattleMons[battler].status2 &= ~(STATUS2_UPROAR);
gBattleMons[battler].status2 &= ~(STATUS2_BIDE);
gStatuses3[battler] &= ~STATUS3_SEMI_INVULNERABLE;
// Clear battler's semi-invulnerable bits if they are not held by Sky Drop.
if (!(gStatuses3[battler] & STATUS3_SKY_DROPPED))
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[battler] != 0xFF && !(gStatuses3[battler] & STATUS3_SKY_DROPPED))
{
// Get the target's battler id
u8 otherSkyDropper = gBattleStruct->skyDropTargets[battler];
// Clears sky_dropped and on_air statuses
gStatuses3[otherSkyDropper] &= ~(STATUS3_SKY_DROPPED | STATUS3_ON_AIR);
// Makes both attacker and target's sprites visible
gSprites[gBattlerSpriteIds[battler]].invisible = FALSE;
gSprites[gBattlerSpriteIds[otherSkyDropper]].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[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE && gBattleStruct->turnEffectsTracker != 24)
{
gBattleMons[otherSkyDropper].status2 &= ~(STATUS2_LOCK_CONFUSE);
// If the target can be confused, confuse them.
// Don't use CanBeConfused, can cause issues in edge cases.
if (!(GetBattlerAbility(otherSkyDropper) == ABILITY_OWN_TEMPO
|| gBattleMons[otherSkyDropper].status2 & STATUS2_CONFUSION
|| IsBattlerTerrainAffected(otherSkyDropper, STATUS_FIELD_MISTY_TERRAIN)))
{
// Set confused status
gBattleMons[otherSkyDropper].status2 |= STATUS2_CONFUSION_TURN(((Random()) % 4) + 2);
// If this CancelMultiTurnMoves is occuring due to attackcanceller
if (gBattlescriptCurrInstr[0] == 0x0)
{
gBattleStruct->skyDropTargets[battler] = 0xFE;
}
// If this CancelMultiTurnMoves is occuring due to VARIOUS_GRAVITY_ON_AIRBORNE_MONS
// Reapplying STATUS3_SKY_DROPPED allows for avoiding unecessary messages when Gravity is applied to the target.
else if (gBattlescriptCurrInstr[0] == 0x76 && gBattlescriptCurrInstr[2] == 76)
{
gBattleStruct->skyDropTargets[battler] = 0xFE;
gStatuses3[otherSkyDropper] |= STATUS3_SKY_DROPPED;
}
// If this CancelMultiTurnMoves is occuring due to cancelmultiturnmoves script
else if (gBattlescriptCurrInstr[0] == 0x76 && gBattlescriptCurrInstr[2] == 0)
{
gBattlerAttacker = otherSkyDropper;
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 3;
}
// If this CancelMultiTurnMoves is occuring due to receiving Sleep/Freeze status
else if (gBattleScripting.moveEffect <= PRIMARY_STATUS_MOVE_EFFECT)
{
gBattlerAttacker = otherSkyDropper;
BattleScriptPush(gBattlescriptCurrInstr + 1);
gBattlescriptCurrInstr = BattleScript_ThrashConfuses - 1;
}
}
}
// Clear skyDropTargets data, unless this CancelMultiTurnMoves is caused by Yawn, attackcanceler, or VARIOUS_GRAVITY_ON_AIRBORNE_MONS
if (!(gBattleMons[otherSkyDropper].status2 & STATUS2_LOCK_CONFUSE) && gBattleStruct->skyDropTargets[battler] < 4)
{
gBattleStruct->skyDropTargets[battler] = 0xFF;
gBattleStruct->skyDropTargets[otherSkyDropper] = 0xFF;
}
}
gDisableStructs[battler].rolloutTimer = 0;
gDisableStructs[battler].furyCutterCounter = 0;
@ -2784,7 +2853,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))
@ -3225,6 +3295,7 @@ void TryClearRageAndFuryCutter(void)
enum
{
CANCELLER_FLAGS,
CANCELLER_SKY_DROP,
CANCELLER_ASLEEP,
CANCELLER_FROZEN,
CANCELLER_TRUANT,
@ -3261,6 +3332,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)
{
@ -4901,7 +4982,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++;
@ -5793,6 +5876,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;
}
@ -9184,6 +9269,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,