#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(); }