Merge branch 'master' into PIE2

This commit is contained in:
PikalaxALT
2019-09-25 13:56:50 -04:00
committed by GitHub
203 changed files with 33707 additions and 96877 deletions
+115 -124
View File
@@ -1,16 +1,17 @@
#include "global.h"
#include "battle.h"
#include "battle_main.h"
#include "util.h"
#include "item.h"
#include "random.h"
#include "pokemon.h"
#include "battle_ai_script_commands.h"
#include "constants/species.h"
#include "constants/abilities.h"
#include "constants/battle_ai.h"
#include "constants/battle_move_effects.h"
#include "constants/moves.h"
extern u16 Random(void);
extern void sub_80C7164(void);
#define AI_ACTION_DONE 0x0001
#define AI_ACTION_FLEE 0x0002
#define AI_ACTION_WATCH 0x0004
@@ -20,8 +21,8 @@ extern void sub_80C7164(void);
#define AI_ACTION_UNK7 0x0040
#define AI_ACTION_UNK8 0x0080
#define AI_THINKING_STRUCT ((struct AI_ThinkingStruct *)(gBattleResources->ai))
#define BATTLE_HISTORY ((struct BattleHistory *)(gBattleResources->battleHistory))
#define AI_THINKING_STRUCT (gBattleResources->ai)
#define BATTLE_HISTORY (gBattleResources->battleHistory)
// AI states
enum
@@ -32,9 +33,16 @@ enum
AIState_DoNotProcess
};
/*
gAIScriptPtr is a pointer to the next battle AI cmd command to read.
when a command finishes processing, gAIScriptPtr is incremented by
the number of bytes that the current command had reserved for arguments
in order to read the next command correctly. refer to battle_ai_scripts.s for the
AI scripts.
*/
extern const u8 *gAIScriptPtr;
extern u8 *BattleAIs[];
extern u16 gLastUsedMove[];
extern u8 *gBattleAI_ScriptsTable[];
static void BattleAICmd_if_random_less_than(void);
static void BattleAICmd_if_random_greater_than(void);
@@ -131,6 +139,11 @@ static void BattleAICmd_if_level_compare(void);
static void BattleAICmd_if_taunted(void);
static void BattleAICmd_if_not_taunted(void);
static void RecordLastUsedMoveByTarget(void);
static void BattleAI_DoAIProcessing(void);
static void AIStackPushVar(const u8 *ptr);
static bool8 AIStackPop(void);
typedef void (*BattleAICmdFunc)(void);
static const BattleAICmdFunc sBattleAICmdTable[] =
@@ -248,23 +261,6 @@ static const u16 sDiscouragedPowerfulMoveEffects[] =
0xFFFF
};
// TODO: move these
extern u8 sBattler_AI;
extern const u32 gBitTable[]; // util.h
extern u32 gStatuses3[]; // battle_2.h
extern u16 gSideAffecting[2];
extern const struct BattleMove gBattleMoves[];
extern u16 gDynamicBasePower;
extern u8 gMoveResultFlags;
extern u8 gCritMultiplier;
extern u16 gCurrentMove;
extern s32 gBattleMoveDamage;
void BattleAI_SetupAIData(void);
void BattleAI_DoAIProcessing(void);
void AIStackPushVar(const u8 *ptr);
bool8 AIStackPop(void);
void BattleAI_HandleItemUseBeforeAISetup(void)
{
s32 i;
@@ -275,9 +271,9 @@ void BattleAI_HandleItemUseBeforeAISetup(void)
// Items are allowed to use in ONLY trainer battles.
// TODO: Use proper flags
if ((gBattleTypeFlags & 0x8)
if ((gBattleTypeFlags & BATTLE_TYPE_TRAINER)
&& (gTrainerBattleOpponent_A != 0x400)
&& !(gBattleTypeFlags & 0x80982)
&& !(gBattleTypeFlags & (BATTLE_TYPE_TRAINER_TOWER | BATTLE_TYPE_EREADER_TRAINER | BATTLE_TYPE_BATTLE_TOWER | BATTLE_TYPE_SAFARI | BATTLE_TYPE_LINK))
)
{
for (i = 0; i < 4; i++)
@@ -318,7 +314,7 @@ void BattleAI_SetupAIData(void)
}
gBattleResources->AI_ScriptsStack->size = 0;
sBattler_AI = gActiveBattler;
gBattlerAttacker = gActiveBattler;
// Decide a random target battlerId in doubles.
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
@@ -331,7 +327,7 @@ void BattleAI_SetupAIData(void)
// There's only one choice in single battles.
else
{
gBattlerTarget = sBattler_AI ^ BIT_SIDE;
gBattlerTarget = gBattlerAttacker ^ BIT_SIDE;
}
// Choose proper trainer ai scripts.
@@ -348,12 +344,12 @@ void BattleAI_SetupAIData(void)
}
else if (!(gBattleTypeFlags & (0x80900)) && (gTrainerBattleOpponent_A != 0x400)) // _080C6ECC
{
if(gBattleTypeFlags & (0x80 << 10))
if (gBattleTypeFlags & (0x80 << 10))
{
AI_THINKING_STRUCT->aiFlags = 1;
return;
}
else if(gBattleTypeFlags & (0x80 << 11))
else if (gBattleTypeFlags & (0x80 << 11))
{
AI_THINKING_STRUCT->aiFlags = 7;
return;
@@ -367,14 +363,14 @@ void BattleAI_SetupAIData(void)
AI_THINKING_STRUCT->aiFlags = gTrainers[gTrainerBattleOpponent_A].aiFlags;
}
u8 BattleAI_GetAIActionToUse(void)
u8 BattleAI_ChooseMoveOrAction(void)
{
u8 currentMoveArray[MAX_MON_MOVES];
u8 consideredMoveArray[MAX_MON_MOVES];
u8 numOfBestMoves;
s32 i;
sub_80C7164();
RecordLastUsedMoveByTarget();
while (AI_THINKING_STRUCT->aiFlags != 0)
{
if (AI_THINKING_STRUCT->aiFlags & 1)
@@ -415,7 +411,7 @@ u8 BattleAI_GetAIActionToUse(void)
return consideredMoveArray[Random() % numOfBestMoves]; // break any ties that exist.
}
void BattleAI_DoAIProcessing(void)
static void BattleAI_DoAIProcessing(void)
{
while (AI_THINKING_STRUCT->aiState != AIState_FinishedProcessing)
{
@@ -424,14 +420,14 @@ void BattleAI_DoAIProcessing(void)
case AIState_DoNotProcess: //Needed to match.
break;
case AIState_SettingUp:
gAIScriptPtr = BattleAIs[AI_THINKING_STRUCT->aiLogicId]; // set the AI ptr.
if (gBattleMons[sBattler_AI].pp[AI_THINKING_STRUCT->movesetIndex] == 0)
gAIScriptPtr = gBattleAI_ScriptsTable[AI_THINKING_STRUCT->aiLogicId]; // set the AI ptr.
if (gBattleMons[gBattlerAttacker].pp[AI_THINKING_STRUCT->movesetIndex] == 0)
{
AI_THINKING_STRUCT->moveConsidered = 0; // don't consider a move you have 0 PP for, idiot.
}
else
{
AI_THINKING_STRUCT->moveConsidered = gBattleMons[sBattler_AI].moves[AI_THINKING_STRUCT->movesetIndex];
AI_THINKING_STRUCT->moveConsidered = gBattleMons[gBattlerAttacker].moves[AI_THINKING_STRUCT->movesetIndex];
}
AI_THINKING_STRUCT->aiState++;
break;
@@ -458,7 +454,7 @@ void BattleAI_DoAIProcessing(void)
}
}
void sub_80C7164(void)
static void RecordLastUsedMoveByTarget(void)
{
s32 i;
@@ -466,30 +462,31 @@ void sub_80C7164(void)
{
if (BATTLE_HISTORY->usedMoves[gBattlerTarget >> 1][i] == 0)
{
BATTLE_HISTORY->usedMoves[gBattlerTarget >> 1][i] = gLastUsedMove[gBattlerTarget];
BATTLE_HISTORY->usedMoves[gBattlerTarget >> 1][i] = gLastMoves[gBattlerTarget];
return;
}
}
}
void sub_80C71A8(u8 a)
// not used
static void ClearBattlerMoveHistory(u8 battlerId)
{
s32 i;
for (i = 0; i < 8; i++)
BATTLE_HISTORY->usedMoves[a / 2][i] = 0;
BATTLE_HISTORY->usedMoves[battlerId / 2][i] = MOVE_NONE;
}
void sub_80C71D0(u8 a, u8 b)
void RecordAbilityBattle(u8 battlerId, u8 abilityId)
{
if (GetBattlerSide(a) == 0)
BATTLE_HISTORY->abilities[GetBattlerPosition(a) & 1] = b;
if (GetBattlerSide(battlerId) == 0)
BATTLE_HISTORY->abilities[GetBattlerPosition(battlerId) & 1] = abilityId;
}
void sub_80C7208(u8 a, u8 b)
void RecordItemEffectBattle(u8 battlerId, u8 itemEffect)
{
if (GetBattlerSide(a) == 0)
BATTLE_HISTORY->itemEffects[GetBattlerPosition(a) & 1] = b;
if (GetBattlerSide(battlerId) == 0)
BATTLE_HISTORY->itemEffects[GetBattlerPosition(battlerId) & 1] = itemEffect;
}
static void BattleAICmd_if_random_less_than(void)
@@ -544,7 +541,7 @@ static void BattleAICmd_if_hp_less_than(void)
u16 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -559,7 +556,7 @@ static void BattleAICmd_if_hp_more_than(void)
u16 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -574,7 +571,7 @@ static void BattleAICmd_if_hp_equal(void)
u16 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -589,7 +586,7 @@ static void BattleAICmd_if_hp_not_equal(void)
u16 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -605,7 +602,7 @@ static void BattleAICmd_if_status(void)
u32 arg;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -623,7 +620,7 @@ static void BattleAICmd_if_not_status(void)
u32 arg;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -641,7 +638,7 @@ static void BattleAICmd_if_status2(void)
u32 arg;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -659,7 +656,7 @@ static void BattleAICmd_if_not_status2(void)
u32 arg;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -677,7 +674,7 @@ static void BattleAICmd_if_status3(void)
u32 arg;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -695,7 +692,7 @@ static void BattleAICmd_if_not_status3(void)
u32 arg;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -713,14 +710,14 @@ static void BattleAICmd_if_status4(void)
u32 arg1, arg2;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
arg1 = GetBattlerPosition(index) & 1;
arg2 = T1_READ_32(gAIScriptPtr + 2);
if ((gSideAffecting[arg1] & arg2) != 0)
if ((gSideStatuses[arg1] & arg2) != 0)
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6);
else
gAIScriptPtr += 10;
@@ -732,14 +729,14 @@ static void BattleAICmd_if_not_status4(void)
u32 arg1, arg2;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
arg1 = GetBattlerPosition(index) & 1;
arg2 = T1_READ_32(gAIScriptPtr + 2);
if ((gSideAffecting[arg1] & arg2) == 0)
if ((gSideStatuses[arg1] & arg2) == 0)
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 6);
else
gAIScriptPtr += 10;
@@ -907,8 +904,8 @@ static void BattleAICmd_if_user_can_damage(void)
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[sBattler_AI].moves[i] != 0
&& gBattleMoves[gBattleMons[sBattler_AI].moves[i]].power != 0)
if (gBattleMons[gBattlerAttacker].moves[i] != 0
&& gBattleMoves[gBattleMons[gBattlerAttacker].moves[i]].power != 0)
break;
}
if (i == MAX_MON_MOVES)
@@ -923,8 +920,8 @@ static void BattleAICmd_if_user_cant_damage(void)
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[sBattler_AI].moves[i] != 0
&& gBattleMoves[gBattleMons[sBattler_AI].moves[i]].power != 0)
if (gBattleMons[gBattlerAttacker].moves[i] != 0
&& gBattleMoves[gBattleMons[gBattlerAttacker].moves[i]].power != 0)
break;
}
if (i != MAX_MON_MOVES)
@@ -944,13 +941,13 @@ static void BattleAICmd_get_type(void)
switch (gAIScriptPtr[1])
{
case 1: // player primary type
AI_THINKING_STRUCT->funcResult = gBattleMons[sBattler_AI].type1;
AI_THINKING_STRUCT->funcResult = gBattleMons[gBattlerAttacker].type1;
break;
case 0: // enemy primary type
AI_THINKING_STRUCT->funcResult = gBattleMons[gBattlerTarget].type1;
break;
case 3: // player secondary type
AI_THINKING_STRUCT->funcResult = gBattleMons[sBattler_AI].type2;
AI_THINKING_STRUCT->funcResult = gBattleMons[gBattlerAttacker].type2;
break;
case 2: // enemy secondary type
AI_THINKING_STRUCT->funcResult = gBattleMons[gBattlerTarget].type2;
@@ -992,17 +989,17 @@ static void BattleAICmd_is_most_powerful_move(void)
{
for (i = 0; sDiscouragedPowerfulMoveEffects[i] != 0xFFFF; i++)
{
if (gBattleMoves[gBattleMons[sBattler_AI].moves[checkedMove]].effect == sDiscouragedPowerfulMoveEffects[i])
if (gBattleMoves[gBattleMons[gBattlerAttacker].moves[checkedMove]].effect == sDiscouragedPowerfulMoveEffects[i])
break;
}
if (gBattleMons[sBattler_AI].moves[checkedMove] != MOVE_NONE
if (gBattleMons[gBattlerAttacker].moves[checkedMove] != MOVE_NONE
&& sDiscouragedPowerfulMoveEffects[i] == 0xFFFF
&& gBattleMoves[gBattleMons[sBattler_AI].moves[checkedMove]].power > 1)
&& gBattleMoves[gBattleMons[gBattlerAttacker].moves[checkedMove]].power > 1)
{
gCurrentMove = gBattleMons[sBattler_AI].moves[checkedMove];
AI_CalcDmg(sBattler_AI, gBattlerTarget);
TypeCalc(gCurrentMove, sBattler_AI, gBattlerTarget);
gCurrentMove = gBattleMons[gBattlerAttacker].moves[checkedMove];
AI_CalcDmg(gBattlerAttacker, gBattlerTarget);
TypeCalc(gCurrentMove, gBattlerAttacker, gBattlerTarget);
moveDmgs[checkedMove] = gBattleMoveDamage * AI_THINKING_STRUCT->simulatedRNG[checkedMove] / 100;
if (moveDmgs[checkedMove] == 0)
moveDmgs[checkedMove] = 1;
@@ -1035,9 +1032,9 @@ static void BattleAICmd_is_most_powerful_move(void)
static void BattleAICmd_get_move(void)
{
if (gAIScriptPtr[1] == USER)
AI_THINKING_STRUCT->funcResult = gLastUsedMove[sBattler_AI];
AI_THINKING_STRUCT->funcResult = gLastMoves[gBattlerAttacker];
else
AI_THINKING_STRUCT->funcResult = gLastUsedMove[gBattlerTarget];
AI_THINKING_STRUCT->funcResult = gLastMoves[gBattlerTarget];
gAIScriptPtr += 2;
}
@@ -1060,7 +1057,7 @@ static void BattleAICmd_if_arg_not_equal(void)
static void BattleAICmd_if_would_go_first(void)
{
if (GetWhoStrikesFirst(sBattler_AI, gBattlerTarget, TRUE) == gAIScriptPtr[1])
if (GetWhoStrikesFirst(gBattlerAttacker, gBattlerTarget, TRUE) == gAIScriptPtr[1])
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
else
gAIScriptPtr += 6;
@@ -1068,7 +1065,7 @@ static void BattleAICmd_if_would_go_first(void)
static void BattleAICmd_if_would_not_go_first(void)
{
if (GetWhoStrikesFirst(sBattler_AI, gBattlerTarget, TRUE) != gAIScriptPtr[1])
if (GetWhoStrikesFirst(gBattlerAttacker, gBattlerTarget, TRUE) != gAIScriptPtr[1])
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
else
gAIScriptPtr += 6;
@@ -1092,7 +1089,7 @@ static void BattleAICmd_count_alive_pokemon(void)
AI_THINKING_STRUCT->funcResult = 0;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -1145,7 +1142,7 @@ static void BattleAICmd_get_ability(void)
u8 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -1218,11 +1215,11 @@ static void BattleAICmd_get_highest_possible_damage(void)
for (i = 0; i < 4; i++)
{
gBattleMoveDamage = 40;
gCurrentMove = gBattleMons[sBattler_AI].moves[i];
gCurrentMove = gBattleMons[gBattlerAttacker].moves[i];
if (gCurrentMove != 0)
{
TypeCalc(gCurrentMove, sBattler_AI, gBattlerTarget);
TypeCalc(gCurrentMove, gBattlerAttacker, gBattlerTarget);
if (gBattleMoveDamage == 120) // Super effective STAB.
gBattleMoveDamage = AI_EFFECTIVENESS_x2;
@@ -1257,7 +1254,7 @@ static void BattleAICmd_if_type_effectiveness(void)
gBattleMoveDamage = AI_EFFECTIVENESS_x1;
gCurrentMove = AI_THINKING_STRUCT->moveConsidered;
TypeCalc(gCurrentMove, sBattler_AI, gBattlerTarget);
TypeCalc(gCurrentMove, gBattlerAttacker, gBattlerTarget);
if (gBattleMoveDamage == 120) // Super effective STAB.
gBattleMoveDamage = AI_EFFECTIVENESS_x2;
@@ -1373,7 +1370,7 @@ static void BattleAICmd_get_weather(void)
AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_RAIN;
if (gBattleWeather & WEATHER_SANDSTORM_ANY)
AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SANDSTORM;
if (gBattleWeather & WEATHER_SUNNY_ANY)
if (gBattleWeather & WEATHER_SUN_ANY)
AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_SUNNY;
if (gBattleWeather & WEATHER_HAIL)
AI_THINKING_STRUCT->funcResult = WEATHER_TYPE_HAIL;
@@ -1402,7 +1399,7 @@ static void BattleAICmd_if_stat_level_less_than(void)
u32 party;
if (gAIScriptPtr[1] == USER)
party = sBattler_AI;
party = gBattlerAttacker;
else
party = gBattlerTarget;
@@ -1417,7 +1414,7 @@ static void BattleAICmd_if_stat_level_more_than(void)
u32 party;
if (gAIScriptPtr[1] == USER)
party = sBattler_AI;
party = gBattlerAttacker;
else
party = gBattlerTarget;
@@ -1432,7 +1429,7 @@ static void BattleAICmd_if_stat_level_equal(void)
u32 party;
if (gAIScriptPtr[1] == USER)
party = sBattler_AI;
party = gBattlerAttacker;
else
party = gBattlerTarget;
@@ -1447,7 +1444,7 @@ static void BattleAICmd_if_stat_level_not_equal(void)
u32 party;
if (gAIScriptPtr[1] == USER)
party = sBattler_AI;
party = gBattlerAttacker;
else
party = gBattlerTarget;
@@ -1471,8 +1468,8 @@ static void BattleAICmd_if_can_faint(void)
gMoveResultFlags = 0;
gCritMultiplier = 1;
gCurrentMove = AI_THINKING_STRUCT->moveConsidered;
AI_CalcDmg(sBattler_AI, gBattlerTarget);
TypeCalc(gCurrentMove, sBattler_AI, gBattlerTarget);
AI_CalcDmg(gBattlerAttacker, gBattlerTarget);
TypeCalc(gCurrentMove, gBattlerAttacker, gBattlerTarget);
gBattleMoveDamage = gBattleMoveDamage * AI_THINKING_STRUCT->simulatedRNG[AI_THINKING_STRUCT->movesetIndex] / 100;
@@ -1500,8 +1497,8 @@ static void BattleAICmd_if_cant_faint(void)
gMoveResultFlags = 0;
gCritMultiplier = 1;
gCurrentMove = AI_THINKING_STRUCT->moveConsidered;
AI_CalcDmg(sBattler_AI, gBattlerTarget);
TypeCalc(gCurrentMove, sBattler_AI, gBattlerTarget);
AI_CalcDmg(gBattlerAttacker, gBattlerTarget);
TypeCalc(gCurrentMove, gBattlerAttacker, gBattlerTarget);
gBattleMoveDamage = gBattleMoveDamage * AI_THINKING_STRUCT->simulatedRNG[AI_THINKING_STRUCT->movesetIndex] / 100;
@@ -1524,7 +1521,7 @@ static void BattleAICmd_if_has_move(void)
case 3:
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[sBattler_AI].moves[i] == *temp_ptr)
if (gBattleMons[gBattlerAttacker].moves[i] == *temp_ptr)
break;
}
if (i == MAX_MON_MOVES)
@@ -1558,7 +1555,7 @@ static void BattleAICmd_if_dont_have_move(void)
case 3:
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[sBattler_AI].moves[i] == *temp_ptr)
if (gBattleMons[gBattlerAttacker].moves[i] == *temp_ptr)
break;
}
if (i != MAX_MON_MOVES)
@@ -1591,7 +1588,7 @@ static void BattleAICmd_if_move_effect(void)
case 3:
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[sBattler_AI].moves[i] != 0 && gBattleMoves[gBattleMons[sBattler_AI].moves[i]].effect == gAIScriptPtr[2])
if (gBattleMons[gBattlerAttacker].moves[i] != 0 && gBattleMoves[gBattleMons[gBattlerAttacker].moves[i]].effect == gAIScriptPtr[2])
break;
}
if (i != MAX_MON_MOVES)
@@ -1603,7 +1600,7 @@ static void BattleAICmd_if_move_effect(void)
case 2:
for (i = 0; i < 8; i++)
{
if (gBattleMons[sBattler_AI].moves[i] != 0 && gBattleMoves[BATTLE_HISTORY->usedMoves[gBattlerTarget >> 1][i]].effect == gAIScriptPtr[2])
if (gBattleMons[gBattlerAttacker].moves[i] != 0 && gBattleMoves[BATTLE_HISTORY->usedMoves[gBattlerTarget >> 1][i]].effect == gAIScriptPtr[2])
break;
}
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3);
@@ -1620,7 +1617,7 @@ static void BattleAICmd_if_not_move_effect(void)
case 3:
for (i = 0; i < MAX_MON_MOVES; i++)
{
if (gBattleMons[sBattler_AI].moves[i] != 0 && gBattleMoves[gBattleMons[sBattler_AI].moves[i]].effect == gAIScriptPtr[2])
if (gBattleMons[gBattlerAttacker].moves[i] != 0 && gBattleMoves[gBattleMons[gBattlerAttacker].moves[i]].effect == gAIScriptPtr[2])
break;
}
if (i != MAX_MON_MOVES)
@@ -1644,13 +1641,13 @@ static void BattleAICmd_if_last_move_did_damage(void)
u8 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
if (gAIScriptPtr[2] == 0)
{
if (gDisableStructs[index].disabledMove == 0)
if (gDisableStructs[index].disabledMove == MOVE_NONE)
{
gAIScriptPtr += 7;
return;
@@ -1663,7 +1660,7 @@ static void BattleAICmd_if_last_move_did_damage(void)
gAIScriptPtr += 7;
return;
}
else if (gDisableStructs[index].encoredMove != 0)
else if (gDisableStructs[index].encoredMove != MOVE_NONE)
{
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 3);
return;
@@ -1707,22 +1704,22 @@ static void BattleAICmd_frlg_safari(void)
{
u8 var;
if(gBattleStruct->safariGoNearCounter)
if (gBattleStruct->safariGoNearCounter)
{
var = gBattleStruct->safariEscapeFactor * 2;
if(var > 20)
if (var > 20)
var = 20;
}
else if(gBattleStruct->safariPkblThrowCounter != 0) // _080C91DC
else if (gBattleStruct->safariPkblThrowCounter != 0) // _080C91DC
{
var = gBattleStruct->safariEscapeFactor / 4;
if(var == 0)
if (var == 0)
var = 1;
}
else
var = gBattleStruct->safariEscapeFactor;
var *= 5;
if((u8)(Random() % 100) < var)
if ((u8)(Random() % 100) < var)
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1);
else
gAIScriptPtr += 5;
@@ -1739,7 +1736,7 @@ static void BattleAICmd_get_hold_effect(void)
u16 side;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -1759,7 +1756,7 @@ static void BattleAICmd_get_gender(void)
u8 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -1773,7 +1770,7 @@ static void BattleAICmd_is_first_turn(void)
u8 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -1787,7 +1784,7 @@ static void BattleAICmd_get_stockpile_count(void)
u8 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -1808,17 +1805,11 @@ static void BattleAICmd_get_used_held_item(void)
u8 battlerId;
if (gAIScriptPtr[1] == AI_USER)
battlerId = sBattler_AI;
battlerId = gBattlerAttacker;
else
battlerId = gBattlerTarget;
// This is likely a leftover from Ruby's code and its ugly ewram access.
#ifdef NONMATCHING
AI_THINKING_STRUCT->funcResult = gBattleStruct->usedHeldItems[battlerId];
#else
AI_THINKING_STRUCT->funcResult = *(u8*)((u8*)(gBattleStruct) + offsetof(struct BattleStruct, usedHeldItems) + (battlerId * 2));
#endif // NONMATCHING
AI_THINKING_STRUCT->funcResult = ((u8 *)gBattleStruct->usedHeldItems)[battlerId * 2];
gAIScriptPtr += 2;
}
@@ -1848,7 +1839,7 @@ static void BattleAICmd_get_protect_count(void)
u8 index;
if (gAIScriptPtr[1] == USER)
index = sBattler_AI;
index = gBattlerAttacker;
else
index = gBattlerTarget;
@@ -1903,7 +1894,7 @@ static void BattleAICmd_if_level_compare(void)
switch (gAIScriptPtr[1])
{
case 0: // greater than
if (gBattleMons[sBattler_AI].level > gBattleMons[gBattlerTarget].level)
if (gBattleMons[gBattlerAttacker].level > gBattleMons[gBattlerTarget].level)
{
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
return;
@@ -1911,7 +1902,7 @@ static void BattleAICmd_if_level_compare(void)
gAIScriptPtr += 6;
return;
case 1: // less than
if (gBattleMons[sBattler_AI].level < gBattleMons[gBattlerTarget].level)
if (gBattleMons[gBattlerAttacker].level < gBattleMons[gBattlerTarget].level)
{
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
return;
@@ -1919,7 +1910,7 @@ static void BattleAICmd_if_level_compare(void)
gAIScriptPtr += 6;
return;
case 2: // equal
if (gBattleMons[sBattler_AI].level == gBattleMons[gBattlerTarget].level)
if (gBattleMons[gBattlerAttacker].level == gBattleMons[gBattlerTarget].level)
{
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 2);
return;
@@ -1931,7 +1922,7 @@ static void BattleAICmd_if_level_compare(void)
static void BattleAICmd_if_taunted(void)
{
if (gDisableStructs[gBattlerTarget].tauntTimer1 != 0)
if (gDisableStructs[gBattlerTarget].tauntTimer != 0)
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1);
else
gAIScriptPtr += 5;
@@ -1939,24 +1930,24 @@ static void BattleAICmd_if_taunted(void)
static void BattleAICmd_if_not_taunted(void)
{
if (gDisableStructs[gBattlerTarget].tauntTimer1 == 0)
if (gDisableStructs[gBattlerTarget].tauntTimer == 0)
gAIScriptPtr = T1_READ_PTR(gAIScriptPtr + 1);
else
gAIScriptPtr += 5;
}
void AIStackPushVar(const u8 *var)
static void AIStackPushVar(const u8 *var)
{
gBattleResources->AI_ScriptsStack->ptr[gBattleResources->AI_ScriptsStack->size++] = var;
}
// unused
void AIStackPushVar_cursor(void)
static void AIStackPushVar_cursor(void)
{
gBattleResources->AI_ScriptsStack->ptr[gBattleResources->AI_ScriptsStack->size++] = gAIScriptPtr;
}
bool8 AIStackPop(void)
static bool8 AIStackPop(void)
{
if (gBattleResources->AI_ScriptsStack->size != 0)
{
+676
View File
@@ -0,0 +1,676 @@
#include "global.h"
#include "battle.h"
#include "battle_anim.h"
#include "battle_controllers.h"
#include "pokemon.h"
#include "random.h"
#include "util.h"
#include "constants/abilities.h"
#include "constants/item_effects.h"
#include "constants/items.h"
#include "constants/moves.h"
#include "constants/species.h"
#include "constants/pokemon.h"
static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng);
static bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent);
static bool8 ShouldUseItem(void);
static bool8 ShouldSwitchIfPerishSong(void)
{
if (gStatuses3[gActiveBattler] & STATUS3_PERISH_SONG
&& gDisableStructs[gActiveBattler].perishSongTimer == 0)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
else
{
return FALSE;
}
}
static bool8 ShouldSwitchIfWonderGuard(void)
{
u8 opposingBattler;
u8 moveFlags;
s32 i, j;
u16 move;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
return FALSE;
if (gBattleMons[GetBattlerAtPosition(B_POSITION_PLAYER_LEFT)].ability == ABILITY_WONDER_GUARD)
{
// Check if Pokemon has a super effective move.
for (opposingBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT), i = 0; i < MAX_MON_MOVES; ++i)
{
move = gBattleMons[gActiveBattler].moves[i];
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[opposingBattler].species, gBattleMons[opposingBattler].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE)
return FALSE;
}
// Find a Pokemon in the party that has a super effective move.
for (i = 0; i < PARTY_SIZE; ++i)
{
if (GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0
|| GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE
|| GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG
|| i == gBattlerPartyIndexes[gActiveBattler])
continue;
GetMonData(&gEnemyParty[i], MON_DATA_SPECIES); // Unused return value.
GetMonData(&gEnemyParty[i], MON_DATA_ABILITY_NUM); // Unused return value.
for (opposingBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT), j = 0; j < MAX_MON_MOVES; ++j)
{
move = GetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j);
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[opposingBattler].species, gBattleMons[opposingBattler].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE && Random() % 3 < 2)
{
// We found a mon.
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = i;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
}
}
}
return FALSE; // There is not a single Pokemon in the party that has a super effective move against a mon with Wonder Guard.
}
static bool8 FindMonThatAbsorbsOpponentsMove(void)
{
u8 battlerIn1, battlerIn2;
u8 absorbingTypeAbility;
s32 i;
if ((HasSuperEffectiveMoveAgainstOpponents(TRUE) && Random() % 3)
|| (gLastLandedMoves[gActiveBattler] == MOVE_NONE))
return FALSE;
if (gLastLandedMoves[gActiveBattler] == 0xFFFF
|| gBattleMoves[gLastLandedMoves[gActiveBattler]].power == 0)
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)))])
battlerIn2 = gActiveBattler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)));
}
else
{
battlerIn1 = gActiveBattler;
battlerIn2 = gActiveBattler;
}
if (gBattleMoves[gLastLandedMoves[gActiveBattler]].type == TYPE_FIRE)
absorbingTypeAbility = ABILITY_FLASH_FIRE;
else if (gBattleMoves[gLastLandedMoves[gActiveBattler]].type == TYPE_WATER)
absorbingTypeAbility = ABILITY_WATER_ABSORB;
else if (gBattleMoves[gLastLandedMoves[gActiveBattler]].type == TYPE_ELECTRIC)
absorbingTypeAbility = ABILITY_VOLT_ABSORB;
else
return FALSE;
if (gBattleMons[gActiveBattler].ability == absorbingTypeAbility)
return FALSE;
for (i = 0; i < PARTY_SIZE; ++i)
{
u16 species;
u8 monAbility;
if ((GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
|| (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE)
|| (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
|| (i == gBattlerPartyIndexes[battlerIn1])
|| (i == gBattlerPartyIndexes[battlerIn2])
|| (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
|| (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2)))
continue;
species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES);
if (GetMonData(&gEnemyParty[i], MON_DATA_ABILITY_NUM) != ABILITY_NONE)
monAbility = gBaseStats[species].abilities[1];
else
monAbility = gBaseStats[species].abilities[0];
if (absorbingTypeAbility == monAbility && Random() & 1)
{
// we found a mon
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = i;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
}
return FALSE;
}
static bool8 ShouldSwitchIfNaturalCure(void)
{
if (!(gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP)
|| (gBattleMons[gActiveBattler].ability != ABILITY_NATURAL_CURE)
|| (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 2))
return FALSE;
if ((gLastLandedMoves[gActiveBattler] == MOVE_NONE || gLastLandedMoves[gActiveBattler] == 0xFFFF) && Random() & 1)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
else if (gBattleMoves[gLastLandedMoves[gActiveBattler]].power == 0 && Random() & 1)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
if (FindMonWithFlagsAndSuperEffective(MOVE_RESULT_DOESNT_AFFECT_FOE, 1)
|| FindMonWithFlagsAndSuperEffective(MOVE_RESULT_NOT_VERY_EFFECTIVE, 1))
return TRUE;
if (Random() & 1)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = PARTY_SIZE;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
return FALSE;
}
static bool8 HasSuperEffectiveMoveAgainstOpponents(bool8 noRng)
{
u8 opposingBattler;
s32 i;
u8 moveFlags;
u16 move;
opposingBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
if (!(gAbsentBattlerFlags & gBitTable[opposingBattler]))
{
for (i = 0; i < MAX_MON_MOVES; ++i)
{
move = gBattleMons[gActiveBattler].moves[i];
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[opposingBattler].species, gBattleMons[opposingBattler].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE)
{
if (noRng || (Random() % 10))
return TRUE;
}
}
}
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
return FALSE;
opposingBattler = GetBattlerAtPosition(BATTLE_PARTNER(B_POSITION_PLAYER_LEFT));
if (!(gAbsentBattlerFlags & gBitTable[opposingBattler]))
{
for (i = 0; i < MAX_MON_MOVES; ++i)
{
move = gBattleMons[gActiveBattler].moves[i];
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[opposingBattler].species, gBattleMons[opposingBattler].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE)
{
if (noRng)
return TRUE;
if (Random() % 10 != 0)
return TRUE;
}
}
}
return FALSE;
}
static bool8 AreStatsRaised(void)
{
u8 buffedStatsValue = 0;
s32 i;
for (i = 0; i < NUM_BATTLE_STATS; ++i)
{
if (gBattleMons[gActiveBattler].statStages[i] > 6)
buffedStatsValue += gBattleMons[gActiveBattler].statStages[i] - 6;
}
return (buffedStatsValue > 3);
}
static bool8 FindMonWithFlagsAndSuperEffective(u8 flags, u8 moduloPercent)
{
u8 battlerIn1, battlerIn2;
s32 i, j;
u16 move;
u8 moveFlags;
if (gLastLandedMoves[gActiveBattler] == 0)
return FALSE;
if ((gLastLandedMoves[gActiveBattler] == 0xFFFF)
|| (gLastHitBy[gActiveBattler] == 0xFF)
|| (gBattleMoves[gLastLandedMoves[gActiveBattler]].power == 0))
return FALSE;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)))])
battlerIn2 = gActiveBattler;
else
battlerIn2 = GetBattlerAtPosition(BATTLE_PARTNER(GetBattlerPosition(gActiveBattler)));
}
else
{
battlerIn1 = gActiveBattler;
battlerIn2 = gActiveBattler;
}
for (i = 0; i < PARTY_SIZE; ++i)
{
u16 species;
u8 monAbility;
if ((GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
|| (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE)
|| (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
|| (i == gBattlerPartyIndexes[battlerIn1])
|| (i == gBattlerPartyIndexes[battlerIn2])
|| (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
|| (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2)))
continue;
species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES);
if (GetMonData(&gEnemyParty[i], MON_DATA_ABILITY_NUM) != ABILITY_NONE)
monAbility = gBaseStats[species].abilities[1];
else
monAbility = gBaseStats[species].abilities[0];
moveFlags = AI_TypeCalc(gLastLandedMoves[gActiveBattler], species, monAbility);
if (moveFlags & flags)
{
battlerIn1 = gLastHitBy[gActiveBattler];
for (j = 0; j < MAX_MON_MOVES; ++j)
{
move = GetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j);
if (move == MOVE_NONE)
continue;
moveFlags = AI_TypeCalc(move, gBattleMons[battlerIn1].species, gBattleMons[battlerIn1].ability);
if (moveFlags & MOVE_RESULT_SUPER_EFFECTIVE && Random() % moduloPercent == 0)
{
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = i;
BtlController_EmitTwoReturnValues(1, B_ACTION_SWITCH, 0);
return TRUE;
}
}
}
}
return FALSE;
}
static bool8 ShouldSwitch(void)
{
u8 battlerIn1, battlerIn2;
s32 i;
s32 availableToSwitch;
if ((gBattleMons[gActiveBattler].status2 & (STATUS2_WRAPPED | STATUS2_ESCAPE_PREVENTION))
|| (gStatuses3[gActiveBattler] & STATUS3_ROOTED)
|| AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBattler, ABILITY_SHADOW_TAG, 0, 0)
|| AbilityBattleEffects(ABILITYEFFECT_CHECK_OTHER_SIDE, gActiveBattler, ABILITY_ARENA_TRAP, 0, 0))
return FALSE; // misses the flying or levitate check
if (AbilityBattleEffects(ABILITYEFFECT_FIELD_SPORT, 0, ABILITY_MAGNET_PULL, 0, 0))
if ((gBattleMons[gActiveBattler].type1 == TYPE_STEEL) || (gBattleMons[gActiveBattler].type2 == TYPE_STEEL))
return FALSE;
availableToSwitch = 0;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK)])
battlerIn2 = gActiveBattler;
else
battlerIn2 = GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK);
}
else
{
battlerIn2 = gActiveBattler;
battlerIn1 = gActiveBattler;
}
for (i = 0; i < PARTY_SIZE; ++i)
{
if ((GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
|| (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_NONE)
|| (GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) == SPECIES_EGG)
|| (i == gBattlerPartyIndexes[battlerIn1])
|| (i == gBattlerPartyIndexes[battlerIn2])
|| (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
|| (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2)))
continue;
++availableToSwitch;
}
if (!availableToSwitch)
return FALSE;
if (ShouldSwitchIfPerishSong()
|| ShouldSwitchIfWonderGuard()
|| FindMonThatAbsorbsOpponentsMove()
|| ShouldSwitchIfNaturalCure())
return TRUE;
if (HasSuperEffectiveMoveAgainstOpponents(FALSE)
|| AreStatsRaised())
return FALSE;
if (FindMonWithFlagsAndSuperEffective(MOVE_RESULT_DOESNT_AFFECT_FOE, 2)
|| FindMonWithFlagsAndSuperEffective(MOVE_RESULT_NOT_VERY_EFFECTIVE, 3))
return TRUE;
return FALSE;
}
void AI_TrySwitchOrUseItem(void)
{
u8 battlerIn1, battlerIn2;
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
if (ShouldSwitch())
{
if (*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) == 6)
{
s32 monToSwitchId = GetMostSuitableMonToSwitchInto();
if (monToSwitchId == 6)
{
if (!(gBattleTypeFlags & BATTLE_TYPE_DOUBLE))
{
battlerIn1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
battlerIn2 = battlerIn1;
}
else
{
battlerIn1 = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
battlerIn2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
}
for (monToSwitchId = 0; monToSwitchId < PARTY_SIZE; ++monToSwitchId)
{
if ((!GetMonData(&gEnemyParty[monToSwitchId], MON_DATA_HP) == 0)
&& (monToSwitchId != gBattlerPartyIndexes[battlerIn1])
&& (monToSwitchId != gBattlerPartyIndexes[battlerIn2])
&& (monToSwitchId != *(gBattleStruct->monToSwitchIntoId + battlerIn1))
&& (monToSwitchId != *(gBattleStruct->monToSwitchIntoId + battlerIn2)))
break;
}
}
*(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1)) = monToSwitchId;
}
*(gBattleStruct->monToSwitchIntoId + gActiveBattler) = *(gBattleStruct->AI_monToSwitchIntoId + (GetBattlerPosition(gActiveBattler) >> 1));
return;
}
else if (ShouldUseItem())
{
return;
}
}
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_MOVE, (gActiveBattler ^ BIT_SIDE) << 8);
}
static void ModulateByTypeEffectiveness(u8 atkType, u8 defType1, u8 defType2, u8 *var)
{
s32 i = 0;
while (TYPE_EFFECT_ATK_TYPE(i) != TYPE_ENDTABLE)
{
if (TYPE_EFFECT_ATK_TYPE(i) == TYPE_FORESIGHT)
{
i += 3;
continue;
}
else if (TYPE_EFFECT_ATK_TYPE(i) == atkType)
{
// Check type1.
if (TYPE_EFFECT_DEF_TYPE(i) == defType1)
*var = (*var * TYPE_EFFECT_MULTIPLIER(i)) / 10;
// Check type2.
if (TYPE_EFFECT_DEF_TYPE(i) == defType2 && defType1 != defType2)
*var = (*var * TYPE_EFFECT_MULTIPLIER(i)) / 10;
}
i += 3;
}
}
u8 GetMostSuitableMonToSwitchInto(void)
{
u8 opposingBattler;
u8 bestDmg; // Note : should be changed to u32 for obvious reasons.
u8 bestMonId;
u8 battlerIn1, battlerIn2;
s32 i, j;
u8 invalidMons;
u16 move;
if (*(gBattleStruct->monToSwitchIntoId + gActiveBattler) != PARTY_SIZE)
return *(gBattleStruct->monToSwitchIntoId + gActiveBattler);
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
battlerIn1 = gActiveBattler;
if (gAbsentBattlerFlags & gBitTable[GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK)])
battlerIn2 = gActiveBattler;
else
battlerIn2 = GetBattlerAtPosition(GetBattlerPosition(gActiveBattler) ^ BIT_FLANK);
// UB: It considers the opponent only player's side even though it can battle alongside player.
opposingBattler = Random() & BIT_FLANK;
if (gAbsentBattlerFlags & gBitTable[opposingBattler])
opposingBattler ^= BIT_FLANK;
}
else
{
opposingBattler = GetBattlerAtPosition(B_POSITION_PLAYER_LEFT);
battlerIn1 = gActiveBattler;
battlerIn2 = gActiveBattler;
}
invalidMons = 0;
while (invalidMons != 0x3F) // All mons are invalid.
{
bestDmg = 0;
bestMonId = 6;
// Find the mon whose type is the most suitable offensively.
for (i = 0; i < PARTY_SIZE; ++i)
{
u16 species = GetMonData(&gEnemyParty[i], MON_DATA_SPECIES);
if (species != SPECIES_NONE
&& GetMonData(&gEnemyParty[i], MON_DATA_HP) != 0
&& !(gBitTable[i] & invalidMons)
&& gBattlerPartyIndexes[battlerIn1] != i
&& gBattlerPartyIndexes[battlerIn2] != i
&& i != *(gBattleStruct->monToSwitchIntoId + battlerIn1)
&& i != *(gBattleStruct->monToSwitchIntoId + battlerIn2))
{
u8 type1 = gBaseStats[species].type1;
u8 type2 = gBaseStats[species].type2;
u8 typeDmg = 10;
ModulateByTypeEffectiveness(gBattleMons[opposingBattler].type1, type1, type2, &typeDmg);
ModulateByTypeEffectiveness(gBattleMons[opposingBattler].type2, type1, type2, &typeDmg);
if (bestDmg < typeDmg)
{
bestDmg = typeDmg;
bestMonId = i;
}
}
else
{
invalidMons |= gBitTable[i];
}
}
// Ok, we know the mon has the right typing but does it have at least one super effective move?
if (bestMonId != PARTY_SIZE)
{
for (i = 0; i < MAX_MON_MOVES; ++i)
{
move = GetMonData(&gEnemyParty[bestMonId], MON_DATA_MOVE1 + i);
if (move != MOVE_NONE && TypeCalc(move, gActiveBattler, opposingBattler) & MOVE_RESULT_SUPER_EFFECTIVE)
break;
}
if (i != MAX_MON_MOVES)
return bestMonId; // Has both the typing and at least one super effective move.
invalidMons |= gBitTable[bestMonId]; // Sorry buddy, we want something better.
}
else
{
invalidMons = 0x3F; // No viable mon to switch.
}
}
gDynamicBasePower = 0;
gBattleStruct->dynamicMoveType = 0;
gBattleScripting.dmgMultiplier = 1;
gMoveResultFlags = 0;
gCritMultiplier = 1;
bestDmg = 0;
bestMonId = 6;
// If we couldn't find the best mon in terms of typing, find the one that deals most damage.
for (i = 0; i < PARTY_SIZE; ++i)
{
if (((u16)(GetMonData(&gEnemyParty[i], MON_DATA_SPECIES)) == SPECIES_NONE)
|| (GetMonData(&gEnemyParty[i], MON_DATA_HP) == 0)
|| (gBattlerPartyIndexes[battlerIn1] == i)
|| (gBattlerPartyIndexes[battlerIn2] == i)
|| (i == *(gBattleStruct->monToSwitchIntoId + battlerIn1))
|| (i == *(gBattleStruct->monToSwitchIntoId + battlerIn2)))
continue;
for (j = 0; j < MAX_MON_MOVES; ++j)
{
move = GetMonData(&gEnemyParty[i], MON_DATA_MOVE1 + j);
gBattleMoveDamage = 0;
if (move != MOVE_NONE && gBattleMoves[move].power != 1)
{
AI_CalcDmg(gActiveBattler, opposingBattler);
TypeCalc(move, gActiveBattler, opposingBattler);
}
if (bestDmg < gBattleMoveDamage)
{
bestDmg = gBattleMoveDamage;
bestMonId = i;
}
}
}
return bestMonId;
}
static u8 GetAI_ItemType(u8 itemId, const u8 *itemEffect) // NOTE: should take u16 as item Id argument
{
if (itemId == ITEM_FULL_RESTORE)
return AI_ITEM_FULL_RESTORE;
else if (itemEffect[4] & ITEM4_HEAL_HP)
return AI_ITEM_HEAL_HP;
else if (itemEffect[3] & ITEM3_STATUS_ALL)
return AI_ITEM_CURE_CONDITION;
else if (itemEffect[0] & (ITEM0_HIGH_CRIT | ITEM0_X_ATTACK) || itemEffect[1] != 0 || itemEffect[2] != 0)
return AI_ITEM_X_STAT;
else if (itemEffect[3] & ITEM3_MIST)
return AI_ITEM_GUARD_SPECS;
else
return AI_ITEM_NOT_RECOGNIZABLE;
}
static bool8 ShouldUseItem(void)
{
s32 i;
u8 validMons = 0;
bool8 shouldUse = FALSE;
for (i = 0; i < PARTY_SIZE; ++i)
if (GetMonData(&gEnemyParty[i], MON_DATA_HP) != 0
&& GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) != SPECIES_NONE
&& GetMonData(&gEnemyParty[i], MON_DATA_SPECIES2) != SPECIES_EGG)
++validMons;
for (i = 0; i < MAX_MON_MOVES; ++i)
{
u16 item;
const u8 *itemEffects;
u8 paramOffset;
u8 battlerSide;
if (i && validMons > (gBattleResources->battleHistory->itemsNo - i) + 1)
continue;
item = gBattleResources->battleHistory->trainerItems[i];
if (item == ITEM_NONE || gItemEffectTable[item - ITEM_POTION] == NULL)
continue;
if (item == ITEM_ENIGMA_BERRY)
itemEffects = gSaveBlock1Ptr->enigmaBerry.itemEffect;
else
itemEffects = gItemEffectTable[item - ITEM_POTION];
*(gBattleStruct->AI_itemType + gActiveBattler / 2) = GetAI_ItemType(item, itemEffects);
switch (*(gBattleStruct->AI_itemType + gActiveBattler / 2))
{
case AI_ITEM_FULL_RESTORE:
if (gBattleMons[gActiveBattler].hp >= gBattleMons[gActiveBattler].maxHP / 4)
break;
if (gBattleMons[gActiveBattler].hp == 0)
break;
shouldUse = TRUE;
break;
case AI_ITEM_HEAL_HP:
paramOffset = GetItemEffectParamOffset(item, 4, 4);
if (paramOffset == 0 || gBattleMons[gActiveBattler].hp == 0)
break;
if (gBattleMons[gActiveBattler].hp < gBattleMons[gActiveBattler].maxHP / 4 || gBattleMons[gActiveBattler].maxHP - gBattleMons[gActiveBattler].hp > itemEffects[paramOffset])
shouldUse = TRUE;
break;
case AI_ITEM_CURE_CONDITION:
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0;
if (itemEffects[3] & ITEM3_SLEEP && gBattleMons[gActiveBattler].status1 & STATUS1_SLEEP)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x20;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_POISON && (gBattleMons[gActiveBattler].status1 & STATUS1_POISON || gBattleMons[gActiveBattler].status1 & STATUS1_TOXIC_POISON))
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x10;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_BURN && gBattleMons[gActiveBattler].status1 & STATUS1_BURN)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x8;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_FREEZE && gBattleMons[gActiveBattler].status1 & STATUS1_FREEZE)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x4;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_PARALYSIS && gBattleMons[gActiveBattler].status1 & STATUS1_PARALYSIS)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x2;
shouldUse = TRUE;
}
if (itemEffects[3] & ITEM3_CONFUSION && gBattleMons[gActiveBattler].status2 & STATUS2_CONFUSION)
{
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x1;
shouldUse = TRUE;
}
break;
case AI_ITEM_X_STAT:
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) = 0;
if (!gDisableStructs[gActiveBattler].isFirstTurn)
break;
if (itemEffects[0] & ITEM0_X_ATTACK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x1;
if (itemEffects[1] & ITEM1_X_DEFEND)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x2;
if (itemEffects[1] & ITEM1_X_SPEED)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x4;
if (itemEffects[2] & ITEM2_X_SPATK)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x8;
if (itemEffects[2] & ITEM2_X_ACCURACY)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x20;
if (itemEffects[0] & ITEM0_HIGH_CRIT)
*(gBattleStruct->AI_itemFlags + gActiveBattler / 2) |= 0x80;
shouldUse = TRUE;
break;
case AI_ITEM_GUARD_SPECS:
battlerSide = GetBattlerSide(gActiveBattler);
if (gDisableStructs[gActiveBattler].isFirstTurn && gSideTimers[battlerSide].mistTimer == 0)
shouldUse = TRUE;
break;
case AI_ITEM_NOT_RECOGNIZABLE:
return FALSE;
}
if (shouldUse)
{
BtlController_EmitTwoReturnValues(1, B_ACTION_USE_ITEM, 0);
*(gBattleStruct->chosenItem + (gActiveBattler / 2) * 2) = item;
gBattleResources->battleHistory->trainerItems[i] = 0;
return shouldUse;
}
}
return FALSE;
}
+246 -118
View File
@@ -6,43 +6,91 @@
#define abs(x) ((x) < 0 ? -(x) : (x))
void sub_8098A6C(u8 taskId);
void sub_8098C08(u8 taskId);
void sub_8098D54(u8 taskId);
void sub_8098EF0(u8 taskId);
void sub_8099004(u8 taskId);
void sub_80990AC(struct Sprite * sprite);
void sub_8099120(struct Sprite * sprite);
void sub_8099144(struct Sprite * sprite);
void sub_8099190(struct Sprite * sprite);
void sub_80991B4(struct Sprite * sprite);
void sub_8099270(struct Sprite * sprite);
void sub_80992E0(struct Sprite * sprite);
void sub_8099394(struct Sprite * sprite);
void sub_809946C(struct Sprite * sprite);
void sub_8099530(u8 taskId);
void sub_8099594(u8 taskId);
void sub_80996B8(u8 taskId);
void sub_8099788(u8 taskId);
void sub_8099908(u8 taskId);
void sub_8099B54(u8 taskId);
void sub_8099CB8(u8 taskId);
static void AnimTask_ShakeMonStep(u8 taskId);
static void AnimTask_ShakeMon2Step(u8 taskId);
static void AnimTask_ShakeMonInPlaceStep(u8 taskId);
static void AnimTask_ShakeAndSinkMonStep(u8 taskId);
static void AnimTask_TranslateMonEllipticalStep(u8 taskId);
static void DoHorizontalLunge(struct Sprite * sprite);
static void ReverseHorizontalLungeDirection(struct Sprite * sprite);
static void DoVerticalDip(struct Sprite * sprite);
static void ReverseVerticalDipDirection(struct Sprite * sprite);
static void SlideMonToOriginalPos(struct Sprite * sprite);
static void SlideMonToOriginalPosStep(struct Sprite * sprite);
static void SlideMonToOffset(struct Sprite * sprite);
static void sub_8099394(struct Sprite * sprite);
static void sub_809946C(struct Sprite * sprite);
static void AnimTask_WindUpLungePart1(u8 taskId);
static void AnimTask_WindUpLungePart2(u8 taskId);
static void sub_80996B8(u8 taskId);
static void AnimTask_SwayMonStep(u8 taskId);
static void AnimTask_ScaleMonAndRestoreStep(u8 taskId);
static void sub_8099B54(u8 taskId);
static void sub_8099CB8(u8 taskId);
const struct SpriteTemplate gUnknown_83D4E4C[] = {
{
0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_80990AC
}, {
0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_8099144
}, {
0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_80991B4
}, {
0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_80992E0
}, {
0, 0, &gDummyOamData, gDummySpriteAnimTable, NULL, gDummySpriteAffineAnimTable, sub_8099394
}
const struct SpriteTemplate gHorizontalLungeSpriteTemplate =
{
.tileTag = 0,
.paletteTag = 0,
.oam = &gDummyOamData,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = DoHorizontalLunge,
};
void sub_80989F8(u8 taskId)
const struct SpriteTemplate gVerticalDipSpriteTemplate =
{
.tileTag = 0,
.paletteTag = 0,
.oam = &gDummyOamData,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = DoVerticalDip,
};
const struct SpriteTemplate gSlideMonToOriginalPosSpriteTemplate =
{
.tileTag = 0,
.paletteTag = 0,
.oam = &gDummyOamData,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SlideMonToOriginalPos,
};
const struct SpriteTemplate gSlideMonToOffsetSpriteTemplate =
{
.tileTag = 0,
.paletteTag = 0,
.oam = &gDummyOamData,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = SlideMonToOffset,
};
const struct SpriteTemplate gUnknown_83D4EB4 =
{
.tileTag = 0,
.paletteTag = 0,
.oam = &gDummyOamData,
.anims = gDummySpriteAnimTable,
.images = NULL,
.affineAnims = gDummySpriteAffineAnimTable,
.callback = sub_8099394,
};
// Task to facilitate simple shaking of a pokemon's picture in battle.
// The shaking alternates between the original position and the target position.
// arg 0: anim battler
// arg 1: x pixel offset
// arg 2: y pixel offset
// arg 3: num times to shake
// arg 4: frame delay
void AnimTask_ShakeMon(u8 taskId)
{
u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
@@ -58,12 +106,12 @@ void sub_80989F8(u8 taskId)
gTasks[taskId].data[3] = gBattleAnimArgs[4];
gTasks[taskId].data[4] = gBattleAnimArgs[1];
gTasks[taskId].data[5] = gBattleAnimArgs[2];
gTasks[taskId].func = sub_8098A6C;
gTasks[taskId].func = AnimTask_ShakeMonStep;
gTasks[taskId].func(taskId);
}
}
void sub_8098A6C(u8 taskId)
static void AnimTask_ShakeMonStep(u8 taskId)
{
if (gTasks[taskId].data[3] == 0)
{
@@ -87,7 +135,14 @@ void sub_8098A6C(u8 taskId)
gTasks[taskId].data[3]--;
}
void sub_8098B1C(u8 taskId)
// Task to facilitate simple shaking of a pokemon's picture in battle.
// The shaking alternates between the positive and negative versions of the specified pixel offsets.
// arg 0: anim battler
// arg 1: x pixel offset
// arg 2: y pixel offset
// arg 3: num times to shake
// arg 4: frame delay
void AnimTask_ShakeMon2(u8 taskId)
{
bool8 abort = FALSE;
u8 spriteId;
@@ -116,7 +171,7 @@ void sub_8098B1C(u8 taskId)
battlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
break;
}
if (!sub_8072DF0(battlerId))
if (!IsBattlerSpriteVisible(battlerId))
abort = TRUE;
spriteId = gBattlerSpriteIds[battlerId];
}
@@ -134,12 +189,12 @@ void sub_8098B1C(u8 taskId)
gTasks[taskId].data[3] = gBattleAnimArgs[4];
gTasks[taskId].data[4] = gBattleAnimArgs[1];
gTasks[taskId].data[5] = gBattleAnimArgs[2];
gTasks[taskId].func = sub_8098C08;
gTasks[taskId].func = AnimTask_ShakeMon2Step;
gTasks[taskId].func(taskId);
}
}
void sub_8098C08(u8 taskId)
static void AnimTask_ShakeMon2Step(u8 taskId)
{
if (gTasks[taskId].data[3] == 0)
{
@@ -163,7 +218,15 @@ void sub_8098C08(u8 taskId)
gTasks[taskId].data[3]--;
}
void sub_8098CD0(u8 taskId)
// Task to facilitate simple shaking of a pokemon's picture in battle.
// The shaking alternates between the positive and negative versions of the specified pixel offsets
// with respect to the current location of the mon's picture.
// arg 0: battler
// arg 1: x offset
// arg 2: y offset
// arg 3: num shakes
// arg 4: delay
void AnimTask_ShakeMonInPlace(u8 taskId)
{
u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
@@ -180,12 +243,12 @@ void sub_8098CD0(u8 taskId)
gTasks[taskId].data[4] = gBattleAnimArgs[4];
gTasks[taskId].data[5] = gBattleAnimArgs[1] * 2;
gTasks[taskId].data[6] = gBattleAnimArgs[2] * 2;
gTasks[taskId].func = sub_8098D54;
gTasks[taskId].func = AnimTask_ShakeMonInPlaceStep;
gTasks[taskId].func(taskId);
}
}
void sub_8098D54(u8 taskId)
static void AnimTask_ShakeMonInPlaceStep(u8 taskId)
{
if (gTasks[taskId].data[3] == 0)
{
@@ -219,7 +282,13 @@ void sub_8098D54(u8 taskId)
gTasks[taskId].data[3]--;
}
void sub_8098E90(u8 taskId)
// Shakes a mon bg horizontally and moves it downward linearly.
// arg 0: battler
// arg 1: x offset
// arg 2: frame delay between each movement
// arg 3: downward speed (subpixel)
// arg 4: duration
void AnimTask_ShakeAndSinkMon(u8 taskId)
{
u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
@@ -229,11 +298,11 @@ void sub_8098E90(u8 taskId)
gTasks[taskId].data[2] = gBattleAnimArgs[2];
gTasks[taskId].data[3] = gBattleAnimArgs[3];
gTasks[taskId].data[4] = gBattleAnimArgs[4];
gTasks[taskId].func = sub_8098EF0;
gTasks[taskId].func = AnimTask_ShakeAndSinkMonStep;
gTasks[taskId].func(taskId);
}
void sub_8098EF0(u8 taskId)
static void AnimTask_ShakeAndSinkMonStep(u8 taskId)
{
u8 spriteId = gTasks[taskId].data[0];
s16 data1 = gTasks[taskId].data[1];
@@ -251,25 +320,32 @@ void sub_8098EF0(u8 taskId)
DestroyAnimVisualTask(taskId);
}
void sub_8098F84(u8 taskId)
// Moves a mon bg picture along an elliptical path that begins
// and ends at the mon's origin location.
// arg 0: battler
// arg 1: ellipse width
// arg 2: ellipse height
// arg 3: num loops
// arg 4: speed (valid values are 0-5)
void AnimTask_TranslateMonElliptical(u8 taskId)
{
u8 r6 = 1;
u8 wavePeriod = 1;
u8 i;
u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
if (gBattleAnimArgs[4] > 5)
gBattleAnimArgs[4] = 5;
for (i = 0; i < gBattleAnimArgs[4]; i++)
r6 *= 2;
wavePeriod *= 2;
gTasks[taskId].data[0] = spriteId;
gTasks[taskId].data[1] = gBattleAnimArgs[1];
gTasks[taskId].data[2] = gBattleAnimArgs[2];
gTasks[taskId].data[3] = gBattleAnimArgs[3];
gTasks[taskId].data[4] = r6;
gTasks[taskId].func = sub_8099004;
gTasks[taskId].data[4] = wavePeriod;
gTasks[taskId].func = AnimTask_TranslateMonEllipticalStep;
gTasks[taskId].func(taskId);
}
void sub_8099004(u8 taskId)
static void AnimTask_TranslateMonEllipticalStep(u8 taskId)
{
u8 spriteId = gTasks[taskId].data[0];
gSprites[spriteId].pos2.x = Sin(gTasks[taskId].data[5], gTasks[taskId].data[1]);
@@ -287,14 +363,26 @@ void sub_8099004(u8 taskId)
}
}
void sub_809907C(u8 taskId)
// Moves a mon bg picture along an elliptical path that begins
// and ends at the mon's origin location. Reverses the direction
// of the path if it's not on the player's side of the battle.
// arg 0: battler
// arg 1: ellipse width
// arg 2: ellipse height
// arg 3: num loops
// arg 4: speed (valid values are 0-5)
void AnimTask_TranslateMonEllipticalRespectSide(u8 taskId)
{
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
gBattleAnimArgs[1] = -gBattleAnimArgs[1];
sub_8098F84(taskId);
AnimTask_TranslateMonElliptical(taskId);
}
void sub_80990AC(struct Sprite * sprite)
// Performs a simple horizontal lunge, where the mon moves
// horizontally, and then moves back in the opposite direction.
// arg 0: duration of single lunge direction
// arg 1: x pixel delta that is applied each frame
static void DoHorizontalLunge(struct Sprite * sprite)
{
sprite->invisible = TRUE;
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
@@ -305,19 +393,24 @@ void sub_80990AC(struct Sprite * sprite)
sprite->data[2] = 0;
sprite->data[3] = gBattlerSpriteIds[gBattleAnimAttacker];
sprite->data[4] = gBattleAnimArgs[0];
StoreSpriteCallbackInData6(sprite, sub_8099120);
sprite->callback = sub_8074DC4;
StoreSpriteCallbackInData6(sprite, ReverseHorizontalLungeDirection);
sprite->callback = TranslateMonSpriteLinear;
}
void sub_8099120(struct Sprite * sprite)
static void ReverseHorizontalLungeDirection(struct Sprite * sprite)
{
sprite->data[0] = sprite->data[4];
sprite->data[1] = -sprite->data[1];
sprite->callback = sub_8074DC4;
sprite->callback = TranslateMonSpriteLinear;
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
}
void sub_8099144(struct Sprite * sprite)
// Performs a simple vertical dipping motion, where moves vertically, and then
// moves back in the opposite direction.
// arg 0: duration of single dip direction
// arg 1: y pixel delta that is applied each frame
// arg 2: battler
static void DoVerticalDip(struct Sprite * sprite)
{
u8 spriteId;
sprite->invisible = TRUE;
@@ -327,19 +420,24 @@ void sub_8099144(struct Sprite * sprite)
sprite->data[2] = gBattleAnimArgs[1];
sprite->data[3] = spriteId;
sprite->data[4] = gBattleAnimArgs[0];
StoreSpriteCallbackInData6(sprite, sub_8099190);
sprite->callback = sub_8074DC4;
StoreSpriteCallbackInData6(sprite, ReverseVerticalDipDirection);
sprite->callback = TranslateMonSpriteLinear;
}
void sub_8099190(struct Sprite * sprite)
static void ReverseVerticalDipDirection(struct Sprite * sprite)
{
sprite->data[0] = sprite->data[4];
sprite->data[2] = -sprite->data[2];
sprite->callback = sub_8074DC4;
sprite->callback = TranslateMonSpriteLinear;
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
}
void sub_80991B4(struct Sprite * sprite)
// Linearly slides a mon's bg picture back to its original sprite position.
// The sprite parameter is a dummy sprite used for facilitating the movement with its callback.
// arg 0: 1 = target or 0 = attacker
// arg 1: direction (0 = horizontal and vertical, 1 = horizontal only, 2 = vertical only)
// arg 2: duration
static void SlideMonToOriginalPos(struct Sprite * sprite)
{
u8 spriteId;
if (gBattleAnimArgs[0] == 0)
@@ -351,7 +449,7 @@ void sub_80991B4(struct Sprite * sprite)
sprite->data[2] = gSprites[spriteId].pos1.x;
sprite->data[3] = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y;
sprite->data[4] = gSprites[spriteId].pos1.y;
sub_80754B8(sprite);
InitSpriteDataForLinearTranslation(sprite);
sprite->data[3] = 0;
sprite->data[4] = 0;
sprite->data[5] = gSprites[spriteId].pos2.x;
@@ -363,10 +461,10 @@ void sub_80991B4(struct Sprite * sprite)
sprite->data[1] = 0;
sprite->data[7] = gBattleAnimArgs[1];
sprite->data[7] |= spriteId << 8;
sprite->callback = sub_8099270;
sprite->callback = SlideMonToOriginalPosStep;
}
void sub_8099270(struct Sprite * sprite)
static void SlideMonToOriginalPosStep(struct Sprite * sprite)
{
u8 data7 = sprite->data[7];
struct Sprite *otherSprite = &gSprites[sprite->data[7] >> 8];
@@ -388,7 +486,15 @@ void sub_8099270(struct Sprite * sprite)
}
}
void sub_80992E0(struct Sprite * sprite)
// Linearly translates a mon to a target offset. The horizontal offset
// is mirrored for the opponent's pokemon, and the vertical offset
// is only mirrored if arg 3 is set to 1.
// arg 0: 0 = attacker, 1 = target
// arg 1: target x pixel offset
// arg 2: target y pixel offset
// arg 3: mirror vertical translation for opposite battle side
// arg 4: duration
static void SlideMonToOffset(struct Sprite * sprite)
{
u8 battlerId;
u8 spriteId;
@@ -408,16 +514,16 @@ void sub_80992E0(struct Sprite * sprite)
sprite->data[2] = gSprites[spriteId].pos1.x + gBattleAnimArgs[1];
sprite->data[3] = gSprites[spriteId].pos1.y;
sprite->data[4] = gSprites[spriteId].pos1.y + gBattleAnimArgs[2];
sub_80754B8(sprite);
InitSpriteDataForLinearTranslation(sprite);
sprite->data[3] = 0;
sprite->data[4] = 0;
sprite->data[5] = spriteId;
sprite->invisible = TRUE;
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
sprite->callback = sub_8074E14;
sprite->callback = TranslateMonSpriteLinearFixedPoint;
}
void sub_8099394(struct Sprite * sprite)
static void sub_8099394(struct Sprite * sprite)
{
u8 battlerId;
u8 spriteId;
@@ -438,7 +544,7 @@ void sub_8099394(struct Sprite * sprite)
sprite->data[2] = sprite->data[1] + gBattleAnimArgs[1];
sprite->data[3] = gSprites[spriteId].pos1.y + gSprites[spriteId].pos2.y;
sprite->data[4] = sprite->data[3] + gBattleAnimArgs[2];
sub_80754B8(sprite);
InitSpriteDataForLinearTranslation(sprite);
sprite->data[3] = gSprites[spriteId].pos2.x << 8;
sprite->data[4] = gSprites[spriteId].pos2.y << 8;
sprite->data[5] = spriteId;
@@ -447,19 +553,29 @@ void sub_8099394(struct Sprite * sprite)
StoreSpriteCallbackInData6(sprite, DestroyAnimSprite);
else
StoreSpriteCallbackInData6(sprite, sub_809946C);
sprite->callback = sub_8074E14;
sprite->callback = TranslateMonSpriteLinearFixedPoint;
}
void sub_809946C(struct Sprite * sprite)
static void sub_809946C(struct Sprite * sprite)
{
gSprites[sprite->data[5]].pos2.x = 0;
gSprites[sprite->data[5]].pos2.y = 0;
DestroyAnimSprite(sprite);
}
void sub_809949C(u8 taskId)
// Task to facilitate a two-part translation animation, in which the sprite
// is first translated in an arc to one position. Then, it "lunges" to a target
// x offset. Used in TAKE_DOWN, for example.
// arg 0: anim bank
// arg 1: horizontal speed (subpixel)
// arg 2: wave amplitude
// arg 3: first duration
// arg 4: delay before starting lunge
// arg 5: target x offset for lunge
// arg 6: lunge duration
void AnimTask_WindUpLunge(u8 taskId)
{
u16 r7 = 0x8000 / gBattleAnimArgs[3];
u16 wavePeriod = 0x8000 / gBattleAnimArgs[3];
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
{
gBattleAnimArgs[1] = -gBattleAnimArgs[1];
@@ -472,11 +588,11 @@ void sub_809949C(u8 taskId)
gTasks[taskId].data[4] = gBattleAnimArgs[4];
gTasks[taskId].data[5] = gBattleAnimArgs[5] * 256 / gBattleAnimArgs[6];
gTasks[taskId].data[6] = gBattleAnimArgs[6];
gTasks[taskId].data[7] = r7;
gTasks[taskId].func = sub_8099530;
gTasks[taskId].data[7] = wavePeriod;
gTasks[taskId].func = AnimTask_WindUpLungePart1;
}
void sub_8099530(u8 taskId)
static void AnimTask_WindUpLungePart1(u8 taskId)
{
u8 spriteId = gTasks[taskId].data[0];
gTasks[taskId].data[11] += gTasks[taskId].data[1];
@@ -484,10 +600,10 @@ void sub_8099530(u8 taskId)
gSprites[spriteId].pos2.y = Sin((u8)(gTasks[taskId].data[10] >> 8), gTasks[taskId].data[2]);
gTasks[taskId].data[10] += gTasks[taskId].data[7];
if (--gTasks[taskId].data[3] == 0)
gTasks[taskId].func = sub_8099594;
gTasks[taskId].func = AnimTask_WindUpLungePart2;
}
void sub_8099594(u8 taskId)
static void AnimTask_WindUpLungePart2(u8 taskId)
{
u8 spriteId;
@@ -514,7 +630,7 @@ void sub_80995FC(u8 taskId)
spriteId = GetAnimBankSpriteId(gBattleAnimArgs[0]);
break;
case 2:
if (!sub_8072DF0(gBattleAnimAttacker ^ BIT_FLANK))
if (!IsBattlerSpriteVisible(gBattleAnimAttacker ^ BIT_FLANK))
{
DestroyAnimVisualTask(taskId);
return;
@@ -522,7 +638,7 @@ void sub_80995FC(u8 taskId)
spriteId = gBattlerSpriteIds[gBattleAnimAttacker ^ BIT_FLANK];
break;
case 3:
if (!sub_8072DF0(gBattleAnimTarget ^ BIT_FLANK))
if (!IsBattlerSpriteVisible(gBattleAnimTarget ^ BIT_FLANK))
{
DestroyAnimVisualTask(taskId);
return;
@@ -541,7 +657,7 @@ void sub_80995FC(u8 taskId)
gTasks[taskId].func = sub_80996B8;
}
void sub_80996B8(u8 taskId)
static void sub_80996B8(u8 taskId)
{
u8 spriteId = gTasks[taskId].data[0];
gSprites[spriteId].pos2.x += gTasks[taskId].data[1];
@@ -549,7 +665,15 @@ void sub_80996B8(u8 taskId)
DestroyAnimVisualTask(taskId);
}
void sub_8099704(u8 taskId)
// Task that facilitates translating the mon bg picture back and forth
// in a swaying motion (uses Sine wave). It can sway either horizontally
// or vertically, but not both.
// arg 0: direction (0 = horizontal, 1 = vertical)
// arg 1: wave amplitude
// arg 2: wave period
// arg 3: num sways
// arg 4: which mon (0 = attacker, 1 = target)
void AnimTask_SwayMon(u8 taskId)
{
u8 spriteId;
if (GetBattlerSide(gBattleAnimAttacker) != B_SIDE_PLAYER)
@@ -565,32 +689,32 @@ void sub_8099704(u8 taskId)
else
gTasks[taskId].data[5] = gBattleAnimTarget;
gTasks[taskId].data[12] = 1;
gTasks[taskId].func = sub_8099788;
gTasks[taskId].func = AnimTask_SwayMonStep;
}
void sub_8099788(u8 taskId)
static void AnimTask_SwayMonStep(u8 taskId)
{
u8 spriteId;
u32 r8;
s16 r5;
u16 tmp;
u32 waveIndex;
s16 sineValue;
u16 sineIndex;
spriteId = gTasks[taskId].data[4];
tmp = gTasks[taskId].data[10] + gTasks[taskId].data[2];
gTasks[taskId].data[10] = tmp;
r8 = tmp >> 8;
r5 = Sin(r8, gTasks[taskId].data[1]);
sineIndex = gTasks[taskId].data[10] + gTasks[taskId].data[2];
gTasks[taskId].data[10] = sineIndex;
waveIndex = sineIndex >> 8;
sineValue = Sin(waveIndex, gTasks[taskId].data[1]);
if (gTasks[taskId].data[0] == 0)
{
gSprites[spriteId].pos2.x = r5;
gSprites[spriteId].pos2.x = sineValue;
}
else if (GetBattlerSide(gTasks[taskId].data[5]) == B_SIDE_PLAYER)
{
gSprites[spriteId].pos2.y = abs(r5);
gSprites[spriteId].pos2.y = abs(sineValue);
}
else
gSprites[spriteId].pos2.y = -abs(r5);
if ((r8 > 0x7F && gTasks[taskId].data[11] == 0 && gTasks[taskId].data[12] == 1) || (r8 < 0x7F && gTasks[taskId].data[11] == 1 && gTasks[taskId].data[12] == 0))
gSprites[spriteId].pos2.y = -abs(sineValue);
if ((waveIndex > 0x7F && gTasks[taskId].data[11] == 0 && gTasks[taskId].data[12] == 1) || (waveIndex < 0x7F && gTasks[taskId].data[11] == 1 && gTasks[taskId].data[12] == 0))
{
gTasks[taskId].data[11] ^= 1;
gTasks[taskId].data[12] ^= 1;
@@ -603,10 +727,16 @@ void sub_8099788(u8 taskId)
}
}
void sub_80998B0(u8 taskId)
// Scales a mon's sprite, and then scales back to its original dimensions.
// arg 0: x scale delta
// arg 1: y scale delta
// arg 2: duration
// arg 3: anim bank
// arg 4: sprite object mode
void AnimTask_ScaleMonAndRestore(u8 taskId)
{
u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[3]);
sub_80758E0(spriteId, gBattleAnimArgs[4]);
PrepareBattlerSpriteForRotScale(spriteId, gBattleAnimArgs[4]);
gTasks[taskId].data[0] = gBattleAnimArgs[0];
gTasks[taskId].data[1] = gBattleAnimArgs[1];
gTasks[taskId].data[2] = gBattleAnimArgs[2];
@@ -614,16 +744,16 @@ void sub_80998B0(u8 taskId)
gTasks[taskId].data[4] = spriteId;
gTasks[taskId].data[10] = 0x100;
gTasks[taskId].data[11] = 0x100;
gTasks[taskId].func = sub_8099908;
gTasks[taskId].func = AnimTask_ScaleMonAndRestoreStep;
}
void sub_8099908(u8 taskId)
static void AnimTask_ScaleMonAndRestoreStep(u8 taskId)
{
u8 spriteId;
gTasks[taskId].data[10] += gTasks[taskId].data[0];
gTasks[taskId].data[11] += gTasks[taskId].data[1];
spriteId = gTasks[taskId].data[4];
obj_id_set_rotscale(spriteId, gTasks[taskId].data[10], gTasks[taskId].data[11], 0);
SetSpriteRotScale(spriteId, gTasks[taskId].data[10], gTasks[taskId].data[11], 0);
if (--gTasks[taskId].data[2] == 0)
{
if (gTasks[taskId].data[3] > 0)
@@ -635,7 +765,7 @@ void sub_8099908(u8 taskId)
}
else
{
sub_8075980(spriteId);
ResetSpriteRotScale(spriteId);
DestroyAnimVisualTask(taskId);
}
}
@@ -644,7 +774,7 @@ void sub_8099908(u8 taskId)
void sub_8099980(u8 taskId)
{
u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]);
sub_80758E0(spriteId, 0);
PrepareBattlerSpriteForRotScale(spriteId, 0);
gTasks[taskId].data[1] = 0;
gTasks[taskId].data[2] = gBattleAnimArgs[0];
if (gBattleAnimArgs[3] != 1)
@@ -654,7 +784,7 @@ void sub_8099980(u8 taskId)
gTasks[taskId].data[4] = gBattleAnimArgs[1];
gTasks[taskId].data[5] = spriteId;
gTasks[taskId].data[6] = gBattleAnimArgs[3];
if (sub_8073788())
if (IsContest())
gTasks[taskId].data[7] = 1;
else
{
@@ -663,7 +793,7 @@ void sub_8099980(u8 taskId)
else
gTasks[taskId].data[7] = GetBattlerSide(gBattleAnimTarget) == B_SIDE_PLAYER ? 1 : 0;
}
if (gTasks[taskId].data[7] && !sub_8073788())
if (gTasks[taskId].data[7] && !IsContest())
{
s16 tmp;
tmp = gTasks[taskId].data[3];
@@ -677,7 +807,7 @@ void sub_8099980(u8 taskId)
void sub_8099A78(u8 taskId)
{
u8 spriteId = GetAnimBankSpriteId(gBattleAnimArgs[2]);
sub_80758E0(spriteId, 0);
PrepareBattlerSpriteForRotScale(spriteId, 0);
gTasks[taskId].data[1] = 0;
gTasks[taskId].data[2] = gBattleAnimArgs[0];
if (gBattleAnimArgs[2] == 0)
@@ -709,11 +839,10 @@ void sub_8099A78(u8 taskId)
gTasks[taskId].func = sub_8099B54;
}
void sub_8099B54(u8 taskId)
static void sub_8099B54(u8 taskId)
{
s16 tmp;
gTasks[taskId].data[3] += gTasks[taskId].data[4];
obj_id_set_rotscale(gTasks[taskId].data[5], 0x100, 0x100, gTasks[taskId].data[3]);
SetSpriteRotScale(gTasks[taskId].data[5], 0x100, 0x100, gTasks[taskId].data[3]);
if (gTasks[taskId].data[7])
sub_80759DC(gTasks[taskId].data[5]);
if (++gTasks[taskId].data[1] >= gTasks[taskId].data[2])
@@ -721,7 +850,7 @@ void sub_8099B54(u8 taskId)
switch (gTasks[taskId].data[6])
{
case 1:
sub_8075980(gTasks[taskId].data[5]);
ResetSpriteRotScale(gTasks[taskId].data[5]);
// fallthrough
case 0:
default:
@@ -729,8 +858,7 @@ void sub_8099B54(u8 taskId)
break;
case 2:
gTasks[taskId].data[1] = 0;
tmp = gTasks[taskId].data[4];
gTasks[taskId].data[4] = -tmp;
gTasks[taskId].data[4] *= -1;
gTasks[taskId].data[6] = 1;
break;
}
@@ -741,7 +869,7 @@ void sub_8099BD4(u8 taskId)
{
if (gBattleAnimArgs[0] == 0)
{
gTasks[taskId].data[15] = gUnknown_2037EEC / 12;
gTasks[taskId].data[15] = gAnimMovePower / 12;
if (gTasks[taskId].data[15] < 1)
gTasks[taskId].data[15] = 1;
if (gTasks[taskId].data[15] > 16)
@@ -749,7 +877,7 @@ void sub_8099BD4(u8 taskId)
}
else
{
gTasks[taskId].data[15] = gUnknown_2037EE8 / 12;
gTasks[taskId].data[15] = gAnimMoveDmg / 12;
if (gTasks[taskId].data[15] < 1)
gTasks[taskId].data[15] = 1;
if (gTasks[taskId].data[15] > 16)
@@ -769,7 +897,7 @@ void sub_8099BD4(u8 taskId)
gTasks[taskId].func = sub_8099CB8;
}
void sub_8099CB8(u8 taskId)
static void sub_8099CB8(u8 taskId)
{
struct Task *task = &gTasks[taskId];
if (++task->data[0] > task->data[1])
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+677
View File
@@ -0,0 +1,677 @@
#include "global.h"
#include "battle.h"
#include "battle_anim.h"
#include "battle_controllers.h"
#include "battle_interface.h"
#include "battle_message.h"
#include "bg.h"
#include "data.h"
#include "item_menu.h"
#include "link.h"
#include "main.h"
#include "m4a.h"
#include "palette.h"
#include "pokeball.h"
#include "pokemon.h"
#include "reshow_battle_screen.h"
#include "sound.h"
#include "task.h"
#include "text.h"
#include "util.h"
#include "window.h"
#include "strings.h"
#include "constants/songs.h"
#include "constants/battle_anim.h"
static void SafariHandleGetMonData(void);
static void SafariHandleGetRawMonData(void);
static void SafariHandleSetMonData(void);
static void SafariHandleSetRawMonData(void);
static void SafariHandleLoadMonSprite(void);
static void SafariHandleSwitchInAnim(void);
static void SafariHandleReturnMonToBall(void);
static void SafariHandleDrawTrainerPic(void);
static void SafariHandleTrainerSlide(void);
static void SafariHandleTrainerSlideBack(void);
static void SafariHandleFaintAnimation(void);
static void SafariHandlePaletteFade(void);
static void SafariHandleSuccessBallThrowAnim(void);
static void SafariHandleBallThrowAnim(void);
static void SafariHandlePause(void);
static void SafariHandleMoveAnimation(void);
static void SafariHandlePrintString(void);
static void SafariHandlePrintSelectionString(void);
static void SafariHandleChooseAction(void);
static void SafariHandleUnknownYesNoBox(void);
static void SafariHandleChooseMove(void);
static void SafariHandleChooseItem(void);
static void SafariHandleChoosePokemon(void);
static void SafariHandleCmd23(void);
static void SafariHandleHealthBarUpdate(void);
static void SafariHandleExpUpdate(void);
static void SafariHandleStatusIconUpdate(void);
static void SafariHandleStatusAnimation(void);
static void SafariHandleStatusXor(void);
static void SafariHandleDataTransfer(void);
static void SafariHandleDMA3Transfer(void);
static void SafariHandlePlayBGM(void);
static void SafariHandleCmd32(void);
static void SafariHandleTwoReturnValues(void);
static void SafariHandleChosenMonReturnValue(void);
static void SafariHandleOneReturnValue(void);
static void SafariHandleOneReturnValue_Duplicate(void);
static void SafariHandleCmd37(void);
static void SafariHandleCmd38(void);
static void SafariHandleCmd39(void);
static void SafariHandleCmd40(void);
static void SafariHandleHitAnimation(void);
static void SafariHandleCmd42(void);
static void SafariHandlePlaySE(void);
static void SafariHandlePlayFanfareOrBGM(void);
static void SafariHandleFaintingCry(void);
static void SafariHandleIntroSlide(void);
static void SafariHandleIntroTrainerBallThrow(void);
static void SafariHandleDrawPartyStatusSummary(void);
static void SafariHandleHidePartyStatusSummary(void);
static void SafariHandleEndBounceEffect(void);
static void SafariHandleSpriteInvisibility(void);
static void SafariHandleBattleAnimation(void);
static void SafariHandleLinkStandbyMsg(void);
static void SafariHandleResetActionMoveSelection(void);
static void SafariHandleCmd55(void);
static void SafariCmdEnd(void);
static void SafariBufferRunCommand(void);
static void SafariBufferExecCompleted(void);
static void CompleteWhenChosePokeblock(void);
static void (*const sSafariBufferCommands[CONTROLLER_CMDS_COUNT])(void) =
{
SafariHandleGetMonData,
SafariHandleGetRawMonData,
SafariHandleSetMonData,
SafariHandleSetRawMonData,
SafariHandleLoadMonSprite,
SafariHandleSwitchInAnim,
SafariHandleReturnMonToBall,
SafariHandleDrawTrainerPic,
SafariHandleTrainerSlide,
SafariHandleTrainerSlideBack,
SafariHandleFaintAnimation,
SafariHandlePaletteFade,
SafariHandleSuccessBallThrowAnim,
SafariHandleBallThrowAnim,
SafariHandlePause,
SafariHandleMoveAnimation,
SafariHandlePrintString,
SafariHandlePrintSelectionString,
SafariHandleChooseAction,
SafariHandleUnknownYesNoBox,
SafariHandleChooseMove,
SafariHandleChooseItem,
SafariHandleChoosePokemon,
SafariHandleCmd23,
SafariHandleHealthBarUpdate,
SafariHandleExpUpdate,
SafariHandleStatusIconUpdate,
SafariHandleStatusAnimation,
SafariHandleStatusXor,
SafariHandleDataTransfer,
SafariHandleDMA3Transfer,
SafariHandlePlayBGM,
SafariHandleCmd32,
SafariHandleTwoReturnValues,
SafariHandleChosenMonReturnValue,
SafariHandleOneReturnValue,
SafariHandleOneReturnValue_Duplicate,
SafariHandleCmd37,
SafariHandleCmd38,
SafariHandleCmd39,
SafariHandleCmd40,
SafariHandleHitAnimation,
SafariHandleCmd42,
SafariHandlePlaySE,
SafariHandlePlayFanfareOrBGM,
SafariHandleFaintingCry,
SafariHandleIntroSlide,
SafariHandleIntroTrainerBallThrow,
SafariHandleDrawPartyStatusSummary,
SafariHandleHidePartyStatusSummary,
SafariHandleEndBounceEffect,
SafariHandleSpriteInvisibility,
SafariHandleBattleAnimation,
SafariHandleLinkStandbyMsg,
SafariHandleResetActionMoveSelection,
SafariHandleCmd55,
SafariCmdEnd,
};
// not used
static void SpriteCB_Null4(struct Sprite *sprite)
{
}
void SetControllerToSafari(void)
{
gBattlerControllerFuncs[gActiveBattler] = SafariBufferRunCommand;
}
static void SafariBufferRunCommand(void)
{
if (gBattleControllerExecFlags & gBitTable[gActiveBattler])
{
if (gBattleBufferA[gActiveBattler][0] < NELEMS(sSafariBufferCommands))
sSafariBufferCommands[gBattleBufferA[gActiveBattler][0]]();
else
SafariBufferExecCompleted();
}
}
static void HandleInputChooseAction(void)
{
if (JOY_NEW(A_BUTTON))
{
PlaySE(SE_SELECT);
switch (gActionSelectionCursor[gActiveBattler])
{
case 0:
BtlController_EmitTwoReturnValues(1, B_ACTION_SAFARI_BALL, 0);
break;
case 1:
BtlController_EmitTwoReturnValues(1, B_ACTION_SAFARI_POKEBLOCK, 0);
break;
case 2:
BtlController_EmitTwoReturnValues(1, B_ACTION_SAFARI_GO_NEAR, 0);
break;
case 3:
BtlController_EmitTwoReturnValues(1, B_ACTION_SAFARI_RUN, 0);
break;
}
SafariBufferExecCompleted();
}
else if (JOY_NEW(DPAD_LEFT))
{
if (gActionSelectionCursor[gActiveBattler] & 1)
{
PlaySE(SE_SELECT);
ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]);
gActionSelectionCursor[gActiveBattler] ^= 1;
ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
}
}
else if (JOY_NEW(DPAD_RIGHT))
{
if (!(gActionSelectionCursor[gActiveBattler] & 1))
{
PlaySE(SE_SELECT);
ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]);
gActionSelectionCursor[gActiveBattler] ^= 1;
ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
}
}
else if (JOY_NEW(DPAD_UP))
{
if (gActionSelectionCursor[gActiveBattler] & 2)
{
PlaySE(SE_SELECT);
ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]);
gActionSelectionCursor[gActiveBattler] ^= 2;
ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
}
}
else if (JOY_NEW(DPAD_DOWN))
{
if (!(gActionSelectionCursor[gActiveBattler] & 2))
{
PlaySE(SE_SELECT);
ActionSelectionDestroyCursorAt(gActionSelectionCursor[gActiveBattler]);
gActionSelectionCursor[gActiveBattler] ^= 2;
ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
}
}
}
static void CompleteOnBattlerSpriteCallbackDummy(void)
{
if (gSprites[gBattlerSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy)
SafariBufferExecCompleted();
}
static void CompleteOnInactiveTextPrinter(void)
{
if (!IsTextPrinterActive(0))
SafariBufferExecCompleted();
}
static void CompleteOnHealthboxSpriteCallbackDummy(void)
{
if (gSprites[gHealthboxSpriteIds[gActiveBattler]].callback == SpriteCallbackDummy)
SafariBufferExecCompleted();
}
static void sub_80DD7B0(void)
{
if (!gPaletteFade.active)
{
gMain.inBattle = FALSE;
gMain.callback1 = gPreBattleCallback1;
SetMainCallback2(gMain.savedCallback);
}
}
static void CompleteOnSpecialAnimDone(void)
{
if (!gDoingBattleAnim || !gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].specialAnimActive)
SafariBufferExecCompleted();
}
static void SafariOpenPokeblockCase(void)
{
if (!gPaletteFade.active)
gBattlerControllerFuncs[gActiveBattler] = CompleteWhenChosePokeblock;
}
static void CompleteWhenChosePokeblock(void)
{
if (gMain.callback2 == BattleMainCB2 && !gPaletteFade.active)
{
BtlController_EmitOneReturnValue(1, gSpecialVar_ItemId);
SafariBufferExecCompleted();
}
}
static void CompleteOnFinishedBattleAnimation(void)
{
if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].animFromTableActive)
SafariBufferExecCompleted();
}
static void SafariBufferExecCompleted(void)
{
gBattlerControllerFuncs[gActiveBattler] = SafariBufferRunCommand;
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
{
u8 playerId = GetMultiplayerId();
PrepareBufferDataTransferLink(2, 4, &playerId);
gBattleBufferA[gActiveBattler][0] = CONTROLLER_TERMINATOR_NOP;
}
else
{
gBattleControllerExecFlags &= ~gBitTable[gActiveBattler];
}
}
// not used
static void CompleteOnFinishedStatusAnimation(void)
{
if (!gBattleSpritesDataPtr->healthBoxesData[gActiveBattler].statusAnimActive)
SafariBufferExecCompleted();
}
static void SafariHandleGetMonData(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleGetRawMonData(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleSetMonData(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleSetRawMonData(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleLoadMonSprite(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleSwitchInAnim(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleReturnMonToBall(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleDrawTrainerPic(void)
{
DecompressTrainerBackPalette(gSaveBlock2Ptr->playerGender, gActiveBattler);
SetMultiuseSpriteTemplateToTrainerBack(gSaveBlock2Ptr->playerGender, GetBattlerPosition(gActiveBattler));
gBattlerSpriteIds[gActiveBattler] = CreateSprite(&gMultiuseSpriteTemplate,
80,
(8 - gTrainerBackPicCoords[gSaveBlock2Ptr->playerGender].size) * 4 + 80,
30);
gSprites[gBattlerSpriteIds[gActiveBattler]].oam.paletteNum = gActiveBattler;
gSprites[gBattlerSpriteIds[gActiveBattler]].pos2.x = 240;
gSprites[gBattlerSpriteIds[gActiveBattler]].data[0] = -2;
gSprites[gBattlerSpriteIds[gActiveBattler]].callback = sub_8033EEC;
gBattlerControllerFuncs[gActiveBattler] = CompleteOnBattlerSpriteCallbackDummy;
}
static void SafariHandleTrainerSlide(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleTrainerSlideBack(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleFaintAnimation(void)
{
SafariBufferExecCompleted();
}
static void SafariHandlePaletteFade(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleSuccessBallThrowAnim(void)
{
gBattleSpritesDataPtr->animationData->ballThrowCaseId = BALL_3_SHAKES_SUCCESS;
gDoingBattleAnim = TRUE;
InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_SAFARI_BALL_THROW);
gBattlerControllerFuncs[gActiveBattler] = CompleteOnSpecialAnimDone;
}
static void SafariHandleBallThrowAnim(void)
{
u8 ballThrowCaseId = gBattleBufferA[gActiveBattler][1];
gBattleSpritesDataPtr->animationData->ballThrowCaseId = ballThrowCaseId;
gDoingBattleAnim = TRUE;
InitAndLaunchSpecialAnimation(gActiveBattler, gActiveBattler, GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT), B_ANIM_SAFARI_BALL_THROW);
gBattlerControllerFuncs[gActiveBattler] = CompleteOnSpecialAnimDone;
}
static void SafariHandlePause(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleMoveAnimation(void)
{
SafariBufferExecCompleted();
}
static void SafariHandlePrintString(void)
{
u16 *stringId;
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
stringId = (u16 *)(&gBattleBufferA[gActiveBattler][2]);
BufferStringBattle(*stringId);
if (sub_80D89B0(*stringId))
BattlePutTextOnWindow(gDisplayedStringBattle, 0x40);
else
BattlePutTextOnWindow(gDisplayedStringBattle, 0);
gBattlerControllerFuncs[gActiveBattler] = CompleteOnInactiveTextPrinter;
}
static void SafariHandlePrintSelectionString(void)
{
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
SafariHandlePrintString();
else
SafariBufferExecCompleted();
}
static void HandleChooseActionAfterDma3(void)
{
if (!IsDma3ManagerBusyWithBgCopy())
{
gBattle_BG0_X = 0;
gBattle_BG0_Y = 160;
gBattlerControllerFuncs[gActiveBattler] = HandleInputChooseAction;
}
}
static void SafariHandleChooseAction(void)
{
s32 i;
gBattlerControllerFuncs[gActiveBattler] = HandleChooseActionAfterDma3;
BattlePutTextOnWindow(gUnknown_83FDA4C, 0);
BattlePutTextOnWindow(gUnknown_83FE747, 2);
for (i = 0; i < 4; ++i)
ActionSelectionDestroyCursorAt(i);
ActionSelectionCreateCursorAt(gActionSelectionCursor[gActiveBattler], 0);
BattleStringExpandPlaceholdersToDisplayedString(gUnknown_83FE6E6);
BattlePutTextOnWindow(gDisplayedStringBattle, 1);
}
static void SafariHandleUnknownYesNoBox(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleChooseMove(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleChooseItem(void)
{
s32 i;
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, RGB_BLACK);
gBattlerControllerFuncs[gActiveBattler] = SafariOpenPokeblockCase;
gBattlerInMenuId = gActiveBattler;
}
static void SafariHandleChoosePokemon(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleCmd23(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleHealthBarUpdate(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleExpUpdate(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleStatusIconUpdate(void)
{
UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_SAFARI_BALLS_TEXT);
SafariBufferExecCompleted();
}
static void SafariHandleStatusAnimation(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleStatusXor(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleDataTransfer(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleDMA3Transfer(void)
{
SafariBufferExecCompleted();
}
static void SafariHandlePlayBGM(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleCmd32(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleTwoReturnValues(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleChosenMonReturnValue(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleOneReturnValue(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleOneReturnValue_Duplicate(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleCmd37(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleCmd38(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleCmd39(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleCmd40(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleHitAnimation(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleCmd42(void)
{
SafariBufferExecCompleted();
}
static void SafariHandlePlaySE(void)
{
s8 pan;
if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER)
pan = SOUND_PAN_ATTACKER;
else
pan = SOUND_PAN_TARGET;
PlaySE12WithPanning(gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8), pan);
SafariBufferExecCompleted();
}
static void SafariHandlePlayFanfareOrBGM(void)
{
PlayFanfare(gBattleBufferA[gActiveBattler][1] | (gBattleBufferA[gActiveBattler][2] << 8));
SafariBufferExecCompleted();
}
static void SafariHandleFaintingCry(void)
{
u16 species = GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_SPECIES);
PlayCry1(species, 25);
SafariBufferExecCompleted();
}
static void SafariHandleIntroSlide(void)
{
HandleIntroSlide(gBattleBufferA[gActiveBattler][1]);
gIntroSlideFlags |= 1;
SafariBufferExecCompleted();
}
static void SafariHandleIntroTrainerBallThrow(void)
{
UpdateHealthboxAttribute(gHealthboxSpriteIds[gActiveBattler], &gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], HEALTHBOX_SAFARI_ALL_TEXT);
sub_804BD94(gActiveBattler);
SetHealthboxSpriteVisible(gHealthboxSpriteIds[gActiveBattler]);
gBattlerControllerFuncs[gActiveBattler] = CompleteOnHealthboxSpriteCallbackDummy;
}
static void SafariHandleDrawPartyStatusSummary(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleHidePartyStatusSummary(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleEndBounceEffect(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleSpriteInvisibility(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleBattleAnimation(void)
{
u8 animationId = gBattleBufferA[gActiveBattler][1];
u16 argument = gBattleBufferA[gActiveBattler][2] | (gBattleBufferA[gActiveBattler][3] << 8);
if (TryHandleLaunchBattleTableAnimation(gActiveBattler, gActiveBattler, gActiveBattler, animationId, argument))
SafariBufferExecCompleted();
else
gBattlerControllerFuncs[gActiveBattler] = CompleteOnFinishedBattleAnimation;
}
static void SafariHandleLinkStandbyMsg(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleResetActionMoveSelection(void)
{
SafariBufferExecCompleted();
}
static void SafariHandleCmd55(void)
{
gBattleOutcome = gBattleBufferA[gActiveBattler][1];
FadeOutMapMusic(5);
BeginFastPaletteFade(3);
SafariBufferExecCompleted();
if ((gBattleTypeFlags & BATTLE_TYPE_LINK) && !(gBattleTypeFlags & BATTLE_TYPE_IS_MASTER))
gBattlerControllerFuncs[gActiveBattler] = sub_80DD7B0;
}
static void SafariCmdEnd(void)
{
}
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
File diff suppressed because it is too large Load Diff
+3200
View File
File diff suppressed because it is too large Load Diff
+96
View File
@@ -0,0 +1,96 @@
#include "global.h"
#include "bg.h"
#include "battle.h"
#include "pokemon.h"
#include "malloc.h"
#include "trainer_tower.h"
#include "battle_util2.h"
void AllocateBattleResources(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER)
InitTrainerTowerBattleStruct();
if (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE)
{
s32 i;
for (i = 0; i < 4; ++i)
gUnknown_3005EE0[i] = AllocZeroed(8);
}
gBattleStruct = AllocZeroed(sizeof(*gBattleStruct));
gBattleResources = AllocZeroed(sizeof(*gBattleResources));
gBattleResources->secretBase = AllocZeroed(sizeof(*gBattleResources->secretBase));
gBattleResources->flags = AllocZeroed(sizeof(*gBattleResources->flags));
gBattleResources->battleScriptsStack = AllocZeroed(sizeof(*gBattleResources->battleScriptsStack));
gBattleResources->battleCallbackStack = AllocZeroed(sizeof(*gBattleResources->battleCallbackStack));
gBattleResources->beforeLvlUp = AllocZeroed(sizeof(*gBattleResources->beforeLvlUp));
gBattleResources->ai = AllocZeroed(sizeof(*gBattleResources->ai));
gBattleResources->battleHistory = AllocZeroed(sizeof(*gBattleResources->battleHistory));
gBattleResources->AI_ScriptsStack = AllocZeroed(sizeof(*gBattleResources->AI_ScriptsStack));
gLinkBattleSendBuffer = AllocZeroed(BATTLE_BUFFER_LINK_SIZE);
gLinkBattleRecvBuffer = AllocZeroed(BATTLE_BUFFER_LINK_SIZE);
gUnknown_2022BB8 = AllocZeroed(0x2000);
gUnknown_2022BBC = AllocZeroed(0x1000);
SetBgTilemapBuffer(1, gUnknown_2022BBC);
SetBgTilemapBuffer(2, gUnknown_2022BBC);
}
void FreeBattleResources(void)
{
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER_TOWER)
FreeTrainerTowerBattleStruct();
if (gBattleTypeFlags & BATTLE_TYPE_POKEDUDE)
{
s32 i;
for (i = 0; i < 4; ++i)
{
FREE_AND_SET_NULL(gUnknown_3005EE0[i]);
}
}
if (gBattleResources != NULL)
{
FREE_AND_SET_NULL(gBattleStruct);
FREE_AND_SET_NULL(gBattleResources->secretBase);
FREE_AND_SET_NULL(gBattleResources->flags);
FREE_AND_SET_NULL(gBattleResources->battleScriptsStack);
FREE_AND_SET_NULL(gBattleResources->battleCallbackStack);
FREE_AND_SET_NULL(gBattleResources->beforeLvlUp);
FREE_AND_SET_NULL(gBattleResources->ai);
FREE_AND_SET_NULL(gBattleResources->battleHistory);
FREE_AND_SET_NULL(gBattleResources->AI_ScriptsStack);
FREE_AND_SET_NULL(gBattleResources);
FREE_AND_SET_NULL(gLinkBattleSendBuffer);
FREE_AND_SET_NULL(gLinkBattleRecvBuffer);
FREE_AND_SET_NULL(gUnknown_2022BB8);
FREE_AND_SET_NULL(gUnknown_2022BBC);
}
}
void AdjustFriendshipOnBattleFaint(u8 battlerId)
{
u8 opposingBattlerId, opposingBattlerId2;
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
{
opposingBattlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
opposingBattlerId2 = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
if (gBattleMons[opposingBattlerId2].level > gBattleMons[opposingBattlerId].level)
opposingBattlerId = opposingBattlerId2;
}
else
{
opposingBattlerId = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
}
if (gBattleMons[opposingBattlerId].level > gBattleMons[battlerId].level)
{
if (gBattleMons[opposingBattlerId].level - gBattleMons[battlerId].level > 29)
AdjustFriendship(&gPlayerParty[gBattlerPartyIndexes[battlerId]], 9);
else
AdjustFriendship(&gPlayerParty[gBattlerPartyIndexes[battlerId]], 7);
}
else
{
AdjustFriendship(&gPlayerParty[gBattlerPartyIndexes[battlerId]], 7);
}
}
+43 -43
View File
@@ -17,20 +17,20 @@ u16 Font6Func(struct TextPrinter *textPrinter)
u16 char_;
struct TextPrinterSubStruct *sub;
sub = &textPrinter->sub_union.sub;
sub = &textPrinter->subUnion.sub;
switch (textPrinter->state)
{
case 0:
if (gMain.heldKeys & (A_BUTTON | B_BUTTON) && sub->font_type_upper)
if (gMain.heldKeys & (A_BUTTON | B_BUTTON) && sub->hasPrintBeenSpedUp)
{
textPrinter->delayCounter = 0;
}
if (textPrinter->delayCounter && textPrinter->text_speed)
if (textPrinter->delayCounter && textPrinter->textSpeed)
{
textPrinter->delayCounter --;
if (gTextFlags.canABSpeedUpPrint && gMain.newKeys & (A_BUTTON | B_BUTTON))
{
sub->font_type_upper = TRUE;
sub->hasPrintBeenSpedUp = TRUE;
textPrinter->delayCounter = 0;
}
return 3;
@@ -41,62 +41,62 @@ u16 Font6Func(struct TextPrinter *textPrinter)
}
else
{
textPrinter->delayCounter = textPrinter->text_speed;
textPrinter->delayCounter = textPrinter->textSpeed;
}
char_ = *textPrinter->subPrinter.currentChar++;
char_ = *textPrinter->printerTemplate.currentChar++;
switch (char_)
{
case EOS:
return 1;
case CHAR_NEWLINE:
textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
textPrinter->subPrinter.currentY += gFonts[textPrinter->subPrinter.fontId].maxLetterHeight + textPrinter->subPrinter.lineSpacing;
textPrinter->printerTemplate.currentX = textPrinter->printerTemplate.x;
textPrinter->printerTemplate.currentY += gFonts[textPrinter->printerTemplate.fontId].maxLetterHeight + textPrinter->printerTemplate.lineSpacing;
return 2;
case PLACEHOLDER_BEGIN:
textPrinter->subPrinter.currentChar++;
textPrinter->printerTemplate.currentChar++;
return 2;
case EXT_CTRL_CODE_BEGIN:
char_ = *textPrinter->subPrinter.currentChar++;
char_ = *textPrinter->printerTemplate.currentChar++;
switch (char_)
{
case 1:
textPrinter->subPrinter.fgColor = *textPrinter->subPrinter.currentChar++;
GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fgColor, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
textPrinter->printerTemplate.fgColor = *textPrinter->printerTemplate.currentChar++;
GenerateFontHalfRowLookupTable(textPrinter->printerTemplate.fgColor, textPrinter->printerTemplate.bgColor, textPrinter->printerTemplate.shadowColor);
return 2;
case 2:
textPrinter->subPrinter.bgColor = *textPrinter->subPrinter.currentChar++;
GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fgColor, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
textPrinter->printerTemplate.bgColor = *textPrinter->printerTemplate.currentChar++;
GenerateFontHalfRowLookupTable(textPrinter->printerTemplate.fgColor, textPrinter->printerTemplate.bgColor, textPrinter->printerTemplate.shadowColor);
return 2;
case 3:
textPrinter->subPrinter.shadowColor = *textPrinter->subPrinter.currentChar++;
GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fgColor, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
textPrinter->printerTemplate.shadowColor = *textPrinter->printerTemplate.currentChar++;
GenerateFontHalfRowLookupTable(textPrinter->printerTemplate.fgColor, textPrinter->printerTemplate.bgColor, textPrinter->printerTemplate.shadowColor);
return 2;
case 4:
textPrinter->subPrinter.fgColor = *textPrinter->subPrinter.currentChar;
textPrinter->subPrinter.bgColor = *++textPrinter->subPrinter.currentChar;
textPrinter->subPrinter.shadowColor = *++textPrinter->subPrinter.currentChar;
textPrinter->subPrinter.currentChar++;
textPrinter->printerTemplate.fgColor = *textPrinter->printerTemplate.currentChar;
textPrinter->printerTemplate.bgColor = *++textPrinter->printerTemplate.currentChar;
textPrinter->printerTemplate.shadowColor = *++textPrinter->printerTemplate.currentChar;
textPrinter->printerTemplate.currentChar++;
GenerateFontHalfRowLookupTable(textPrinter->subPrinter.fgColor, textPrinter->subPrinter.bgColor, textPrinter->subPrinter.shadowColor);
GenerateFontHalfRowLookupTable(textPrinter->printerTemplate.fgColor, textPrinter->printerTemplate.bgColor, textPrinter->printerTemplate.shadowColor);
return 2;
case 5:
textPrinter->subPrinter.currentChar++;
textPrinter->printerTemplate.currentChar++;
return 2;
case 6:
sub->font_type = *textPrinter->subPrinter.currentChar;
textPrinter->subPrinter.currentChar++;
sub->glyphId = *textPrinter->printerTemplate.currentChar;
textPrinter->printerTemplate.currentChar++;
return 2;
case 7:
return 2;
case 8:
textPrinter->delayCounter = *textPrinter->subPrinter.currentChar++;
textPrinter->delayCounter = *textPrinter->printerTemplate.currentChar++;
textPrinter->state = 6;
return 2;
case 9:
textPrinter->state = 1;
if (gTextFlags.autoScroll)
{
sub->frames_visible_counter = 0;
sub->autoScrollDelay = 0;
}
return 3;
case 10:
@@ -104,19 +104,19 @@ u16 Font6Func(struct TextPrinter *textPrinter)
return 3;
case 11:
case 16:
textPrinter->subPrinter.currentChar += 2;
textPrinter->printerTemplate.currentChar += 2;
return 2;
case 12:
char_ = *++textPrinter->subPrinter.currentChar;
char_ = *++textPrinter->printerTemplate.currentChar;
break;
case 13:
textPrinter->subPrinter.currentX = textPrinter->subPrinter.x + *textPrinter->subPrinter.currentChar++;
textPrinter->printerTemplate.currentX = textPrinter->printerTemplate.x + *textPrinter->printerTemplate.currentChar++;
return 2;
case 14:
textPrinter->subPrinter.currentY = textPrinter->subPrinter.y + *textPrinter->subPrinter.currentChar++;
textPrinter->printerTemplate.currentY = textPrinter->printerTemplate.y + *textPrinter->printerTemplate.currentChar++;
return 2;
case 15:
FillWindowPixelBuffer(textPrinter->subPrinter.windowId, PIXEL_FILL(textPrinter->subPrinter.bgColor));
FillWindowPixelBuffer(textPrinter->printerTemplate.windowId, PIXEL_FILL(textPrinter->printerTemplate.bgColor));
return 2;
}
break;
@@ -129,15 +129,15 @@ u16 Font6Func(struct TextPrinter *textPrinter)
TextPrinterInitDownArrowCounters(textPrinter);
return 3;
case 0xF9:
char_ = *textPrinter->subPrinter.currentChar++| 0x100;
char_ = *textPrinter->printerTemplate.currentChar++| 0x100;
break;
case 0xF8:
textPrinter->subPrinter.currentChar++;
textPrinter->printerTemplate.currentChar++;
return 0;
}
DecompressGlyphFont6(char_);
CopyGlyphToWindow(textPrinter);
textPrinter->subPrinter.currentX += gGlyphInfo[0x80] + textPrinter->subPrinter.letterSpacing;
textPrinter->printerTemplate.currentX += gGlyphInfo[0x80] + textPrinter->printerTemplate.letterSpacing;
return 0;
case 1:
if (TextPrinterWait(textPrinter))
@@ -148,9 +148,9 @@ u16 Font6Func(struct TextPrinter *textPrinter)
case 2:
if (TextPrinterWaitWithDownArrow(textPrinter))
{
FillWindowPixelBuffer(textPrinter->subPrinter.windowId, PIXEL_FILL(textPrinter->subPrinter.bgColor));
textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
textPrinter->subPrinter.currentY = textPrinter->subPrinter.y;
FillWindowPixelBuffer(textPrinter->printerTemplate.windowId, PIXEL_FILL(textPrinter->printerTemplate.bgColor));
textPrinter->printerTemplate.currentX = textPrinter->printerTemplate.x;
textPrinter->printerTemplate.currentY = textPrinter->printerTemplate.y;
textPrinter->state = 0;
}
return 3;
@@ -158,8 +158,8 @@ u16 Font6Func(struct TextPrinter *textPrinter)
if (TextPrinterWaitWithDownArrow(textPrinter))
{
TextPrinterClearDownArrow(textPrinter);
textPrinter->scrollDistance = gFonts[textPrinter->subPrinter.fontId].maxLetterHeight + textPrinter->subPrinter.lineSpacing;
textPrinter->subPrinter.currentX = textPrinter->subPrinter.x;
textPrinter->scrollDistance = gFonts[textPrinter->printerTemplate.fontId].maxLetterHeight + textPrinter->printerTemplate.lineSpacing;
textPrinter->printerTemplate.currentX = textPrinter->printerTemplate.x;
textPrinter->state = 4;
}
return 3;
@@ -168,15 +168,15 @@ u16 Font6Func(struct TextPrinter *textPrinter)
{
if (textPrinter->scrollDistance < gUnknown_846FB08[gSaveBlock2Ptr->optionsTextSpeed])
{
ScrollWindow(textPrinter->subPrinter.windowId, 0, textPrinter->scrollDistance, PIXEL_FILL(textPrinter->subPrinter.bgColor));
ScrollWindow(textPrinter->printerTemplate.windowId, 0, textPrinter->scrollDistance, PIXEL_FILL(textPrinter->printerTemplate.bgColor));
textPrinter->scrollDistance = 0;
}
else
{
ScrollWindow(textPrinter->subPrinter.windowId, 0, gUnknown_846FB08[gSaveBlock2Ptr->optionsTextSpeed], PIXEL_FILL(textPrinter->subPrinter.bgColor));
ScrollWindow(textPrinter->printerTemplate.windowId, 0, gUnknown_846FB08[gSaveBlock2Ptr->optionsTextSpeed], PIXEL_FILL(textPrinter->printerTemplate.bgColor));
textPrinter->scrollDistance -= gUnknown_846FB08[gSaveBlock2Ptr->optionsTextSpeed];
}
CopyWindowToVram(textPrinter->subPrinter.windowId, 2);
CopyWindowToVram(textPrinter->printerTemplate.windowId, 2);
}
else
{
@@ -216,7 +216,7 @@ static void DecompressGlyphFont6(u16 glyph)
gGlyphInfo[0x81] = 0x10;
}
u32 GetGlyphWidthFont6(u16 font_type, bool32 isJapanese)
s32 GetGlyphWidthFont6(u16 font_type, bool32 isJapanese)
{
return 0x10;
}
+2167
View File
File diff suppressed because it is too large Load Diff
+1 -1
View File
@@ -6059,4 +6059,4 @@
"secondaryId": 0
}
]
}
}
+1 -1
View File
@@ -1,6 +1,6 @@
#include "global.h"
#include "bg.h"
#include "data2.h"
#include "data.h"
#include "decompress.h"
#include "gpu_regs.h"
#include "graphics.h"
+69 -254
View File
@@ -1,5 +1,6 @@
#include "global.h"
#include "text.h"
#include "blit.h"
#include "gpu_regs.h"
#include "task.h"
#include "wild_encounter.h"
@@ -502,261 +503,75 @@ void sub_812E6DC(u8 windowId, const u8 * src, u16 x, u16 y)
}
}
// Yeah, no, I'm not bothering with this
NAKED
static void sub_812E768(void * a0, void * a1, u16 a2, u16 a3, u16 a4, u16 a5, u16 a6, u16 a7)
static void sub_812E768(const struct Bitmap *src, struct Bitmap *dst, u16 srcX, u16 srcY, u16 dstX, u16 dstY, u16 width, u16 height)
{
asm_unified("\tpush {r4-r7,lr}\n"
"\tmov r7, r10\n"
"\tmov r6, r9\n"
"\tmov r5, r8\n"
"\tpush {r5-r7}\n"
"\tsub sp, 0x28\n"
"\tstr r0, [sp]\n"
"\tstr r1, [sp, 0x4]\n"
"\tldr r0, [sp, 0x48]\n"
"\tldr r4, [sp, 0x4C]\n"
"\tldr r1, [sp, 0x50]\n"
"\tldr r5, [sp, 0x54]\n"
"\tlsls r2, 16\n"
"\tlsrs r2, 16\n"
"\tstr r2, [sp, 0x8]\n"
"\tlsls r3, 16\n"
"\tlsrs r3, 16\n"
"\tlsls r0, 16\n"
"\tlsrs r0, 16\n"
"\tstr r0, [sp, 0xC]\n"
"\tlsls r4, 16\n"
"\tlsrs r4, 16\n"
"\tlsls r1, 16\n"
"\tlsrs r1, 16\n"
"\tlsls r5, 16\n"
"\tlsrs r5, 16\n"
"\tldr r2, [sp, 0x4]\n"
"\tldrh r0, [r2, 0x4]\n"
"\tldr r2, [sp, 0xC]\n"
"\tsubs r0, r2\n"
"\tldr r2, [sp, 0x8]\n"
"\tadds r2, r1, r2\n"
"\tstr r2, [sp, 0x10]\n"
"\tcmp r0, r1\n"
"\tbge _0812E7B4\n"
"\tldr r1, [sp, 0x8]\n"
"\tadds r0, r1\n"
"\tstr r0, [sp, 0x10]\n"
"_0812E7B4:\n"
"\tldr r2, [sp, 0x4]\n"
"\tldrh r1, [r2, 0x6]\n"
"\tsubs r0, r1, r4\n"
"\tcmp r0, r5\n"
"\tbge _0812E7C6\n"
"\tadds r0, r3, r1\n"
"\tsubs r0, r4\n"
"\tstr r0, [sp, 0x14]\n"
"\tb _0812E7CA\n"
"_0812E7C6:\n"
"\tadds r5, r3, r5\n"
"\tstr r5, [sp, 0x14]\n"
"_0812E7CA:\n"
"\tldr r0, [sp]\n"
"\tldrh r1, [r0, 0x4]\n"
"\tmovs r2, 0x7\n"
"\tadds r0, r1, 0\n"
"\tands r0, r2\n"
"\tadds r1, r0\n"
"\tasrs r1, 3\n"
"\tstr r1, [sp, 0x18]\n"
"\tldr r0, [sp, 0x4]\n"
"\tldrh r1, [r0, 0x4]\n"
"\tadds r0, r1, 0\n"
"\tands r0, r2\n"
"\tadds r1, r0\n"
"\tasrs r1, 3\n"
"\tstr r1, [sp, 0x1C]\n"
"\tmov r12, r3\n"
"\tmov r8, r4\n"
"\tldr r1, [sp, 0x14]\n"
"\tcmp r12, r1\n"
"\tblt _0812E7F4\n"
"\tb _0812E932\n"
"_0812E7F4:\n"
"\tldr r5, [sp, 0x8]\n"
"\tldr r6, [sp, 0xC]\n"
"\tmov r2, r12\n"
"\tadds r2, 0x1\n"
"\tstr r2, [sp, 0x20]\n"
"\tmov r0, r8\n"
"\tadds r0, 0x1\n"
"\tstr r0, [sp, 0x24]\n"
"\tldr r1, [sp, 0x10]\n"
"\tcmp r5, r1\n"
"\tblt _0812E80C\n"
"\tb _0812E922\n"
"_0812E80C:\n"
"\tmovs r7, 0x1\n"
"\tmovs r2, 0xF0\n"
"\tmov r10, r2\n"
"\tmovs r0, 0xF\n"
"\tmov r9, r0\n"
"_0812E816:\n"
"\tasrs r0, r5, 1\n"
"\tmovs r1, 0x3\n"
"\tands r0, r1\n"
"\tldr r2, [sp]\n"
"\tldr r1, [r2]\n"
"\tadds r1, r0\n"
"\tasrs r0, r5, 3\n"
"\tlsls r0, 5\n"
"\tadds r1, r0\n"
"\tmov r2, r12\n"
"\tasrs r0, r2, 3\n"
"\tldr r2, [sp, 0x18]\n"
"\tmuls r0, r2\n"
"\tlsls r0, 5\n"
"\tadds r1, r0\n"
"\tmov r2, r12\n"
"\tlsls r0, r2, 29\n"
"\tlsrs r0, 27\n"
"\tadds r3, r1, r0\n"
"\tasrs r0, r6, 1\n"
"\tmovs r1, 0x3\n"
"\tands r0, r1\n"
"\tldr r2, [sp, 0x4]\n"
"\tldr r1, [r2]\n"
"\tadds r1, r0\n"
"\tasrs r0, r6, 3\n"
"\tlsls r0, 5\n"
"\tadds r1, r0\n"
"\tmov r2, r8\n"
"\tasrs r0, r2, 3\n"
"\tldr r2, [sp, 0x1C]\n"
"\tmuls r0, r2\n"
"\tlsls r0, 5\n"
"\tadds r1, r0\n"
"\tmov r2, r8\n"
"\tlsls r0, r2, 29\n"
"\tlsrs r0, 27\n"
"\tadds r4, r1, r0\n"
"\tadds r0, r4, 0\n"
"\tands r0, r7\n"
"\tcmp r0, 0\n"
"\tbeq _0812E8C2\n"
"\tsubs r4, 0x1\n"
"\tadds r0, r6, 0\n"
"\tands r0, r7\n"
"\tcmp r0, 0\n"
"\tbeq _0812E89A\n"
"\tldrh r0, [r4]\n"
"\tldr r2, _0812E88C @ =0x00000fff\n"
"\tands r2, r0\n"
"\tadds r0, r5, 0\n"
"\tands r0, r7\n"
"\tcmp r0, 0\n"
"\tbeq _0812E890\n"
"\tldrb r1, [r3]\n"
"\tmov r0, r10\n"
"\tands r0, r1\n"
"\tlsls r0, 8\n"
"\tb _0812E912\n"
"\t.align 2, 0\n"
"_0812E88C: .4byte 0x00000fff\n"
"_0812E890:\n"
"\tldrb r1, [r3]\n"
"\tmov r0, r9\n"
"\tands r0, r1\n"
"\tlsls r0, 12\n"
"\tb _0812E912\n"
"_0812E89A:\n"
"\tldrh r0, [r4]\n"
"\tldr r2, _0812E8B4 @ =0x0000f0ff\n"
"\tands r2, r0\n"
"\tadds r0, r5, 0\n"
"\tands r0, r7\n"
"\tcmp r0, 0\n"
"\tbeq _0812E8B8\n"
"\tldrb r1, [r3]\n"
"\tmov r0, r10\n"
"\tands r0, r1\n"
"\tlsls r0, 4\n"
"\tb _0812E912\n"
"\t.align 2, 0\n"
"_0812E8B4: .4byte 0x0000f0ff\n"
"_0812E8B8:\n"
"\tldrb r1, [r3]\n"
"\tmov r0, r9\n"
"\tands r0, r1\n"
"\tlsls r0, 8\n"
"\tb _0812E912\n"
"_0812E8C2:\n"
"\tadds r0, r6, 0\n"
"\tands r0, r7\n"
"\tcmp r0, 0\n"
"\tbeq _0812E8EE\n"
"\tldrh r0, [r4]\n"
"\tldr r2, _0812E8E0 @ =0x0000ff0f\n"
"\tands r2, r0\n"
"\tadds r0, r5, 0\n"
"\tands r0, r7\n"
"\tcmp r0, 0\n"
"\tbeq _0812E8E4\n"
"\tldrb r1, [r3]\n"
"\tmov r0, r10\n"
"\tb _0812E910\n"
"\t.align 2, 0\n"
"_0812E8E0: .4byte 0x0000ff0f\n"
"_0812E8E4:\n"
"\tldrb r1, [r3]\n"
"\tmov r0, r9\n"
"\tands r0, r1\n"
"\tlsls r0, 4\n"
"\tb _0812E912\n"
"_0812E8EE:\n"
"\tldrh r0, [r4]\n"
"\tldr r2, _0812E908 @ =0x0000fff0\n"
"\tands r2, r0\n"
"\tadds r0, r5, 0\n"
"\tands r0, r7\n"
"\tcmp r0, 0\n"
"\tbeq _0812E90C\n"
"\tldrb r1, [r3]\n"
"\tmov r0, r10\n"
"\tands r0, r1\n"
"\tlsrs r0, 4\n"
"\tb _0812E912\n"
"\t.align 2, 0\n"
"_0812E908: .4byte 0x0000fff0\n"
"_0812E90C:\n"
"\tldrb r1, [r3]\n"
"\tmov r0, r9\n"
"_0812E910:\n"
"\tands r0, r1\n"
"_0812E912:\n"
"\torrs r2, r0\n"
"\tstrh r2, [r4]\n"
"\tadds r5, 0x1\n"
"\tadds r6, 0x1\n"
"\tldr r0, [sp, 0x10]\n"
"\tcmp r5, r0\n"
"\tbge _0812E922\n"
"\tb _0812E816\n"
"_0812E922:\n"
"\tldr r1, [sp, 0x20]\n"
"\tmov r12, r1\n"
"\tldr r2, [sp, 0x24]\n"
"\tmov r8, r2\n"
"\tldr r0, [sp, 0x14]\n"
"\tcmp r12, r0\n"
"\tbge _0812E932\n"
"\tb _0812E7F4\n"
"_0812E932:\n"
"\tadd sp, 0x28\n"
"\tpop {r3-r5}\n"
"\tmov r8, r3\n"
"\tmov r9, r4\n"
"\tmov r10, r5\n"
"\tpop {r4-r7}\n"
"\tpop {r0}\n"
"\tbx r0");
s32 loopSrcY, loopDstY, loopSrcX, loopDstX, xEnd, yEnd, multiplierSrcY, multiplierDstY;
u16 toOrr;
const u8 *pixelsSrc;
u16 *pixelsDst;
if (dst->width - dstX < width)
xEnd = dst->width - dstX + srcX;
else
xEnd = width + srcX;
if (dst->height - dstY < height)
yEnd = srcY + dst->height - dstY;
else
yEnd = srcY + height;
multiplierSrcY = (src->width + (src->width & 7)) >> 3;
multiplierDstY = (dst->width + (dst->width & 7)) >> 3;
for (loopSrcY = srcY, loopDstY = dstY; loopSrcY < yEnd; loopSrcY++, loopDstY++)
{
for (loopSrcX = srcX, loopDstX = dstX; loopSrcX < xEnd; loopSrcX++, loopDstX++)
{
#ifndef NONMATCHING
asm("":::"r4");
#endif
pixelsSrc = src->pixels + ((loopSrcX >> 1) & 3) + ((loopSrcX >> 3) << 5) + (((loopSrcY >> 3) * multiplierSrcY) << 5) + ((u32)(loopSrcY << 0x1d) >> 0x1B);
pixelsDst = (u16 *)(dst->pixels + ((loopDstX >> 1) & 3) + ((loopDstX >> 3) << 5) + ((( loopDstY >> 3) * multiplierDstY) << 5) + ((u32)( loopDstY << 0x1d) >> 0x1B));
if ((uintptr_t)pixelsDst & 0x1)
{
pixelsDst = (void *)pixelsDst - 1;
if (loopDstX & 0x1)
{
toOrr = *pixelsDst & 0x0fff;
if (loopSrcX & 0x1)
*pixelsDst = toOrr | ((*pixelsSrc & 0xf0) << 8);
else
*pixelsDst = toOrr | ((*pixelsSrc & 0x0f) << 12);
}
else
{
toOrr = *pixelsDst & 0xf0ff;
if (loopSrcX & 0x1)
*pixelsDst = toOrr | ((*pixelsSrc & 0xf0) << 4);
else
*pixelsDst = toOrr | ((*pixelsSrc & 0x0f) << 8);
}
}
else
{
if (loopDstX & 1)
{
toOrr = *pixelsDst & 0xff0f;
if (loopSrcX & 1)
*pixelsDst = toOrr | ((*pixelsSrc & 0xf0) << 0);
else
*pixelsDst = toOrr | ((*pixelsSrc & 0x0f) << 4);
}
else
{
toOrr = *pixelsDst & 0xfff0;
if (loopSrcX & 1)
*pixelsDst = toOrr | ((*pixelsSrc & 0xf0) >> 4);
else
*pixelsDst = toOrr | ((*pixelsSrc & 0x0f) >> 0);
}
}
}
}
}
#define tEvA data[0]
+4 -4
View File
@@ -134,7 +134,7 @@ static void ResetTTDataBuffer(void)
{
memset(gDecompressionBuffer, 0, 0x2000);
gLinkType = 0x5502;
sub_8009804();
OpenLink();
SetSuppressLinkErrorMessage(TRUE);
}
@@ -156,7 +156,7 @@ bool32 sub_81436EC(void)
static bool32 IsEReaderConnectionSane(void)
{
if (sub_800AA48() && GetLinkPlayerCount_2() == 2)
if (IsLinkMaster() && GetLinkPlayerCount_2() == 2)
return TRUE;
return FALSE;
}
@@ -171,7 +171,7 @@ u32 sub_8143770(u8 * r4, u16 * r5)
switch (*r4)
{
case 0:
if (sub_800AA48() && GetLinkPlayerCount_2() > 1)
if (IsLinkMaster() && GetLinkPlayerCount_2() > 1)
{
*r4 = 1;
;
@@ -193,7 +193,7 @@ u32 sub_8143770(u8 * r4, u16 * r5)
if (GetLinkPlayerCount_2() == 2)
{
PlaySE(SE_TOY_G);
sub_800A5BC();
CheckShouldAdvanceLinkState();
*r5 = 0;
*r4 = 3;
}
+3 -3
View File
@@ -155,7 +155,7 @@ static bool32 mevent_send_func(struct mevent_srv_sub * svr)
switch (svr->seqno)
{
case 0:
if (sub_800A4BC())
if (IsLinkTaskFinished())
{
header.ident = svr->sendIdent;
header.size = svr->sendSize;
@@ -167,7 +167,7 @@ static bool32 mevent_send_func(struct mevent_srv_sub * svr)
}
break;
case 1:
if (sub_800A4BC())
if (IsLinkTaskFinished())
{
if (mevent_has_received(svr->sendPlayerNo))
{
@@ -189,7 +189,7 @@ static bool32 mevent_send_func(struct mevent_srv_sub * svr)
}
break;
case 2:
if (sub_800A4BC())
if (IsLinkTaskFinished())
{
if (CalcCRC16WithTable(svr->sendBfr, svr->sendSize) != svr->sendCRC)
sub_80FA190();
+39 -46
View File
@@ -5,21 +5,20 @@
#include "random.h"
#include "main.h"
#include "text.h"
#include "data2.h"
#include "data.h"
#include "string_util.h"
#include "battle.h"
#include "battle_2.h"
#include "battle_main.h"
#include "item.h"
#include "event_data.h"
#include "util.h"
#include "pokemon_storage_system.h"
#include "data2.h"
#include "data.h"
#include "battle_gfx_sfx_util.h"
#include "battle_controllers.h"
#include "evolution_scene.h"
#include "battle_message.h"
#include "battle_util.h"
#include "battle_ai_script_commands.h"
#include "link.h"
#include "m4a.h"
#include "sound.h"
@@ -1792,7 +1791,7 @@ void CreateBoxMon(struct BoxPokemon *boxMon, u16 species, u8 level, u8 fixedIV,
if (gBaseStats[species].abilities[1])
{
value = personality & 1;
SetBoxMonData(boxMon, MON_DATA_ALT_ABILITY, &value);
SetBoxMonData(boxMon, MON_DATA_ABILITY_NUM, &value);
}
GiveBoxMonInitialMoveset(boxMon);
@@ -1941,8 +1940,8 @@ void CreateBattleTowerMon(struct Pokemon *mon, struct BattleTowerPokemon *src)
SetMonData(mon, MON_DATA_SPEED_EV, &src->speedEV);
SetMonData(mon, MON_DATA_SPATK_EV, &src->spAttackEV);
SetMonData(mon, MON_DATA_SPDEF_EV, &src->spDefenseEV);
value = src->altAbility;
SetMonData(mon, MON_DATA_ALT_ABILITY, &value);
value = src->abilityNum;
SetMonData(mon, MON_DATA_ABILITY_NUM, &value);
value = src->hpIV;
SetMonData(mon, MON_DATA_HP_IV, &value);
value = src->attackIV;
@@ -1998,7 +1997,7 @@ void sub_803E23C(struct Pokemon *mon, struct BattleTowerPokemon *dest)
dest->speedIV = GetMonData(mon, MON_DATA_SPEED_IV, NULL);
dest->spAttackIV = GetMonData(mon, MON_DATA_SPATK_IV, NULL);
dest->spDefenseIV = GetMonData(mon, MON_DATA_SPDEF_IV, NULL);
dest->altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL);
dest->abilityNum = GetMonData(mon, MON_DATA_ABILITY_NUM, NULL);
dest->personality = GetMonData(mon, MON_DATA_PERSONALITY, NULL);
GetMonData(mon, MON_DATA_NICKNAME, dest->nickname);
}
@@ -2553,7 +2552,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
damage /= 2;
// sunny
if (gBattleWeather & WEATHER_SUNNY_ANY)
if (gBattleWeather & WEATHER_SUN_ANY)
{
switch (type)
{
@@ -2568,7 +2567,7 @@ s32 CalculateBaseDamage(struct BattlePokemon *attacker, struct BattlePokemon *de
}
// flash fire triggered
if ((gBattleResources->flags->flags[battlerIdAtk] & UNKNOWN_FLAG_FLASH_FIRE) && type == TYPE_FIRE)
if ((gBattleResources->flags->flags[battlerIdAtk] & RESOURCE_FLAG_FLASH_FIRE) && type == TYPE_FIRE)
damage = (15 * damage) / 10;
}
@@ -2592,7 +2591,7 @@ u8 CountAliveMonsInBattle(u8 caseId)
case BATTLE_ALIVE_ATK_SIDE:
for (i = 0; i < 4; i++)
{
if (GetBattlerSide(i) == GetBattlerSide(sBattler_AI) && !(gAbsentBattlerFlags & gBitTable[i]))
if (GetBattlerSide(i) == GetBattlerSide(gBattlerAttacker) && !(gAbsentBattlerFlags & gBitTable[i]))
retVal++;
}
break;
@@ -3100,8 +3099,8 @@ u32 GetBoxMonData(struct BoxPokemon *boxMon, s32 field, u8 *data)
case MON_DATA_IS_EGG:
retVal = substruct3->isEgg;
break;
case MON_DATA_ALT_ABILITY:
retVal = substruct3->altAbility;
case MON_DATA_ABILITY_NUM:
retVal = substruct3->abilityNum;
break;
case MON_DATA_COOL_RIBBON:
retVal = substruct3->coolRibbon;
@@ -3503,8 +3502,8 @@ void SetBoxMonData(struct BoxPokemon *boxMon, s32 field, const void *dataArg)
else
boxMon->isEgg = 0;
break;
case MON_DATA_ALT_ABILITY:
SET8(substruct3->altAbility);
case MON_DATA_ABILITY_NUM:
SET8(substruct3->abilityNum);
break;
case MON_DATA_COOL_RIBBON:
SET8(substruct3->coolRibbon);
@@ -3699,9 +3698,9 @@ u8 GetMonsStateToDoubles(void)
return (aliveCount > 1) ? PLAYER_HAS_TWO_USABLE_MONS : PLAYER_HAS_ONE_USABLE_MON;
}
u8 GetAbilityBySpecies(u16 species, bool8 altAbility)
u8 GetAbilityBySpecies(u16 species, bool8 abilityNum)
{
if (altAbility)
if (abilityNum)
gLastUsedAbility = gBaseStats[species].abilities[1];
else
gLastUsedAbility = gBaseStats[species].abilities[0];
@@ -3712,8 +3711,8 @@ u8 GetAbilityBySpecies(u16 species, bool8 altAbility)
u8 GetMonAbility(struct Pokemon *mon)
{
u16 species = GetMonData(mon, MON_DATA_SPECIES, NULL);
u8 altAbility = GetMonData(mon, MON_DATA_ALT_ABILITY, NULL);
return GetAbilityBySpecies(species, altAbility);
u8 abilityNum = GetMonData(mon, MON_DATA_ABILITY_NUM, NULL);
return GetAbilityBySpecies(species, abilityNum);
}
static void CreateSecretBaseEnemyParty(struct SecretBaseRecord *secretBaseRecord)
@@ -3859,11 +3858,11 @@ static void CopyPlayerPartyMonToBattleData(u8 battlerId, u8 partyIndex)
gBattleMons[battlerId].spAttack = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPATK, NULL);
gBattleMons[battlerId].spDefense = GetMonData(&gPlayerParty[partyIndex], MON_DATA_SPDEF, NULL);
gBattleMons[battlerId].isEgg = GetMonData(&gPlayerParty[partyIndex], MON_DATA_IS_EGG, NULL);
gBattleMons[battlerId].altAbility = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ALT_ABILITY, NULL);
gBattleMons[battlerId].abilityNum = GetMonData(&gPlayerParty[partyIndex], MON_DATA_ABILITY_NUM, NULL);
gBattleMons[battlerId].otId = GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_ID, NULL);
gBattleMons[battlerId].type1 = gBaseStats[gBattleMons[battlerId].species].type1;
gBattleMons[battlerId].type2 = gBaseStats[gBattleMons[battlerId].species].type2;
gBattleMons[battlerId].ability = GetAbilityBySpecies(gBattleMons[battlerId].species, gBattleMons[battlerId].altAbility);
gBattleMons[battlerId].ability = GetAbilityBySpecies(gBattleMons[battlerId].species, gBattleMons[battlerId].abilityNum);
GetMonData(&gPlayerParty[partyIndex], MON_DATA_NICKNAME, nickname);
StringCopy10(gBattleMons[battlerId].nickname, nickname);
GetMonData(&gPlayerParty[partyIndex], MON_DATA_OT_NAME, gBattleMons[battlerId].otName);
@@ -4118,14 +4117,14 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
{
gAbsentBattlerFlags &= ~gBitTable[sp34];
CopyPlayerPartyMonToBattleData(sp34, pokemon_order_func(gBattlerPartyIndexes[sp34]));
if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.unk4 < 255)
gBattleResults.unk4++;
if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.numRevivesUsed < 255)
gBattleResults.numRevivesUsed++;
}
else
{
gAbsentBattlerFlags &= ~gBitTable[gActiveBattler ^ 2];
if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.unk4 < 255)
gBattleResults.unk4++;
if (GetBattlerSide(gActiveBattler) == 0 && gBattleResults.numRevivesUsed < 255)
gBattleResults.numRevivesUsed++;
}
}
}
@@ -4165,13 +4164,13 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
gBattleMons[sp34].hp = data;
if (!(r10 & 0x10) && GetBattlerSide(gActiveBattler) == 0)
{
if (gBattleResults.unk3 < 255)
gBattleResults.unk3++;
if (gBattleResults.numHealingItemsUsed < 255)
gBattleResults.numHealingItemsUsed++;
// I have to re-use this variable to match.
r5 = gActiveBattler;
gActiveBattler = sp34;
BtlController_EmitGetMonData(0, 0, 0);
MarkBufferBankForExecution(gActiveBattler);
MarkBattlerForControllerExec(gActiveBattler);
gActiveBattler = r5;
}
}
@@ -4205,7 +4204,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
SetMonData(mon, MON_DATA_PP1 + r5, &data);
if (gMain.inBattle
&& sp34 != 4 && !(gBattleMons[sp34].status2 & 0x200000)
&& !(gDisableStructs[sp34].unk18_b & gBitTable[r5]))
&& !(gDisableStructs[sp34].mimickedMoves & gBitTable[r5]))
gBattleMons[sp34].pp[r5] = data;
retVal = FALSE;
}
@@ -4230,7 +4229,7 @@ bool8 PokemonUseItemEffects(struct Pokemon *mon, u16 item, u8 partyIndex, u8 mov
SetMonData(mon, MON_DATA_PP1 + moveIndex, &data);
if (gMain.inBattle
&& sp34 != 4 && !(gBattleMons[sp34].status2 & 0x200000)
&& !(gDisableStructs[sp34].unk18_b & gBitTable[moveIndex]))
&& !(gDisableStructs[sp34].mimickedMoves & gBitTable[moveIndex]))
gBattleMons[sp34].pp[moveIndex] = data;
retVal = FALSE;
}
@@ -5845,7 +5844,7 @@ const u8 *Battle_PrintStatBoosterEffectMessage(u16 itemId)
}
else
{
sBattler_AI = gBattlerInMenuId;
gBattlerAttacker = gBattlerInMenuId;
BattleStringExpandPlaceholdersToDisplayedString(BattleText_GetPumped);
}
}
@@ -5853,7 +5852,7 @@ const u8 *Battle_PrintStatBoosterEffectMessage(u16 itemId)
if (itemEffect[3] & 0x80)
{
sBattler_AI = gBattlerInMenuId;
gBattlerAttacker = gBattlerInMenuId;
BattleStringExpandPlaceholdersToDisplayedString(BattleText_MistShroud);
}
@@ -6205,9 +6204,9 @@ bool8 sub_80435E0(void)
return retVal;
}
bool8 GetLinkTrainerFlankId(u8 linkPlayerId)
bool16 GetLinkTrainerFlankId(u8 linkPlayerId)
{
bool8 retVal = FALSE;
bool16 retVal = FALSE;
switch (gLinkPlayers[linkPlayerId].id)
{
case 0:
@@ -6222,7 +6221,7 @@ bool8 GetLinkTrainerFlankId(u8 linkPlayerId)
return retVal;
}
s32 GetBankMultiplayerId(u16 a1)
s32 GetBattlerMultiplayerId(u16 a1)
{
s32 id;
for (id = 0; id < MAX_LINK_PLAYERS; id++)
@@ -6701,10 +6700,10 @@ const u32 *GetMonFrontSpritePal(struct Pokemon *mon)
u16 species = GetMonData(mon, MON_DATA_SPECIES2, 0);
u32 otId = GetMonData(mon, MON_DATA_OT_ID, 0);
u32 personality = GetMonData(mon, MON_DATA_PERSONALITY, 0);
return GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality);
return GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality);
}
const u32 *GetFrontSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality)
const u32 *GetMonSpritePalFromSpeciesAndPersonality(u16 species, u32 otId, u32 personality)
{
u32 shinyValue;
@@ -6814,15 +6813,9 @@ void BoxMonRestorePP(struct BoxPokemon *boxMon)
}
}
// SetMonPreventsSwitchingString
void sub_8044348(void)
void SetMonPreventsSwitchingString(void)
{
#ifdef NONMATCHING
gLastUsedAbility = gBattleStruct -> abilityPreventingSwitchout; // fixed from the original
#else
gLastUsedAbility = ((u8 *) gBattleStruct)[0xac]; // huh? why is this wrong?
#endif
gLastUsedAbility = gBattleStruct -> abilityPreventingSwitchout;
gBattleTextBuff1[0] = B_BUFF_PLACEHOLDER_BEGIN;
gBattleTextBuff1[1] = B_BUFF_MON_NICK_WITH_PREFIX;
gBattleTextBuff1[2] = gBattleStruct->battlerPreventingSwitchout;
@@ -6879,7 +6872,7 @@ static bool8 IsShinyOtIdPersonality(u32 otId, u32 personality)
u8 *GetTrainerPartnerName(void)
{
u8 id = GetMultiplayerId();
return gLinkPlayers[GetBankMultiplayerId(gLinkPlayers[id].id ^ 2)].name;
return gLinkPlayers[GetBattlerMultiplayerId(gLinkPlayers[id].id ^ 2)].name;
}
u8 GetPlayerPartyHighestLevel(void)
+3 -3
View File
@@ -1,7 +1,7 @@
#include "global.h"
#include "constants/species.h"
#include "constants/items.h"
#include "data2.h"
#include "data.h"
#include "malloc.h"
#include "main.h"
#include "task.h"
@@ -871,7 +871,7 @@ void sub_8110F90(u8 unused)
gSaveBlock1Ptr->location.mapNum = 19;
gSaveBlock1Ptr->location.warpId = -1;
gUnknown_203ADF8 = 0;
gUnknown_2031DD8 = 1;
gDisableMapMusicChangeOnMapLoad = 1;
sub_8082740(1);
sub_8111368();
}
@@ -1567,7 +1567,7 @@ void sub_81120AC(u8 taskId)
switch (data[0])
{
case 0:
gUnknown_2031DD8 = 0;
gDisableMapMusicChangeOnMapLoad = 0;
Overworld_PlaySpecialMapMusic();
sub_811229C();
FillWindowPixelRect(gUnknown_203ADFE[0], 0xF, 0, 0, gUnknown_845661C[0].width * 8, gUnknown_845661C[0].height * 8);
+1 -1
View File
@@ -26,7 +26,7 @@ void sub_812C334(s32 *, s32 *);
void sub_812BFDC(void)
{
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_POKEDUDE)) && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT))
if (!(gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_OLDMAN_TUTORIAL | BATTLE_TYPE_POKEDUDE)) && (gBattleOutcome == B_OUTCOME_WON || gBattleOutcome == B_OUTCOME_CAUGHT))
{
struct QuestLogStruct_TrainerBattleRecord * questLogTrainerBattleRecord = Alloc(sizeof(struct QuestLogStruct_TrainerBattleRecord));
struct QuestLogStruct_WildBattleRecord * questLogWildBattleRecord = Alloc(sizeof(struct QuestLogStruct_WildBattleRecord));
+322
View File
@@ -0,0 +1,322 @@
#include "global.h"
#include "bg.h"
#include "palette.h"
#include "pokemon.h"
#include "main.h"
#include "link.h"
#include "data.h"
#include "sprite.h"
#include "text.h"
#include "gpu_regs.h"
#include "scanline_effect.h"
#include "help_system.h"
#include "battle.h"
#include "battle_interface.h"
#include "battle_anim.h"
#include "battle_controllers.h"
#include "reshow_battle_screen.h"
#include "constants/species.h"
static void CB2_ReshowBattleScreenAfterMenu(void);
static void sub_8077AAC(void);
static bool8 LoadBattlerSpriteGfx(u8 battlerId);
static void CreateBattlerSprite(u8 battlerId);
static void CreateHealthboxSprite(u8 battlerId);
void nullsub_44(void)
{
}
void ReshowBattleScreenAfterMenu(void)
{
gPaletteFade.bufferTransferDisabled = 1;
SetHBlankCallback(NULL);
SetGpuReg(REG_OFFSET_MOSAIC, 0);
gBattleScripting.reshowMainState = 0;
gBattleScripting.reshowHelperState = 0;
if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
{
if (gBattleTypeFlags & BATTLE_TYPE_TRAINER)
{
if (gBattleTypeFlags & BATTLE_TYPE_DOUBLE)
HelpSystem_SetSomeVariable2(0x19);
else
HelpSystem_SetSomeVariable2(0x18);
}
else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
{
HelpSystem_SetSomeVariable2(0x1A);
}
else
{
HelpSystem_SetSomeVariable2(0x17);
}
}
SetMainCallback2(CB2_ReshowBattleScreenAfterMenu);
}
static void CB2_ReshowBattleScreenAfterMenu(void)
{
u8 opponentBattler;
u16 species;
switch (gBattleScripting.reshowMainState)
{
case 0:
ResetSpriteData();
break;
case 1:
SetVBlankCallback(NULL);
ScanlineEffect_Clear();
sub_800F324();
SetBgAttribute(1, BG_ATTR_CHARBASEINDEX, 0);
SetBgAttribute(2, BG_ATTR_CHARBASEINDEX, 0);
ShowBg(0);
ShowBg(1);
ShowBg(2);
ShowBg(3);
ResetPaletteFade();
gBattle_BG0_X = 0;
gBattle_BG0_Y = 0;
gBattle_BG1_X = 0;
gBattle_BG1_Y = 0;
gBattle_BG2_X = 0;
gBattle_BG2_Y = 0;
gBattle_BG3_X = 0;
gBattle_BG3_Y = 0;
break;
case 2:
CpuFastFill(0, (void *)VRAM, VRAM_SIZE);
break;
case 3:
LoadBattleTextboxAndBackground();
break;
case 4:
FreeAllSpritePalettes();
gReservedSpritePaletteCount = 4;
break;
case 5:
ClearSpritesHealthboxAnimData();
break;
case 6:
if (BattleLoadAllHealthBoxesGfx(gBattleScripting.reshowHelperState))
{
gBattleScripting.reshowHelperState = 0;
}
else
{
++gBattleScripting.reshowHelperState;
--gBattleScripting.reshowMainState;
}
break;
case 7:
if (!LoadBattlerSpriteGfx(0))
--gBattleScripting.reshowMainState;
break;
case 8:
if (!LoadBattlerSpriteGfx(1))
--gBattleScripting.reshowMainState;
break;
case 9:
if (!LoadBattlerSpriteGfx(2))
--gBattleScripting.reshowMainState;
break;
case 0xA:
if (!LoadBattlerSpriteGfx(3))
--gBattleScripting.reshowMainState;
break;
case 0xB:
CreateBattlerSprite(0);
break;
case 0xC:
CreateBattlerSprite(1);
break;
case 0xD:
CreateBattlerSprite(2);
break;
case 0xE:
CreateBattlerSprite(3);
break;
case 0xF:
CreateHealthboxSprite(0);
break;
case 0x10:
CreateHealthboxSprite(1);
break;
case 0x11:
CreateHealthboxSprite(2);
break;
case 0x12:
CreateHealthboxSprite(3);
break;
case 0x13:
LoadAndCreateEnemyShadowSprites();
opponentBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_LEFT);
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[opponentBattler]], MON_DATA_SPECIES);
SetBattlerShadowSpriteCallback(opponentBattler, species);
if (IsDoubleBattle())
{
opponentBattler = GetBattlerAtPosition(B_POSITION_OPPONENT_RIGHT);
species = GetMonData(&gEnemyParty[gBattlerPartyIndexes[opponentBattler]], MON_DATA_SPECIES);
SetBattlerShadowSpriteCallback(opponentBattler, species);
}
ActionSelectionCreateCursorAt(gActionSelectionCursor[gBattlerInMenuId], 0);
if (gWirelessCommType && gReceivedRemoteLinkPlayers)
{
LoadWirelessStatusIndicatorSpriteGfx();
CreateWirelessStatusIndicatorSprite(0, 0);
}
break;
case 0x14:
SetVBlankCallback(VBlankCB_Battle);
sub_8077AAC();
BeginHardwarePaletteFade(0xFF, 0, 0x10, 0, 1);
gPaletteFade.bufferTransferDisabled = 0;
SetMainCallback2(BattleMainCB2);
sub_80357C8();
break;
default:
break;
}
++gBattleScripting.reshowMainState;
}
static void sub_8077AAC(void)
{
EnableInterrupts(INTR_FLAG_VBLANK);
SetGpuReg(REG_OFFSET_BLDCNT, 0);
SetGpuReg(REG_OFFSET_BLDALPHA, 0);
SetGpuReg(REG_OFFSET_BLDY, 0);
SetGpuReg(REG_OFFSET_WININ, 0x3F);
SetGpuReg(REG_OFFSET_WINOUT, 0x3F);
SetGpuReg(REG_OFFSET_WIN0H, 0);
SetGpuReg(REG_OFFSET_WIN0V, 0);
SetGpuReg(REG_OFFSET_WIN1H, 0);
SetGpuReg(REG_OFFSET_WIN1V, 0);
SetGpuRegBits(REG_OFFSET_DISPCNT, DISPCNT_OBJ_1D_MAP | DISPCNT_OBJ_ON | DISPCNT_WIN0_ON | DISPCNT_OBJWIN_ON);
}
static bool8 LoadBattlerSpriteGfx(u8 battler)
{
if (battler < gBattlersCount)
{
if (GetBattlerSide(battler) != B_SIDE_PLAYER)
{
if ((gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_GHOST)) == BATTLE_TYPE_GHOST)
DecompressGhostFrontPic(&gEnemyParty[gBattlerPartyIndexes[battler]], battler);
else if (!gBattleSpritesDataPtr->battlerData[battler].behindSubstitute)
BattleLoadOpponentMonSpriteGfx(&gEnemyParty[gBattlerPartyIndexes[battler]], battler);
else
BattleLoadSubstituteOrMonSpriteGfx(battler, FALSE);
}
else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && battler == B_POSITION_PLAYER_LEFT) // Should be checking position, not battler.
DecompressTrainerBackPalette(gSaveBlock2Ptr->playerGender, battler);
else if (gBattleTypeFlags & BATTLE_TYPE_OLDMAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT) // Should be checking position, not battler.
DecompressTrainerBackPalette(5, battler);
else if (!gBattleSpritesDataPtr->battlerData[battler].behindSubstitute)
BattleLoadPlayerMonSpriteGfx(&gPlayerParty[gBattlerPartyIndexes[battler]], battler);
else
BattleLoadSubstituteOrMonSpriteGfx(battler, FALSE);
gBattleScripting.reshowHelperState = 0;
}
return TRUE;
}
static void CreateBattlerSprite(u8 battler)
{
if (battler < gBattlersCount)
{
u8 posY;
if ((gBattleTypeFlags & (BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_GHOST)) == BATTLE_TYPE_GHOST)
posY = GetGhostSpriteDefault_Y(battler);
else if (gBattleSpritesDataPtr->battlerData[battler].behindSubstitute)
posY = GetSubstituteSpriteDefault_Y(battler);
else
posY = GetBattlerSpriteDefault_Y(battler);
if (GetBattlerSide(battler) != B_SIDE_PLAYER)
{
if (GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_HP) == 0)
return;
SetMultiuseSpriteTemplateToPokemon(GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES), GetBattlerPosition(battler));
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, GetBattlerSpriteCoord(battler, 2), posY, GetBattlerSpriteSubpriority(battler));
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = battler;
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCallbackDummy;
gSprites[gBattlerSpriteIds[battler]].data[0] = battler;
gSprites[gBattlerSpriteIds[battler]].data[2] = GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES);
StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], gBattleMonForms[battler]);
}
else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && battler == B_POSITION_PLAYER_LEFT)
{
SetMultiuseSpriteTemplateToTrainerBack(gSaveBlock2Ptr->playerGender, GetBattlerPosition(B_POSITION_PLAYER_LEFT));
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, 0x50,
(8 - gTrainerBackPicCoords[gSaveBlock2Ptr->playerGender].size) * 4 + 80,
GetBattlerSpriteSubpriority(0));
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = battler;
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCallbackDummy;
gSprites[gBattlerSpriteIds[battler]].data[0] = battler;
}
else if (gBattleTypeFlags & BATTLE_TYPE_OLDMAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT)
{
SetMultiuseSpriteTemplateToTrainerBack(5, GetBattlerPosition(0));
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, 0x50,
(8 - gTrainerBackPicCoords[5].size) * 4 + 80,
GetBattlerSpriteSubpriority(0));
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = battler;
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCallbackDummy;
gSprites[gBattlerSpriteIds[battler]].data[0] = battler;
}
else if (GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_HP) == 0)
{
return;
}
else
{
SetMultiuseSpriteTemplateToPokemon(GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES), GetBattlerPosition(battler));
gBattlerSpriteIds[battler] = CreateSprite(&gMultiuseSpriteTemplate, GetBattlerSpriteCoord(battler, 2), posY, GetBattlerSpriteSubpriority(battler));
gSprites[gBattlerSpriteIds[battler]].oam.paletteNum = battler;
gSprites[gBattlerSpriteIds[battler]].callback = SpriteCallbackDummy;
gSprites[gBattlerSpriteIds[battler]].data[0] = battler;
gSprites[gBattlerSpriteIds[battler]].data[2] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_SPECIES);
StartSpriteAnim(&gSprites[gBattlerSpriteIds[battler]], gBattleMonForms[battler]);
}
gSprites[gBattlerSpriteIds[battler]].invisible = gBattleSpritesDataPtr->battlerData[battler].invisible;
}
}
static void CreateHealthboxSprite(u8 battler)
{
if (battler < gBattlersCount)
{
u8 healthboxSpriteId;
if (gBattleTypeFlags & BATTLE_TYPE_SAFARI && battler == B_POSITION_PLAYER_LEFT)
healthboxSpriteId = CreateSafariPlayerHealthboxSprites();
else if (gBattleTypeFlags & BATTLE_TYPE_OLDMAN_TUTORIAL && battler == B_POSITION_PLAYER_LEFT)
return;
else
healthboxSpriteId = CreateBattlerHealthboxSprites(battler);
gHealthboxSpriteIds[battler] = healthboxSpriteId;
InitBattlerHealthboxCoords(battler);
SetHealthboxSpriteVisible(healthboxSpriteId);
if (GetBattlerSide(battler) != B_SIDE_PLAYER)
UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gEnemyParty[gBattlerPartyIndexes[battler]], HEALTHBOX_ALL);
else if (gBattleTypeFlags & BATTLE_TYPE_SAFARI)
UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gPlayerParty[gBattlerPartyIndexes[battler]], HEALTHBOX_SAFARI_ALL_TEXT);
else
UpdateHealthboxAttribute(gHealthboxSpriteIds[battler], &gPlayerParty[gBattlerPartyIndexes[battler]], HEALTHBOX_ALL);
if (GetBattlerPosition(battler) == B_POSITION_OPPONENT_RIGHT || GetBattlerPosition(battler) == B_POSITION_PLAYER_RIGHT)
DummyBattleInterfaceFunc(gHealthboxSpriteIds[battler], TRUE);
else
DummyBattleInterfaceFunc(gHealthboxSpriteIds[battler], FALSE);
if (GetBattlerSide(battler) != B_SIDE_PLAYER)
{
if (GetMonData(&gEnemyParty[gBattlerPartyIndexes[battler]], MON_DATA_HP) == 0)
SetHealthboxSpriteInvisible(healthboxSpriteId);
}
else if (!(gBattleTypeFlags & BATTLE_TYPE_SAFARI) && GetMonData(&gPlayerParty[gBattlerPartyIndexes[battler]], MON_DATA_HP) == 0)
{
SetHealthboxSpriteInvisible(healthboxSpriteId);
}
}
}
+4 -4
View File
@@ -68,7 +68,7 @@ const struct SaveSectionOffsets gSaveSectionOffsets[] =
extern void DoSaveFailedScreen(u8 saveType); // save_failed_screen
extern void sub_800AB9C(void); // link
extern bool8 sub_800A4BC(void); // link
extern bool8 IsLinkTaskFinished(void); // link
extern void save_serialize_map(void); // fieldmap
extern void sub_804C1C0(void); // load_save
extern void sav2_gender2_inplace_and_xFE(void); // load_save
@@ -865,7 +865,7 @@ void sub_80DA634(u8 taskId)
gTasks[taskId].data[0] = 2;
break;
case 2:
if (sub_800A4BC())
if (IsLinkTaskFinished())
{
save_serialize_map();
gTasks[taskId].data[0] = 3;
@@ -899,7 +899,7 @@ void sub_80DA634(u8 taskId)
gTasks[taskId].data[0] = 8;
break;
case 8:
if (sub_800A4BC())
if (IsLinkTaskFinished())
{
sub_80DA434();
gTasks[taskId].data[0] = 9;
@@ -910,7 +910,7 @@ void sub_80DA634(u8 taskId)
gTasks[taskId].data[0] = 10;
break;
case 10:
if (sub_800A4BC())
if (IsLinkTaskFinished())
gTasks[taskId].data[0]++;
break;
case 11:
+1 -1
View File
@@ -25,7 +25,7 @@
#include "start_menu.h"
#include "script_menu.h"
#include "string_util.h"
#include "data2.h"
#include "data.h"
#include "field_specials.h"
#include "constants/items.h"
#include "script_pokemon_util_80A0058.h"
+2 -2
View File
@@ -15,7 +15,7 @@ struct Fanfare
};
// TODO: what are these
extern u8 gUnknown_2031DD8;
extern u8 gDisableMapMusicChangeOnMapLoad;
extern u8 gUnknown_203ADFA;
extern u8 gUnknown_203F174;
@@ -571,7 +571,7 @@ void PlayBGM(u16 songNum)
void PlaySE(u16 songNum)
{
if(gUnknown_2031DD8 == 0 && gUnknown_203ADFA != 2)
if(gDisableMapMusicChangeOnMapLoad == 0 && gUnknown_203ADFA != 2)
m4aSongNumStart(songNum);
}
+1 -1
View File
@@ -23,7 +23,7 @@
#include "event_data.h"
#include "load_save.h"
#include "battle_transition.h"
#include "battle_2.h"
#include "battle_main.h"
#include "battle.h"
#include "global.fieldmap.h"
#include "teachy_tv.h"
+351 -833
View File
File diff suppressed because it is too large Load Diff
+30 -30
View File
@@ -45,27 +45,27 @@ void DeactivateAllTextPrinters (void)
{
int printer;
for (printer = 0; printer < NUM_TEXT_PRINTERS; ++printer)
sTextPrinters[printer].sub_union.sub.active = 0;
sTextPrinters[printer].active = 0;
}
u16 AddTextPrinterParameterized(u8 windowId, u8 fontId, const u8 *str, u8 x, u8 y, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
{
struct TextPrinterTemplate subPrinter;
struct TextPrinterTemplate printerTemplate;
subPrinter.currentChar = str;
subPrinter.windowId = windowId;
subPrinter.fontId = fontId;
subPrinter.x = x;
subPrinter.y = y;
subPrinter.currentX = x;
subPrinter.currentY = y;
subPrinter.letterSpacing = gFonts[fontId].letterSpacing;
subPrinter.lineSpacing = gFonts[fontId].lineSpacing;
subPrinter.unk = gFonts[fontId].unk;
subPrinter.fgColor = gFonts[fontId].fgColor;
subPrinter.bgColor = gFonts[fontId].bgColor;
subPrinter.shadowColor = gFonts[fontId].shadowColor;
return AddTextPrinter(&subPrinter, speed, callback);
printerTemplate.currentChar = str;
printerTemplate.windowId = windowId;
printerTemplate.fontId = fontId;
printerTemplate.x = x;
printerTemplate.y = y;
printerTemplate.currentX = x;
printerTemplate.currentY = y;
printerTemplate.letterSpacing = gFonts[fontId].letterSpacing;
printerTemplate.lineSpacing = gFonts[fontId].lineSpacing;
printerTemplate.unk = gFonts[fontId].unk;
printerTemplate.fgColor = gFonts[fontId].fgColor;
printerTemplate.bgColor = gFonts[fontId].bgColor;
printerTemplate.shadowColor = gFonts[fontId].shadowColor;
return AddTextPrinter(&printerTemplate, speed, callback);
}
bool16 AddTextPrinter(struct TextPrinterTemplate *textSubPrinter, u8 speed, void (*callback)(struct TextPrinterTemplate *, u16))
@@ -76,18 +76,18 @@ bool16 AddTextPrinter(struct TextPrinterTemplate *textSubPrinter, u8 speed, void
if (!gFonts)
return FALSE;
sTempTextPrinter.sub_union.sub.active = 1;
sTempTextPrinter.active = 1;
sTempTextPrinter.state = 0;
sTempTextPrinter.text_speed = speed;
sTempTextPrinter.textSpeed = speed;
sTempTextPrinter.delayCounter = 0;
sTempTextPrinter.scrollDistance = 0;
for (i = 0; i < 7; ++i)
{
sTempTextPrinter.sub_union.sub_fields[i] = 0;
sTempTextPrinter.subUnion.fields[i] = 0;
}
sTempTextPrinter.subPrinter = *textSubPrinter;
sTempTextPrinter.printerTemplate = *textSubPrinter;
sTempTextPrinter.callback = callback;
sTempTextPrinter.minLetterSpacing = 0;
sTempTextPrinter.japanese = 0;
@@ -95,12 +95,12 @@ bool16 AddTextPrinter(struct TextPrinterTemplate *textSubPrinter, u8 speed, void
GenerateFontHalfRowLookupTable(textSubPrinter->fgColor, textSubPrinter->bgColor, textSubPrinter->shadowColor);
if (speed != TEXT_SPEED_FF && speed != 0x0)
{
--sTempTextPrinter.text_speed;
--sTempTextPrinter.textSpeed;
sTextPrinters[textSubPrinter->windowId] = sTempTextPrinter;
}
else
{
sTempTextPrinter.text_speed = 0;
sTempTextPrinter.textSpeed = 0;
for (j = 0; j < 0x400; ++j)
{
if ((u32)RenderFont(&sTempTextPrinter) == 1)
@@ -108,8 +108,8 @@ bool16 AddTextPrinter(struct TextPrinterTemplate *textSubPrinter, u8 speed, void
}
if (speed != TEXT_SPEED_FF)
CopyWindowToVram(sTempTextPrinter.subPrinter.windowId, 2);
sTextPrinters[textSubPrinter->windowId].sub_union.sub.active = 0;
CopyWindowToVram(sTempTextPrinter.printerTemplate.windowId, 2);
sTextPrinters[textSubPrinter->windowId].active = 0;
}
return TRUE;
}
@@ -121,18 +121,18 @@ void RunTextPrinters(void)
for (i = 0; i < 0x20; ++i)
{
if (sTextPrinters[i].sub_union.sub.active != 0)
if (sTextPrinters[i].active != 0)
{
temp = RenderFont(&sTextPrinters[i]);
switch (temp) {
case 0:
CopyWindowToVram(sTextPrinters[i].subPrinter.windowId, 2);
CopyWindowToVram(sTextPrinters[i].printerTemplate.windowId, 2);
case 3:
if (sTextPrinters[i].callback != 0)
sTextPrinters[i].callback(&sTextPrinters[i].subPrinter, temp);
sTextPrinters[i].callback(&sTextPrinters[i].printerTemplate, temp);
break;
case 1:
sTextPrinters[i].sub_union.sub.active = 0;
sTextPrinters[i].active = 0;
break;
}
}
@@ -141,7 +141,7 @@ void RunTextPrinters(void)
bool16 IsTextPrinterActive(u8 id)
{
return sTextPrinters[id].sub_union.sub.active;
return sTextPrinters[id].active;
}
u32 RenderFont(struct TextPrinter *textPrinter)
@@ -149,7 +149,7 @@ u32 RenderFont(struct TextPrinter *textPrinter)
u32 ret;
while (TRUE)
{
ret = gFonts[textPrinter->subPrinter.fontId].fontFunction(textPrinter);
ret = gFonts[textPrinter->printerTemplate.fontId].fontFunction(textPrinter);
if (ret != 2)
return ret;
}
+1 -1
View File
@@ -21,7 +21,7 @@
#include "pokemon_storage_system.h"
#include "string_util.h"
#include "party_menu.h"
#include "data2.h"
#include "data.h"
#include "scanline_effect.h"
#include "sound.h"
#include "strings.h"
+3 -3
View File
@@ -104,7 +104,7 @@ void LoadPicPaletteByTagOrSlot(u16 species, u32 otId, u32 personality, u8 palett
if (paletteTag == 0xFFFF)
{
sCreatingSpriteTemplate.paletteTag = 0xFFFF;
LoadCompressedPalette(GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality), 0x100 + paletteSlot * 0x10, 0x20);
LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), 0x100 + paletteSlot * 0x10, 0x20);
}
else
{
@@ -130,7 +130,7 @@ void LoadPicPaletteByTagOrSlot(u16 species, u32 otId, u32 personality, u8 palett
void LoadPicPaletteBySlot(u16 species, u32 otId, u32 personality, u8 paletteSlot, bool8 isTrainer)
{
if (!isTrainer)
LoadCompressedPalette(GetFrontSpritePalFromSpeciesAndPersonality(species, otId, personality), paletteSlot * 0x10, 0x20);
LoadCompressedPalette(GetMonSpritePalFromSpeciesAndPersonality(species, otId, personality), paletteSlot * 0x10, 0x20);
else
LoadCompressedPalette(gTrainerFrontPicPaletteTable[species].data, paletteSlot * 0x10, 0x20);
}
@@ -278,7 +278,7 @@ u16 FreeAndDestroyMonPicSprite(u16 spriteId)
return FreeAndDestroyPicSpriteInternal(spriteId);
}
u16 sub_810C228(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId)
u16 LoadMonPicInWindow(u16 species, u32 otId, u32 personality, bool8 isFrontPic, u8 paletteSlot, u8 windowId)
{
return sub_810C0C0(species, otId, personality, isFrontPic, 0, 0, paletteSlot, windowId, FALSE);
}
+5 -5
View File
@@ -17,7 +17,7 @@
#include "battle_setup.h"
#include "battle_transition.h"
#include "battle.h"
#include "battle_2.h"
#include "battle_main.h"
#include "overworld.h"
#include "item.h"
#include "window.h"
@@ -626,12 +626,12 @@ void sub_815DA28(u8 * dest)
StringCopyN(dest, gUnknown_203F45C->unk_00, 11);
}
u8 sub_815DA3C(void)
u8 GetTrainerTowerTrainerFrontSpriteId(void)
{
return gFacilityClassToPicIndex[gUnknown_203F45C->unk_3D];
}
void sub_815DA54(void)
void InitTrainerTowerBattleStruct(void)
{
u16 r10;
s32 r9;
@@ -660,7 +660,7 @@ void sub_815DA54(void)
sub_815DD2C();
}
void sub_815DBDC(void)
void FreeTrainerTowerBattleStruct(void)
{
Free(gUnknown_203F45C);
gUnknown_203F45C = NULL;
@@ -1122,7 +1122,7 @@ void sub_815E124(u8 taskId)
void sub_815E160(void)
{
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_FACTORY;
gBattleTypeFlags = BATTLE_TYPE_TRAINER | BATTLE_TYPE_TRAINER_TOWER;
if (gUnknown_203F458->unk_0004.trainers[gUnknown_203F458->unk_0000].unk_002 == 1)
gBattleTypeFlags |= BATTLE_TYPE_DOUBLE;
gTrainerBattleOpponent_A = 0;
+1 -1
View File
@@ -364,7 +364,7 @@ void FillWindowPixelRect(u8 windowId, u8 fillValue, u16 x, u16 y, u16 width, u16
FillBitmapRect4Bit(&pixelRect, x, y, width, height, fillValue);
}
void CopyToWindowPixelBuffer(u8 windowId, const u8 *src, u16 size, u16 tileOffset)
void CopyToWindowPixelBuffer(u8 windowId, const void *src, u16 size, u16 tileOffset)
{
if (size != 0)
CpuCopy16(src, gWindows[windowId].tileData + (0x20 * tileOffset), size);