diff options
Diffstat (limited to 'src/contest_link.c')
-rw-r--r-- | src/contest_link.c | 563 |
1 files changed, 563 insertions, 0 deletions
diff --git a/src/contest_link.c b/src/contest_link.c new file mode 100644 index 000000000..ae6975268 --- /dev/null +++ b/src/contest_link.c @@ -0,0 +1,563 @@ +#include "global.h" +#include "contest.h" +#include "decompress.h" +#include "event_data.h" +#include "link.h" +#include "pokemon.h" +#include "random.h" +#include "task.h" +#include "contest_link.h" + +static void Task_LinkContest_StartInitFlags(u8); +static void Task_LinkContest_InitFlags(u8); + +#define tState data[0] +#define tDelayTimer data[1] +#define tCategories(i) data[(i) + 1] +#define tLeaderIds(i) data[(i) + 5] +#define tCategory data[9] +#define tTimer data[11] +#define tStandbyState data[12] + +bool32 LinkContest_SendBlock(void *src, u16 size) +{ + memcpy(gDecompressionBuffer, src, size); + if (SendBlock(bitmask_all_link_players_but_self(), gDecompressionBuffer, size)) + return TRUE; + else + return FALSE; +} + +bool8 LinkContest_GetBlockReceived(u8 flag) +{ + u8 mask = (1 << flag); + if (!(GetBlockReceivedStatus() & mask)) + { + return FALSE; + } + else + { + ResetBlockReceivedFlag(flag); + return TRUE; + } +} + +bool8 LinkContest_GetBlockReceivedFromAllPlayers(void) +{ + if (GetBlockReceivedStatus() == GetLinkPlayerCountAsBitFlags()) + { + ResetBlockReceivedFlags(); + return TRUE; + } + else + { + return FALSE; + } +} + +void Task_LinkContest_Init(u8 taskId) +{ + u8 i; + + for (i = 0; i < CONTESTANT_COUNT; i++) + gBlockRecvBuffer[i][0] = 0xFF; + + gTasks[taskId].tState = 0; + gTasks[taskId].func = Task_LinkContest_StartInitFlags; +} + +static void Task_LinkContest_StartInitFlags(u8 taskId) +{ + gTasks[taskId].func = Task_LinkContest_InitFlags; +} + +static void Task_LinkContest_InitFlags(u8 taskId) +{ + int i; + + if (!gReceivedRemoteLinkPlayers) + return; + + gContestPlayerMonIndex = GetMultiplayerId(); + gNumLinkContestPlayers = GetLinkPlayerCount(); + gLinkContestFlags = LINK_CONTEST_FLAG_IS_LINK; + if (gWirelessCommType == 1) + gLinkContestFlags = LINK_CONTEST_FLAG_IS_LINK | LINK_CONTEST_FLAG_IS_WIRELESS; + + // Get number of players using Emerald/FRLG + for (i = 0; i < gNumLinkContestPlayers && (u32)(gLinkPlayers[i].version & 0xFF) - 1 > VERSION_RUBY - 1; i++) + ; + + if (i < gNumLinkContestPlayers) + gLinkContestFlags |= LINK_CONTEST_FLAG_HAS_RS_PLAYER; + + SwitchTaskToFollowupFunc(taskId); +} + +bool32 LinkContest_TryLinkStandby(s16 *state) +{ + // Skip standby for RS cabled links + if (gLinkContestFlags & LINK_CONTEST_FLAG_HAS_RS_PLAYER) + return TRUE; + + switch (*state) + { + case 0: + if (IsLinkTaskFinished()) + { + SetLinkStandbyCallback(); + (*state)++; + } + return FALSE; + case 1: + (*state)++; + return FALSE; + default: + if (IsLinkTaskFinished() != TRUE) + return FALSE; + else + return TRUE; + } +} + +void Task_LinkContest_CommunicateMonsRS(u8 taskId) +{ + int i; + + if (!LinkContest_TryLinkStandby(&gTasks[taskId].tStandbyState)) + return; + + switch (gTasks[taskId].tState) + { + case 0: + // Send players mon + if (GetMultiplayerId() == 0) + { + if (IsLinkTaskFinished()) + { + memcpy(gBlockSendBuffer, &gContestMons[gContestPlayerMonIndex], sizeof(struct ContestPokemon)); + gTasks[taskId].tState = 10; + } + } + else + { + memcpy(gBlockSendBuffer, &gContestMons[gContestPlayerMonIndex], sizeof(struct ContestPokemon)); + gTasks[taskId].tState = 1; + } + break; + case 1: + // Wait for other players data + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + for (i = 0; i < gNumLinkContestPlayers; i++) + { + memcpy(&gContestMons[i], gBlockRecvBuffer[i], sizeof(struct ContestPokemon)); + StripPlayerAndMonNamesForLinkContest(&gContestMons[i], gLinkPlayers[i].language); + } + + gTasks[taskId].tState++; + } + break; + case 10: + // Only if leader. Request other players data + if (++gTasks[taskId].tTimer > 300) + { + SendBlockRequest(2); + gTasks[taskId].tState = 1; + } + break; + default: + gTasks[taskId].tState = 0; + gTasks[taskId].tTimer = 0; + gTasks[taskId].tStandbyState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateRngRS(u8 taskId) +{ + switch (gTasks[taskId].tState) + { + case 0: + if (GetMultiplayerId() == 0) + { + if (IsLinkTaskFinished() && LinkContest_SendBlock(&gRngValue, sizeof(gRngValue)) == TRUE) + gTasks[taskId].tState++; + } + else + { + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceived(0)) + { + memcpy(&gRngValue, gBlockRecvBuffer[0], sizeof(gRngValue)); + memcpy(&gContestRngValue, gBlockRecvBuffer[0], sizeof(gContestRngValue)); + gTasks[taskId].tState++; + } + break; + default: + gTasks[taskId].tState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateCategoryRS(u8 taskId) +{ + int i; + + if (!LinkContest_TryLinkStandby(&gTasks[taskId].tStandbyState)) + return; + + switch (gTasks[taskId].tState) + { + case 0: + gBlockSendBuffer[0] = gTasks[taskId].tCategory; + if (GetMultiplayerId() == 0) + { + if (IsLinkTaskFinished()) + gTasks[taskId].tState = 10; + } + else + { + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + for (i = 0; i < gNumLinkContestPlayers; i++) + gTasks[taskId].tCategories(i) = gBlockRecvBuffer[i][0]; + + gTasks[taskId].tState++; + } + break; + case 10: + if (++gTasks[taskId].tTimer > 10) + { + SendBlockRequest(2); + gTasks[taskId].tState = 1; + } + break; + default: + gTasks[taskId].tState = 0; + gTasks[taskId].tTimer = 0; + gTasks[taskId].tStandbyState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateMonIdxs(u8 taskId) +{ + switch (gTasks[taskId].tState) + { + case 0: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(&gContestPlayerMonIndex, sizeof(gContestPlayerMonIndex)) == TRUE) + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + gTasks[taskId].tState++; + break; + default: + gTasks[taskId].tState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateMoveSelections(u8 taskId) +{ + int i; + + switch (gTasks[taskId].tState) + { + case 0: + if (IsLinkTaskFinished()) + { + // Send player's move selection + if (LinkContest_SendBlock(&eContestantStatus[gContestPlayerMonIndex].currMove, sizeof(eContestantStatus[gContestPlayerMonIndex].currMove)) == TRUE) + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + // Receive partners' move selections + for (i = 0; i < gNumLinkContestPlayers; i++) + eContestantStatus[i].currMove = gBlockRecvBuffer[i][0]; + + gTasks[taskId].tState++; + } + break; + default: + gTasks[taskId].tState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateFinalStandings(u8 taskId) +{ + switch (gTasks[taskId].tState) + { + case 0: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestMonTotalPoints, sizeof(gContestMonTotalPoints)) == 1) + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestMonTotalPoints, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(gContestMonTotalPoints)); + gTasks[taskId].tState++; + } + break; + case 2: + case 5: + case 8: + case 11: + if (gTasks[taskId].tDelayTimer++ > 10) + { + gTasks[taskId].tDelayTimer = 0; + gTasks[taskId].tState++; + } + break; + case 3: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestMonAppealPointTotals, sizeof(gContestMonAppealPointTotals)) == 1) + gTasks[taskId].tState++; + } + break; + case 4: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestMonAppealPointTotals, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(gContestMonAppealPointTotals)); + gTasks[taskId].tState++; + } + break; + case 6: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestMonRound2Points, sizeof(gContestMonRound2Points)) == 1) + gTasks[taskId].tState++; + } + break; + case 7: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestMonRound2Points, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(gContestMonRound2Points)); + gTasks[taskId].tState++; + } + break; + case 9: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestFinalStandings, sizeof(gContestFinalStandings)) == 1) + gTasks[taskId].tState++; + } + break; + case 10: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestFinalStandings, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(gContestFinalStandings)); + gTasks[taskId].tState++; + } + break; + default: + gTasks[taskId].tState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateAppealsState(u8 taskId) +{ + switch (gTasks[taskId].tState) + { + case 0: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(eContestantStatus, CONTESTANT_COUNT * sizeof(struct ContestantStatus)) == 1) + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(eContestantStatus, gBlockRecvBuffer[gContestLinkLeaderIndex], CONTESTANT_COUNT * sizeof(struct ContestantStatus)); + gTasks[taskId].tState++; + } + break; + case 2: + case 5: + case 8: + case 11: + if (gTasks[taskId].tDelayTimer++ > 10) + { + gTasks[taskId].tDelayTimer = 0; + gTasks[taskId].tState++; + } + break; + case 3: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestResources->appealResults, sizeof(struct ContestAppealMoveResults)) == 1) + gTasks[taskId].tState++; + } + break; + case 4: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestResources->appealResults, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(struct ContestAppealMoveResults)); + gTasks[taskId].tState++; + } + break; + case 6: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestResources->excitement, sizeof(struct ContestExcitement)) == 1) + gTasks[taskId].tState++; + } + break; + case 7: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestResources->excitement, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(struct ContestExcitement)); + gTasks[taskId].tState++; + } + break; + case 9: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestantTurnOrder, sizeof(gContestantTurnOrder)) == 1) + gTasks[taskId].tState++; + } + break; + case 10: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestantTurnOrder, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(gContestantTurnOrder)); + gTasks[taskId].tState++; + } + break; + default: + gTasks[taskId].tState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateLeaderIdsRS(u8 taskId) +{ + int i; + + if (!LinkContest_TryLinkStandby(&gTasks[taskId].tStandbyState)) + return; + + switch (gTasks[taskId].tState) + { + case 0: + gBlockSendBuffer[0] = 0x6E; + if (GetMultiplayerId() == 0) + { + if (IsLinkTaskFinished()) + gTasks[taskId].tState = 10; + } + else + { + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + for (i = 0; i < CONTESTANT_COUNT; i++) + gTasks[taskId].tLeaderIds(i) = gBlockRecvBuffer[i][0]; + + gTasks[taskId].tState++; + } + break; + case 10: + if (++gTasks[taskId].tTimer > 10) + { + SendBlockRequest(2); + gTasks[taskId].tState = 1; + } + break; + default: + gTasks[taskId].tState = 0; + gTasks[taskId].tTimer = 0; + gTasks[taskId].tStandbyState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateRound1Points(u8 taskId) +{ + if (!LinkContest_TryLinkStandby(&gTasks[taskId].tStandbyState)) + return; + + switch (gTasks[taskId].tState) + { + case 0: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestMonRound1Points, sizeof(gContestMonRound1Points)) == 1) + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestMonRound1Points, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(gContestMonRound1Points)); + gTasks[taskId].tState++; + } + break; + default: + gTasks[taskId].tState = 0; + gTasks[taskId].tStandbyState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} + +void Task_LinkContest_CommunicateTurnOrder(u8 taskId) +{ + if (!LinkContest_TryLinkStandby(&gTasks[taskId].tStandbyState)) + return; + + switch (gTasks[taskId].tState) + { + case 0: + if (IsLinkTaskFinished()) + { + if (LinkContest_SendBlock(gContestantTurnOrder, sizeof(gContestantTurnOrder)) == 1) + gTasks[taskId].tState++; + } + break; + case 1: + if (LinkContest_GetBlockReceivedFromAllPlayers()) + { + memcpy(gContestantTurnOrder, gBlockRecvBuffer[gContestLinkLeaderIndex], sizeof(gContestantTurnOrder)); + gTasks[taskId].tState++; + } + break; + default: + gTasks[taskId].tState = 0; + gTasks[taskId].tStandbyState = 0; + SwitchTaskToFollowupFunc(taskId); + break; + } +} |