mirror of
https://github.com/Ninjdai1/pokeemerald.git
synced 2024-12-27 04:04:17 +01:00
Merge pull request #1923 from WiserVisor/battle_engine
Added Sky Drop to Battle Engine
This commit is contained in:
commit
97baedbd5e
@ -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
|
||||
|
@ -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::
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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:
|
||||
|
@ -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]];
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user