summaryrefslogtreecommitdiff
path: root/src/contest_util.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/contest_util.c')
-rw-r--r--src/contest_util.c578
1 files changed, 578 insertions, 0 deletions
diff --git a/src/contest_util.c b/src/contest_util.c
new file mode 100644
index 000000000..34db5a975
--- /dev/null
+++ b/src/contest_util.c
@@ -0,0 +1,578 @@
+#include "global.h"
+#include "contest_util.h"
+#include "battle.h"
+#include "berry.h"
+#include "choose_party.h"
+#include "constants/items.h"
+#include "constants/species.h"
+#include "contest.h"
+#include "contest_link_util.h"
+#include "contest_painting.h"
+#include "data2.h"
+#include "daycare.h"
+#include "debug.h"
+#include "decompress.h"
+#include "event_data.h"
+#include "ewram.h"
+#include "link.h"
+#include "load_save.h"
+#include "main.h"
+#include "menu.h"
+#include "overworld.h"
+#include "pokedex.h"
+#include "pokemon.h"
+#include "random.h"
+#include "task.h"
+
+#define CONTEST_ENTRY_PIC_LEFT 10
+#define CONTEST_ENTRY_PIC_TOP 3
+
+extern struct SpriteTemplate gCreatingSpriteTemplate;
+
+extern u8 gSelectedOrderFromParty[];
+
+extern u16 gSpecialVar_ContestCategory;
+extern u16 gSpecialVar_ContestRank;
+
+extern u8 gContestMonPartyIndex;
+extern u8 gUnknown_0203856C;
+
+void SetContestTrainerGfxIds(void)
+{
+ gSaveBlock1.vars[VAR_OBJ_GFX_ID_0 - VARS_START] = gContestMons[0].trainerGfxId;
+ gSaveBlock1.vars[VAR_OBJ_GFX_ID_1 - VARS_START] = gContestMons[1].trainerGfxId;
+ gSaveBlock1.vars[VAR_OBJ_GFX_ID_2 - VARS_START] = gContestMons[2].trainerGfxId;
+}
+
+void GetNpcContestantLocalId(void)
+{
+ u16 localId;
+ u8 specialVar = gSpecialVar_0x8005;
+
+ switch(specialVar)
+ {
+ case 0:
+ localId = 3;
+ break;
+ case 1:
+ localId = 4;
+ break;
+ case 2:
+ localId = 5;
+ break;
+ default:
+ localId = 100;
+ break;
+ }
+ gSpecialVar_0x8004 = localId;
+}
+
+void BufferContestTrainerAndMonNames(void)
+{
+ Contest_GetTrainerNameI_StringVar1();
+ Contest_GetNicknameI_StringVar1();
+ Contest_GetSpeciesNameI_StringVar1();
+}
+
+void DoesContestCategoryHaveMuseumPainting(void)
+{
+ u16 contestWinner;
+
+ switch(gSpecialVar_ContestCategory)
+ {
+ case CONTEST_CATEGORY_COOL:
+ contestWinner = CONTEST_WINNER_MUSEUM_COOL - 1;
+ break;
+ case CONTEST_CATEGORY_BEAUTY:
+ contestWinner = CONTEST_WINNER_MUSEUM_BEAUTY - 1;
+ break;
+ case CONTEST_CATEGORY_CUTE:
+ contestWinner = CONTEST_WINNER_MUSEUM_CUTE - 1;
+ break;
+ case CONTEST_CATEGORY_SMART:
+ contestWinner = CONTEST_WINNER_MUSEUM_SMART - 1;
+ break;
+ case CONTEST_CATEGORY_TOUGH:
+ default:
+ contestWinner = CONTEST_WINNER_MUSEUM_TOUGH - 1;
+ break;
+ }
+
+ if (gSaveBlock1.contestWinners[contestWinner].species == SPECIES_NONE)
+ gSpecialVar_0x8004 = FALSE;
+ else
+ gSpecialVar_0x8004 = TRUE;
+}
+
+void SaveMuseumContestPainting(void)
+{
+ Contest_SaveWinner(CONTEST_SAVE_FOR_MUSEUM);
+}
+
+void ShouldReadyContestArtist(void)
+{
+ if(!gContestFinalStandings[gContestPlayerMonIndex]
+ && gSpecialVar_ContestRank == CONTEST_RANK_MASTER
+ &&
+ gContestMonTotalPoints[gContestPlayerMonIndex] >= 800)
+ {
+ gSpecialVar_0x8004 = TRUE;
+ }
+ else
+ {
+ gSpecialVar_0x8004 = FALSE;
+ }
+}
+
+u8 CountPlayerMuseumPaintings(void)
+{
+ u8 retVar = 0;
+ int i;
+
+ for (i = 0; i < 5; i++)
+ if (gSaveBlock1.museumPortraits[i].species != 0)
+ retVar++;
+
+ return retVar;
+}
+
+void GetContestantNamesAtRank(void)
+{
+ s16 conditions[4];
+ s32 i;
+ s32 j;
+ s16 condition;
+ u8 contestantOffset;
+ u8 tieRank;
+ s8 numAtCondition;
+ u8 rank;
+
+ // Get round 1 points
+ for (i = 0; i < 4; i++)
+ conditions[i] = gContestMonRound1Points[i];
+
+ // Sort round 1 points
+ for (i = 0; i < 3; i++)
+ {
+ for (j = 3; j > i; j--)
+ {
+ if (conditions[j - 1] < conditions[j])
+ {
+ int temp;
+ SWAP(conditions[j], conditions[j - 1], temp)
+ }
+ }
+ }
+
+ // Get round1 points at specified rank
+ condition = conditions[gSpecialVar_0x8006];
+
+ // Count number of contestants with the same number of points
+ numAtCondition = 0;
+ tieRank = 0;
+
+ for (i = 0; i < 4; i++)
+ {
+ if (conditions[i] == condition)
+ {
+ numAtCondition++;
+ if (i == gSpecialVar_0x8006)
+ tieRank = numAtCondition;
+ }
+ }
+
+ // Get rank of first contestant with the same number of points
+ for (i = 0; i < 4; i++)
+ {
+ if (conditions[i] == condition)
+ break;
+ }
+ rank = i;
+
+ // Get contestant id of player at rank (taking ties into account)
+ contestantOffset = tieRank;
+ for (i = 0; i < 4; i++)
+ {
+ if (condition == gContestMonRound1Points[i])
+ {
+ if (contestantOffset == 1)
+ break;
+ contestantOffset--;
+ }
+ }
+
+ // Use contestant id to get names
+ Contest_CopyAndConvertNicknameI_Intl(gStringVar1, i);
+
+ if (gIsLinkContest & 1)
+ Contest_CopyAndConvertTrainerName_Intl(gStringVar2, gLinkPlayers[i].name);
+ else
+ Contest_CopyAndConvertTrainerName_Intl(gStringVar2, gContestMons[i].trainerName);
+
+ // Return adjusted rank
+ if (numAtCondition == 1)
+ gSpecialVar_0x8006 = rank;
+ else if (tieRank == numAtCondition)
+ gSpecialVar_0x8006 = rank;
+ else
+ gSpecialVar_0x8006 = rank + 4;
+}
+
+void ShowContestWinnerCleanup(void)
+{
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+}
+
+// File boundary?
+
+void ShowContestWinner(void)
+{
+ if(gUnknown_0203856C)
+ {
+ sub_80AAF30();
+ eCurContestWinnerIsForArtist = TRUE;
+ eCurContestWinnerSaveIdx = GetContestWinnerSaveIdx(CONTEST_SAVE_FOR_ARTIST, 0);
+ Contest_SaveWinner(3);
+ gUnknown_0203856C = 0;
+ }
+ SetMainCallback2(CB2_ContestPainting);
+ gMain.savedCallback = ShowContestWinnerCleanup;
+}
+
+void ScrSpecial_SetLinkContestTrainerGfxIdx(void)
+{
+ VarSet(VAR_OBJ_GFX_ID_0, gContestMons[0].trainerGfxId);
+ VarSet(VAR_OBJ_GFX_ID_1, gContestMons[1].trainerGfxId);
+ VarSet(VAR_OBJ_GFX_ID_2, gContestMons[2].trainerGfxId);
+ VarSet(VAR_OBJ_GFX_ID_3, gContestMons[3].trainerGfxId);
+}
+
+bool8 GiveMonArtistRibbon(void)
+{
+ u8 ribbon = GetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_ARTIST_RIBBON);
+
+ if(ribbon == FALSE
+ && gContestFinalStandings[gContestPlayerMonIndex] == 0
+ && gSpecialVar_ContestRank == 3
+ && gContestMonTotalPoints[gContestPlayerMonIndex] >= 800)
+ {
+ ribbon = TRUE;
+ SetMonData(&gPlayerParty[gContestMonPartyIndex], MON_DATA_ARTIST_RIBBON, &ribbon);
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+u8 sub_80C5044(void)
+{
+ return gUnknown_0203856C;
+}
+
+void ShowContestEntryMonPic(void)
+{
+ const struct CompressedSpritePalette *palette;
+ u32 var1, var2;
+ u16 species;
+ u8 spriteId;
+ u8 taskId;
+
+ if(FindTaskIdByFunc(sub_80C5190) == 0xFF)
+ {
+ u8 left = CONTEST_ENTRY_PIC_LEFT;
+ u8 top = CONTEST_ENTRY_PIC_TOP;
+
+ Menu_DrawStdWindowFrame(left, top, 19, 13);
+ species = gContestMons[gSpecialVar_0x8006].species;
+ var1 = gContestMons[gSpecialVar_0x8006].personality;
+ var2 = gContestMons[gSpecialVar_0x8006].otId;
+ taskId = CreateTask(sub_80C5190, 0x50);
+ gTasks[taskId].data[0] = 0;
+ gTasks[taskId].data[1] = species;
+ HandleLoadSpecialPokePic(
+ &gMonFrontPicTable[species],
+ gMonFrontPicCoords[species].coords,
+ gMonFrontPicCoords[species].y_offset,
+ gMonSpriteGfx_Sprite_ptr[0],
+ gMonSpriteGfx_Sprite_ptr[1],
+ species,
+ var1);
+ palette = GetMonSpritePalStructFromOtIdPersonality(species, var2, var1);
+ LoadCompressedObjectPalette(palette);
+ GetMonSpriteTemplate_803C56C(species, 1);
+ gCreatingSpriteTemplate.paletteTag = palette->tag;
+ spriteId = CreateSprite(&gCreatingSpriteTemplate, 0x78, 0x40, 0);
+ gTasks[taskId].data[2] = spriteId;
+ gTasks[taskId].data[3] = left;
+ gTasks[taskId].data[4] = top;
+ gSprites[spriteId].callback = SpriteCallbackDummy;
+ gSprites[spriteId].oam.priority = 0;
+ }
+}
+
+void sub_80C5164(void)
+{
+ u8 taskId = FindTaskIdByFunc(sub_80C5190);
+
+ if(taskId != 0xFF)
+ gTasks[taskId].data[0]++;
+}
+
+void sub_80C5190(u8 taskId)
+{
+ struct Task *task = &gTasks[taskId];
+ struct Sprite *sprite;
+
+ switch(task->data[0])
+ {
+ case 2:
+ sprite = &gSprites[task->data[2]];
+ FreeSpritePaletteByTag(GetSpritePaletteTagByPaletteNum(sprite->oam.paletteNum));
+
+ if(sprite->oam.affineMode)
+ FreeOamMatrix(sprite->oam.matrixNum);
+
+ DestroySprite(sprite);
+ task->data[0]++;
+ break;
+ case 0:
+ task->data[0]++;
+ break;
+ case 3:
+ Menu_EraseWindowRect(task->data[3], task->data[4], task->data[3] + 9, task->data[4] + 10);
+ DestroyTask(taskId);
+ break;
+ case 1:
+ default:
+ break;
+ }
+}
+
+void ScriptGetMultiplayerId(void)
+{
+ if(gIsLinkContest & 1)
+ gSpecialVar_Result = GetMultiplayerId();
+ else
+ gSpecialVar_Result = 4;
+}
+
+void ScriptRandom(void)
+{
+ u16 random;
+ u16 *scriptPtr;
+
+ if(gIsLinkContest & 1)
+ {
+ gContestRngValue = 1103515245 * gContestRngValue + 24691;
+ random = gContestRngValue >> 16;
+ scriptPtr = &gSpecialVar_Result;
+ }
+ else
+ {
+ scriptPtr = &gSpecialVar_Result;
+ random = Random();
+ }
+ *scriptPtr = random % *scriptPtr;
+}
+
+void ScrSpecial_HealPlayerParty(void)
+{
+ u8 i, j;
+ u8 ppBonuses;
+ u8 arg[4];
+
+ // restore HP.
+ for(i = 0; i < gPlayerPartyCount; i++)
+ {
+ u16 maxHP = GetMonData(&gPlayerParty[i], MON_DATA_MAX_HP);
+ arg[0] = maxHP;
+ arg[1] = maxHP >> 8;
+ SetMonData(&gPlayerParty[i], MON_DATA_HP, arg);
+ ppBonuses = GetMonData(&gPlayerParty[i], MON_DATA_PP_BONUSES);
+
+ // restore PP.
+ for(j = 0; j < 4; j++)
+ {
+ arg[0] = CalculatePPWithBonus(GetMonData(&gPlayerParty[i], MON_DATA_MOVE1 + j), ppBonuses, j);
+ SetMonData(&gPlayerParty[i], MON_DATA_PP1 + j, arg);
+ }
+
+ // since status is u32, the four 0 assignments here are probably for safety to prevent undefined data from reaching SetMonData.
+ arg[0] = 0;
+ arg[1] = 0;
+ arg[2] = 0;
+ arg[3] = 0;
+ SetMonData(&gPlayerParty[i], MON_DATA_STATUS, arg);
+ }
+}
+
+u8 ScriptGiveMon(u16 species, u8 level, u16 item, u32 unused1, u32 unused2, u8 unused3)
+{
+ u16 nationalDexNum;
+ int sentToPc;
+ u8 heldItem[2];
+ struct Pokemon mon;
+
+ CreateMon(&mon, species, level, 32, 0, 0, 0, 0);
+ heldItem[0] = item;
+ heldItem[1] = item >> 8;
+ SetMonData(&mon, MON_DATA_HELD_ITEM, heldItem);
+ sentToPc = GiveMonToPlayer(&mon);
+ nationalDexNum = SpeciesToNationalPokedexNum(species);
+
+ switch(sentToPc)
+ {
+ case 0:
+ case 1:
+ GetSetPokedexFlag(nationalDexNum, 2);
+ GetSetPokedexFlag(nationalDexNum, 3);
+ break;
+ }
+ return sentToPc;
+}
+
+u8 ScriptGiveEgg(u16 species)
+{
+ struct Pokemon mon;
+ u8 isEgg;
+
+ CreateEgg(&mon, species, TRUE);
+ isEgg = TRUE;
+ SetMonData(&mon, MON_DATA_IS_EGG, &isEgg);
+
+ return GiveMonToPlayer(&mon);
+}
+
+void HasEnoughMonsForDoubleBattle(void)
+{
+ switch (GetMonsStateToDoubles())
+ {
+ case PLAYER_HAS_TWO_USABLE_MONS:
+ gSpecialVar_Result = PLAYER_HAS_TWO_USABLE_MONS;
+ break;
+ case PLAYER_HAS_ONE_MON:
+ gSpecialVar_Result = PLAYER_HAS_ONE_MON;
+ break;
+ case PLAYER_HAS_ONE_USABLE_MON:
+ gSpecialVar_Result = PLAYER_HAS_ONE_USABLE_MON;
+ break;
+ }
+}
+
+bool8 CheckPartyMonHasHeldItem(u16 item)
+{
+ int i;
+
+ for(i = 0; i < 6; i++)
+ {
+ u16 species = GetMonData(&gPlayerParty[i], MON_DATA_SPECIES2);
+ if(species != SPECIES_NONE && species != SPECIES_EGG && GetMonData(&gPlayerParty[i], MON_DATA_HELD_ITEM) == item)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+bool8 GetNameOfEnigmaBerryInPlayerParty(void)
+{
+ bool8 hasItem = CheckPartyMonHasHeldItem(ITEM_ENIGMA_BERRY);
+
+ if(hasItem == TRUE)
+ GetBerryNameByBerryType(ItemIdToBerryType(ITEM_ENIGMA_BERRY), gStringVar1);
+
+ return hasItem;
+}
+
+void CreateScriptedWildMon(u16 species, u8 level, u16 item)
+{
+ u8 heldItem[2];
+
+ ZeroEnemyPartyMons();
+ CreateMon(&gEnemyParty[0], species, level, 0x20, 0, 0, 0, 0);
+
+ if(item)
+ {
+ heldItem[0] = item;
+ heldItem[1] = item >> 8;
+ SetMonData(&gEnemyParty[0], MON_DATA_HELD_ITEM, heldItem);
+ }
+}
+
+void ScriptSetMonMoveSlot(u8 monIndex, u16 move, u8 slot)
+{
+ if(monIndex > 6)
+ monIndex = gPlayerPartyCount - 1;
+
+ SetMonMoveSlot(&gPlayerParty[monIndex], move, slot);
+}
+
+void sub_80C5568(void)
+{
+ gMain.savedCallback = sub_80C5580;
+ sub_8121E10();
+}
+
+void sub_80C5580(void)
+{
+ u8 var = gSelectedOrderFromParty[0];
+
+ switch(var)
+ {
+ case 0:
+ gSpecialVar_Result = 0;
+ break;
+ default:
+ gSpecialVar_Result = 1;
+ break;
+ }
+
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+}
+
+void ChooseBattleTowerPlayerParty(void)
+{
+ gMain.savedCallback = SetBattleTowerPlayerParty;
+ sub_8121E34();
+}
+
+void SetBattleTowerPlayerParty(void)
+{
+ u8 var = gSelectedOrderFromParty[0];
+
+ switch(var)
+ {
+ case 0: // player quit battle tower?
+ LoadPlayerParty();
+ gSpecialVar_Result = 0;
+ break;
+ default: // load battle tower.
+ ReducePlayerPartyToThree();
+ gSpecialVar_Result = 1;
+ break;
+ }
+
+ SetMainCallback2(CB2_ReturnToFieldContinueScriptPlayMapMusic);
+}
+
+void ReducePlayerPartyToThree(void)
+{
+ struct Pokemon party[3];
+ int i;
+
+ CpuFill32(0, party, sizeof party);
+
+ // copy the selected pokemon according to the order.
+ for(i = 0; i < 3; i++)
+ if(gSelectedOrderFromParty[i]) // as long as the order keeps going (did the player select 1 mon? 2? 3?), do not stop
+ party[i] = gPlayerParty[gSelectedOrderFromParty[i] - 1]; // index is 0 based, not literal
+
+ // delete the last 3 pokemon
+ CpuFill32(0, gPlayerParty, sizeof gPlayerParty);
+
+ // overwrite the first 3 with the order copied to.
+ for(i = 0; i < 3; i++)
+ gPlayerParty[i] = party[i];
+
+ CalculatePlayerPartyCount();
+}