diff --git a/asm/macros/battle_script.inc b/asm/macros/battle_script.inc index 1405dd2582..5cef3c769e 100644 --- a/asm/macros/battle_script.inc +++ b/asm/macros/battle_script.inc @@ -1778,6 +1778,10 @@ various \battler, VARIOUS_SET_BEAK_BLAST .endm + .macro swapsidestatuses + various BS_ATTACKER, VARIOUS_SWAP_SIDE_STATUSES + .endm + @ helpful macros .macro setstatchanger stat:req, stages:req, down:req setbyte sSTATCHANGER \stat | \stages << 3 | \down << 7 diff --git a/data/battle_scripts_1.s b/data/battle_scripts_1.s index 6f074b6643..bf501678c2 100644 --- a/data/battle_scripts_1.s +++ b/data/battle_scripts_1.s @@ -376,6 +376,19 @@ gBattleScriptsForMoveEffects:: @ 82D86A8 .4byte BattleScript_EffectCorrosiveGas .4byte BattleScript_EffectBeakBlast .4byte BattleScript_EffectTerrainPulse + .4byte BattleScript_EffectCourtChange + +BattleScript_EffectCourtChange:: + attackcanceler + accuracycheck BattleScript_PrintMoveMissed, ACC_CURR_MOVE + attackstring + ppreduce + swapsidestatuses + attackanimation + waitanimation + printstring STRINGID_COURTCHANGE + waitmessage 0x40 + goto BattleScript_MoveEnd BattleScript_EffectBeakBlast:: attackcanceler diff --git a/include/constants/battle_move_effects.h b/include/constants/battle_move_effects.h index d975da2fb0..b6ad6e487f 100644 --- a/include/constants/battle_move_effects.h +++ b/include/constants/battle_move_effects.h @@ -360,7 +360,8 @@ #define EFFECT_CORROSIVE_GAS 354 #define EFFECT_BEAK_BLAST 355 #define EFFECT_TERRAIN_PULSE 356 +#define EFFECT_COURT_CHANGE 357 -#define NUM_BATTLE_MOVE_EFFECTS 357 +#define NUM_BATTLE_MOVE_EFFECTS 358 #endif // GUARD_CONSTANTS_BATTLE_MOVE_EFFECTS_H diff --git a/include/constants/battle_script_commands.h b/include/constants/battle_script_commands.h index ea96e6b4d7..8ae661af38 100644 --- a/include/constants/battle_script_commands.h +++ b/include/constants/battle_script_commands.h @@ -175,6 +175,7 @@ #define VARIOUS_TRY_ACTIVATE_GRIM_NEIGH 104 #define VARIOUS_TRY_SET_CORROSIVE_GAS 105 #define VARIOUS_SET_BEAK_BLAST 106 +#define VARIOUS_SWAP_SIDE_STATUSES 107 // Cmd_manipulatedamage #define DMG_CHANGE_SIGN 0 diff --git a/include/constants/battle_string_ids.h b/include/constants/battle_string_ids.h index 698b7e595f..cfe25be1b0 100644 --- a/include/constants/battle_string_ids.h +++ b/include/constants/battle_string_ids.h @@ -574,8 +574,9 @@ #define STRINGID_METEORBEAMCHARGING 570 #define STRINGID_ITEMMELTED 571 #define STRINGID_HEATUPBEAK 572 +#define STRINGID_COURTCHANGE 573 -#define BATTLESTRINGS_COUNT 573 +#define BATTLESTRINGS_COUNT 574 // The below IDs are all indexes into battle message tables, // used to determine which of a set of messages to print. diff --git a/src/battle_message.c b/src/battle_message.c index d2ae86e134..2a9d80424d 100644 --- a/src/battle_message.c +++ b/src/battle_message.c @@ -700,9 +700,11 @@ static const u8 sText_PkmnGotOverItsInfatuation[] = _("{B_SCR_ACTIVE_NAME_WITH_P static const u8 sText_MeteorBeamCharging[] = _("{B_ATK_NAME_WITH_PREFIX} is overflowing\nwith space energy!"); static const u8 sText_PkmnItemMelted[] = _("{B_ATK_NAME_WITH_PREFIX} corroded\n{B_DEF_NAME_WITH_PREFIX}'s {B_LAST_ITEM}!"); static const u8 sText_HeatingUpBeak[] = _("{B_ATK_NAME_WITH_PREFIX} started\nheating up its beak!"); +static const u8 sText_CourtChange[] = _("{B_ATK_NAME_WITH_PREFIX} swapped the battle\neffects affecting each side!"); const u8 *const gBattleStringsTable[BATTLESTRINGS_COUNT] = { + [STRINGID_COURTCHANGE - 12] = sText_CourtChange, [STRINGID_HEATUPBEAK - 12] = sText_HeatingUpBeak, [STRINGID_ITEMMELTED - 12] = sText_PkmnItemMelted, [STRINGID_METEORBEAMCHARGING - 12] = sText_MeteorBeamCharging, diff --git a/src/battle_script_commands.c b/src/battle_script_commands.c index 0565f06d11..3e91205ac1 100644 --- a/src/battle_script_commands.c +++ b/src/battle_script_commands.c @@ -8467,6 +8467,169 @@ static void Cmd_various(void) case VARIOUS_SET_BEAK_BLAST: gProtectStructs[gActiveBattler].beakBlastCharge = 1; break; + case VARIOUS_SWAP_SIDE_STATUSES: + /* This code is a mess, but idk how to do it better without changing how Side Statuses and + Side timers work. + The problem is that not all side statuses are affected by Court Change*/ + + //todo: add pledge related effects + //todo: add gigamax related effects + + //swap side status sides + bits = gSideStatuses[0]; //Stores sides status temp + + //Reflect + if (gSideStatuses[1] & SIDE_STATUS_REFLECT) + gSideStatuses[0] |= SIDE_STATUS_REFLECT; + else + gSideStatuses[0] &= ~(SIDE_STATUS_REFLECT); + + if (bits & SIDE_STATUS_REFLECT) + gSideStatuses[1] |= SIDE_STATUS_REFLECT; + else + gSideStatuses[1] &= ~(SIDE_STATUS_REFLECT); + + //Light screen + if (gSideStatuses[1] & SIDE_STATUS_LIGHTSCREEN) + gSideStatuses[0] |= SIDE_STATUS_LIGHTSCREEN; + else + gSideStatuses[0] &= ~(SIDE_STATUS_LIGHTSCREEN); + + if (bits & SIDE_STATUS_LIGHTSCREEN) + gSideStatuses[1] |= SIDE_STATUS_LIGHTSCREEN; + else + gSideStatuses[1] &= ~(SIDE_STATUS_LIGHTSCREEN); + + //Safeguard + if (gSideStatuses[1] & SIDE_STATUS_SAFEGUARD) + gSideStatuses[0] |= SIDE_STATUS_SAFEGUARD; + else + gSideStatuses[0] &= ~(SIDE_STATUS_SAFEGUARD); + + if (bits & SIDE_STATUS_SAFEGUARD) + gSideStatuses[1] |= SIDE_STATUS_SAFEGUARD; + else + gSideStatuses[1] &= ~(SIDE_STATUS_SAFEGUARD); + + //Mist + if (gSideStatuses[1] & SIDE_STATUS_MIST) + gSideStatuses[0] |= SIDE_STATUS_MIST; + else + gSideStatuses[0] &= ~(SIDE_STATUS_MIST); + + if (bits & SIDE_STATUS_MIST) + gSideStatuses[1] |= SIDE_STATUS_MIST; + else + gSideStatuses[1] &= ~(SIDE_STATUS_MIST); + + //AuroraVeil + if (gSideStatuses[1] & SIDE_STATUS_AURORA_VEIL) + gSideStatuses[0] |= SIDE_STATUS_AURORA_VEIL; + else + gSideStatuses[0] &= ~(SIDE_STATUS_AURORA_VEIL); + + if (bits & SIDE_STATUS_AURORA_VEIL) + gSideStatuses[1] |= SIDE_STATUS_AURORA_VEIL; + else + gSideStatuses[1] &= ~(SIDE_STATUS_AURORA_VEIL); + + //Sticky Web + if (gSideStatuses[1] & SIDE_STATUS_STICKY_WEB) + gSideStatuses[0] |= SIDE_STATUS_STICKY_WEB; + else + gSideStatuses[0] &= ~(SIDE_STATUS_STICKY_WEB); + + if (bits & SIDE_STATUS_STICKY_WEB) + gSideStatuses[1] |= SIDE_STATUS_STICKY_WEB; + else + gSideStatuses[1] &= ~(SIDE_STATUS_STICKY_WEB); + + //Spikes + if (gSideStatuses[1] & SIDE_STATUS_SPIKES) + gSideStatuses[0] |= SIDE_STATUS_SPIKES; + else + gSideStatuses[0] &= ~(SIDE_STATUS_SPIKES); + + if (bits & SIDE_STATUS_SPIKES) + gSideStatuses[1] |= SIDE_STATUS_SPIKES; + else + gSideStatuses[1] &= ~(SIDE_STATUS_SPIKES); + + //Toxic Spikes + if (gSideStatuses[1] & SIDE_STATUS_TOXIC_SPIKES) + gSideStatuses[0] |= SIDE_STATUS_TOXIC_SPIKES; + else + gSideStatuses[0] &= ~(SIDE_STATUS_TOXIC_SPIKES); + + if (bits & SIDE_STATUS_TOXIC_SPIKES) + gSideStatuses[1] |= SIDE_STATUS_TOXIC_SPIKES; + else + gSideStatuses[1] &= ~(SIDE_STATUS_TOXIC_SPIKES); + + //Stealth Rock + if (gSideStatuses[1] & SIDE_STATUS_STEALTH_ROCK) + gSideStatuses[0] |= SIDE_STATUS_STEALTH_ROCK; + else + gSideStatuses[0] &= ~(SIDE_STATUS_STEALTH_ROCK); + + if (bits & SIDE_STATUS_STEALTH_ROCK) + gSideStatuses[1] |= SIDE_STATUS_STEALTH_ROCK; + else + gSideStatuses[1] &= ~(SIDE_STATUS_STEALTH_ROCK); + + //Tailwind + if (gSideStatuses[1] & SIDE_STATUS_TAILWIND) + gSideStatuses[0] |= SIDE_STATUS_TAILWIND; + else + gSideStatuses[0] &= ~(SIDE_STATUS_TAILWIND); + + if (bits & SIDE_STATUS_TAILWIND) + gSideStatuses[1] |= SIDE_STATUS_TAILWIND; + else + gSideStatuses[1] &= ~(SIDE_STATUS_TAILWIND); + + + //Swap affected status timers + bits = gSideTimers[0].reflectTimer; + gSideTimers[0].reflectTimer = gSideTimers[1].reflectTimer; + gSideTimers[1].reflectTimer = bits; + + bits = gSideTimers[0].lightscreenTimer; + gSideTimers[0].lightscreenTimer = gSideTimers[1].lightscreenTimer; + gSideTimers[1].lightscreenTimer = bits; + + bits = gSideTimers[0].mistTimer; + gSideTimers[0].mistTimer = gSideTimers[1].mistTimer; + gSideTimers[1].mistTimer = bits; + + bits = gSideTimers[0].safeguardTimer; + gSideTimers[0].safeguardTimer = gSideTimers[1].safeguardTimer; + gSideTimers[1].safeguardTimer = bits; + + bits = gSideTimers[0].spikesAmount; + gSideTimers[0].spikesAmount = gSideTimers[1].spikesAmount; + gSideTimers[1].spikesAmount = bits; + + bits = gSideTimers[0].toxicSpikesAmount; + gSideTimers[0].toxicSpikesAmount = gSideTimers[1].toxicSpikesAmount; + gSideTimers[1].toxicSpikesAmount = bits; + + bits = gSideTimers[0].stealthRockAmount; + gSideTimers[0].stealthRockAmount = gSideTimers[1].stealthRockAmount; + gSideTimers[1].stealthRockAmount = bits; + + bits = gSideTimers[0].stickyWebAmount; + gSideTimers[0].stickyWebAmount = gSideTimers[1].stickyWebAmount; + gSideTimers[1].stickyWebAmount = bits; + + bits = gSideTimers[0].auroraVeilTimer; + gSideTimers[0].auroraVeilTimer = gSideTimers[1].auroraVeilTimer; + gSideTimers[1].auroraVeilTimer = bits; + + bits = gSideTimers[0].tailwindTimer; + gSideTimers[0].tailwindTimer = gSideTimers[1].tailwindTimer; + gSideTimers[1].tailwindTimer = bits; + break; } gBattlescriptCurrInstr += 3; diff --git a/src/data/battle_moves.h b/src/data/battle_moves.h index 8bcdccc850..6c8bdd7b70 100644 --- a/src/data/battle_moves.h +++ b/src/data/battle_moves.h @@ -10898,7 +10898,7 @@ const struct BattleMove gBattleMoves[MOVES_COUNT] = [MOVE_COURT_CHANGE] = { - .effect = EFFECT_PLACEHOLDER, //TODO + .effect = EFFECT_COURT_CHANGE, .power = 0, .type = TYPE_NORMAL, .accuracy = 100,