Skip to content

Commit

Permalink
Fixes Shell Side Arm (#4753)
Browse files Browse the repository at this point in the history
* Fixes Shell Side Arm

* Fixes to random call

* hardcoded the effect to the move

* minor change

* minor change 2

* applied reviews
  • Loading branch information
AlexOn1ine authored Jun 12, 2024
1 parent 5ebdcdc commit 9c72392
Show file tree
Hide file tree
Showing 15 changed files with 221 additions and 120 deletions.
8 changes: 2 additions & 6 deletions asm/macros/battle_script.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1637,11 +1637,11 @@
.macro trygulpmissile
callnative BS_TryGulpMissile
.endm

.macro tryactivategulpmissile
callnative BS_TryActivateGulpMissile
.endm

.macro tryquash failInstr:req
callnative BS_TryQuash
.4byte \failInstr
Expand Down Expand Up @@ -2211,10 +2211,6 @@
.4byte \failInstr
.endm

.macro shellsidearmcheck
various BS_ATTACKER, VARIOUS_SHELL_SIDE_ARM_CHECK
.endm

.macro jumpifteanoberry jumpInstr:req
various BS_ATTACKER, VARIOUS_TEATIME_TARGETS
.4byte \jumpInstr
Expand Down
4 changes: 0 additions & 4 deletions data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -719,10 +719,6 @@ BattleScript_FlingMissed:
ppreduce
goto BattleScript_MoveMissedPause

BattleScript_EffectShellSideArm::
shellsidearmcheck
goto BattleScript_EffectHit

BattleScript_EffectPhotonGeyser::
setphotongeysercategory
goto BattleScript_EffectHit
Expand Down
1 change: 1 addition & 0 deletions include/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -779,6 +779,7 @@ struct BattleStruct
u8 supremeOverlordCounter[MAX_BATTLERS_COUNT];
u8 quickClawRandom[MAX_BATTLERS_COUNT];
u8 quickDrawRandom[MAX_BATTLERS_COUNT];
u8 shellSideArmCategory[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT];
};

// The palaceFlags member of struct BattleStruct contains 1 flag per move to indicate which moves the AI should consider,
Expand Down
1 change: 0 additions & 1 deletion include/battle_scripts.h
Original file line number Diff line number Diff line change
Expand Up @@ -796,7 +796,6 @@ extern const u8 BattleScript_EffectPlasmaFists[];
extern const u8 BattleScript_EffectHyperspaceFury[];
extern const u8 BattleScript_EffectAuraWheel[];
extern const u8 BattleScript_EffectPhotonGeyser[];
extern const u8 BattleScript_EffectShellSideArm[];
extern const u8 BattleScript_EffectNoRetreat[];
extern const u8 BattleScript_EffectTarShot[];
extern const u8 BattleScript_EffectPoltergeist[];
Expand Down
3 changes: 2 additions & 1 deletion include/battle_util.h
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ u32 IsAbilityOnOpposingSide(u32 battler, u32 ability);
u32 IsAbilityOnField(u32 ability);
u32 IsAbilityOnFieldExcept(u32 battler, u32 ability);
u32 IsAbilityPreventingEscape(u32 battler);
bool32 IsBattlerProtected(u32 battler, u32 move);
bool32 IsBattlerProtected(u32 battlerAtk, u32 battlerDef, u32 move);
bool32 CanBattlerEscape(u32 battler); // no ability check
void BattleScriptExecute(const u8 *BS_ptr);
void BattleScriptPushCursorAndCallback(const u8 *BS_ptr);
Expand Down Expand Up @@ -206,6 +206,7 @@ bool32 IsBelchPreventingMove(u32 battler, u32 move);
bool32 HasEnoughHpToEatBerry(u32 battler, u32 hpFraction, u32 itemId);
bool32 IsPartnerMonFromSameTrainer(u32 battler);
u8 GetCategoryBasedOnStats(u32 battler);
void SetShellSideArmCategory(void);
bool32 MoveIsAffectedBySheerForce(u32 move);
bool32 TestIfSheerForceAffected(u32 battler, u16 move);
void TryRestoreHeldItems(void);
Expand Down
1 change: 0 additions & 1 deletion include/constants/battle_move_effects.h
Original file line number Diff line number Diff line change
Expand Up @@ -302,7 +302,6 @@ enum {
EFFECT_HYPERSPACE_FURY,
EFFECT_AURA_WHEEL,
EFFECT_PHOTON_GEYSER,
EFFECT_SHELL_SIDE_ARM,
EFFECT_TERRAIN_PULSE,
EFFECT_NO_RETREAT,
EFFECT_TAR_SHOT,
Expand Down
57 changes: 28 additions & 29 deletions include/constants/battle_script_commands.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,35 +208,34 @@
#define VARIOUS_JUMP_IF_WEATHER_AFFECTED 116
#define VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED 117
#define VARIOUS_SET_ATTACKER_STICKY_WEB_USER 118
#define VARIOUS_SHELL_SIDE_ARM_CHECK 119
#define VARIOUS_TRY_NO_RETREAT 120
#define VARIOUS_TRY_TAR_SHOT 121
#define VARIOUS_CAN_TAR_SHOT_WORK 122
#define VARIOUS_CHECK_POLTERGEIST 123
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 124
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 125
#define VARIOUS_JUMP_IF_UNDER_200 126
#define VARIOUS_SET_SKY_DROP 127
#define VARIOUS_CLEAR_SKY_DROP 128
#define VARIOUS_SKY_DROP_YAWN 129
#define VARIOUS_CURE_CERTAIN_STATUSES 130
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 131
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 132
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 133
#define VARIOUS_SAVE_BATTLER_ITEM 134
#define VARIOUS_RESTORE_BATTLER_ITEM 135
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 136
#define VARIOUS_SET_BEAK_BLAST 137
#define VARIOUS_SWAP_SIDE_STATUSES 138
#define VARIOUS_SWAP_STATS 139
#define VARIOUS_TEATIME_INVUL 140
#define VARIOUS_TEATIME_TARGETS 141
#define VARIOUS_TRY_WIND_RIDER_POWER 142
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 143
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 144
#define VARIOUS_STORE_HEALING_WISH 145
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 146
#define VARIOUS_TRY_REVIVAL_BLESSING 147
#define VARIOUS_TRY_NO_RETREAT 119
#define VARIOUS_TRY_TAR_SHOT 120
#define VARIOUS_CAN_TAR_SHOT_WORK 121
#define VARIOUS_CHECK_POLTERGEIST 122
#define VARIOUS_CUT_1_3_HP_RAISE_STATS 123
#define VARIOUS_TRY_END_NEUTRALIZING_GAS 124
#define VARIOUS_JUMP_IF_UNDER_200 125
#define VARIOUS_SET_SKY_DROP 126
#define VARIOUS_CLEAR_SKY_DROP 127
#define VARIOUS_SKY_DROP_YAWN 128
#define VARIOUS_CURE_CERTAIN_STATUSES 129
#define VARIOUS_TRY_RESET_NEGATIVE_STAT_STAGES 130
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_BERRY 131
#define VARIOUS_JUMP_IF_LAST_USED_ITEM_HOLD_EFFECT 132
#define VARIOUS_SAVE_BATTLER_ITEM 133
#define VARIOUS_RESTORE_BATTLER_ITEM 134
#define VARIOUS_BATTLER_ITEM_TO_LAST_USED_ITEM 135
#define VARIOUS_SET_BEAK_BLAST 136
#define VARIOUS_SWAP_SIDE_STATUSES 137
#define VARIOUS_SWAP_STATS 138
#define VARIOUS_TEATIME_INVUL 139
#define VARIOUS_TEATIME_TARGETS 140
#define VARIOUS_TRY_WIND_RIDER_POWER 141
#define VARIOUS_ACTIVATE_WEATHER_CHANGE_ABILITIES 142
#define VARIOUS_ACTIVATE_TERRAIN_CHANGE_ABILITIES 143
#define VARIOUS_STORE_HEALING_WISH 144
#define VARIOUS_HIT_SWITCH_TARGET_FAILED 145
#define VARIOUS_TRY_REVIVAL_BLESSING 146

// Cmd_manipulatedamage
#define DMG_CHANGE_SIGN 0
Expand Down
1 change: 1 addition & 0 deletions include/random.h
Original file line number Diff line number Diff line change
Expand Up @@ -189,6 +189,7 @@ enum RandomTag
RNG_TRACE,
RNG_FICKLE_BEAM,
RNG_AI_ABILITY,
RNG_SHELL_SIDE_ARM,
};

#define RandomWeighted(tag, ...) \
Expand Down
5 changes: 3 additions & 2 deletions src/battle_ai_util.c
Original file line number Diff line number Diff line change
Expand Up @@ -477,8 +477,9 @@ s32 AI_CalcDamage(u32 move, u32 battlerAtk, u32 battlerDef, u8 *typeEffectivenes
}
else if (gMovesInfo[move].effect == EFFECT_PHOTON_GEYSER)
gBattleStruct->swapDamageCategory = (GetCategoryBasedOnStats(gBattlerAttacker) == DAMAGE_CATEGORY_PHYSICAL);

if (gMovesInfo[move].effect == EFFECT_NATURE_POWER)
else if (move == MOVE_SHELL_SIDE_ARM && gBattleStruct->shellSideArmCategory[battlerAtk][battlerDef] == DAMAGE_CATEGORY_SPECIAL)
gBattleStruct->swapDamageCategory = TRUE;
else if (gMovesInfo[move].effect == EFFECT_NATURE_POWER)
move = GetNaturePowerMove();

gBattleStruct->dynamicMoveType = 0;
Expand Down
8 changes: 5 additions & 3 deletions src/battle_main.c
Original file line number Diff line number Diff line change
Expand Up @@ -3677,8 +3677,8 @@ const u8* FaintClearSetData(u32 battler)
gBattleStruct->zmove.toBeUsed[battler] = MOVE_NONE;
gBattleStruct->zmove.effect = EFFECT_HIT;
// Clear Dynamax data
UndoDynamax(battler);
UndoDynamax(battler);

return result;
}

Expand Down Expand Up @@ -4162,6 +4162,7 @@ static void TryDoEventsBeforeFirstTurn(void)

memset(gQueuedStatBoosts, 0, sizeof(gQueuedStatBoosts)); // erase all totem boosts just to be safe

SetShellSideArmCategory();
SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers

if (gBattleTypeFlags & BATTLE_TYPE_ARENA)
Expand Down Expand Up @@ -4254,6 +4255,7 @@ void BattleTurnPassed(void)

*(&gBattleStruct->absentBattlerFlags) = gAbsentBattlerFlags;
BattlePutTextOnWindow(gText_EmptyString3, B_WIN_MSG);
SetShellSideArmCategory();
SetAiLogicDataForTurn(AI_DATA); // get assumed abilities, hold effects, etc of all battlers
gBattleMainFunc = HandleTurnActionSelectionState;

Expand Down Expand Up @@ -5835,7 +5837,7 @@ static void TryEvolvePokemon(void)
sTriedEvolving |= gBitTable[i];

if (species == SPECIES_NONE && (gLeveledUpInBattle & gBitTable[i]))
{
{
gLeveledUpInBattle &= ~(gBitTable[i]);
species = GetEvolutionTargetSpecies(&gPlayerParty[i], EVO_MODE_BATTLE_ONLY, gLeveledUpInBattle, NULL);
}
Expand Down
56 changes: 10 additions & 46 deletions src/battle_script_commands.c
Original file line number Diff line number Diff line change
Expand Up @@ -1479,7 +1479,7 @@ static void Cmd_attackcanceler(void)
gBattlescriptCurrInstr = BattleScript_TookAttack;
RecordAbilityBattle(gBattlerTarget, gLastUsedAbility);
}
else if (IsBattlerProtected(gBattlerTarget, gCurrentMove)
else if (IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove)
&& (gCurrentMove != MOVE_CURSE || IS_BATTLER_OF_TYPE(gBattlerAttacker, TYPE_GHOST))
&& (!gBattleMoveEffects[gMovesInfo[gCurrentMove].effect].twoTurnEffect || (gBattleMons[gBattlerAttacker].status2 & STATUS2_MULTIPLETURNS))
&& gMovesInfo[gCurrentMove].effect != EFFECT_SUCKER_PUNCH
Expand Down Expand Up @@ -1535,7 +1535,7 @@ static void Cmd_unused5(void)
{
CMD_ARGS(const u8 *failInstr);

if (IsBattlerProtected(gBattlerTarget, gCurrentMove))
if (IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove))
{
gMoveResultFlags |= MOVE_RESULT_MISSED;
JumpIfMoveFailed(sizeof(*cmd), MOVE_NONE);
Expand All @@ -1550,7 +1550,7 @@ static void Cmd_unused5(void)
static bool8 JumpIfMoveAffectedByProtect(u16 move)
{
bool8 affected = FALSE;
if (IsBattlerProtected(gBattlerTarget, move))
if (IsBattlerProtected(gBattlerAttacker, gBattlerTarget, move))
{
gMoveResultFlags |= MOVE_RESULT_MISSED;
JumpIfMoveFailed(7, move);
Expand Down Expand Up @@ -2009,6 +2009,8 @@ static void Cmd_damagecalc(void)
u8 moveType;

GET_MOVE_TYPE(gCurrentMove, moveType);
if (gBattleStruct->shellSideArmCategory[gBattlerAttacker][gBattlerTarget] == DAMAGE_CATEGORY_SPECIAL && gCurrentMove == MOVE_SHELL_SIDE_ARM)
gBattleStruct->swapDamageCategory = TRUE;
gBattleMoveDamage = CalculateMoveDamage(gCurrentMove, gBattlerAttacker, gBattlerTarget, moveType, 0, gIsCriticalHit, TRUE, TRUE);
gBattlescriptCurrInstr = cmd->nextInstr;
}
Expand Down Expand Up @@ -2106,7 +2108,7 @@ static void Cmd_adjustdamage(void)
gLastUsedItem = gBattleMons[gBattlerTarget].item;
gSpecialStatuses[gBattlerTarget].focusBanded = FALSE;
gSpecialStatuses[gBattlerTarget].focusSashed = FALSE;

}
else if (gSpecialStatuses[gBattlerTarget].sturdied)
{
Expand Down Expand Up @@ -3225,8 +3227,8 @@ void SetMoveEffect(bool32 primary, bool32 certain)
{
gBattleMons[gEffectBattler].status2 |= sStatusFlagsForMoveEffects[gBattleScripting.moveEffect];
gBattlescriptCurrInstr++;
}
else
}
else
{
gBattlescriptCurrInstr++;
}
Expand Down Expand Up @@ -6285,7 +6287,7 @@ static void Cmd_moveend(void)
break;
}
}

if (!(gBattleStruct->lastMoveFailed & gBitTable[gBattlerAttacker]
|| (!gSpecialStatuses[gBattlerAttacker].dancerUsedMove
&& gBattleStruct->bouncedMoveIsUsed)))
Expand Down Expand Up @@ -10487,44 +10489,6 @@ static void Cmd_various(void)
gBattlescriptCurrInstr = cmd->nextInstr;
return;
}
case VARIOUS_SHELL_SIDE_ARM_CHECK: // 0% chance GameFreak actually checks this way according to DaWobblefet, but this is the only functional explanation at the moment
{
VARIOUS_ARGS();

u32 attackerAtkStat = gBattleMons[gBattlerAttacker].attack;
u32 targetDefStat = gBattleMons[gBattlerTarget].defense;
u32 attackerSpAtkStat = gBattleMons[gBattlerAttacker].spAttack;
u32 targetSpDefStat = gBattleMons[gBattlerTarget].spDefense;
u8 statStage;
u32 physical;
u32 special;

gBattleStruct->swapDamageCategory = FALSE;

statStage = gBattleMons[gBattlerAttacker].statStages[STAT_ATK];
attackerAtkStat *= gStatStageRatios[statStage][0];
attackerAtkStat /= gStatStageRatios[statStage][1];

statStage = gBattleMons[gBattlerTarget].statStages[STAT_DEF];
targetDefStat *= gStatStageRatios[statStage][0];
targetDefStat /= gStatStageRatios[statStage][1];

physical = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * gMovesInfo[gCurrentMove].power * attackerAtkStat) / targetDefStat) / 50);

statStage = gBattleMons[gBattlerAttacker].statStages[STAT_SPATK];
attackerSpAtkStat *= gStatStageRatios[statStage][0];
attackerSpAtkStat /= gStatStageRatios[statStage][1];

statStage = gBattleMons[gBattlerTarget].statStages[STAT_SPDEF];
targetSpDefStat *= gStatStageRatios[statStage][0];
targetSpDefStat /= gStatStageRatios[statStage][1];

special = ((((2 * gBattleMons[gBattlerAttacker].level / 5 + 2) * gMovesInfo[gCurrentMove].power * attackerSpAtkStat) / targetSpDefStat) / 50);

if (((physical > special) || (physical == special && (Random() % 2) == 0)))
gBattleStruct->swapDamageCategory = TRUE;
break;
}
case VARIOUS_JUMP_IF_LEAF_GUARD_PROTECTED:
{
VARIOUS_ARGS(const u8 *jumpInstr);
Expand Down Expand Up @@ -13903,7 +13867,7 @@ static void Cmd_trymemento(void)
if (B_MEMENTO_FAIL >= GEN_4
&& (gBattleCommunication[MISS_TYPE] == B_MSG_PROTECTED
|| gStatuses3[gBattlerTarget] & STATUS3_SEMI_INVULNERABLE
|| IsBattlerProtected(gBattlerTarget, gCurrentMove)
|| IsBattlerProtected(gBattlerAttacker, gBattlerTarget, gCurrentMove)
|| DoesSubstituteBlockMove(gBattlerAttacker, gBattlerTarget, gCurrentMove)))
{
// Failed, target was protected.
Expand Down
Loading

0 comments on commit 9c72392

Please sign in to comment.