diff --git a/charmap.txt b/charmap.txt index 8e0493408d..a377636d32 100644 --- a/charmap.txt +++ b/charmap.txt @@ -407,6 +407,8 @@ B_ATK_TEAM2 = FD 38 B_DEF_NAME = FD 39 B_DEF_TEAM1 = FD 3A B_DEF_TEAM2 = FD 3B +B_ACTIVE_NAME = FD 3C +B_ACTIVE_NAME2 = FD 3D @ no Illusion check @ indicates the end of a town/city name (before " TOWN" or " CITY") NAME_END = FC 00 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index e5c8f18b58..caffaa1553 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -4946,6 +4946,7 @@ BattleScript_FaintedMonTryChooseAnother: jumpifword CMP_COMMON_BITS, gHitMarker, HITMARKER_x400000, BattleScript_FaintedMonChooseAnother jumpifbyte CMP_EQUAL, sBATTLE_STYLE, 0x1, BattleScript_FaintedMonChooseAnother jumpifcantswitch BS_PLAYER1, BattleScript_FaintedMonChooseAnother + setbyte sILLUSION_NICK_HACK, 1 printstring STRINGID_ENEMYABOUTTOSWITCHPKMN setbyte gBattleCommunication, 0x0 yesnobox diff --git a/include/battle.h b/include/battle.h index 520b4c136d..cb514f764c 100644 --- a/include/battle.h +++ b/include/battle.h @@ -429,9 +429,10 @@ struct MegaEvolutionData struct Illusion { - u8 on:1; - u8 broken:1; - u8 partyId:3; + u8 on; + u8 set; + u8 broken; + u8 partyId; struct Pokemon *mon; }; @@ -616,6 +617,7 @@ struct BattleScripting u16 savedMoveEffect; // For moves hitting multiple targets. u16 moveEffect; u16 multihitMoveEffect; + u8 illusionNickHack; // To properly display nick in STRINGID_ENEMYABOUTTOSWITCHPKMN. }; // rom_80A5C6C diff --git a/include/battle_message.h b/include/battle_message.h index 0236cc7934..89dce66df4 100644 --- a/include/battle_message.h +++ b/include/battle_message.h @@ -64,6 +64,8 @@ #define B_TXT_DEF_NAME 0x39 #define B_TXT_DEF_TEAM1 0x3A // Your/The opposing #define B_TXT_DEF_TEAM2 0x3B // your/the opposing +#define B_TXT_ACTIVE_NAME 0x3C +#define B_TXT_ACTIVE_NAME2 0x3D // no Illusion check // for B_TXT_BUFF1, B_TXT_BUFF2 and B_TXT_BUFF3 diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index 364aad8e5d..7173b17dbf 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -34,6 +34,7 @@ #define sSAVED_MOVE_EFFECT gBattleScripting + 0x2C #define sMOVE_EFFECT gBattleScripting + 0x2E #define sMULTIHIT_EFFECT gBattleScripting + 0x30 +#define sILLUSION_NICK_HACK gBattleScripting + 0x32 #define cMULTISTRING_CHOOSER gBattleCommunication + 5 diff --git a/src/battle_gfx_sfx_util.c b/src/battle_gfx_sfx_util.c index 24366d9de2..1020d1f437 100644 --- a/src/battle_gfx_sfx_util.c +++ b/src/battle_gfx_sfx_util.c @@ -411,7 +411,7 @@ bool8 TryHandleLaunchBattleTableAnimation(u8 activeBattler, u8 atkBattler, u8 de } if (tableId == B_ANIM_ILLUSION_OFF) - ClearIllusionMon(activeBattler); + gBattleStruct->illusion[activeBattler].broken = 1; gBattleAnimAttacker = atkBattler; gBattleAnimTarget = defBattler; @@ -1158,11 +1158,6 @@ void ClearTemporarySpeciesSpriteData(u8 battlerId, bool8 dontClearSubstitute) gBattleMonForms[battlerId] = 0; if (!dontClearSubstitute) ClearBehindSubstituteBit(battlerId); - - if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) - SetIllusionMon(&gPlayerParty[gBattlerPartyIndexes[battlerId]], battlerId); - else - SetIllusionMon(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId); } void AllocateMonSpritesGfx(void) diff --git a/src/battle_main.c b/src/battle_main.c index ae4c87d831..085dfb2b07 100644 --- a/src/battle_main.c +++ b/src/battle_main.c @@ -2971,6 +2971,7 @@ void SwitchInClearSetData(void) s32 i; struct DisableStruct disableStructCopy = gDisableStructs[gActiveBattler]; + ClearIllusionMon(gActiveBattler); if (gBattleMoves[gCurrentMove].effect != EFFECT_BATON_PASS) { for (i = 0; i < NUM_BATTLE_STATS; i++) diff --git a/src/battle_message.c b/src/battle_message.c index ccc9b5e64f..738c90180b 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -19,6 +19,7 @@ #include "text.h" #include "trainer_hill.h" #include "window.h" +#include "constants/abilities.h" #include "constants/battle_string_ids.h" #include "constants/frontier_util.h" #include "constants/items.h" @@ -1529,7 +1530,7 @@ const u8 gText_PkmnIsEvolving[] = _("What?\n{STR_VAR_1} is evolving!"); const u8 gText_CongratsPkmnEvolved[] = _("Congratulations! Your {STR_VAR_1}\nevolved into {STR_VAR_2}!{WAIT_SE}\p"); const u8 gText_PkmnStoppedEvolving[] = _("Huh? {STR_VAR_1}\nstopped evolving!\p"); const u8 gText_EllipsisQuestionMark[] = _("……?\p"); -const u8 gText_WhatWillPkmnDo[] = _("What will\n{B_ACTIVE_NAME_WITH_PREFIX} do?"); +const u8 gText_WhatWillPkmnDo[] = _("What will\n{B_ACTIVE_NAME2} do?"); const u8 gText_WhatWillPkmnDo2[] = _("What will\n{B_PLAYER_NAME} do?"); const u8 gText_WhatWillWallyDo[] = _("What will\nWALLY do?"); const u8 gText_LinkStandby[] = _("{PAUSE 16}Link standby…"); @@ -2919,6 +2920,18 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) GetBattlerNick(gBattlerTarget, text); toCpy = text; break; + case B_TXT_ACTIVE_NAME: // active name + GetBattlerNick(gActiveBattler, text); + toCpy = text; + break; + case B_TXT_ACTIVE_NAME2: // active battlerId name with prefix, no illusion + if (GetBattlerSide(gActiveBattler) == B_SIDE_PLAYER) + GetMonData(&gPlayerParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_NICKNAME, text); + else + GetMonData(&gEnemyParty[gBattlerPartyIndexes[gActiveBattler]], MON_DATA_NICKNAME, text); + StringGetEnd10(text); + toCpy = text; + break; case B_TXT_EFF_NAME_WITH_PREFIX: // effect battlerId name with prefix HANDLE_NICKNAME_STRING_CASE(gEffectBattler) break; @@ -3234,6 +3247,37 @@ u32 BattleStringExpandPlaceholders(const u8 *src, u8 *dst) return dstID; } +static void IllusionNickHack(u32 battlerId, u32 partyId, u8 *dst) +{ + s32 id, i; + // we know it's gEnemyParty + struct Pokemon *mon = &gEnemyParty[partyId], *partnerMon; + + if (GetMonAbility(mon) == ABILITY_ILLUSION) + { + if (IsBattlerAlive(BATTLE_PARTNER(battlerId))) + partnerMon = &gEnemyParty[gBattlerPartyIndexes[BATTLE_PARTNER(battlerId)]]; + else + partnerMon = mon; + + // Find last alive non-egg pokemon. + for (i = PARTY_SIZE - 1; i >= 0; i--) + { + id = i; + if (GetMonData(&gEnemyParty[id], MON_DATA_SANITY_HAS_SPECIES) + && GetMonData(&gEnemyParty[id], MON_DATA_HP) + && &gEnemyParty[id] != mon + && &gEnemyParty[id] != partnerMon) + { + GetMonData(&gEnemyParty[id], MON_DATA_NICKNAME, dst); + return; + } + } + } + + GetMonData(mon, MON_DATA_NICKNAME, dst); +} + static void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst) { u32 srcID = 1; @@ -3306,6 +3350,12 @@ static void ExpandBattleTextBuffPlaceholders(const u8 *src, u8 *dst) { GetBattlerNick(src[srcID + 1], dst); } + else if (gBattleScripting.illusionNickHack) // for STRINGID_ENEMYABOUTTOSWITCHPKMN + { + gBattleScripting.illusionNickHack = 0; + IllusionNickHack(src[srcID + 1], src[srcID + 2], dst); + StringGetEnd10(dst); + } else { if (GetBattlerSide(src[srcID + 1]) == B_SIDE_PLAYER) diff --git a/src/battle_util.c b/src/battle_util.c index 716e568478..f510f264ea 100644 --- a/src/battle_util.c +++ b/src/battle_util.c @@ -3802,7 +3802,7 @@ u8 AbilityBattleEffects(u8 caseID, u8 battler, u8 ability, u8 special, u16 moveA } break; case ABILITY_ILLUSION: - if (gBattleStruct->illusion[battler].on && !gBattleStruct->illusion[battler].broken && IsBattlerAlive(battler) && TARGET_TURN_DAMAGED) + if (gBattleStruct->illusion[gBattlerTarget].on && !gBattleStruct->illusion[gBattlerTarget].broken && TARGET_TURN_DAMAGED) { BattleScriptPushCursor(); gBattlescriptCurrInstr = BattleScript_IllusionOff; @@ -6750,7 +6750,16 @@ bool32 CanBattlerGetOrLoseItem(u8 battlerId, u16 itemId) struct Pokemon *GetIllusionMonPtr(u32 battlerId) { - if (!gBattleStruct->illusion[battlerId].on || gBattleStruct->illusion[battlerId].broken) + if (gBattleStruct->illusion[battlerId].broken) + return NULL; + if (!gBattleStruct->illusion[battlerId].set) + { + if (GetBattlerSide(battlerId) == B_SIDE_PLAYER) + SetIllusionMon(&gPlayerParty[gBattlerPartyIndexes[battlerId]], battlerId); + else + SetIllusionMon(&gEnemyParty[gBattlerPartyIndexes[battlerId]], battlerId); + } + if (!gBattleStruct->illusion[battlerId].on) return NULL; return gBattleStruct->illusion[battlerId].mon; @@ -6758,9 +6767,7 @@ struct Pokemon *GetIllusionMonPtr(u32 battlerId) void ClearIllusionMon(u32 battlerId) { - gBattleStruct->illusion[battlerId].on = 0; - gBattleStruct->illusion[battlerId].mon = NULL; - gBattleStruct->illusion[battlerId].broken = 1; + memset(&gBattleStruct->illusion[battlerId], 0, sizeof(gBattleStruct->illusion[battlerId])); } bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId) @@ -6768,6 +6775,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId) struct Pokemon *party, *partnerMon; s32 i, id; + gBattleStruct->illusion[battlerId].set = 1; if (GetMonAbility(mon) != ABILITY_ILLUSION) return FALSE; @@ -6784,7 +6792,7 @@ bool32 SetIllusionMon(struct Pokemon *mon, u32 battlerId) // Find last alive non-egg pokemon. for (i = PARTY_SIZE - 1; i >= 0; i--) { - id = GetPartyIdFromBattlePartyId(i); + id = i; if (GetMonData(&party[id], MON_DATA_SANITY_HAS_SPECIES) && GetMonData(&party[id], MON_DATA_HP) && &party[id] != mon