mirror of
https://github.com/rh-hideout/pokeemerald-expansion.git
synced 2026-03-21 18:04:50 -05:00
Fixes octolock not ending after user switched out (#7556)
Co-authored-by: Bassoonian <iasperbassoonian@gmail.com>
This commit is contained in:
parent
0a3c281cdd
commit
6df3a48ca2
|
|
@ -1440,9 +1440,8 @@
|
|||
callnative BS_TryRevertWeatherForm
|
||||
.endm
|
||||
|
||||
.macro trysetoctolock battler:req, failInstr:req
|
||||
.macro trysetoctolock failInstr:req
|
||||
callnative BS_TrySetOctolock
|
||||
.byte \battler
|
||||
.4byte \failInstr
|
||||
.endm
|
||||
|
||||
|
|
@ -1737,7 +1736,7 @@
|
|||
callnative BS_ActivateTerrainChangeAbilities
|
||||
.byte \battler
|
||||
.endm
|
||||
|
||||
|
||||
.macro resetterrainabilityflags
|
||||
callnative BS_ResetTerrainAbilityFlags
|
||||
.endm
|
||||
|
|
|
|||
|
|
@ -868,7 +868,7 @@ BattleScript_EffectOctolock::
|
|||
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
|
||||
attackstring
|
||||
ppreduce
|
||||
trysetoctolock BS_TARGET, BattleScript_ButItFailed
|
||||
trysetoctolock BattleScript_ButItFailed
|
||||
attackanimation
|
||||
waitanimation
|
||||
printstring STRINGID_CANTESCAPEBECAUSEOFCURRENTMOVE
|
||||
|
|
|
|||
|
|
@ -12,36 +12,33 @@ In general, `gBattlescriptCurrInstr` tracks the current battle script position a
|
|||
```
|
||||
`callnative` uses the last battle script command ID in order to pass a native function as an argument. Additional optional arguments are added recursively via a macro, so no need to worry about how they need to align to the amount of instructions to skip.
|
||||
|
||||
Now, how might we add a custom `callnative` command? Here are the steps. We will use `BS_TrySetOctolock` as an example.
|
||||
Now, how might we add a custom `callnative` command? Here are the steps. We will use `BS_JumpIfTerrainAffected` as an example.
|
||||
### 1. Create a macro in `asm/macros/battle_script.inc`. For example:
|
||||
```c
|
||||
.macro trysetoctolock battler:req, failInstr:req
|
||||
callnative BS_TrySetOctolock
|
||||
.macro jumpifterrainaffected battler:req, terrainFlags:req, jumpInstr:req
|
||||
callnative BS_JumpIfTerrainAffected
|
||||
.byte \battler
|
||||
.4byte \failInstr
|
||||
.4byte \terrainFlags
|
||||
.4byte \jumpInstr
|
||||
.endm
|
||||
```
|
||||
### 2. Add your new callnative command ID to `src/battle_script_commands.c`. For example:
|
||||
```c
|
||||
void BS_TrySetOctolock(void)
|
||||
void BS_JumpIfTerrainAffected(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler, const u8 *failInstr);
|
||||
NATIVE_ARGS(u8 battler, u32 flags, const u8 *jumpInstr);
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
|
||||
if (gDisableStructs[battler].octolock)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
if (IsBattlerTerrainAffected(battler, cmd->flags))
|
||||
gBattlescriptCurrInstr = cmd->jumpInstr;
|
||||
else
|
||||
{
|
||||
gDisableStructs[battler].octolock = TRUE;
|
||||
gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION;
|
||||
gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
```
|
||||
Each of the arguments defined in the macro (`battler`, `failInstr`) need to be called at the start of the command using `NATIVE_ARGS`.
|
||||
Each of the arguments defined in the macro (`battler`, `flags`, `failInstr`) need to be called at the start of the command using `NATIVE_ARGS`.
|
||||
The byte count in the macro should correspond to the type that will be used for the command (eg, `u8` is `byte`, while the pointer are `4byte`).
|
||||
These arguments can then be accessed as `cmd->battler` and `cmd->battler`.
|
||||
`gBattlescriptCurrInstr = cmd->nextInstr;` advances to the next instruction.
|
||||
These arguments can then be accessed as `cmd->battler`, `cmd->flags` and `cmd->failInstr`.
|
||||
Note that for `cmd->battler` we need to use `GetBattlerForBattleScript` to fetch the correct battler because with the macro we are accessing a scripting command that doesn't corresponds to `gBattlerTarget`, `gBattlerAttacker`, etc.
|
||||
For the battler argument specifically, most of the time the battler is accessed through `gBattlerAttacker`, `gBattlerTarget` and the battler argument left out.
|
||||
In the majority of cases, this is fine since the script commands are mostly used for moves and the interaction is usually between an attacker and target.
|
||||
A script command usually ends with either a jump or next instruction `gBattlescriptCurrInstr = cmd->nextInstr / cmd->nextInstr;` advancing to the next instruction.
|
||||
|
|
|
|||
|
|
@ -133,7 +133,7 @@ struct DisableStruct
|
|||
u8 neutralizingGas:1;
|
||||
u8 iceFaceActivationPrevention:1; // fixes hit escape move edge case
|
||||
u8 unnerveActivated:1; // Unnerve and As One (Unnerve part) activate only once per switch in
|
||||
u8 padding:3;
|
||||
u8 octolockedBy:3;
|
||||
};
|
||||
|
||||
// Fully Cleared each turn after end turn effects are done. A few things are cleared before end turn effects
|
||||
|
|
|
|||
|
|
@ -3173,6 +3173,8 @@ void SwitchInClearSetData(u32 battler)
|
|||
gBattleMons[i].status2 &= ~STATUS2_WRAPPED;
|
||||
if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler)
|
||||
gStatuses4[i] &= ~STATUS4_SYRUP_BOMB;
|
||||
if (gDisableStructs[i].octolock && gDisableStructs[i].octolockedBy == battler)
|
||||
gDisableStructs[i].octolock = FALSE;
|
||||
}
|
||||
|
||||
gActionSelectionCursor[battler] = 0;
|
||||
|
|
@ -3291,6 +3293,8 @@ const u8* FaintClearSetData(u32 battler)
|
|||
gBattleMons[i].status2 &= ~STATUS2_WRAPPED;
|
||||
if ((gStatuses4[i] & STATUS4_SYRUP_BOMB) && gBattleStruct->stickySyrupdBy[i] == battler)
|
||||
gStatuses4[i] &= ~STATUS4_SYRUP_BOMB;
|
||||
if (gDisableStructs[i].octolock && gDisableStructs[i].octolockedBy == battler)
|
||||
gDisableStructs[i].octolock = FALSE;
|
||||
}
|
||||
|
||||
gActionSelectionCursor[battler] = 0;
|
||||
|
|
|
|||
|
|
@ -17447,18 +17447,18 @@ void BS_TryReflectType(void)
|
|||
|
||||
void BS_TrySetOctolock(void)
|
||||
{
|
||||
NATIVE_ARGS(u8 battler, const u8 *failInstr);
|
||||
u32 battler = GetBattlerForBattleScript(cmd->battler);
|
||||
NATIVE_ARGS(const u8 *failInstr);
|
||||
|
||||
if (gDisableStructs[battler].octolock)
|
||||
if (gDisableStructs[gBattlerTarget].octolock)
|
||||
{
|
||||
gBattlescriptCurrInstr = cmd->failInstr;
|
||||
}
|
||||
else
|
||||
{
|
||||
gDisableStructs[battler].octolock = TRUE;
|
||||
gBattleMons[battler].status2 |= STATUS2_ESCAPE_PREVENTION;
|
||||
gDisableStructs[battler].battlerPreventingEscape = gBattlerAttacker;
|
||||
gDisableStructs[gBattlerTarget].octolock = TRUE;
|
||||
gDisableStructs[gBattlerTarget].octolockedBy = gBattlerAttacker;
|
||||
gBattleMons[gBattlerTarget].status2 |= STATUS2_ESCAPE_PREVENTION;
|
||||
gDisableStructs[gBattlerTarget].battlerPreventingEscape = gBattlerAttacker;
|
||||
gBattlescriptCurrInstr = cmd->nextInstr;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -152,3 +152,28 @@ SINGLE_BATTLE_TEST("Octolock triggers Defiant for both stat reductions")
|
|||
MESSAGE("The opposing Bisharp's Attack sharply rose!");
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Octolock ends after user that set the lock switches out")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(player, MOVE_OCTOLOCK); }
|
||||
TURN { SWITCH(player, 1); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_OCTOLOCK, player);
|
||||
MESSAGE("The opposing Wobbuffet can no longer escape because of Octolock!");
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("The opposing Wobbuffet's Defense fell!");
|
||||
NOT ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("The opposing Wobbuffet's Sp. Def fell!");
|
||||
NONE_OF {
|
||||
ANIMATION(ANIM_TYPE_GENERAL, B_ANIM_STATS_CHANGE, opponent);
|
||||
MESSAGE("The opposing Wobbuffet's Defense fell!");
|
||||
MESSAGE("The opposing Wobbuffet's Sp. Def fell!");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -122,3 +122,16 @@ SINGLE_BATTLE_TEST("Sky Drop stops the confusion count until the target is dropp
|
|||
ANIMATION(ANIM_TYPE_STATUS, B_ANIM_STATUS_CONFUSION, player);
|
||||
}
|
||||
}
|
||||
|
||||
SINGLE_BATTLE_TEST("Sky Drop fails if the targe is in a semi-invulnerable state")
|
||||
{
|
||||
GIVEN {
|
||||
PLAYER(SPECIES_WOBBUFFET);
|
||||
OPPONENT(SPECIES_WOBBUFFET);
|
||||
} WHEN {
|
||||
TURN { MOVE(opponent, MOVE_FLY); MOVE(player, MOVE_SKY_DROP); }
|
||||
} SCENE {
|
||||
ANIMATION(ANIM_TYPE_MOVE, MOVE_FLY, opponent);
|
||||
NOT ANIMATION(ANIM_TYPE_MOVE, MOVE_SKY_DROP, player);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user