Skip to content

Commit

Permalink
Merge pull request #83 from lhearachel/battle-dev
Browse files Browse the repository at this point in the history
Document JumpToMove and CheckCritical commands
  • Loading branch information
lhearachel authored Oct 13, 2023
2 parents 9e2fd83 + 5ba21a4 commit 5d7407f
Show file tree
Hide file tree
Showing 7 changed files with 266 additions and 214 deletions.
18 changes: 17 additions & 1 deletion include/overlay016/ov16_0223DF00.h
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,9 @@

#include "enums.h"

#define ENEMY_IN_SLOT_RIGHT 0
#define ENEMY_IN_SLOT_LEFT 2

UnkStruct_02018340 * ov16_0223DF00(BattleSystem * param0);
UnkStruct_0205AA50 * ov16_0223DF04(BattleSystem * param0, int param1);
u32 BattleSystem_BattleType(BattleSystem * param0);
Expand Down Expand Up @@ -120,7 +123,20 @@ int ov16_0223E22C(BattleSystem * param0);
int ov16_0223E240(BattleSystem * param0);
int BattleSystem_MapHeader(BattleSystem * param0);
int BattleSystem_Partner(BattleSystem * param0, int param1);
int ov16_0223E2A4(BattleSystem * param0, int param1, int param2);

/**
* @brief Get the battler who is an enemy of the input attacker and occupies
* a particular slot on the opposing team.
*
* If the battle is a double-battle, then this will only ever return the
* singular opponent.
*
* @param battleSys
* @param attacker
* @param slot
* @return Battler who is an enemy and in the given slot on the enemy team.
*/
int BattleSystem_EnemyInSlot(BattleSystem *battleSys, int attacker, int slot);
BOOL ov16_0223E30C(BattleSystem * param0, int param1, int param2, int param3, int param4);
u32 BattleSystem_BattleStatus(BattleSystem * param0);
int ov16_0223EBF8(BattleSystem * param0);
Expand Down
37 changes: 35 additions & 2 deletions include/overlay016/ov16_0225177C.h
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,26 @@ void BattleSystem_NoExpGain(BattleContext * param0, int param1);
void BattleSystem_FlagExpGain(BattleSystem * param0, BattleContext * param1, int param2);
BOOL BattleSystem_CheckPrimaryEffect(BattleSystem * param0, BattleContext * param1, int * param2);
BOOL BattleSystem_TriggerSecondaryEffect(BattleSystem *battleSys, BattleContext *battleCtx, int *nextSeq);
int BattleSystem_Defender(BattleSystem * param0, BattleContext * param1, int param2, u16 param3, int param4, int param5);

/**
* @brief Find the defender for the move.
*
* The defender can be chosen at random in certain scenarios, but only while
* the randomize parameter is TRUE:
*
* 1. The move's range is Me First
* 2. The move's range is Acupressure
* 3. The move is a standard single-target attack, e.g., Thunderbolt
*
* @param battleSys
* @param battleCtx
* @param attacker
* @param move The move being used
* @param randomize If TRUE, permit randomization of target-selection for certain moves
* @param inRange An input range to prefer for the move over whatever range is set on the move data
* @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);
void BattleMon_CopyToParty(BattleSystem * param0, BattleContext * param1, int param2);
Expand Down Expand Up @@ -335,7 +354,21 @@ int BattleSystem_CheckImmunityAbilities(BattleContext * param0, int param1, int
BOOL BattleSystem_TriggerTurnEndAbility(BattleSystem * param0, BattleContext * param1, int param2);
int BattleSystem_Divide(int param0, int param1);
int BattleSystem_ShowMonChecks(BattleSystem * param0, BattleContext * param1);
int BattleSystem_RandomOpponent(BattleSystem * param0, BattleContext * param1, int param2);

/**
* @brief Pick a random opponent for the given attacker.
*
* In a single-battle, this will always return the lone opponent.
*
* In a double-battle, if one of the two opponents has fainted, then the other
* opponent will always be chosen.
*
* @param battleSys
* @param battleCtx
* @param attacker
* @return A random opponent of the attacker's.
*/
int BattleSystem_RandomOpponent(BattleSystem *battleSys, BattleContext *battleCtx, int attacker);
BOOL BattleSystem_TriggerAbilityOnHit(BattleSystem *battleSys, BattleContext *battleCtx, int *nextSeq);
BOOL BattleSystem_RecoverStatusByAbility(BattleSystem * param0, BattleContext * param1, int param2, int param3);
BOOL ov16_022577A4(BattleContext * param0, int param1, int param2);
Expand Down
14 changes: 7 additions & 7 deletions src/overlay016/battle_controller.c
Original file line number Diff line number Diff line change
Expand Up @@ -1901,17 +1901,17 @@ static void BattleController_TurnEnd(BattleSystem *battleSys, BattleContext *bat

static void BattleController_FightCommand(BattleSystem *battleSys, BattleContext *battleCtx)
{
BOOL overrideMoveChoice = FALSE;
BOOL randomizeTarget = FALSE;
battleCtx->attacker = battleCtx->battlerActionOrder[battleCtx->turnOrderCounter];

if (ATTACKER_TURN_FLAGS.struggling) {
battleCtx->moveTemp = MOVE_STRUGGLE;
overrideMoveChoice = TRUE;
randomizeTarget = TRUE;
} else if (ATTACKING_MON.moveEffectsData.encoredMove
&& ATTACKING_MON.moveEffectsData.encoredMove == ATTACKING_MON.moves[ATTACKING_MON.moveEffectsData.encoredMoveSlot]) {
// Attacker is locked into one of its moves by Encore
battleCtx->moveTemp = ATTACKING_MON.moveEffectsData.encoredMove;
overrideMoveChoice = TRUE;
randomizeTarget = TRUE;
} else if (ATTACKING_MON.moveEffectsData.encoredMove
&& ATTACKING_MON.moveEffectsData.encoredMove != ATTACKING_MON.moves[ATTACKING_MON.moveEffectsData.encoredMoveSlot]) {
// Attacker is Encored, but does not actually know the move in the Encored slot. This can
Expand All @@ -1922,7 +1922,7 @@ static void BattleController_FightCommand(BattleSystem *battleSys, BattleContext
ATTACKING_MON.moveEffectsData.encoredMove = MOVE_NONE;
ATTACKING_MON.moveEffectsData.encoredMoveSlot = 0;
ATTACKING_MON.moveEffectsData.encoredTurns = 0;
overrideMoveChoice = TRUE;
randomizeTarget = TRUE;
} else if (BattleSystem_CanPickCommand(battleCtx, battleCtx->attacker) == FALSE) {
// Relock the attacker into its move. There should be no override here, as the attacker
// should not have been able to choose any input.
Expand All @@ -1931,14 +1931,14 @@ static void BattleController_FightCommand(BattleSystem *battleSys, BattleContext
// If the attacker somehow selected a move that it does not know, prefer the move that's
// actually in the chosen slot.
battleCtx->moveTemp = ATTACKING_MON.moves[battleCtx->moveSlot[battleCtx->attacker]];
overrideMoveChoice = TRUE;
randomizeTarget = TRUE;
} else {
battleCtx->moveTemp = ATTACKING_MON.moves[battleCtx->moveSlot[battleCtx->attacker]];
}

battleCtx->moveCur = battleCtx->moveTemp;
battleCtx->command = BATTLE_CONTROL_BEFORE_MOVE;
battleCtx->defender = BattleSystem_Defender(battleSys, battleCtx, battleCtx->attacker, battleCtx->moveTemp, overrideMoveChoice, 0);
battleCtx->defender = BattleSystem_Defender(battleSys, battleCtx, battleCtx->attacker, battleCtx->moveTemp, randomizeTarget, 0);

BattleIO_ClearMessageBox(battleSys);
}
Expand Down Expand Up @@ -2225,7 +2225,7 @@ static int BattleController_CheckObedience(BattleSystem *battleSys, BattleContex
ATTACKING_MOVE = rand2;
battleCtx->moveTemp = ATTACKING_MON.moves[ATTACKING_MOVE];
battleCtx->moveCur = battleCtx->moveTemp;
battleCtx->defender = BattleSystem_Defender(battleSys, battleCtx, battleCtx->attacker, battleCtx->moveTemp, 1, 0);
battleCtx->defender = BattleSystem_Defender(battleSys, battleCtx, battleCtx->attacker, battleCtx->moveTemp, TRUE, 0);

if (battleCtx->defender == BATTLER_NONE) {
ATTACKER_ACTION[BATTLE_ACTION_CHOOSE_TARGET] = BattleSystem_RandomOpponent(battleSys, battleCtx, battleCtx->attacker);
Expand Down
99 changes: 69 additions & 30 deletions src/overlay016/battle_script.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,8 +139,8 @@ static BOOL BtlCmd_IfMonData(BattleSystem *battleSys, BattleContext *battleCtx);
static BOOL BtlCmd_FadeOut(BattleSystem *battleSys, BattleContext *battleCtx);
static BOOL BtlCmd_JumpToSub(BattleSystem *battleSys, BattleContext *battleCtx);
static BOOL BtlCmd_JumpToBattleEffect(BattleSystem *battleSys, BattleContext *battleCtx);
static BOOL ov16_02241C28(BattleSystem * param0, BattleContext * param1);
static BOOL ov16_02241CD0(BattleSystem * param0, BattleContext * param1);
static BOOL BtlCmd_JumpToMove(BattleSystem *battleSys, BattleContext *battleCtx);
static BOOL BtlCmd_CheckCritical(BattleSystem *battleSys, BattleContext *battleCtx);
static BOOL ov16_02241D34(BattleSystem * param0, BattleContext * param1);
static BOOL ov16_02241EB0(BattleSystem * param0, BattleContext * param1);
static BOOL ov16_02241EF0(BattleSystem * param0, BattleContext * param1);
Expand Down Expand Up @@ -399,8 +399,8 @@ static const BtlCmd sBattleCommands[] = {
BtlCmd_FadeOut,
BtlCmd_JumpToSub,
BtlCmd_JumpToBattleEffect,
ov16_02241C28,
ov16_02241CD0,
BtlCmd_JumpToMove,
BtlCmd_CheckCritical,
ov16_02241D34,
ov16_02241EB0,
ov16_02241EF0,
Expand Down Expand Up @@ -2318,45 +2318,84 @@ static BOOL BtlCmd_JumpToBattleEffect(BattleSystem *battleSys, BattleContext *ba
return FALSE;
}

static BOOL ov16_02241C28 (BattleSystem * param0, BattleContext * param1)
/**
* @brief Jump to the move sequence for the chosen move.
*
* This is specifically for moves which call other moves (e.g., Assist, Me
* First, Metronome, Sleep Talk) by setting battleCtx->msgMoveTemp.
*
* Inputs:
* 1. A flag indicating if the target is set on input. In practice, this is
* always FALSE in vanilla.
*
* Side effects:
* - The system control flag to skip the attack message is turned off.
* - The system control flag signalling that the move's animation has played
* is turned off.
* - battleCtx->moveCur is reassigned to battleCtx->msgMoveTemp.
* - The defender is assigned for the move.
* - The battler's chosen target is reassigned to the assigned defender.
*
* @param battleSys
* @param battleCtx
* @return FALSE
*/
static BOOL BtlCmd_JumpToMove(BattleSystem *battleSys, BattleContext *battleCtx)
{
int v0;

BattleScript_Iter(param1, 1);

v0 = BattleScript_Read(param1);
BattleScript_Iter(battleCtx, 1);
BOOL targetIsSet = BattleScript_Read(battleCtx);

param1->battleStatusMask &= (0x1 ^ 0xffffffff);
param1->battleStatusMask &= (0x4000 ^ 0xffffffff);
param1->moveCur = param1->msgMoveTemp;
battleCtx->battleStatusMask &= ~SYSCTL_SKIP_ATTACK_MESSAGE;
battleCtx->battleStatusMask &= ~SYSCTL_PLAYED_MOVE_ANIMATION;
battleCtx->moveCur = battleCtx->msgMoveTemp;

if (v0 == 0) {
param1->defender = BattleSystem_Defender(param0, param1, param1->attacker, param1->msgMoveTemp, 1, 0);
BattleSystem_RedirectTarget(param0, param1, param1->attacker, param1->msgMoveTemp);
param1->battlerActions[param1->attacker][1] = param1->defender;
if (targetIsSet == FALSE) {
battleCtx->defender = BattleSystem_Defender(battleSys, battleCtx, battleCtx->attacker, battleCtx->msgMoveTemp, TRUE, 0);
BattleSystem_RedirectTarget(battleSys, battleCtx, battleCtx->attacker, battleCtx->msgMoveTemp);
battleCtx->battlerActions[battleCtx->attacker][BATTLE_ACTION_CHOOSE_TARGET] = battleCtx->defender;
}

if (param1->defender == 0xff) {
param1->commandNext = 38;
BattleScript_Jump(param1, 1, (0 + 281));
if (battleCtx->defender == BATTLER_NONE) {
battleCtx->commandNext = BATTLE_CONTROL_UPDATE_MOVE_BUFFERS;
BattleScript_Jump(battleCtx, NARC_INDEX_BATTLE__SKILL__SUB_SEQ, BATTLE_SUBSEQ_NO_TARGET);
} else {
BattleScript_Jump(param1, 0, param1->moveCur);
BattleScript_Jump(battleCtx, NARC_INDEX_BATTLE__SKILL__WAZA_SEQ, battleCtx->moveCur);
}

return 0;
return FALSE;
}

static BOOL ov16_02241CD0 (BattleSystem * param0, BattleContext * param1)
/**
* @brief Check if a critical hit should occur.
*
* If the battle is either the catching tutorial or the player's first battle,
* then this will always flag no critical hits.
*
* Side effects:
* - battleCtx->criticalMul is set to the multiplier to be applied to the total
* move damage for a critical hit.
*
* @param battleSys
* @param battleCtx
* @return FALSE
*/
static BOOL BtlCmd_CheckCritical(BattleSystem *battleSys, BattleContext *battleCtx)
{
BattleScript_Iter(param1, 1);
BattleScript_Iter(battleCtx, 1);

if ((BattleSystem_BattleType(param0) & 0x400) || (BattleSystem_BattleStatus(param0) & 0x1)) {
param1->criticalMul = 1;
if ((BattleSystem_BattleType(battleSys) & BATTLE_TYPE_CATCH_TUTORIAL)
|| (BattleSystem_BattleStatus(battleSys) & BATTLE_STATUS_FIRST_BATTLE)) {
battleCtx->criticalMul = 1;
} else {
param1->criticalMul = BattleSystem_CalcCriticalMulti(param0, param1, param1->attacker, param1->defender, param1->criticalBoosts, BattleContext_Get(param0, param1, 0, param1->defender));
battleCtx->criticalMul = BattleSystem_CalcCriticalMulti(battleSys,
battleCtx,
battleCtx->attacker,
battleCtx->defender,
battleCtx->criticalBoosts,
BattleContext_Get(battleSys, battleCtx, BATTLECTX_SIDE_CONDITIONS_MASK, battleCtx->defender));
}

return 0;
return FALSE;
}

static BOOL ov16_02241D34 (BattleSystem * param0, BattleContext * param1)
Expand Down Expand Up @@ -5802,8 +5841,8 @@ static BOOL ov16_02246688 (BattleSystem * param0, BattleContext * param1)
BattleScript_Iter(param1, 1);

v0 = BattleScript_Read(param1);
v6 = ov16_0223E2A4(param0, param1->attacker, 0);
v7 = ov16_0223E2A4(param0, param1->attacker, 2);
v6 = BattleSystem_EnemyInSlot(param0, param1->attacker, 0);
v7 = BattleSystem_EnemyInSlot(param0, param1->attacker, 2);

param1->battleMons[v6].moveEffectsMask |= 0x40000000;
param1->battleMons[v7].moveEffectsMask |= 0x40000000;
Expand Down
26 changes: 13 additions & 13 deletions src/overlay016/ov16_0223DF00.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ int ov16_0223E22C(BattleSystem * param0);
int ov16_0223E240(BattleSystem * param0);
int BattleSystem_MapHeader(BattleSystem * param0);
int BattleSystem_Partner(BattleSystem *battleSys, int battler);
int ov16_0223E2A4(BattleSystem * param0, int param1, int param2);
int BattleSystem_EnemyInSlot(BattleSystem *battleSys, int attacker, int slot);
BOOL ov16_0223E30C(BattleSystem * param0, int param1, int param2, int param3, int param4);
u32 ov16_0223EBEC(BattleSystem * param0);
int ov16_0223EBF8(BattleSystem * param0);
Expand Down Expand Up @@ -543,26 +543,26 @@ int BattleSystem_Partner (BattleSystem *battleSys, int battler)
return i;
}

int ov16_0223E2A4 (BattleSystem * param0, int param1, int param2)
int BattleSystem_EnemyInSlot(BattleSystem *battleSys, int attacker, int slot)
{
int v0;
int v1;
u32 v2;

v1 = BattleSystem_MaxBattlers(param0);
v2 = BattleSystem_BattleType(param0);
int maxBattlers = BattleSystem_MaxBattlers(battleSys);
u32 battleType = BattleSystem_BattleType(battleSys);

if ((v2 & 0x2) == 0) {
return param1 ^ 1;
// In double battles, return the singular opponent
if ((battleType & BATTLE_TYPE_DOUBLES) == FALSE) {
return attacker ^ 1;
}

for (v0 = 0; v0 < v1; v0++) {
if ((v0 != param1) && ((BattleSystem_BattlerSlot(param0, v0) & 2) == param2) && (Battler_Side(param0, v0) != Battler_Side(param0, param1))) {
int battler;
for (battler = 0; battler < maxBattlers; battler++) {
if (battler != attacker
&& (BattleSystem_BattlerSlot(battleSys, battler) & 2) == slot
&& Battler_Side(battleSys, battler) != Battler_Side(battleSys, attacker)) {
break;
}
}

return v0;
return battler;
}

BOOL ov16_0223E30C (BattleSystem * param0, int param1, int param2, int param3, int param4)
Expand Down
Loading

0 comments on commit 5d7407f

Please sign in to comment.