Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document JumpToMove and CheckCritical commands #83

Merged
merged 3 commits into from
Oct 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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