pokeemerald/src/recorded_battle.c
2019-01-29 14:36:02 -06:00

887 lines
27 KiB
C

#include "global.h"
#include "battle.h"
#include "recorded_battle.h"
#include "main.h"
#include "pokemon.h"
#include "random.h"
#include "event_data.h"
#include "link.h"
#include "string_util.h"
#include "palette.h"
#include "save.h"
#include "alloc.h"
#include "util.h"
#include "task.h"
#include "text.h"
#include "battle_setup.h"
#include "frontier_util.h"
#include "constants/trainers.h"
#define BATTLER_RECORD_SIZE 664
#define ILLEGAL_BATTLE_TYPES ((BATTLE_TYPE_LINK | BATTLE_TYPE_SAFARI | BATTLE_TYPE_FIRST_BATTLE \
| BATTLE_TYPE_WALLY_TUTORIAL | BATTLE_TYPE_ROAMER | BATTLE_TYPE_EREADER_TRAINER \
| BATTLE_TYPE_KYOGRE_GROUDON | BATTLE_TYPE_LEGENDARY | BATTLE_TYPE_REGI \
| BATTLE_TYPE_RECORDED | BATTLE_TYPE_TRAINER_HILL | BATTLE_TYPE_SECRET_BASE \
| BATTLE_TYPE_GROUDON | BATTLE_TYPE_KYOGRE | BATTLE_TYPE_RAYQUAZA))
struct PlayerInfo
{
u32 trainerId;
u8 name[PLAYER_NAME_LENGTH + 1];
u8 gender;
u16 battlerId;
u16 language;
};
struct MovePp
{
u16 moves[4];
u8 pp[4];
};
struct RecordedBattleSave
{
struct Pokemon playerParty[PARTY_SIZE];
struct Pokemon opponentParty[PARTY_SIZE];
u8 playersName[MAX_BATTLERS_COUNT][PLAYER_NAME_LENGTH + 1];
u8 playersGender[MAX_BATTLERS_COUNT];
u32 playersTrainerId[MAX_BATTLERS_COUNT];
u8 playersLanguage[MAX_BATTLERS_COUNT];
u32 rngSeed;
u32 battleFlags;
u8 playersBattlers[MAX_BATTLERS_COUNT];
u16 opponentA;
u16 opponentB;
u16 partnerId;
u16 field_4FA;
u8 lvlMode;
u8 frontierFacility;
u8 frontierBrainSymbol;
u8 battleScene:1;
u8 textSpeed:3;
u32 AI_scripts;
u8 recordMixFriendName[PLAYER_NAME_LENGTH + 1];
u8 recordMixFriendClass;
u8 apprenticeId;
u16 easyChatSpeech[6];
u8 recordMixFriendLanguage;
u8 apprenticeLanguage;
u8 battleRecord[MAX_BATTLERS_COUNT][BATTLER_RECORD_SIZE];
u32 checksum;
};
EWRAM_DATA u32 gRecordedBattleRngSeed = 0;
EWRAM_DATA u32 gBattlePalaceMoveSelectionRngValue = 0;
EWRAM_DATA static u8 sBattleRecords[MAX_BATTLERS_COUNT][BATTLER_RECORD_SIZE] = {0};
EWRAM_DATA static u16 sRecordedBytesNo[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA static u16 sUnknown_0203C79C[4] = {0};
EWRAM_DATA static u16 sUnknown_0203C7A4[4] = {0};
EWRAM_DATA static u8 sUnknown_0203C7AC = 0;
EWRAM_DATA static u8 sLvlMode = 0;
EWRAM_DATA static u8 sFrontierFacility = 0;
EWRAM_DATA static u8 sFrontierBrainSymbol = 0;
EWRAM_DATA static MainCallback sCallback2_AfterRecordedBattle = NULL;
EWRAM_DATA u8 gUnknown_0203C7B4 = 0;
EWRAM_DATA static u8 sUnknown_0203C7B5 = 0;
EWRAM_DATA static u8 sBattleScene = 0;
EWRAM_DATA static u8 sTextSpeed = 0;
EWRAM_DATA static u32 sBattleFlags = 0;
EWRAM_DATA static u32 sAI_Scripts = 0;
EWRAM_DATA static struct Pokemon sSavedPlayerParty[PARTY_SIZE] = {0};
EWRAM_DATA static struct Pokemon sSavedOpponentParty[PARTY_SIZE] = {0};
EWRAM_DATA static u16 sPlayerMonMoves[2][4] = {0};
EWRAM_DATA static struct PlayerInfo sPlayers[MAX_BATTLERS_COUNT] = {0};
EWRAM_DATA static u8 sUnknown_0203CCD0 = 0;
EWRAM_DATA static u8 sRecordMixFriendName[PLAYER_NAME_LENGTH + 1] = {0};
EWRAM_DATA static u8 sRecordMixFriendClass = 0;
EWRAM_DATA static u8 sApprenticeId = 0;
EWRAM_DATA static u16 sEasyChatSpeech[6] = {0};
EWRAM_DATA static u8 sBattleOutcome = 0;
IWRAM_DATA static u8 sRecordMixFriendLanguage;
IWRAM_DATA static u8 sApprenticeLanguage;
// this file's functions
static u8 sub_8185278(u8 *arg0, u8 *arg1, u8 *arg2);
static bool32 CopyRecordedBattleFromSave(struct RecordedBattleSave *dst);
static void RecordedBattle_RestoreSavedParties(void);
static void CB2_RecordedBattle(void);
void sub_8184DA4(u8 arg0)
{
s32 i, j;
sUnknown_0203C7AC = arg0;
sUnknown_0203CCD0 = 0;
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
sRecordedBytesNo[i] = 0;
sUnknown_0203C79C[i] = 0;
sUnknown_0203C7A4[i] = 0;
if (arg0 == 1)
{
for (j = 0; j < BATTLER_RECORD_SIZE; j++)
{
sBattleRecords[i][j] = 0xFF;
}
sBattleFlags = gBattleTypeFlags;
sAI_Scripts = gBattleResources->ai->aiFlags;
}
}
}
void sub_8184E58(void)
{
s32 i, j;
if (sUnknown_0203C7AC == 1)
{
gRecordedBattleRngSeed = gRngValue;
sFrontierFacility = VarGet(VAR_FRONTIER_FACILITY);
sFrontierBrainSymbol = GetFronterBrainSymbol();
}
else if (sUnknown_0203C7AC == 2)
{
gRngValue = gRecordedBattleRngSeed;
}
if (gBattleTypeFlags & BATTLE_TYPE_LINK)
{
u8 linkPlayersCount;
u8 text[30];
gUnknown_0203C7B4 = GetMultiplayerId();
linkPlayersCount = GetLinkPlayerCount();
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
sPlayers[i].trainerId = gLinkPlayers[i].trainerId;
sPlayers[i].gender = gLinkPlayers[i].gender;
sPlayers[i].battlerId = gLinkPlayers[i].id;
sPlayers[i].language = gLinkPlayers[i].language;
if (i < linkPlayersCount)
{
StringCopy(text, gLinkPlayers[i].name);
StripExtCtrlCodes(text);
StringCopy(sPlayers[i].name, text);
}
else
{
for (j = 0; j < PLAYER_NAME_LENGTH + 1; j++)
sPlayers[i].name[j] = gLinkPlayers[i].name[j];
}
}
}
else
{
sPlayers[0].trainerId = (gSaveBlock2Ptr->playerTrainerId[0])
| (gSaveBlock2Ptr->playerTrainerId[1] << 8)
| (gSaveBlock2Ptr->playerTrainerId[2] << 16)
| (gSaveBlock2Ptr->playerTrainerId[3] << 24);
sPlayers[0].gender = gSaveBlock2Ptr->playerGender;
sPlayers[0].battlerId = 0;
sPlayers[0].language = gGameLanguage;
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
sPlayers[0].name[i] = gSaveBlock2Ptr->playerName[i];
}
}
void RecordedBattle_SetBattlerAction(u8 battlerId, u8 action)
{
if (sRecordedBytesNo[battlerId] < BATTLER_RECORD_SIZE && sUnknown_0203C7AC != 2)
{
sBattleRecords[battlerId][sRecordedBytesNo[battlerId]++] = action;
}
}
void RecordedBattle_ClearBattlerAction(u8 battlerId, u8 bytesToClear)
{
s32 i;
for (i = 0; i < bytesToClear; i++)
{
sRecordedBytesNo[battlerId]--;
sBattleRecords[battlerId][sRecordedBytesNo[battlerId]] = 0xFF;
if (sRecordedBytesNo[battlerId] == 0)
break;
}
}
u8 RecordedBattle_GetBattlerAction(u8 battlerId)
{
// Trying to read past array or invalid action byte, battle is over.
if (sRecordedBytesNo[battlerId] >= BATTLER_RECORD_SIZE || sBattleRecords[battlerId][sRecordedBytesNo[battlerId]] == 0xFF)
{
gSpecialVar_Result = gBattleOutcome = B_OUTCOME_PLAYER_TELEPORTED; // hah
ResetPaletteFadeControl();
BeginNormalPaletteFade(0xFFFFFFFF, 0, 0, 0x10, 0);
SetMainCallback2(CB2_QuitRecordedBattle);
return 0xFF;
}
else
{
return sBattleRecords[battlerId][sRecordedBytesNo[battlerId]++];
}
}
u8 sub_81850D0(void)
{
return sUnknown_0203C7AC;
}
u8 sub_81850DC(u8 *arg0)
{
u8 i, j;
u8 ret = 0;
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
if (sRecordedBytesNo[i] != sUnknown_0203C79C[i])
{
arg0[ret++] = i;
arg0[ret++] = sRecordedBytesNo[i] - sUnknown_0203C79C[i];
for (j = 0; j < sRecordedBytesNo[i] - sUnknown_0203C79C[i]; j++)
{
arg0[ret++] = sBattleRecords[i][sUnknown_0203C79C[i] + j];
}
sUnknown_0203C79C[i] = sRecordedBytesNo[i];
}
}
return ret;
}
void sub_81851A8(u8 *arg0)
{
s32 i;
u8 var1 = 2;
u8 var2;
if (!(gBattleTypeFlags & BATTLE_TYPE_LINK))
return;
for (i = 0; i < GetLinkPlayerCount(); i++)
{
if ((gLinkPlayers[i].version & 0xFF) != VERSION_EMERALD)
return;
}
if (!(gBattleTypeFlags & BATTLE_TYPE_IS_MASTER))
{
for (var2 = *arg0; var2 != 0;)
{
u8 unkVar = sub_8185278(arg0, &var1, &var2);
u8 unkVar2 = sub_8185278(arg0, &var1, &var2);
for (i = 0; i < unkVar2; i++)
{
sBattleRecords[unkVar][sUnknown_0203C7A4[unkVar]++] = sub_8185278(arg0, &var1, &var2);
}
}
}
}
static u8 sub_8185278(u8 *arg0, u8 *arg1, u8 *arg2)
{
(*arg2)--;
return arg0[(*arg1)++];
}
bool32 CanCopyRecordedBattleSaveData(void)
{
struct RecordedBattleSave *dst = AllocZeroed(sizeof(struct RecordedBattleSave));
bool32 ret = CopyRecordedBattleFromSave(dst);
Free(dst);
return ret;
}
static bool32 IsRecordedBattleSaveValid(struct RecordedBattleSave *save)
{
if (save->battleFlags == 0)
return FALSE;
if (save->battleFlags & ILLEGAL_BATTLE_TYPES)
return FALSE;
if (CalcByteArraySum((void*)(save), sizeof(*save) - 4) != save->checksum)
return FALSE;
return TRUE;
}
static bool32 RecordedBattleToSave(struct RecordedBattleSave *battleSave, struct RecordedBattleSave *saveSection)
{
memset(saveSection, 0, 0x1000);
memcpy(saveSection, battleSave, sizeof(*battleSave));
saveSection->checksum = CalcByteArraySum((void*)(saveSection), sizeof(*saveSection) - 4);
if (sub_8153634(31, (void*)(saveSection)) != 1)
return FALSE;
else
return TRUE;
}
bool32 MoveRecordedBattleToSaveData(void)
{
s32 i, j;
bool32 ret;
struct RecordedBattleSave *battleSave, *savSection;
u8 var;
var = 0;
battleSave = AllocZeroed(sizeof(struct RecordedBattleSave));
savSection = AllocZeroed(0x1000);
for (i = 0; i < PARTY_SIZE; i++)
{
battleSave->playerParty[i] = sSavedPlayerParty[i];
battleSave->opponentParty[i] = sSavedOpponentParty[i];
}
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
for (j = 0; j < PLAYER_NAME_LENGTH + 1; j++)
{
battleSave->playersName[i][j] = sPlayers[i].name[j];
}
battleSave->playersGender[i] = sPlayers[i].gender;
battleSave->playersLanguage[i] = sPlayers[i].language;
battleSave->playersBattlers[i] = sPlayers[i].battlerId;
battleSave->playersTrainerId[i] = sPlayers[i].trainerId;
}
battleSave->rngSeed = gRecordedBattleRngSeed;
if (sBattleFlags & BATTLE_TYPE_LINK)
{
battleSave->battleFlags = (sBattleFlags & ~(BATTLE_TYPE_LINK | BATTLE_TYPE_20)) | BATTLE_TYPE_x2000000;
if (sBattleFlags & BATTLE_TYPE_IS_MASTER)
{
battleSave->battleFlags |= BATTLE_TYPE_x80000000;
}
else if (sBattleFlags & BATTLE_TYPE_MULTI)
{
switch (sPlayers[0].battlerId)
{
case 0:
case 2:
if (!(sPlayers[gUnknown_0203C7B4].battlerId & 1))
battleSave->battleFlags |= BATTLE_TYPE_x80000000;
break;
case 1:
case 3:
if ((sPlayers[gUnknown_0203C7B4].battlerId & 1))
battleSave->battleFlags |= BATTLE_TYPE_x80000000;
break;
}
}
}
else
{
battleSave->battleFlags = sBattleFlags;
}
battleSave->opponentA = gTrainerBattleOpponent_A;
battleSave->opponentB = gTrainerBattleOpponent_B;
battleSave->partnerId = gPartnerTrainerId;
battleSave->field_4FA = gUnknown_0203C7B4;
battleSave->lvlMode = gSaveBlock2Ptr->frontier.lvlMode;
battleSave->frontierFacility = sFrontierFacility;
battleSave->frontierBrainSymbol = sFrontierBrainSymbol;
battleSave->battleScene = gSaveBlock2Ptr->optionsBattleSceneOff;
battleSave->textSpeed = gSaveBlock2Ptr->optionsTextSpeed;
battleSave->AI_scripts = sAI_Scripts;
if (gTrainerBattleOpponent_A >= TRAINER_RECORD_MIXING_FRIEND && gTrainerBattleOpponent_A < TRAINER_RECORD_MIXING_APPRENTICE)
{
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
battleSave->recordMixFriendName[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].name[i];
battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
if (sBattleOutcome == B_OUTCOME_WON)
{
for (i = 0; i < 6; i++)
battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].speechLost[i];
}
else
{
for (i = 0; i < 6; i++)
battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].speechWon[i];
}
battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_FRIEND].language;
}
else if (gTrainerBattleOpponent_B >= TRAINER_RECORD_MIXING_FRIEND && gTrainerBattleOpponent_B < TRAINER_RECORD_MIXING_APPRENTICE)
{
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
battleSave->recordMixFriendName[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].name[i];
battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
if (sBattleOutcome == B_OUTCOME_WON)
{
for (i = 0; i < 6; i++)
battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].speechLost[i];
}
else
{
for (i = 0; i < 6; i++)
battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].speechWon[i];
}
battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_FRIEND].language;
}
else if (gPartnerTrainerId >= TRAINER_RECORD_MIXING_FRIEND && gPartnerTrainerId < TRAINER_RECORD_MIXING_APPRENTICE)
{
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
battleSave->recordMixFriendName[i] = gSaveBlock2Ptr->frontier.towerRecords[gPartnerTrainerId - TRAINER_RECORD_MIXING_FRIEND].name[i];
battleSave->recordMixFriendClass = gSaveBlock2Ptr->frontier.towerRecords[gPartnerTrainerId - TRAINER_RECORD_MIXING_FRIEND].facilityClass;
battleSave->recordMixFriendLanguage = gSaveBlock2Ptr->frontier.towerRecords[gPartnerTrainerId - TRAINER_RECORD_MIXING_FRIEND].language;
}
if (gTrainerBattleOpponent_A >= TRAINER_RECORD_MIXING_APPRENTICE)
{
battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_APPRENTICE].id;
for (i = 0; i < 6; i++)
battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_APPRENTICE].easyChatWords[i];
battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_A - TRAINER_RECORD_MIXING_APPRENTICE].language;
}
else if (gTrainerBattleOpponent_B >= TRAINER_RECORD_MIXING_APPRENTICE)
{
battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_APPRENTICE].id;
for (i = 0; i < 6; i++)
battleSave->easyChatSpeech[i] = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_APPRENTICE].easyChatWords[i];
battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[gTrainerBattleOpponent_B - TRAINER_RECORD_MIXING_APPRENTICE].language;
}
else if (gPartnerTrainerId >= TRAINER_RECORD_MIXING_APPRENTICE)
{
battleSave->apprenticeId = gSaveBlock2Ptr->apprentices[gPartnerTrainerId - TRAINER_RECORD_MIXING_APPRENTICE].id;
battleSave->apprenticeLanguage = gSaveBlock2Ptr->apprentices[gPartnerTrainerId - TRAINER_RECORD_MIXING_APPRENTICE].language;
}
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
for (j = 0; j < BATTLER_RECORD_SIZE; j++)
{
battleSave->battleRecord[i][j] = sBattleRecords[i][j];
}
}
while (1)
{
ret = RecordedBattleToSave(battleSave, savSection);
if (ret == TRUE)
break;
var++;
if (var >= 3)
break;
}
free(battleSave);
free(savSection);
return ret;
}
static bool32 TryCopyRecordedBattleSaveData(struct RecordedBattleSave *dst, struct SaveSection *saveBuffer)
{
if (TryCopySpecialSaveSection(SECTOR_ID_RECORDED_BATTLE, (void*)(saveBuffer)) != 1)
return FALSE;
memcpy(dst, saveBuffer, sizeof(struct RecordedBattleSave));
if (!IsRecordedBattleSaveValid(dst))
return FALSE;
return TRUE;
}
static bool32 CopyRecordedBattleFromSave(struct RecordedBattleSave *dst)
{
struct SaveSection *savBuffer = AllocZeroed(sizeof(struct SaveSection));
bool32 ret = TryCopyRecordedBattleSaveData(dst, savBuffer);
Free(savBuffer);
return ret;
}
static void CB2_RecordedBattleEnd(void)
{
gSaveBlock2Ptr->frontier.lvlMode = sLvlMode;
gBattleOutcome = 0;
gBattleTypeFlags = 0;
gTrainerBattleOpponent_A = 0;
gTrainerBattleOpponent_B = 0;
gPartnerTrainerId = 0;
RecordedBattle_RestoreSavedParties();
SetMainCallback2(sCallback2_AfterRecordedBattle);
}
#define tFramesToWait data[0]
static void Task_StartAfterCountdown(u8 taskId)
{
if (--gTasks[taskId].tFramesToWait == 0)
{
gMain.savedCallback = CB2_RecordedBattleEnd;
SetMainCallback2(CB2_InitBattle);
DestroyTask(taskId);
}
}
static void SetVariablesForRecordedBattle(struct RecordedBattleSave *src)
{
bool8 var;
s32 i, j;
ZeroPlayerPartyMons();
ZeroEnemyPartyMons();
for (i = 0; i < PARTY_SIZE; i++)
{
gPlayerParty[i] = src->playerParty[i];
gEnemyParty[i] = src->opponentParty[i];
}
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
for (var = FALSE, j = 0; j < PLAYER_NAME_LENGTH + 1; j++)
{
gLinkPlayers[i].name[j] = src->playersName[i][j];
if (src->playersName[i][j] == EOS)
var = TRUE;
}
gLinkPlayers[i].gender = src->playersGender[i];
gLinkPlayers[i].language = src->playersLanguage[i];
gLinkPlayers[i].id = src->playersBattlers[i];
gLinkPlayers[i].trainerId = src->playersTrainerId[i];
if (var)
ConvertInternationalString(gLinkPlayers[i].name, gLinkPlayers[i].language);
}
gRecordedBattleRngSeed = src->rngSeed;
gBattleTypeFlags = src->battleFlags | BATTLE_TYPE_RECORDED;
gTrainerBattleOpponent_A = src->opponentA;
gTrainerBattleOpponent_B = src->opponentB;
gPartnerTrainerId = src->partnerId;
gUnknown_0203C7B4 = src->field_4FA;
sLvlMode = gSaveBlock2Ptr->frontier.lvlMode;
sFrontierFacility = src->frontierFacility;
sFrontierBrainSymbol = src->frontierBrainSymbol;
sBattleScene = src->battleScene;
sTextSpeed = src->textSpeed;
sAI_Scripts = src->AI_scripts;
for (i = 0; i < PLAYER_NAME_LENGTH + 1; i++)
{
sRecordMixFriendName[i] = src->recordMixFriendName[i];
}
sRecordMixFriendClass = src->recordMixFriendClass;
sApprenticeId = src->apprenticeId;
sRecordMixFriendLanguage = src->recordMixFriendLanguage;
sApprenticeLanguage = src->apprenticeLanguage;
for (i = 0; i < 6; i++)
{
sEasyChatSpeech[i] = src->easyChatSpeech[i];
}
gSaveBlock2Ptr->frontier.lvlMode = src->lvlMode;
for (i = 0; i < MAX_BATTLERS_COUNT; i++)
{
for (j = 0; j < BATTLER_RECORD_SIZE; j++)
{
sBattleRecords[i][j] = src->battleRecord[i][j];
}
}
}
void PlayRecordedBattle(void (*CB2_After)(void))
{
struct RecordedBattleSave *battleSave = AllocZeroed(sizeof(struct RecordedBattleSave));
if (CopyRecordedBattleFromSave(battleSave) == TRUE)
{
u8 taskId;
RecordedBattle_SaveParties();
SetVariablesForRecordedBattle(battleSave);
taskId = CreateTask(Task_StartAfterCountdown, 1);
gTasks[taskId].tFramesToWait = 128;
sCallback2_AfterRecordedBattle = CB2_After;
PlayMapChosenOrBattleBGM(FALSE);
SetMainCallback2(CB2_RecordedBattle);
}
Free(battleSave);
}
#undef tFramesToWait
static void CB2_RecordedBattle(void)
{
AnimateSprites();
BuildOamBuffer();
RunTasks();
}
u8 GetRecordedBattleFrontierFacility(void)
{
return sFrontierFacility;
}
u8 GetRecordedBattleFronterBrainSymbol(void)
{
return sFrontierBrainSymbol;
}
void RecordedBattle_SaveParties(void)
{
s32 i;
for (i = 0; i < PARTY_SIZE; i++)
{
sSavedPlayerParty[i] = gPlayerParty[i];
sSavedOpponentParty[i] = gEnemyParty[i];
}
}
static void RecordedBattle_RestoreSavedParties(void)
{
s32 i;
for (i = 0; i < PARTY_SIZE; i++)
{
gPlayerParty[i] = sSavedPlayerParty[i];
gEnemyParty[i] = sSavedOpponentParty[i];
}
}
u8 GetActiveBattlerLinkPlayerGender(void)
{
s32 i;
for (i = 0; i < MAX_LINK_PLAYERS; i++)
{
if (gLinkPlayers[i].id == gActiveBattler)
break;
}
if (i != MAX_LINK_PLAYERS)
return gLinkPlayers[i].gender;
return 0;
}
void sub_8185F84(void)
{
sUnknown_0203C7B5 = 0;
}
void sub_8185F90(u16 arg0)
{
sUnknown_0203C7B5 |= (arg0 & 0x8000) >> 0xF;
}
u8 sub_8185FAC(void)
{
return sUnknown_0203C7B5;
}
u8 GetBattleSceneInRecordedBattle(void)
{
return sBattleScene;
}
u8 GetTextSpeedInRecordedBattle(void)
{
return sTextSpeed;
}
void RecordedBattle_CopyBattlerMoves(void)
{
s32 i;
if (GetBattlerSide(gActiveBattler) == B_SIDE_OPPONENT)
return;
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
return;
if (sUnknown_0203C7AC == 2)
return;
for (i = 0; i < MAX_MON_MOVES; i++)
{
sPlayerMonMoves[gActiveBattler / 2][i] = gBattleMons[gActiveBattler].moves[i];
}
}
#define ACTION_MOVE_CHANGE 6
void sub_818603C(u8 arg0)
{
s32 battlerId, j, k;
if (gBattleTypeFlags & (BATTLE_TYPE_LINK | BATTLE_TYPE_x2000000))
return;
for (battlerId = 0; battlerId < gBattlersCount; battlerId++)
{
if (GetBattlerSide(battlerId) != B_SIDE_OPPONENT) // player's side only
{
if (arg0 == 1)
{
for (j = 0; j < MAX_MON_MOVES; j++)
{
if (gBattleMons[battlerId].moves[j] != sPlayerMonMoves[battlerId / 2][j])
break;
}
if (j != MAX_MON_MOVES) // player's mon's move has been changed
{
RecordedBattle_SetBattlerAction(battlerId, ACTION_MOVE_CHANGE);
for (j = 0; j < MAX_MON_MOVES; j++)
{
for (k = 0; k < MAX_MON_MOVES; k++)
{
if (gBattleMons[battlerId].moves[j] == sPlayerMonMoves[battlerId / 2][k])
{
RecordedBattle_SetBattlerAction(battlerId, k);
break;
}
}
}
}
}
else
{
if (sBattleRecords[battlerId][sRecordedBytesNo[battlerId]] == ACTION_MOVE_CHANGE)
{
u8 ppBonuses[4];
u8 array1[4];
u8 array2[4];
struct MovePp movePp;
u8 array3[8];
u8 var;
RecordedBattle_GetBattlerAction(battlerId);
for (j = 0; j < MAX_MON_MOVES; j++)
{
ppBonuses[j] = ((gBattleMons[battlerId].ppBonuses & ((3 << (j << 1)))) >> (j << 1));
}
for (j = 0; j < MAX_MON_MOVES; j++)
{
array1[j] = RecordedBattle_GetBattlerAction(battlerId);
movePp.moves[j] = gBattleMons[battlerId].moves[array1[j]];
movePp.pp[j] = gBattleMons[battlerId].pp[array1[j]];
array3[j] = ppBonuses[array1[j]];
array2[j] = (gDisableStructs[battlerId].mimickedMoves & gBitTable[j]) >> j;
}
for (j = 0; j < MAX_MON_MOVES; j++)
{
gBattleMons[battlerId].moves[j] = movePp.moves[j];
gBattleMons[battlerId].pp[j] = movePp.pp[j];
}
gBattleMons[battlerId].ppBonuses = 0;
gDisableStructs[battlerId].mimickedMoves = 0;
for (j = 0; j < MAX_MON_MOVES; j++)
{
gBattleMons[battlerId].ppBonuses |= (array3[j]) << (j << 1);
gDisableStructs[battlerId].mimickedMoves |= (array2[j]) << (j);
}
if (!(gBattleMons[battlerId].status2 & STATUS2_TRANSFORMED))
{
for (j = 0; j < MAX_MON_MOVES; j++)
{
ppBonuses[j] = ((GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PP_BONUSES, NULL) & ((3 << (j << 1)))) >> (j << 1));
}
for (j = 0; j < MAX_MON_MOVES; j++)
{
movePp.moves[j] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_MOVE1 + array1[j], NULL);
movePp.pp[j] = GetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PP1 + array1[j], NULL);
array3[j] = ppBonuses[array1[j]];
}
for (j = 0; j < MAX_MON_MOVES; j++)
{
SetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_MOVE1 + j, &movePp.moves[j]);
SetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PP1 + j, &movePp.pp[j]);
}
var = 0;
for (j = 0; j < MAX_MON_MOVES; j++)
{
var |= (array3[j]) << (j << 1);
}
SetMonData(&gPlayerParty[gBattlerPartyIndexes[battlerId]], MON_DATA_PP_BONUSES, &var);
}
gChosenMoveByBattler[battlerId] = gBattleMons[battlerId].moves[*(gBattleStruct->chosenMovePositions + battlerId)];
}
}
}
}
}
u32 GetAiScriptsInRecordedBattle(void)
{
return sAI_Scripts;
}
void sub_8186444(void)
{
sUnknown_0203CCD0 = 1;
}
bool8 sub_8186450(void)
{
return (sUnknown_0203CCD0 == 0);
}
void sub_8186468(u8 *dst)
{
s32 i;
for (i = 0; i < 8; i++)
dst[i] = sRecordMixFriendName[i];
dst[7] = EOS;
ConvertInternationalString(dst, sRecordMixFriendLanguage);
}
u8 GetRecordedBattleRecordMixFriendClass(void)
{
return sRecordMixFriendClass;
}
u8 GetRecordedBattleApprenticeId(void)
{
return sApprenticeId;
}
u8 GetRecordedBattleRecordMixFriendLanguage(void)
{
return sRecordMixFriendLanguage;
}
u8 GetRecordedBattleApprenticeLanguage(void)
{
return sApprenticeLanguage;
}
void RecordedBattle_SaveBattleOutcome(void)
{
sBattleOutcome = gBattleOutcome;
}
u16 *GetRecordedBattleEasyChatSpeech(void)
{
return sEasyChatSpeech;
}