Skip to content

Commit

Permalink
Encapsulate move data (#5852)
Browse files Browse the repository at this point in the history
  • Loading branch information
AsparagusEduardo authored Jan 1, 2025
1 parent 13fba7b commit 9669a05
Show file tree
Hide file tree
Showing 402 changed files with 3,320 additions and 2,822 deletions.
4 changes: 2 additions & 2 deletions asm/macros/battle_script.inc
Original file line number Diff line number Diff line change
Expand Up @@ -1520,8 +1520,8 @@
.4byte \jumpInstr
.endm

.macro jumpifargument argument:req, jumpInstr:req
callnative BS_JumpIfArgument
.macro jumpifmovepropertyargument argument:req, jumpInstr:req
callnative BS_JumpIfMovePropertyArgument
.byte \argument
.4byte \jumpInstr
.endm
Expand Down
2 changes: 1 addition & 1 deletion data/battle_scripts_1.s
Original file line number Diff line number Diff line change
Expand Up @@ -9454,7 +9454,7 @@ BattleScript_EffectHitSetRemoveTerrain::
accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE
attackstring
ppreduce
jumpifargument ARG_TRY_REMOVE_TERRAIN_FAIL, BattleScript_RemoveTerrain
jumpifmovepropertyargument ARG_TRY_REMOVE_TERRAIN_FAIL, BattleScript_RemoveTerrain
critcalc
damagecalc
adjustdamage
Expand Down
14 changes: 7 additions & 7 deletions docs/tutorials/how_to_testing_system.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ This can be translated to an automated test as follows:
```
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_STUN_SPORE].effect == EFFECT_PARALYZE);
ASSUME(GetMoveEffect(MOVE_STUN_SPORE) == EFFECT_PARALYZE);
}
SINGLE_BATTLE_TEST("Stun Spore inflicts paralysis")
Expand Down Expand Up @@ -78,7 +78,7 @@ This can again be translated as follows:
SINGLE_BATTLE_TEST("Stun Spore does not affect Grass-types")
{
GIVEN {
ASSUME(gMovesInfo[MOVE_STUN_SPORE].powderMove);
ASSUME(IsPowderMove(MOVE_STUN_SPORE));
ASSUME(gSpeciesInfo[SPECIES_ODDISH].types[0] == TYPE_GRASS);
PLAYER(SPECIES_ODDISH); // 1.
OPPONENT(SPECIES_ODDISH); // 2.
Expand Down Expand Up @@ -111,7 +111,7 @@ SINGLE_BATTLE_TEST("Meditate raises Attack", s16 damage)
PARAMETRIZE { raiseAttack = FALSE; }
PARAMETRIZE { raiseAttack = TRUE; }
GIVEN {
ASSUME(gMovesInfo[MOVE_TACKLE].category == DAMAGE_CATEGORY_PHYSICAL);
ASSUME(GetMoveCategory(MOVE_TACKLE) == DAMAGE_CATEGORY_PHYSICAL);
PLAYER(SPECIES_WOBBUFFET);
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
Expand Down Expand Up @@ -146,7 +146,7 @@ The overworld is not available, so it is only possible to test commands which do
### `ASSUME`
`ASSUME(cond)`
Causes the test to be skipped if `cond` is false. Used to document any prerequisites of the test, e.g. to test Burn reducing the Attack of a Pokémon we can observe the damage of a physical attack with and without the burn. To document that this test assumes the attack is physical we can use:
`ASSUME(gMovesInfo[MOVE_WHATEVER].category == DAMAGE_CATEGORY_PHYSICAL);`
`ASSUME(GetMoveCategory(MOVE_WHATEVER) == DAMAGE_CATEGORY_PHYSICAL);`

### `ASSUMPTIONS`
```
Expand All @@ -159,7 +159,7 @@ Should be placed immediately after any `#includes` and contain any `ASSUME` stat
```
ASSUMPTIONS
{
ASSUME(gMovesInfo[MOVE_POISON_STING].effect == EFFECT_POISON_HIT);
ASSUME(GetMoveEffect(MOVE_POISON_STING) == EFFECT_POISON_HIT);
}
```

Expand Down Expand Up @@ -201,7 +201,7 @@ SINGLE_BATTLE_TEST("Blaze boosts Fire-type moves in a pinch", s16 damage)
PARAMETRIZE { hp = 99; }
PARAMETRIZE { hp = 33; }
GIVEN {
ASSUME(gMovesInfo[MOVE_EMBER].type == TYPE_FIRE);
ASSUME(GetMoveType(MOVE_EMBER) == TYPE_FIRE);
PLAYER(SPECIES_CHARMANDER) { Ability(ABILITY_BLAZE); MaxHP(99); HP(hp); }
OPPONENT(SPECIES_WOBBUFFET);
} WHEN {
Expand Down Expand Up @@ -233,7 +233,7 @@ SINGLE_BATTLE_TEST("Paralysis has a 25% chance of skipping the turn")
All `BattleRandom` calls involving tag will return the same number, so this cannot be used to have two moves independently hit or miss, for example.

If the tag is not provided, runs the test 50 times and computes an approximate pass ratio.
`PASSES_RANDOMLY(gMovesInfo[move].accuracy, 100);`
`PASSES_RANDOMLY(GetMoveAccuracy(move), 100);`
Note that this mode of PASSES_RANDOMLY makes the tests run very slowly and should be avoided where possible. If the mechanic you are testing is missing its tag, you should add it.

### `GIVEN`
Expand Down
38 changes: 19 additions & 19 deletions include/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "battle_dynamax.h"
#include "battle_terastal.h"
#include "battle_gimmick.h"
#include "move.h"
#include "random.h" // for rng_value_t

// Helper for accessing command arguments and advancing gBattlescriptCurrInstr.
Expand Down Expand Up @@ -70,20 +71,6 @@
// Special indicator value for shellBellDmg in SpecialStatus
#define IGNORE_SHELL_BELL 0xFFFF

// For defining EFFECT_HIT etc. with battle TV scores and flags etc.
struct __attribute__((packed, aligned(2))) BattleMoveEffect
{
const u8 *battleScript;
u16 battleTvScore:3;
u16 encourageEncore:1;
u16 twoTurnEffect:1;
u16 semiInvulnerableEffect:1;
u16 usesProtectCounter:1;
u16 padding:9;
};

#define GET_MOVE_BATTLESCRIPT(move) gBattleMoveEffects[gMovesInfo[move].effect].battleScript

struct ResourceFlags
{
u32 flags[MAX_BATTLERS_COUNT];
Expand Down Expand Up @@ -864,11 +851,25 @@ STATIC_ASSERT(sizeof(((struct BattleStruct *)0)->palaceFlags) * 8 >= MAX_BATTLER
#define F_DYNAMIC_TYPE_IGNORE_PHYSICALITY (1 << 6) // If set, the dynamic type's physicality won't be used for certain move effects.
#define F_DYNAMIC_TYPE_SET (1 << 7) // Set for all dynamic types to distinguish a dynamic type of Normal (0) from no dynamic type.

#define IS_MOVE_PHYSICAL(move) (GetBattleMoveCategory(move) == DAMAGE_CATEGORY_PHYSICAL)
#define IS_MOVE_SPECIAL(move) (GetBattleMoveCategory(move) == DAMAGE_CATEGORY_SPECIAL)
#define IS_MOVE_STATUS(move) (gMovesInfo[move].category == DAMAGE_CATEGORY_STATUS)
static inline bool32 IsBattleMovePhysical(u32 move)
{
return GetBattleMoveCategory(move) == DAMAGE_CATEGORY_PHYSICAL;
}

static inline bool32 IsBattleMoveSpecial(u32 move)
{
return GetBattleMoveCategory(move) == DAMAGE_CATEGORY_SPECIAL;
}

#define IS_MOVE_RECOIL(move)(gMovesInfo[move].recoil > 0 || gMovesInfo[move].effect == EFFECT_RECOIL_IF_MISS)
static inline bool32 IsBattleMoveStatus(u32 move)
{
return GetMoveCategory(move) == DAMAGE_CATEGORY_STATUS;
}

static inline bool32 IsBattleMoveRecoil(u32 move)
{
return GetMoveRecoil(move) > 0 || GetMoveEffect(move) == EFFECT_RECOIL_IF_MISS;
}

/* Checks if 'battlerId' is any of the types.
* Passing multiple types is more efficient than calling this multiple
Expand Down Expand Up @@ -1176,7 +1177,6 @@ extern u32 gFieldStatuses;
extern struct FieldTimer gFieldTimers;
extern u8 gBattlerAbility;
extern struct QueuedStatBoost gQueuedStatBoosts[MAX_BATTLERS_COUNT];
extern const struct BattleMoveEffect gBattleMoveEffects[];

extern void (*gPreBattleCallback1)(void);
extern void (*gBattleMainFunc)(void);
Expand Down
2 changes: 1 addition & 1 deletion include/battle_main.h
Original file line number Diff line number Diff line change
Expand Up @@ -72,7 +72,7 @@ void SwapTurnOrder(u8 id1, u8 id2);
u32 GetBattlerTotalSpeedStatArgs(u32 battler, u32 ability, u32 holdEffect);
u32 GetBattlerTotalSpeedStat(u32 battler);
s8 GetChosenMovePriority(u32 battlerId);
s8 GetMovePriority(u32 battlerId, u16 move);
s8 GetBattleMovePriority(u32 battlerId, u16 move);
s32 GetWhichBattlerFasterArgs(u32 battler1, u32 battler2, bool32 ignoreChosenMoves, u32 ability1, u32 ability2,
u32 holdEffectBattler1, u32 holdEffectBattler2, u32 speedBattler1, u32 speedBattler2, s32 priority1, s32 priority2);
s32 GetWhichBattlerFasterOrTies(u32 battler1, u32 battler2, bool32 ignoreChosenMoves);
Expand Down
6 changes: 4 additions & 2 deletions include/battle_util.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#ifndef GUARD_BATTLE_UTIL_H
#define GUARD_BATTLE_UTIL_H

#include "move.h"

#define MOVE_LIMITATION_ZEROMOVE (1 << 0)
#define MOVE_LIMITATION_PP (1 << 1)
#define MOVE_LIMITATION_DISABLED (1 << 2)
Expand Down Expand Up @@ -226,7 +228,7 @@ u32 ItemBattleEffects(enum ItemEffect, u32 battler, bool32 moveTurn);
void ClearVariousBattlerFlags(u32 battler);
void HandleAction_RunBattleScript(void);
u32 SetRandomTarget(u32 battler);
u32 GetMoveTarget(u16 move, u8 setTarget);
u32 GetBattleMoveTarget(u16 move, u8 setTarget);
u8 GetAttackerObedienceForAction();
u32 GetBattlerHoldEffect(u32 battler, bool32 checkNegating);
u32 GetBattlerHoldEffectIgnoreAbility(u32 battler, bool32 checkNegating);
Expand Down Expand Up @@ -328,7 +330,7 @@ u32 GetBattlerType(u32 battler, u32 typeIndex, bool32 ignoreTera);
bool8 CanMonParticipateInSkyBattle(struct Pokemon *mon);
bool8 IsMonBannedFromSkyBattles(u16 species);
void RemoveBattlerType(u32 battler, u8 type);
u32 GetMoveType(u32 move);
u32 GetBattleMoveType(u32 move);
void TryActivateSleepClause(u32 battler, u32 indexInParty);
void TryDeactivateSleepClause(u32 battlerSide, u32 indexInParty);
bool32 IsSleepClauseActiveForSide(u32 battlerSide);
Expand Down
2 changes: 1 addition & 1 deletion include/constants/battle.h
Original file line number Diff line number Diff line change
Expand Up @@ -520,7 +520,7 @@
#define MOVE_TARGET_ALLY (1 << 7)
#define MOVE_TARGET_ALL_BATTLERS ((1 << 8) | MOVE_TARGET_USER) // No functionality for status moves

// For the second argument of GetMoveTarget, when no target override is needed
// For the second argument of GetBattleMoveTarget, when no target override is needed
#define NO_TARGET_OVERRIDE 0

// Constants for Parental Bond
Expand Down
Loading

0 comments on commit 9669a05

Please sign in to comment.