Add functionality to Poké Flute and Town Map (#5405)

* Add functionality to Poké Flute and Town Map

* Poke flute in-battle

* Address reviews

* Update item_use.c

* Update battle_message.c

* Update battle_script_commands.c

* Update battle_script_commands.c

* Update battle_script_commands.c

* Update battle_script_commands.c

* Update battle_script_commands.c

* Update battle_script_commands.c
This commit is contained in:
kittenchilly 2024-10-03 03:52:59 -05:00 committed by GitHub
parent f082fe7e42
commit 44bf14e6fd
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
12 changed files with 190 additions and 9 deletions

View file

@ -1731,6 +1731,14 @@
.4byte \jumpInstr
.endm
.macro checkpokeflute
callnative BS_CheckPokeFlute
.endm
.macro waitfanfare
callnative BS_WaitFanfare
.endm
@ various command changed to more readable macros
.macro cancelmultiturnmoves battler:req
various \battler, VARIOUS_CANCEL_MULTI_TURN_MOVES

View file

@ -25,6 +25,7 @@ gBattlescriptsForUsingItem::
.4byte BattleScript_ItemRestoreHP @ EFFECT_ITEM_REVIVE
.4byte BattleScript_ItemRestorePP @ EFFECT_ITEM_RESTORE_PP
.4byte BattleScript_ItemIncreaseAllStats @ EFFECT_ITEM_INCREASE_ALL_STATS
.4byte BattleScript_UsePokeFlute @ EFFECT_ITEM_USE_POKE_FLUTE
.align 2
gBattlescriptsForSafariActions::
@ -110,6 +111,25 @@ BattleScript_ItemIncreaseStat::
waitmessage B_WAIT_TIME_LONG
end
BattleScript_UsePokeFlute::
checkpokeflute
jumpifbyte CMP_EQUAL, cMULTISTRING_CHOOSER, 1, BattleScript_PokeFluteWakeUp
printstring STRINGID_POKEFLUTECATCHY
waitmessage B_WAIT_TIME_LONG
goto BattleScript_PokeFluteEnd
BattleScript_PokeFluteWakeUp::
printstring STRINGID_POKEFLUTE
waitmessage B_WAIT_TIME_LONG
fanfare MUS_RG_POKE_FLUTE
waitfanfare
printstring STRINGID_MONHEARINGFLUTEAWOKE
waitmessage B_WAIT_TIME_LONG
updatestatusicon BS_PLAYER2
waitstate
BattleScript_PokeFluteEnd::
finishaction
BattleScript_ItemSetMist::
call BattleScript_UseItemMessage
setmist

View file

@ -713,8 +713,11 @@
#define STRINGID_PKMNMADESHELLGLEAM 711
#define STRINGID_FICKLEBEAMDOUBLED 712
#define STRINGID_COMMANDERACTIVATES 713
#define STRINGID_POKEFLUTECATCHY 714
#define STRINGID_POKEFLUTE 715
#define STRINGID_MONHEARINGFLUTEAWOKE 716
#define BATTLESTRINGS_COUNT 714
#define BATTLESTRINGS_COUNT 717
// This is the string id that gBattleStringsTable starts with.
// String ids before this (e.g. STRINGID_INTROMSG) are not in the table,

View file

@ -1077,6 +1077,7 @@
#define EFFECT_ITEM_REVIVE 9
#define EFFECT_ITEM_RESTORE_PP 10
#define EFFECT_ITEM_INCREASE_ALL_STATS 11
#define EFFECT_ITEM_USE_POKE_FLUTE 12
// Enigma Berry dummy constant
#define EFFECT_ITEM_ENIGMA_BERRY_EREADER 1

View file

@ -47,6 +47,8 @@ u8 CheckIfItemIsTMHMOrEvolutionStone(u16 itemId);
void FieldUseFunc_VsSeeker(u8 taskId);
void Task_ItemUse_CloseMessageBoxAndReturnToField_VsSeeker(u8 taskId);
void DisplayDadsAdviceCannotUseItemMessage(u8 taskId, bool8 isUsingRegisteredKeyItemOnField);
void ItemUseOutOfBattle_PokeFlute(u8 taskId);
void ItemUseOutOfBattle_TownMap(u8 taskId);
enum {
BALL_THROW_UNABLE_TWO_MONS,

View file

@ -833,6 +833,9 @@ extern const u8 gText_UsedVar2WildRepelled[];
extern const u8 gText_BoxFull[];
extern const u8 gText_WontHaveEffect[];
extern const u8 gText_NextFusionMon[];
extern const u8 gText_PlayedPokeFluteCatchy[];
extern const u8 gText_PlayedPokeFlute[];
extern const u8 gText_PokeFluteAwakenedMon[];
extern const u8 gText_LevelSymbol[];
extern const u8 gText_PkmnInfo[];

View file

@ -2244,6 +2244,10 @@ static bool32 ShouldUseItem(u32 battler)
if (gBattleStruct->itemPartyIndex[battler] != PARTY_SIZE) // Revive if possible.
shouldUse = TRUE;
break;
case EFFECT_ITEM_USE_POKE_FLUTE:
if (gBattleMons[battler].status1 & STATUS1_SLEEP)
shouldUse = TRUE;
break;
default:
return FALSE;
}

View file

@ -517,6 +517,9 @@ static const u8 sText_PkmnsItemRestoredHPALittle[] = _("{B_SCR_ACTIVE_NAME_WITH_
static const u8 sText_ItemAllowsOnlyYMove[] = _("{B_LAST_ITEM} allows the\nuse of only {B_CURRENT_MOVE}!\p");
static const u8 sText_PkmnHungOnWithX[] = _("{B_DEF_NAME_WITH_PREFIX} hung on\nusing its {B_LAST_ITEM}!");
const u8 gText_EmptyString3[] = _("");
static const u8 sText_PlayedFluteCatchyTune[] = _("{B_PLAYER_NAME} played the {B_LAST_ITEM}.\pNow, that's a catchy tune!");
static const u8 sText_PlayedThe[] = _("{B_PLAYER_NAME} played the\n{B_LAST_ITEM}.");
static const u8 sText_PkmnHearingFluteAwoke[] = _("The POKéMON hearing the FLUTE\nawoke!");
static const u8 sText_YouThrowABallNowRight[] = _("You throw a BALL now, right?\nI… I'll do my best!");
// early declaration of strings
@ -1555,6 +1558,9 @@ const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] =
[STRINGID_ITEMWASUSEDUP - BATTLESTRINGS_TABLE_START] = sText_ItemWasUsedUp,
[STRINGID_ATTACKERLOSTITSTYPE - BATTLESTRINGS_TABLE_START] = sText_AttackerLostItsType,
[STRINGID_CLOAKEDINAHARSHLIGHT - BATTLESTRINGS_TABLE_START] = sText_PkmnIsCloakedInAHarshLight,
[STRINGID_POKEFLUTECATCHY - BATTLESTRINGS_TABLE_START] = sText_PlayedFluteCatchyTune,
[STRINGID_POKEFLUTE - BATTLESTRINGS_TABLE_START] = sText_PlayedThe,
[STRINGID_MONHEARINGFLUTEAWOKE - BATTLESTRINGS_TABLE_START] = sText_PkmnHearingFluteAwoke,
};
const u16 gTrainerUsedItemStringIds[] =

View file

@ -12556,14 +12556,19 @@ static void Cmd_updatestatusicon(void)
if (gBattleControllerExecFlags)
return;
if (cmd->battler != BS_ATTACKER_WITH_PARTNER)
if (cmd->battler == BS_PLAYER2)
{
battler = GetBattlerForBattleScript(cmd->battler);
BtlController_EmitStatusIconUpdate(battler, BUFFER_A, gBattleMons[battler].status1, gBattleMons[battler].status2);
MarkBattlerForControllerExec(battler);
for (battler = gBattleControllerExecFlags; battler < gBattlersCount; battler++)
{
if (!(gAbsentBattlerFlags & (1u << battler)))
{
BtlController_EmitStatusIconUpdate(battler, BUFFER_A, gBattleMons[battler].status1, gBattleMons[battler].status2);
MarkBattlerForControllerExec(battler);
}
}
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
else if (cmd->battler == BS_ATTACKER_WITH_PARTNER)
{
battler = gBattlerAttacker;
if (!(gAbsentBattlerFlags & (1u << battler)))
@ -12582,6 +12587,13 @@ static void Cmd_updatestatusicon(void)
}
gBattlescriptCurrInstr = cmd->nextInstr;
}
else
{
battler = GetBattlerForBattleScript(cmd->battler);
BtlController_EmitStatusIconUpdate(battler, BUFFER_A, gBattleMons[battler].status1, gBattleMons[battler].status2);
MarkBattlerForControllerExec(battler);
gBattlescriptCurrInstr = cmd->nextInstr;
}
}
static void Cmd_setmist(void)
@ -17425,3 +17437,62 @@ void BS_JumpIfCommanderActive(void)
else
gBattlescriptCurrInstr = cmd->nextInstr;
}
static void UpdatePokeFlutePartyStatus(struct Pokemon* party, u8 position)
{
s32 i;
u8 battler;
u32 monToCheck, status;
u16 species, abilityNum;
monToCheck = 0;
for (i = 0; i < PARTY_SIZE; i++)
{
species = GetMonData(&party[i], MON_DATA_SPECIES_OR_EGG);
abilityNum = GetMonData(&party[i], MON_DATA_ABILITY_NUM);
status = GetMonData(&party[i], MON_DATA_STATUS);
if (species != SPECIES_NONE
&& species != SPECIES_EGG
&& status & AILMENT_FNT
&& GetAbilityBySpecies(species, abilityNum) != ABILITY_SOUNDPROOF)
monToCheck |= (1 << i);
}
if (monToCheck)
{
battler = GetBattlerAtPosition(position);
status = 0;
BtlController_EmitSetMonData(battler, BUFFER_A, REQUEST_STATUS_BATTLE, monToCheck, 4, &status);
MarkBattlerForControllerExec(battler);
gBattleCommunication[MULTISTRING_CHOOSER] = 1;
}
}
void BS_CheckPokeFlute(void)
{
NATIVE_ARGS();
gBattleCommunication[MULTISTRING_CHOOSER] = 0;
s32 i;
for (i = 0; i < gBattlersCount; i++)
{
if (GetBattlerAbility(i) != ABILITY_SOUNDPROOF)
{
gBattleMons[i].status1 &= ~STATUS1_SLEEP;
gBattleMons[i].status2 &= ~STATUS2_NIGHTMARE;
}
}
UpdatePokeFlutePartyStatus(gPlayerParty, B_POSITION_PLAYER_LEFT);
UpdatePokeFlutePartyStatus(gEnemyParty, B_POSITION_OPPONENT_LEFT);
gBattlescriptCurrInstr = cmd->nextInstr;
}
void BS_WaitFanfare(void)
{
NATIVE_ARGS();
if (!IsFanfareTaskInactive())
return;
gBattlescriptCurrInstr = cmd->nextInstr;
}

View file

@ -12262,7 +12262,7 @@ const struct Item gItemsInfo[] =
.importance = 1,
.pocket = POCKET_KEY_ITEMS,
.type = ITEM_USE_BAG_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
.fieldUseFunc = ItemUseOutOfBattle_TownMap,
.iconPic = gItemIcon_TownMap,
.iconPalette = gItemIconPalette_TownMap,
},
@ -12442,7 +12442,8 @@ const struct Item gItemsInfo[] =
.importance = 1,
.pocket = POCKET_KEY_ITEMS,
.type = ITEM_USE_BAG_MENU,
.fieldUseFunc = ItemUseOutOfBattle_CannotUse,
.fieldUseFunc = ItemUseOutOfBattle_PokeFlute,
.battleUsage = EFFECT_ITEM_USE_POKE_FLUTE,
.iconPic = gItemIcon_PokeFlute,
.iconPalette = gItemIconPalette_PokeFlute,
},

View file

@ -1284,7 +1284,7 @@ void ItemUseInBattle_BagMenu(u8 taskId)
else
{
PlaySE(SE_SELECT);
if (!(B_TRY_CATCH_TRAINER_BALL >= GEN_4 && (ItemId_GetBattleUsage(gSpecialVar_ItemId) == EFFECT_ITEM_THROW_BALL) && (gBattleTypeFlags & BATTLE_TYPE_TRAINER)))
if (!ItemId_GetImportance(gSpecialVar_ItemId) && !(B_TRY_CATCH_TRAINER_BALL >= GEN_4 && (ItemId_GetBattleUsage(gSpecialVar_ItemId) == EFFECT_ITEM_THROW_BALL) && (gBattleTypeFlags & BATTLE_TYPE_TRAINER)))
RemoveUsedItem();
ScheduleBgCopyTilemapToVram(2);
if (!InBattlePyramid())
@ -1499,4 +1499,63 @@ void Task_ItemUse_CloseMessageBoxAndReturnToField_VsSeeker(u8 taskId)
Task_CloseCantUseKeyItemMessage(taskId);
}
static void Task_DisplayPokeFluteMessage(u8 taskId)
{
if (WaitFanfare(FALSE))
{
if (gTasks[taskId].data[3] == 0)
DisplayItemMessage(taskId, FONT_NORMAL, gText_PokeFluteAwakenedMon, CloseItemMessage);
else
DisplayItemMessageOnField(taskId, gText_PokeFluteAwakenedMon, Task_CloseCantUseKeyItemMessage);
}
}
static void Task_PlayPokeFlute(u8 taskId)
{
PlayFanfareByFanfareNum(FANFARE_RG_POKE_FLUTE);
gTasks[taskId].func = Task_DisplayPokeFluteMessage;
}
void ItemUseOutOfBattle_PokeFlute(u8 taskId)
{
bool32 wokeSomeoneUp = FALSE;
u32 i;
for (i = 0; i < CalculatePlayerPartyCount(); i++)
{
if (!ExecuteTableBasedItemEffect(&gPlayerParty[i], ITEM_AWAKENING, i, 0))
wokeSomeoneUp = TRUE;
}
if (wokeSomeoneUp)
{
if (gTasks[taskId].data[3] == 0)
DisplayItemMessage(taskId, FONT_NORMAL, gText_PlayedPokeFlute, Task_PlayPokeFlute);
else
DisplayItemMessageOnField(taskId, gText_PlayedPokeFlute, Task_PlayPokeFlute);
}
else
{
if (gTasks[taskId].data[3] == 0)
DisplayItemMessage(taskId, FONT_NORMAL, gText_PlayedPokeFluteCatchy, CloseItemMessage);
else
DisplayItemMessageOnField(taskId, gText_PlayedPokeFluteCatchy, Task_CloseCantUseKeyItemMessage);
}
}
static void ItemUseOnFieldCB_TownMap(u8 taskId)
{
LockPlayerFieldControls();
ScriptContext_SetupScript(EventScript_RegionMap);
DestroyTask(taskId);
}
void ItemUseOutOfBattle_TownMap(u8 taskId)
{
sItemUseOnFieldCB = ItemUseOnFieldCB_TownMap;
gFieldCallback = FieldCB_UseItemOnField;
gBagMenu->newScreenCallback = CB2_ReturnToField;
Task_FadeAndCloseBagMenu(taskId);
}
#undef tUsingRegisteredKeyItem

View file

@ -196,6 +196,9 @@ const u8 gText_TheBattle[] = _("the battle");
const u8 gText_ThePokemonList[] = _("the POKéMON LIST");
const u8 gText_TheShop[] = _("the shop");
const u8 gText_ThePC[] = _("the PC");
const u8 gText_PlayedPokeFluteCatchy[] = _("Played the POKé FLUTE.\pNow, that's a catchy tune!{PAUSE_UNTIL_PRESS}");
const u8 gText_PlayedPokeFlute[] = _("Played the POKé FLUTE.");
const u8 gText_PokeFluteAwakenedMon[] = _("The POKé FLUTE awakened sleeping\nPOKéMON.{PAUSE_UNTIL_PRESS}");
const u8 *const gBagMenu_ReturnToStrings[] =
{