diff options
Diffstat (limited to 'src/contest_util.c')
-rw-r--r-- | src/contest_util.c | 578 |
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(); +} |