Skip to content

Commit

Permalink
Merge pull request #110 from lhearachel/battle-dev
Browse files Browse the repository at this point in the history
Document type-effectiveness routines, Check/Trigger for redirection abilities
  • Loading branch information
lhearachel authored Nov 9, 2023
2 parents cfec633 + 5937b5c commit c30b9cb
Show file tree
Hide file tree
Showing 12 changed files with 504 additions and 342 deletions.
8 changes: 8 additions & 0 deletions include/battle/btlcmd.h
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,14 @@ enum CheckHaveOp {
};

enum StatusEffect {
STATUS_EFFECT_NONE = 0,

STATUS_EFFECT_SLEEP,
STATUS_EFFECT_POISON,
STATUS_EFFECT_BURN,
STATUS_EFFECT_FREEZE,
STATUS_EFFECT_PARALYSIS,

STATUS_EFFECT_LEVEL_UP = 8,

STATUS_EFFECT_STAGE_UP = 12,
Expand Down
1 change: 1 addition & 0 deletions include/constants/battle/moves.h
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,7 @@

#define MOVE_STATUS_DID_NOT_AFFECT (MOVE_STATUS_INEFFECTIVE | MOVE_STATUS_WONDER_GUARD)
#define MOVE_STATUS_GENERAL_MISS (MOVE_STATUS_MISSED | MOVE_STATUS_SEMI_INVULNERABLE)
#define MOVE_STATUS_BASIC_EFFECTIVENESS (MOVE_STATUS_SUPER_EFFECTIVE | MOVE_STATUS_NOT_VERY_EFFECTIVE)

#define RANGE_SINGLE_TARGET 0
#define RANGE_SINGLE_TARGET_SPECIAL (1 << 0)
Expand Down
3 changes: 2 additions & 1 deletion include/constants/battle/system_control.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,10 @@
#define SYSCTL_BATON_PASS (1 << 8)
#define SYSCTL_LAST_OF_MULTI_TURN (1 << 9)
#define SYSCTL_NONSTANDARD_ACC_CHECK (1 << 10) // used by Future Sight and OHKO moves
#define SYSCTL_IGNORE_TYPE_CHECKS (1 << 11)
#define SYSCTL_MOVE_HIT (1 << 13) // this indicates that the move hit its target(s)
#define SYSCTL_PLAYED_MOVE_ANIMATION (1 << 14)
#define SYSCTL_SKIP_TYPE_CHECK (1 << 15)
#define SYSCTL_IGNORE_IMMUNITIES (1 << 15)
#define SYSCTL_FAIL_STAT_STAGE_CHANGE (1 << 17)
#define SYSCTL_HIT_DURING_SHADOW_FORCE (1 << 19)
#define SYSCTL_REUSE_LAST_MOVE (1 << 20)
Expand Down
2 changes: 1 addition & 1 deletion include/constants/items.h
Original file line number Diff line number Diff line change
Expand Up @@ -173,7 +173,7 @@ enum {
#define HOLD_EFFECT_ARCEUS_ELECTRIC 128
#define HOLD_EFFECT_ARCEUS_GRASS 129
#define HOLD_EFFECT_ARCEUS_ICE 130
#define HOLD_EFFECT_ARCEUS_FIGHT 131
#define HOLD_EFFECT_ARCEUS_FIGHTING 131
#define HOLD_EFFECT_ARCEUS_POISON 132
#define HOLD_EFFECT_ARCEUS_GROUND 133
#define HOLD_EFFECT_ARCEUS_FLYING 134
Expand Down
82 changes: 77 additions & 5 deletions include/overlay016/ov16_0225177C.h
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
#include "battle/battle_context.h"
#include "battle/battle_mon.h"
#include "battle/battle_message.h"
#include "battle/btlcmd.h"

enum BattleContextParam {
BATTLECTX_SIDE_CONDITIONS_MASK = 0,
Expand Down Expand Up @@ -356,8 +357,31 @@ BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext
* @return The chosen defender for the move
*/
int BattleSystem_Defender(BattleSystem *battleSys, BattleContext *battleCtx, int attacker, u16 move, BOOL randomize, int inRange);
void BattleSystem_RedirectTarget(BattleSystem * param0, BattleContext * param1, int param2, u16 param3);
BOOL BattleMove_TriggerRedirectionAbilities(BattleSystem * param0, BattleContext * param1);

/**
* @brief Check for redirection abilities given an attacker using a certain move.
*
* This routine will update the appropriate flags and the current target if the
* used move is Electric- or Water-type, has single-target range, and at least
* one other battler on the field has Lightning Rod or Storm Drain, respectively.
*
* @param battleSys
* @param battleCtx
* @param attacker
* @param move
*/
void BattleSystem_CheckRedirectionAbilities(BattleSystem *battleSys, BattleContext *battleCtx, int attacker, u16 move);

/**
* @brief Trigger a redirection ability's effect and load the appropriate
* subscript for execution.
*
* @param battleSys
* @param battleCtx
* @return TRUE if a subscript was loaded and should be executed for the effect,
* FALSE otherwise.
*/
BOOL BattleSystem_TriggerRedirectionAbilities(BattleSystem *battleSys, BattleContext *battleCtx);
void BattleMon_CopyToParty(BattleSystem * param0, BattleContext * param1, int param2);

/**
Expand All @@ -380,7 +404,16 @@ void Battler_LockMoveChoice(BattleSystem *battleSys, BattleContext *battleCtx, i
* @param battler
*/
void Battler_UnlockMoveChoice(BattleSystem *battleSys, BattleContext *battleCtx, int battler);
int ov16_02253F7C(BattleContext * param0, int param1);

/**
* @brief Calculate the status effect value for a battler's non-volatile
* condition, if any.
*
* @param battleCtx
* @param battler
* @return A value representing the battler's status non-volatile status.
*/
enum StatusEffect Battler_StatusCondition(BattleContext *battleCtx, int battler);
BOOL BattleSystem_CheckTrainerMessage(BattleSystem * param0, BattleContext * param1);
void BattleContext_Init(BattleContext * param0);
void BattleContext_InitCounters(BattleSystem * param0, BattleContext * param1);
Expand Down Expand Up @@ -419,8 +452,47 @@ void BattleSystem_SetupNextTurn(BattleSystem * param0, BattleContext * param1);
int BattleSystem_CheckStruggling(BattleSystem * param0, BattleContext * param1, int param2, int param3, int param4);
BOOL BattleSystem_CanUseMove(BattleSystem *battleSys, BattleContext *battleCtx, int battler, int moveSlot, BattleMessage *msgOut);
int Battler_SlotForMove(BattleMon * param0, u16 param1);
int BattleSystem_CheckTypeChart(BattleSystem * param0, BattleContext * param1, int param2, int param3, int param4, int param5, int param6, u32 * param7);
void ov16_022552D4(BattleContext * param0, int param1, int param2, int param3, int param4, int param5, int param6, int param7, u32 * param8);

/**
* @brief Apply type-chart effectiveness for a given move against its target.
*
* This encapsulates the following multipliers:
* - Same-Type Attack Bonus (and its modification by the ability Adaptability)
* - Super/Not Very Effective multipliers for each of the defender's types
* - Type-effectiveness overrides for effects like Iron Ball, Roost, and Miracle Eye
* - Wonder Guard's override for moves that are not super-effective
* - Expert Belt's multiplier for super-effective moves
* - Filter and Solid Rock's multipliers for defenders taking super-effective damage
* - Tinted Lens's multiplier for defenders taking not-very-effective damage
*
* The move status mask will also be updated with the correct flags.
*
* @param battleSys
* @param battleCtx
* @param move
* @param inType If this is non-zero, then it will be regarded as the move's type
* @param attacker
* @param defender
* @param damage Pre-calculated starting damage value
* @param[out] moveStatusMask
* @return Damage value after applying the type-chart and related multipliers
*/
int BattleSystem_ApplyTypeChart(BattleSystem *battleSys, BattleContext *battleCtx, int move, int inType, int attacker, int defender, int damage, u32 *moveStatusMask);

/**
* @brief Calculate the effectiveness mask of the given move.
*
* @param battleCtx
* @param move
* @param inType If this is non-zero, then it will be regarded as the move's type
* @param attackerAbility
* @param defenderAbility
* @param defenderItemEffect
* @param defenderType1
* @param defenderType2
* @param[out] moveStatusMask
*/
void BattleSystem_CalcEffectiveness(BattleContext *battleCtx, int move, int inType, int attackerAbility, int defenderAbility, int defenderItemEffect, int defenderType1, int defenderType2, u32 *moveStatusMask);
BOOL BattleContext_MoveFailed(BattleContext * param0, int param1);

/**
Expand Down
2 changes: 1 addition & 1 deletion res/items/pl_item_data.csv
Original file line number Diff line number Diff line change
Expand Up @@ -280,7 +280,7 @@ ITEM_SPLASH_PLATE,1000,HOLD_EFFECT_ARCEUS_WATER,20,0,0,90,0,31,false,false,POCKE
ITEM_ZAP_PLATE,1000,HOLD_EFFECT_ARCEUS_ELECTRIC,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0
ITEM_MEADOW_PLATE,1000,HOLD_EFFECT_ARCEUS_GRASS,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0
ITEM_ICICLE_PLATE,1000,HOLD_EFFECT_ARCEUS_ICE,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0
ITEM_FIST_PLATE,1000,HOLD_EFFECT_ARCEUS_FIGHT,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0
ITEM_FIST_PLATE,1000,HOLD_EFFECT_ARCEUS_FIGHTING,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0
ITEM_TOXIC_PLATE,1000,HOLD_EFFECT_ARCEUS_POISON,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0
ITEM_EARTH_PLATE,1000,HOLD_EFFECT_ARCEUS_GROUND,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0
ITEM_SKY_PLATE,1000,HOLD_EFFECT_ARCEUS_FLYING,20,0,0,90,0,31,false,false,POCKET_ITEMS,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,false,false,false,false,false,false,false,false,false,false,false,false,false,false,0,0,0,0,0,0,0,0,0,0,0
Expand Down
30 changes: 15 additions & 15 deletions src/overlay014/ov14_0221FC20.c
Original file line number Diff line number Diff line change
Expand Up @@ -1469,7 +1469,7 @@ static void ov14_02221060 (BattleSystem * param0, BattleContext * param1)
v4 = ov14_0222327C(param0, param1, param1->aiContext.attacker, v3);

if (v3) {
v1 = BattleSystem_CheckTypeChart(param0, param1, v3, v4, param1->aiContext.attacker, param1->aiContext.defender, v1, &v2);
v1 = BattleSystem_ApplyTypeChart(param0, param1, v3, v4, param1->aiContext.attacker, param1->aiContext.defender, v1, &v2);

if (v1 == 60 * 2) {
v1 = 80;
Expand Down Expand Up @@ -1505,7 +1505,7 @@ static void ov14_02221114 (BattleSystem * param0, BattleContext * param1)
v1 = ov14_02222CF0(param1);
v2 = 40;
v3 = 0;
v2 = BattleSystem_CheckTypeChart(param0, param1, param1->aiContext.move, ov14_0222327C(param0, param1, param1->aiContext.attacker, param1->aiContext.move), param1->aiContext.attacker, param1->aiContext.defender, v2, &v3);
v2 = BattleSystem_ApplyTypeChart(param0, param1, param1->aiContext.move, ov14_0222327C(param0, param1, param1->aiContext.attacker, param1->aiContext.move), param1->aiContext.attacker, param1->aiContext.defender, v2, &v3);

if (v2 == 60 * 2) {
v2 = 80;
Expand Down Expand Up @@ -3272,7 +3272,7 @@ static s32 ov14_02222E84 (BattleSystem * param0, BattleContext * param1, u16 par
param1->battleStatusMask |= 0x800;
}

v5 = BattleSystem_CheckTypeChart(param0, param1, param2, v2, param5, param1->aiContext.defender, v5, &v4);
v5 = BattleSystem_ApplyTypeChart(param0, param1, param2, v2, param5, param1->aiContext.defender, v5, &v4);
param1->battleStatusMask &= (0x800 ^ 0xffffffff);

if (v4 & (0x8 | 0x800 | 0x100000 | 0x40000)) {
Expand Down Expand Up @@ -3413,7 +3413,7 @@ static BOOL ov14_0222342C (BattleSystem * param0, BattleContext * param1, int pa

if (v2) {
v4 = 0;
BattleSystem_CheckTypeChart(param0, param1, v2, v3, param2, param2 ^ 1, 0, &v4);
BattleSystem_ApplyTypeChart(param0, param1, v2, v3, param2, param2 ^ 1, 0, &v4);

if (v4 & 0x2) {
return 0;
Expand All @@ -3431,7 +3431,7 @@ static BOOL ov14_0222342C (BattleSystem * param0, BattleContext * param1, int pa

if (v2) {
v4 = 0;
ov16_022552D4(param1, v2, v3, Pokemon_GetValue(v5, MON_DATA_ABILITY, NULL), Battler_Ability(param1, param2 ^ 1), Battler_HeldItemEffect(param1, param2 ^ 1), BattleMon_Get(param1, param2 ^ 1, 27, NULL), BattleMon_Get(param1, param2 ^ 1, 28, NULL), &v4);
BattleSystem_CalcEffectiveness(param1, v2, v3, Pokemon_GetValue(v5, MON_DATA_ABILITY, NULL), Battler_Ability(param1, param2 ^ 1), Battler_HeldItemEffect(param1, param2 ^ 1), BattleMon_Get(param1, param2 ^ 1, 27, NULL), BattleMon_Get(param1, param2 ^ 1, 28, NULL), &v4);

if (v4 & 0x2) {
if ((BattleSystem_RandNext(param0) % 3) < 2) {
Expand Down Expand Up @@ -3479,7 +3479,7 @@ static BOOL ov14_022235F0 (BattleSystem * param0, BattleContext * param1, int pa
v8 = 0;

if (param1->battleMons[v2].curHP) {
BattleSystem_CheckTypeChart(param0, param1, v6, v7, param2, v2, 0, &v8);
BattleSystem_ApplyTypeChart(param0, param1, v6, v7, param2, v2, 0, &v8);
}

if ((v8 & 0x8) == 0) {
Expand All @@ -3489,7 +3489,7 @@ static BOOL ov14_022235F0 (BattleSystem * param0, BattleContext * param1, int pa
v8 = 0;

if (param1->battleMons[v3].curHP) {
BattleSystem_CheckTypeChart(param0, param1, v6, v7, param2, v3, 0, &v8);
BattleSystem_ApplyTypeChart(param0, param1, v6, v7, param2, v3, 0, &v8);
}

if ((v8 & 0x8) == 0) {
Expand Down Expand Up @@ -3525,7 +3525,7 @@ static BOOL ov14_022235F0 (BattleSystem * param0, BattleContext * param1, int pa
v8 = 0;

if (param1->battleMons[v2].curHP) {
ov16_022552D4(param1, v6, v7, Pokemon_GetValue(v12, MON_DATA_ABILITY, NULL), Battler_Ability(param1, v2), Battler_HeldItemEffect(param1, v2), BattleMon_Get(param1, v2, 27, NULL), BattleMon_Get(param1, v2, 28, NULL), &v8);
BattleSystem_CalcEffectiveness(param1, v6, v7, Pokemon_GetValue(v12, MON_DATA_ABILITY, NULL), Battler_Ability(param1, v2), Battler_HeldItemEffect(param1, v2), BattleMon_Get(param1, v2, 27, NULL), BattleMon_Get(param1, v2, 28, NULL), &v8);
}

if (v8 & 0x2) {
Expand All @@ -3538,7 +3538,7 @@ static BOOL ov14_022235F0 (BattleSystem * param0, BattleContext * param1, int pa
v8 = 0;

if (param1->battleMons[v3].curHP) {
ov16_022552D4(param1, v6, v7, Pokemon_GetValue(v12, MON_DATA_ABILITY, NULL), Battler_Ability(param1, v3), Battler_HeldItemEffect(param1, v3), BattleMon_Get(param1, v3, 27, NULL), BattleMon_Get(param1, v3, 28, NULL), &v8);
BattleSystem_CalcEffectiveness(param1, v6, v7, Pokemon_GetValue(v12, MON_DATA_ABILITY, NULL), Battler_Ability(param1, v3), Battler_HeldItemEffect(param1, v3), BattleMon_Get(param1, v3, 27, NULL), BattleMon_Get(param1, v3, 28, NULL), &v8);
}

if (v8 & 0x2) {
Expand All @@ -3564,7 +3564,7 @@ static BOOL ov14_022235F0 (BattleSystem * param0, BattleContext * param1, int pa
v8 = 0;

if (param1->battleMons[v2].curHP) {
ov16_022552D4(param1, v6, v7, Pokemon_GetValue(v12, MON_DATA_ABILITY, NULL), Battler_Ability(param1, v2), Battler_HeldItemEffect(param1, v2), BattleMon_Get(param1, v2, 27, NULL), BattleMon_Get(param1, v2, 28, NULL), &v8);
BattleSystem_CalcEffectiveness(param1, v6, v7, Pokemon_GetValue(v12, MON_DATA_ABILITY, NULL), Battler_Ability(param1, v2), Battler_HeldItemEffect(param1, v2), BattleMon_Get(param1, v2, 27, NULL), BattleMon_Get(param1, v2, 28, NULL), &v8);
}

if (v8 == 0) {
Expand All @@ -3577,7 +3577,7 @@ static BOOL ov14_022235F0 (BattleSystem * param0, BattleContext * param1, int pa
v8 = 0;

if (param1->battleMons[v3].curHP) {
ov16_022552D4(param1, v6, v7, Pokemon_GetValue(v12, MON_DATA_ABILITY, NULL), Battler_Ability(param1, v3), Battler_HeldItemEffect(param1, v3), BattleMon_Get(param1, v3, 27, NULL), BattleMon_Get(param1, v3, 28, NULL), &v8);
BattleSystem_CalcEffectiveness(param1, v6, v7, Pokemon_GetValue(v12, MON_DATA_ABILITY, NULL), Battler_Ability(param1, v3), Battler_HeldItemEffect(param1, v3), BattleMon_Get(param1, v3, 27, NULL), BattleMon_Get(param1, v3, 28, NULL), &v8);
}

if (v8 == 0) {
Expand Down Expand Up @@ -3613,7 +3613,7 @@ static BOOL ov14_02223B34 (BattleSystem * param0, BattleContext * param1, int pa

if (v4) {
v1 = 0;
BattleSystem_CheckTypeChart(param0, param1, v4, v5, param2, v2, 0, &v1);
BattleSystem_ApplyTypeChart(param0, param1, v4, v5, param2, v2, 0, &v1);

if (v1 & 0x2) {
if (param3) {
Expand Down Expand Up @@ -3641,7 +3641,7 @@ static BOOL ov14_02223B34 (BattleSystem * param0, BattleContext * param1, int pa

if (v4) {
v1 = 0;
BattleSystem_CheckTypeChart(param0, param1, v4, v5, param2, v2, 0, &v1);
BattleSystem_ApplyTypeChart(param0, param1, v4, v5, param2, v2, 0, &v1);

if (v1 & 0x2) {
if (param3) {
Expand Down Expand Up @@ -3760,7 +3760,7 @@ static BOOL ov14_02223E10 (BattleSystem * param0, BattleContext * param1, int pa
v6 = 0;
v5 = ov14_0222327C(param0, param1, param1->moveHitBattler[param2], param1->moveHit[param2]);

ov16_022552D4(param1, param1->moveHit[param2], v5, Battler_Ability(param1, param1->moveHitBattler[param2]), Pokemon_GetValue(v9, MON_DATA_ABILITY, NULL), BattleSystem_GetItemData(param1, Pokemon_GetValue(v9, MON_DATA_HELD_ITEM, NULL), 1), Pokemon_GetValue(v9, MON_DATA_TYPE_1, NULL), Pokemon_GetValue(v9, MON_DATA_TYPE_2, NULL), &v6);
BattleSystem_CalcEffectiveness(param1, param1->moveHit[param2], v5, Battler_Ability(param1, param1->moveHitBattler[param2]), Pokemon_GetValue(v9, MON_DATA_ABILITY, NULL), BattleSystem_GetItemData(param1, Pokemon_GetValue(v9, MON_DATA_HELD_ITEM, NULL), 1), Pokemon_GetValue(v9, MON_DATA_TYPE_1, NULL), Pokemon_GetValue(v9, MON_DATA_TYPE_2, NULL), &v6);

if (v6 & param3) {
for (v1 = 0; v1 < 4; v1++) {
Expand All @@ -3769,7 +3769,7 @@ static BOOL ov14_02223E10 (BattleSystem * param0, BattleContext * param1, int pa

if (v4) {
v6 = 0;
ov16_022552D4(param1, v4, v5, Pokemon_GetValue(v9, MON_DATA_ABILITY, NULL), Battler_Ability(param1, param1->moveHitBattler[param2]), Battler_HeldItemEffect(param1, param1->moveHitBattler[param2]), BattleMon_Get(param1, param1->moveHitBattler[param2], 27, NULL), BattleMon_Get(param1, param1->moveHitBattler[param2], 28, NULL), &v6);
BattleSystem_CalcEffectiveness(param1, v4, v5, Pokemon_GetValue(v9, MON_DATA_ABILITY, NULL), Battler_Ability(param1, param1->moveHitBattler[param2]), Battler_HeldItemEffect(param1, param1->moveHitBattler[param2]), BattleMon_Get(param1, param1->moveHitBattler[param2], 27, NULL), BattleMon_Get(param1, param1->moveHitBattler[param2], 28, NULL), &v6);

if (v6 & 0x2) {
if ((BattleSystem_RandNext(param0) % param4) == 0) {
Expand Down
Loading

0 comments on commit c30b9cb

Please sign in to comment.